Merge branch 'ads-master-vscode-2020-05-08T03-58-31'

This commit is contained in:
Anthony Dresser
2020-05-08 00:58:57 -07:00
206 changed files with 5072 additions and 2444 deletions
+19
View File
@@ -145,6 +145,25 @@
"order": 2
}
},
{
"type": "node",
"request": "launch",
"name": "Main Process",
"runtimeExecutable": "${workspaceFolder}/scripts/code.sh",
"windows": {
"runtimeExecutable": "${workspaceFolder}/scripts/code.bat",
},
"runtimeArgs": [
"--no-cached-data"
],
"outFiles": [
"${workspaceFolder}/out/**/*.js"
],
"presentation": {
"group": "1_vscode",
"order": 1
}
},
{
"type": "chrome",
"request": "launch",
@@ -2,54 +2,76 @@ steps:
- task: NodeTool@0
inputs:
versionSpec: "12.13.0"
- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@3 # {{SQL CARBON EDIT}} update version
inputs:
versionSpec: "1.x"
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
inputs:
keyfile: 'build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock, !samples/**/yarn.lock'
targetfolder: '**/node_modules, !**/node_modules/**/node_modules, !samples/**/node_modules'
vstsFeed: 'npm-cache' # {{SQL CARBON EDIT}} update build cache
- script: |
CHILD_CONCURRENCY=1 yarn --frozen-lockfile
displayName: Install Dependencies
condition: and(succeeded(), ne(variables['CacheRestored'], 'true'))
- task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1
inputs:
keyfile: 'build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock, !samples/**/yarn.lock'
targetfolder: '**/node_modules, !**/node_modules/**/node_modules, !samples/**/node_modules'
vstsFeed: 'npm-cache' # {{SQL CARBON EDIT}} update build cache
condition: and(succeeded(), ne(variables['CacheRestored'], 'true'))
- script: |
yarn electron x64
displayName: Download Electron
- script: |
yarn gulp hygiene
displayName: Run Hygiene Checks
- script: | # {{SQL CARBON EDIT}} add step
yarn strict-vscode
displayName: Run Strict Null Check.
# - script: | {{SQL CARBON EDIT}} remove step
# yarn monaco-compile-check
# displayName: Run Monaco Editor Checks
- script: |
yarn valid-layers-check
displayName: Run Valid Layers Checks
- script: |
yarn compile
displayName: Compile Sources
# - script: | {{SQL CARBON EDIT}} remove step
# yarn download-builtin-extensions
# displayName: Download Built-in Extensions
- script: |
./scripts/test.sh --tfs "Unit Tests"
displayName: Run Unit Tests (Electron)
# - script: | {{SQL CARBON EDIT}} disable
# yarn test-browser --browser chromium --browser webkit --browser firefox
# displayName: Run Unit Tests (Browser)
# - script: | {{SQL CARBON EDIT}} disable
# ./scripts/test-integration.sh --tfs "Integration Tests"
# displayName: Run Integration Tests (Electron)
# - task: PublishPipelineArtifact@0
# inputs:
# artifactName: crash-dump-macos
# targetPath: .build/crashes
# displayName: 'Publish Crash Reports'
# condition: succeededOrFailed()
- task: PublishTestResults@2
displayName: Publish Tests Results
inputs:
@@ -2,13 +2,5 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
</dict>
</plist>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
</dict>
</plist>
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
</plist>
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
</dict>
</plist>
@@ -152,15 +152,29 @@ steps:
displayName: Run smoke tests (Browser)
condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false'))
- task: PublishPipelineArtifact@0
inputs:
artifactName: crash-dump-macos
targetPath: .build/crashes
displayName: 'Publish Crash Reports'
condition: succeededOrFailed()
- script: |
set -e
APP_ROOT=$(agent.builddirectory)/VSCode-darwin
APP_NAME="`ls $APP_ROOT | head -n 1`"
HELPER_APP_NAME="`echo $APP_NAME | sed -e 's/^Visual Studio //;s/\.app$//'`"
APP_FRAMEWORK_PATH="$APP_ROOT/$APP_NAME/Contents/Frameworks"
security create-keychain -p pwd $(agent.tempdirectory)/buildagent.keychain
security default-keychain -s $(agent.tempdirectory)/buildagent.keychain
security unlock-keychain -p pwd $(agent.tempdirectory)/buildagent.keychain
echo "$(macos-developer-certificate)" | base64 -D > $(agent.tempdirectory)/cert.p12
security import $(agent.tempdirectory)/cert.p12 -k $(agent.tempdirectory)/buildagent.keychain -P "$(macos-developer-certificate-key)" -T /usr/bin/codesign
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k pwd $(agent.tempdirectory)/buildagent.keychain
codesign -s 99FM488X57 --deep --force --options runtime --entitlements build/azure-pipelines/darwin/entitlements.plist $(agent.builddirectory)/VSCode-darwin/*.app
codesign -s 99FM488X57 --deep --force --options runtime --entitlements build/azure-pipelines/darwin/entitlements.plist "$APP_ROOT"/*.app
codesign -s 99FM488X57 --force --options runtime --entitlements build/azure-pipelines/darwin/helper-gpu-entitlements.plist "$APP_FRAMEWORK_PATH/$HELPER_APP_NAME Helper (GPU).app"
codesign -s 99FM488X57 --force --options runtime --entitlements build/azure-pipelines/darwin/helper-plugin-entitlements.plist "$APP_FRAMEWORK_PATH/$HELPER_APP_NAME Helper (Plugin).app"
codesign -s 99FM488X57 --force --options runtime --entitlements build/azure-pipelines/darwin/helper-renderer-entitlements.plist "$APP_FRAMEWORK_PATH/$HELPER_APP_NAME Helper (Renderer).app"
displayName: Set Hardened Entitlements
- script: |
@@ -7,57 +7,80 @@ steps:
sudo chmod +x /etc/init.d/xvfb
sudo update-rc.d xvfb defaults
sudo service xvfb start
- task: NodeTool@0
inputs:
versionSpec: "12.13.0"
- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@3
inputs:
versionSpec: "1.x"
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
inputs:
keyfile: 'build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock, !samples/**/yarn.lock'
targetfolder: '**/node_modules, !**/node_modules/**/node_modules, !samples/**/node_modules'
vstsFeed: 'npm-cache' # {{SQL CARBON EDIT}} update build cache
- script: |
CHILD_CONCURRENCY=1 yarn --frozen-lockfile
displayName: Install Dependencies
condition: and(succeeded(), ne(variables['CacheRestored'], 'true'))
- task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1
inputs:
keyfile: 'build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock, !samples/**/yarn.lock'
targetfolder: '**/node_modules, !**/node_modules/**/node_modules, !samples/**/node_modules'
vstsFeed: 'npm-cache' # {{SQL CARBON EDIT}} update build cache
condition: and(succeeded(), ne(variables['CacheRestored'], 'true'))
- script: |
yarn electron x64
displayName: Download Electron
- script: |
yarn gulp hygiene
displayName: Run Hygiene Checks
- script: | # {{SQL CARBON EDIT}} add strict null check
yarn strict-vscode
displayName: Run Strict Null Check
# - script: | {{SQL CARBON EDIT}} remove monaco editor checks
# yarn monaco-compile-check
# displayName: Run Monaco Editor Checks
- script: |
yarn valid-layers-check
displayName: Run Valid Layers Checks
- script: |
yarn compile
displayName: Compile Sources
# - script: | {{SQL CARBON EDIT}} remove step
# yarn download-builtin-extensions
# displayName: Download Built-in Extensions
- script: |
DISPLAY=:10 ./scripts/test.sh --tfs "Unit Tests"
displayName: Run Unit Tests (Electron)
# - script: | {{SQL CARBON EDIT}} disable
# DISPLAY=:10 yarn test-browser --browser chromium
# displayName: Run Unit Tests (Browser)
# - script: | {{SQL CARBON EDIT}} disable
# DISPLAY=:10 ./scripts/test-integration.sh --tfs "Integration Tests"
# displayName: Run Integration Tests (Electron)
# - task: PublishPipelineArtifact@0
# inputs:
# artifactName: crash-dump-linux
# targetPath: .build/crashes
# displayName: 'Publish Crash Reports'
# condition: succeededOrFailed()
- task: PublishTestResults@2
displayName: Publish Tests Results
inputs:
@@ -140,6 +140,13 @@ steps:
displayName: Run integration tests (Browser)
condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false'))
- task: PublishPipelineArtifact@0
inputs:
artifactName: crash-dump-linux
targetPath: .build/crashes
displayName: 'Publish Crash Reports'
condition: succeededOrFailed()
- script: |
set -e
yarn gulp "vscode-linux-x64-build-deb"
@@ -2,59 +2,83 @@ steps:
- task: NodeTool@0
inputs:
versionSpec: "12.13.0"
- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@3 # {{SQL CARBON EDIT}} update version
inputs:
versionSpec: "1.x"
- task: UsePythonVersion@0
inputs:
versionSpec: '2.x'
addToPath: true
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
inputs:
keyfile: 'build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock, !samples/**/yarn.lock'
targetfolder: '**/node_modules, !**/node_modules/**/node_modules, !samples/**/node_modules'
vstsFeed: 'npm-cache' # {{SQL CARBON EDIT}} update build cache
- powershell: |
yarn --frozen-lockfile
env:
CHILD_CONCURRENCY: "1"
displayName: Install Dependencies
condition: and(succeeded(), ne(variables['CacheRestored'], 'true'))
- task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1
inputs:
keyfile: 'build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock, !samples/**/yarn.lock'
targetfolder: '**/node_modules, !**/node_modules/**/node_modules, !samples/**/node_modules'
vstsFeed: 'npm-cache' # {{SQL CARBON EDIT}} update build cache
condition: and(succeeded(), ne(variables['CacheRestored'], 'true'))
- powershell: |
yarn electron
displayName: Download Electron
- script: |
yarn gulp hygiene
displayName: Run Hygiene Checks
- script: | # {{SQL CARBON EDIT}} add step
yarn strict-vscode
displayName: Run Strict Null Check
# - powershell: | {{SQL CARBON EDIT}} remove step
# yarn monaco-compile-check
# displayName: Run Monaco Editor Checks
- script: |
yarn valid-layers-check
displayName: Run Valid Layers Checks
- powershell: |
yarn compile
displayName: Compile Sources
# - powershell: | {{SQL CARBON EDIT}} remove step
# yarn download-builtin-extensions
# displayName: Download Built-in Extensions
- powershell: |
.\scripts\test.bat --tfs "Unit Tests"
displayName: Run Unit Tests (Electron)
# - powershell: | {{SQL CARBON EDIT}} disable
# yarn test-browser --browser chromium --browser firefox
# displayName: Run Unit Tests (Browser)
# - powershell: | {{SQL CARBON EDIT}} disable
# .\scripts\test-integration.bat --tfs "Integration Tests"
# displayName: Run Integration Tests (Electron)
# - task: PublishPipelineArtifact@0
# displayName: 'Publish Crash Reports'
# inputs:
# artifactName: crash-dump-windows
# targetPath: .build\crashes
# condition: succeededOrFailed()
- task: PublishTestResults@2
displayName: Publish Tests Results
inputs:
@@ -149,6 +149,13 @@ steps:
displayName: Run integration tests (Browser)
condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false'))
- task: PublishPipelineArtifact@0
inputs:
artifactName: crash-dump-windows-$(VSCODE_ARCH)
targetPath: .build\crashes
displayName: 'Publish Crash Reports'
condition: succeededOrFailed()
- task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1
inputs:
ConnectedServiceName: 'ESRP CodeSign'
+1
View File
@@ -430,6 +430,7 @@ function markNodes(languageService, options) {
|| ts.isIndexSignatureDeclaration(member)
|| ts.isCallSignatureDeclaration(member)
|| memberName === '[Symbol.iterator]'
|| memberName === '[Symbol.toStringTag]'
|| memberName === 'toJSON'
|| memberName === 'toString'
|| memberName === 'dispose' // TODO: keeping all `dispose` methods
+1
View File
@@ -548,6 +548,7 @@ function markNodes(languageService: ts.LanguageService, options: ITreeShakingOpt
|| ts.isIndexSignatureDeclaration(member)
|| ts.isCallSignatureDeclaration(member)
|| memberName === '[Symbol.iterator]'
|| memberName === '[Symbol.toStringTag]'
|| memberName === 'toJSON'
|| memberName === 'toString'
|| memberName === 'dispose'// TODO: keeping all `dispose` methods
+5
View File
@@ -409,6 +409,11 @@
"command": "git.timeline.copyCommitMessage",
"title": "%command.timelineCopyCommitMessage%",
"category": "Git"
},
{
"command": "git.rebaseAbort",
"title": "%command.rebaseAbort%",
"category": "Git"
}
],
"keybindings": [
+1
View File
@@ -63,6 +63,7 @@
"command.showOutput": "Show Git Output",
"command.ignore": "Add to .gitignore",
"command.revealInExplorer": "Reveal in Side Bar",
"command.rebaseAbort": "Abort Rebase",
"command.stashIncludeUntracked": "Stash (Include Untracked)",
"command.stash": "Stash",
"command.stashPop": "Pop Stash...",
+4
View File
@@ -2494,6 +2494,10 @@ export class CommandCenter {
env.clipboard.writeText(item.message);
}
@command('git.rebaseAbort', { repository: true })
async rebaseAbort(repository: Repository): Promise<void> {
await repository.rebaseAbort();
}
private createCommand(id: string, key: string, method: Function, options: CommandOptions): (...args: any[]) => any {
const result = (...args: any[]) => {
+4
View File
@@ -1333,6 +1333,10 @@ export class Repository {
}
}
async rebaseAbort(): Promise<void> {
await this.run(['rebase', '--abort']);
}
async rebaseContinue(): Promise<void> {
const args = ['rebase', '--continue'];
+5
View File
@@ -303,6 +303,7 @@ export const enum Operation {
CheckIgnore = 'CheckIgnore',
GetObjectDetails = 'GetObjectDetails',
SubmoduleUpdate = 'SubmoduleUpdate',
RebaseAbort = 'RebaseAbort',
RebaseContinue = 'RebaseContinue',
FindTrackingBranches = 'GetTracking',
Apply = 'Apply',
@@ -1331,6 +1332,10 @@ export class Repository implements Disposable {
});
}
async rebaseAbort(): Promise<void> {
await this.run(Operation.RebaseAbort, async () => await this.repository.rebaseAbort());
}
checkIgnore(filePaths: string[]): Promise<Set<string>> {
return this.run(Operation.CheckIgnore, () => {
return new Promise<Set<string>>((resolve, reject) => {
@@ -77,6 +77,12 @@ interface JSONSchemaSettings {
schema?: any;
}
namespace SettingIds {
export const enableFormatter = 'json.format.enable';
export const enableSchemaDownload = 'json.schemaDownload.enable';
export const maxItemsComputed = 'json.maxItemsComputed';
}
let telemetryReporter: TelemetryReporter | undefined;
export function activate(context: ExtensionContext) {
@@ -107,10 +113,8 @@ export function activate(context: ExtensionContext) {
id: 'status.json.resolveError',
name: localize('json.resolveError', "JSON: Schema Resolution Error"),
alignment: StatusBarAlignment.Right,
priority: 0
priority: 0,
});
schemaResolutionErrorStatusBarItem.command = '_json.retryResolveSchema';
schemaResolutionErrorStatusBarItem.tooltip = localize('json.schemaResolutionErrorMessage', 'Unable to resolve schema.') + ' ' + localize('json.clickToRetry', 'Click to retry.');
schemaResolutionErrorStatusBarItem.text = '$(alert)';
toDispose.push(schemaResolutionErrorStatusBarItem);
@@ -200,6 +204,7 @@ export function activate(context: ExtensionContext) {
toDispose.push(disposable);
client.onReady().then(() => {
const schemaDocuments: { [uri: string]: boolean } = {};
let schemaDownloadEnabled = true;
// handle content request
client.onRequest(VSCodeContentRequest.type, (uriPath: string) => {
@@ -208,12 +213,16 @@ export function activate(context: ExtensionContext) {
return Promise.reject(new Error(localize('untitled.schema', 'Unable to load {0}', uri.toString())));
}
if (uri.scheme !== 'http' && uri.scheme !== 'https') {
if (schemaDownloadEnabled) {
return workspace.openTextDocument(uri).then(doc => {
schemaDocuments[uri.toString()] = true;
return doc.getText();
}, error => {
return Promise.reject(error);
});
} else {
return Promise.reject(localize('schemaDownloadDisabled', 'Downloading schemas is disabled through setting \'{0}\'', SettingIds.enableSchemaDownload));
}
} else {
if (telemetryReporter && uri.authority === 'schema.management.azure.com') {
/* __GDPR__
@@ -294,30 +303,26 @@ export function activate(context: ExtensionContext) {
client.sendNotification(SchemaAssociationNotification.type, getSchemaAssociations(context));
});
// manually register / deregister format provider based on the `html.format.enable` setting avoiding issues with late registration. See #71652.
// manually register / deregister format provider based on the `json.format.enable` setting avoiding issues with late registration. See #71652.
updateFormatterRegistration();
toDispose.push({ dispose: () => rangeFormatting && rangeFormatting.dispose() });
toDispose.push(workspace.onDidChangeConfiguration(e => e.affectsConfiguration('html.format.enable') && updateFormatterRegistration()));
updateSchemaDownloadSetting();
toDispose.push(workspace.onDidChangeConfiguration(e => {
if (e.affectsConfiguration(SettingIds.enableFormatter)) {
updateFormatterRegistration();
} else if (e.affectsConfiguration(SettingIds.enableSchemaDownload)) {
updateSchemaDownloadSetting();
}
}));
client.onNotification(ResultLimitReachedNotification.type, message => {
window.showInformationMessage(`${message}\nUse setting 'json.maxItemsComputed' to configure the limit.`);
window.showInformationMessage(`${message}\n${localize('configureLimit', 'Use setting \'{0}\' to configure the limit.', SettingIds.maxItemsComputed)}`);
});
});
const languageConfiguration: LanguageConfiguration = {
wordPattern: /("(?:[^\\\"]*(?:\\.)?)*"?)|[^\s{}\[\],:]+/,
indentationRules: {
increaseIndentPattern: /({+(?=([^"]*"[^"]*")*[^"}]*$))|(\[+(?=([^"]*"[^"]*")*[^"\]]*$))/,
decreaseIndentPattern: /^\s*[}\]],?\s*$/
}
};
languages.setLanguageConfiguration('json', languageConfiguration);
languages.setLanguageConfiguration('jsonc', languageConfiguration);
function updateFormatterRegistration() {
const formatEnabled = workspace.getConfiguration().get('json.format.enable');
const formatEnabled = workspace.getConfiguration().get(SettingIds.enableFormatter);
if (!formatEnabled && rangeFormatting) {
rangeFormatting.dispose();
rangeFormatting = undefined;
@@ -340,6 +345,31 @@ export function activate(context: ExtensionContext) {
});
}
}
function updateSchemaDownloadSetting() {
schemaDownloadEnabled = workspace.getConfiguration().get(SettingIds.enableSchemaDownload) !== false;
if (schemaDownloadEnabled) {
schemaResolutionErrorStatusBarItem.tooltip = localize('json.schemaResolutionErrorMessage', 'Unable to resolve schema. Click to retry.');
schemaResolutionErrorStatusBarItem.command = '_json.retryResolveSchema';
handleRetryResolveSchemaCommand();
} else {
schemaResolutionErrorStatusBarItem.tooltip = localize('json.schemaResolutionDisabledMessage', 'Downloading schemas is disabled. Click to configure.');
schemaResolutionErrorStatusBarItem.command = { command: 'workbench.action.openSettings', arguments: [SettingIds.enableSchemaDownload], title: '' };
}
}
});
const languageConfiguration: LanguageConfiguration = {
wordPattern: /("(?:[^\\\"]*(?:\\.)?)*"?)|[^\s{}\[\],:]+/,
indentationRules: {
increaseIndentPattern: /({+(?=([^"]*"[^"]*")*[^"}]*$))|(\[+(?=([^"]*"[^"]*")*[^"\]]*$))/,
decreaseIndentPattern: /^\s*[}\]],?\s*$/
}
};
languages.setLanguageConfiguration('json', languageConfiguration);
languages.setLanguageConfiguration('jsonc', languageConfiguration);
}
@@ -386,7 +416,7 @@ function getSchemaAssociations(_context: ExtensionContext): ISchemaAssociation[]
function getSettings(): Settings {
const httpSettings = workspace.getConfiguration('http');
const resultLimit: number = Math.trunc(Math.max(0, Number(workspace.getConfiguration().get('json.maxItemsComputed')))) || 5000;
const resultLimit: number = Math.trunc(Math.max(0, Number(workspace.getConfiguration().get(SettingIds.maxItemsComputed)))) || 5000;
const settings: Settings = {
http: {
@@ -95,6 +95,12 @@
"type": "number",
"default": 5000,
"description": "%json.maxItemsComputed.desc%"
},
"json.schemaDownload.enable": {
"type": "boolean",
"default": true,
"description": "%json.enableSchemaDownload.desc%",
"tags": ["usesOnlineServices"]
}
}
},
@@ -12,5 +12,6 @@
"json.colorDecorators.enable.deprecationMessage": "The setting `json.colorDecorators.enable` has been deprecated in favor of `editor.colorDecorators`.",
"json.schemaResolutionErrorMessage": "Unable to resolve schema.",
"json.clickToRetry": "Click to retry.",
"json.maxItemsComputed.desc": "The maximum number of outline symbols and folding regions computed (limited for performance reasons)."
"json.maxItemsComputed.desc": "The maximum number of outline symbols and folding regions computed (limited for performance reasons).",
"json.enableSchemaDownload.desc": "When enabled, JSON schemas can be fetched from http and https locations."
}
@@ -90,7 +90,8 @@ function createContext(): TestContext {
storagePath: '',
globalStoragePath: '',
logPath: '',
extensionUri: vscode.Uri.parse('')
extensionUri: vscode.Uri.parse(''),
environmentVariableCollection: { } as any
},
outputChannel: {
name: '',
@@ -22,6 +22,7 @@ export class MockExtensionContext implements vscode.ExtensionContext {
constructor() {
this.subscriptions = [];
}
environmentVariableCollection: vscode.EnvironmentVariableCollection;
}
export class MockOutputChannel implements vscode.OutputChannel {
@@ -33,7 +33,8 @@ export function createContext(): TestContext {
storagePath: '',
globalStoragePath: '',
logPath: '',
extensionUri: vscode.Uri.parse('')
extensionUri: vscode.Uri.parse(''),
environmentVariableCollection: undefined as any
},
};
}
@@ -10,7 +10,7 @@ let fs = require('fs');
let https = require('https');
let url = require('url');
// list of languagesIs not shipped with VSCode. The information is used to associate an icon with a language association
// list of languagesId not shipped with VSCode. The information is used to associate an icon with a language association
let nonBuiltInLanguages = { // { fileNames, extensions }
"r": { extensions: ['r', 'rhistory', 'rprofile', 'rt'] },
"argdown": { extensions: ['ad', 'adown', 'argdown', 'argdn'] },
@@ -32,10 +32,16 @@ let nonBuiltInLanguages = { // { fileNames, extensions }
"haml": { extensions: ['haml'] },
"stylus": { extensions: ['styl'] },
"vala": { extensions: ['vala'] },
"todo": { fileNames: ['todo'] },
"jsonc": { extensions: ['json'] }
"todo": { fileNames: ['todo'] }
};
// list of languagesId that inherit the icon from another language
let inheritIconFromLanguage = {
"jsonc": 'json',
"postcss": 'css',
"django-html": 'html'
}
let FROM_DISK = true; // set to true to take content from a repo checked out next to the vscode repo
let font, fontMappingsFile, fileAssociationFile, colorsFile;
@@ -358,6 +364,16 @@ exports.update = function () {
}
}
}
for (let lang in inheritIconFromLanguage) {
let superLang = inheritIconFromLanguage[lang];
let def = lang2Def[superLang];
if (def) {
lang2Def[lang] = def;
} else {
console.log('skipping icon def for ' + lang + ': no icon for ' + superLang + ' defined');
}
}
return download(colorsFile).then(function (content) {
+1 -1
View File
@@ -6,7 +6,7 @@
"git": {
"name": "seti-ui",
"repositoryUrl": "https://github.com/jesseweed/seti-ui",
"commitHash": "4b3e0a3d0ca8999430bc3aa9f2c8324e6922b3de"
"commitHash": "8f22764c37feb7f706465f5186132111a2401b6b"
}
},
"version": "0.1.0"
Binary file not shown.
@@ -966,399 +966,413 @@
"fontCharacter": "\\E06C",
"fontColor": "#519aba"
},
"_pug_light": {
"_prolog_light": {
"fontCharacter": "\\E06E",
"fontColor": "#cc6d2e"
},
"_prolog": {
"fontCharacter": "\\E06E",
"fontColor": "#e37933"
},
"_pug_light": {
"fontCharacter": "\\E06F",
"fontColor": "#b8383d"
},
"_pug": {
"fontCharacter": "\\E06E",
"fontCharacter": "\\E06F",
"fontColor": "#cc3e44"
},
"_puppet_light": {
"fontCharacter": "\\E06F",
"fontCharacter": "\\E070",
"fontColor": "#b7b73b"
},
"_puppet": {
"fontCharacter": "\\E06F",
"fontCharacter": "\\E070",
"fontColor": "#cbcb41"
},
"_python_light": {
"fontCharacter": "\\E070",
"fontCharacter": "\\E071",
"fontColor": "#498ba7"
},
"_python": {
"fontCharacter": "\\E070",
"fontCharacter": "\\E071",
"fontColor": "#519aba"
},
"_react_light": {
"fontCharacter": "\\E072",
"fontCharacter": "\\E073",
"fontColor": "#498ba7"
},
"_react": {
"fontCharacter": "\\E072",
"fontCharacter": "\\E073",
"fontColor": "#519aba"
},
"_react_1_light": {
"fontCharacter": "\\E072",
"fontCharacter": "\\E073",
"fontColor": "#cc6d2e"
},
"_react_1": {
"fontCharacter": "\\E072",
"fontCharacter": "\\E073",
"fontColor": "#e37933"
},
"_react_2_light": {
"fontCharacter": "\\E072",
"fontCharacter": "\\E073",
"fontColor": "#b7b73b"
},
"_react_2": {
"fontCharacter": "\\E072",
"fontCharacter": "\\E073",
"fontColor": "#cbcb41"
},
"_reasonml_light": {
"fontCharacter": "\\E073",
"fontCharacter": "\\E074",
"fontColor": "#b8383d"
},
"_reasonml": {
"fontCharacter": "\\E073",
"fontCharacter": "\\E074",
"fontColor": "#cc3e44"
},
"_rmd_light": {
"fontColor": "#498ba7"
},
"_rmd": {
"fontColor": "#519aba"
},
"_rollup_light": {
"fontCharacter": "\\E074",
"fontCharacter": "\\E075",
"fontColor": "#b8383d"
},
"_rollup": {
"fontCharacter": "\\E074",
"fontCharacter": "\\E075",
"fontColor": "#cc3e44"
},
"_ruby_light": {
"fontCharacter": "\\E075",
"fontCharacter": "\\E076",
"fontColor": "#b8383d"
},
"_ruby": {
"fontCharacter": "\\E075",
"fontCharacter": "\\E076",
"fontColor": "#cc3e44"
},
"_rust_light": {
"fontCharacter": "\\E076",
"fontCharacter": "\\E077",
"fontColor": "#627379"
},
"_rust": {
"fontCharacter": "\\E076",
"fontCharacter": "\\E077",
"fontColor": "#6d8086"
},
"_salesforce_light": {
"fontCharacter": "\\E077",
"fontCharacter": "\\E078",
"fontColor": "#498ba7"
},
"_salesforce": {
"fontCharacter": "\\E077",
"fontCharacter": "\\E078",
"fontColor": "#519aba"
},
"_sass_light": {
"fontCharacter": "\\E078",
"fontCharacter": "\\E079",
"fontColor": "#dd4b78"
},
"_sass": {
"fontCharacter": "\\E078",
"fontCharacter": "\\E079",
"fontColor": "#f55385"
},
"_sbt_light": {
"fontCharacter": "\\E079",
"fontCharacter": "\\E07A",
"fontColor": "#498ba7"
},
"_sbt": {
"fontCharacter": "\\E079",
"fontCharacter": "\\E07A",
"fontColor": "#519aba"
},
"_scala_light": {
"fontCharacter": "\\E07A",
"fontCharacter": "\\E07B",
"fontColor": "#b8383d"
},
"_scala": {
"fontCharacter": "\\E07A",
"fontCharacter": "\\E07B",
"fontColor": "#cc3e44"
},
"_shell_light": {
"fontCharacter": "\\E07D",
"fontCharacter": "\\E07E",
"fontColor": "#455155"
},
"_shell": {
"fontCharacter": "\\E07D",
"fontCharacter": "\\E07E",
"fontColor": "#4d5a5e"
},
"_slim_light": {
"fontCharacter": "\\E07E",
"fontCharacter": "\\E07F",
"fontColor": "#cc6d2e"
},
"_slim": {
"fontCharacter": "\\E07E",
"fontCharacter": "\\E07F",
"fontColor": "#e37933"
},
"_smarty_light": {
"fontCharacter": "\\E07F",
"fontCharacter": "\\E080",
"fontColor": "#b7b73b"
},
"_smarty": {
"fontCharacter": "\\E07F",
"fontCharacter": "\\E080",
"fontColor": "#cbcb41"
},
"_spring_light": {
"fontCharacter": "\\E080",
"fontCharacter": "\\E081",
"fontColor": "#7fae42"
},
"_spring": {
"fontCharacter": "\\E080",
"fontCharacter": "\\E081",
"fontColor": "#8dc149"
},
"_stylelint_light": {
"fontCharacter": "\\E081",
"fontCharacter": "\\E082",
"fontColor": "#bfc2c1"
},
"_stylelint": {
"fontCharacter": "\\E081",
"fontCharacter": "\\E082",
"fontColor": "#d4d7d6"
},
"_stylelint_1_light": {
"fontCharacter": "\\E081",
"fontCharacter": "\\E082",
"fontColor": "#455155"
},
"_stylelint_1": {
"fontCharacter": "\\E081",
"fontCharacter": "\\E082",
"fontColor": "#4d5a5e"
},
"_stylus_light": {
"fontCharacter": "\\E082",
"fontCharacter": "\\E083",
"fontColor": "#7fae42"
},
"_stylus": {
"fontCharacter": "\\E082",
"fontCharacter": "\\E083",
"fontColor": "#8dc149"
},
"_sublime_light": {
"fontCharacter": "\\E083",
"fontCharacter": "\\E084",
"fontColor": "#cc6d2e"
},
"_sublime": {
"fontCharacter": "\\E083",
"fontCharacter": "\\E084",
"fontColor": "#e37933"
},
"_svg_light": {
"fontCharacter": "\\E084",
"fontCharacter": "\\E085",
"fontColor": "#9068b0"
},
"_svg": {
"fontCharacter": "\\E084",
"fontCharacter": "\\E085",
"fontColor": "#a074c4"
},
"_svg_1_light": {
"fontCharacter": "\\E084",
"fontCharacter": "\\E085",
"fontColor": "#498ba7"
},
"_svg_1": {
"fontCharacter": "\\E084",
"fontCharacter": "\\E085",
"fontColor": "#519aba"
},
"_swift_light": {
"fontCharacter": "\\E085",
"fontCharacter": "\\E086",
"fontColor": "#cc6d2e"
},
"_swift": {
"fontCharacter": "\\E085",
"fontCharacter": "\\E086",
"fontColor": "#e37933"
},
"_terraform_light": {
"fontCharacter": "\\E086",
"fontCharacter": "\\E087",
"fontColor": "#9068b0"
},
"_terraform": {
"fontCharacter": "\\E086",
"fontCharacter": "\\E087",
"fontColor": "#a074c4"
},
"_tex_light": {
"fontCharacter": "\\E087",
"fontCharacter": "\\E088",
"fontColor": "#498ba7"
},
"_tex": {
"fontCharacter": "\\E087",
"fontCharacter": "\\E088",
"fontColor": "#519aba"
},
"_tex_1_light": {
"fontCharacter": "\\E087",
"fontCharacter": "\\E088",
"fontColor": "#b7b73b"
},
"_tex_1": {
"fontCharacter": "\\E087",
"fontCharacter": "\\E088",
"fontColor": "#cbcb41"
},
"_tex_2_light": {
"fontCharacter": "\\E087",
"fontCharacter": "\\E088",
"fontColor": "#cc6d2e"
},
"_tex_2": {
"fontCharacter": "\\E087",
"fontCharacter": "\\E088",
"fontColor": "#e37933"
},
"_tex_3_light": {
"fontCharacter": "\\E087",
"fontCharacter": "\\E088",
"fontColor": "#bfc2c1"
},
"_tex_3": {
"fontCharacter": "\\E087",
"fontCharacter": "\\E088",
"fontColor": "#d4d7d6"
},
"_todo": {
"fontCharacter": "\\E089"
"fontCharacter": "\\E08A"
},
"_tsconfig_light": {
"fontCharacter": "\\E08A",
"fontCharacter": "\\E08B",
"fontColor": "#498ba7"
},
"_tsconfig": {
"fontCharacter": "\\E08A",
"fontCharacter": "\\E08B",
"fontColor": "#519aba"
},
"_twig_light": {
"fontCharacter": "\\E08B",
"fontCharacter": "\\E08C",
"fontColor": "#7fae42"
},
"_twig": {
"fontCharacter": "\\E08B",
"fontCharacter": "\\E08C",
"fontColor": "#8dc149"
},
"_typescript_light": {
"fontCharacter": "\\E08C",
"fontCharacter": "\\E08D",
"fontColor": "#498ba7"
},
"_typescript": {
"fontCharacter": "\\E08C",
"fontCharacter": "\\E08D",
"fontColor": "#519aba"
},
"_typescript_1_light": {
"fontCharacter": "\\E08C",
"fontCharacter": "\\E08D",
"fontColor": "#b7b73b"
},
"_typescript_1": {
"fontCharacter": "\\E08C",
"fontCharacter": "\\E08D",
"fontColor": "#cbcb41"
},
"_vala_light": {
"fontCharacter": "\\E08D",
"fontCharacter": "\\E08E",
"fontColor": "#627379"
},
"_vala": {
"fontCharacter": "\\E08D",
"fontCharacter": "\\E08E",
"fontColor": "#6d8086"
},
"_video_light": {
"fontCharacter": "\\E08E",
"fontCharacter": "\\E08F",
"fontColor": "#dd4b78"
},
"_video": {
"fontCharacter": "\\E08E",
"fontCharacter": "\\E08F",
"fontColor": "#f55385"
},
"_vue_light": {
"fontCharacter": "\\E08F",
"fontCharacter": "\\E090",
"fontColor": "#7fae42"
},
"_vue": {
"fontCharacter": "\\E08F",
"fontCharacter": "\\E090",
"fontColor": "#8dc149"
},
"_wasm_light": {
"fontCharacter": "\\E090",
"fontCharacter": "\\E091",
"fontColor": "#9068b0"
},
"_wasm": {
"fontCharacter": "\\E090",
"fontCharacter": "\\E091",
"fontColor": "#a074c4"
},
"_wat_light": {
"fontCharacter": "\\E091",
"fontCharacter": "\\E092",
"fontColor": "#9068b0"
},
"_wat": {
"fontCharacter": "\\E091",
"fontCharacter": "\\E092",
"fontColor": "#a074c4"
},
"_webpack_light": {
"fontCharacter": "\\E092",
"fontCharacter": "\\E093",
"fontColor": "#498ba7"
},
"_webpack": {
"fontCharacter": "\\E092",
"fontCharacter": "\\E093",
"fontColor": "#519aba"
},
"_wgt_light": {
"fontCharacter": "\\E093",
"fontCharacter": "\\E094",
"fontColor": "#498ba7"
},
"_wgt": {
"fontCharacter": "\\E093",
"fontCharacter": "\\E094",
"fontColor": "#519aba"
},
"_windows_light": {
"fontCharacter": "\\E094",
"fontCharacter": "\\E095",
"fontColor": "#498ba7"
},
"_windows": {
"fontCharacter": "\\E094",
"fontCharacter": "\\E095",
"fontColor": "#519aba"
},
"_word_light": {
"fontCharacter": "\\E095",
"fontCharacter": "\\E096",
"fontColor": "#498ba7"
},
"_word": {
"fontCharacter": "\\E095",
"fontCharacter": "\\E096",
"fontColor": "#519aba"
},
"_xls_light": {
"fontCharacter": "\\E096",
"fontCharacter": "\\E097",
"fontColor": "#7fae42"
},
"_xls": {
"fontCharacter": "\\E096",
"fontCharacter": "\\E097",
"fontColor": "#8dc149"
},
"_xml_light": {
"fontCharacter": "\\E097",
"fontCharacter": "\\E098",
"fontColor": "#cc6d2e"
},
"_xml": {
"fontCharacter": "\\E097",
"fontCharacter": "\\E098",
"fontColor": "#e37933"
},
"_yarn_light": {
"fontCharacter": "\\E098",
"fontCharacter": "\\E099",
"fontColor": "#498ba7"
},
"_yarn": {
"fontCharacter": "\\E098",
"fontCharacter": "\\E099",
"fontColor": "#519aba"
},
"_yml_light": {
"fontCharacter": "\\E099",
"fontCharacter": "\\E09A",
"fontColor": "#9068b0"
},
"_yml": {
"fontCharacter": "\\E099",
"fontCharacter": "\\E09A",
"fontColor": "#a074c4"
},
"_zip_light": {
"fontCharacter": "\\E09A",
"fontCharacter": "\\E09B",
"fontColor": "#b8383d"
},
"_zip": {
"fontCharacter": "\\E09A",
"fontCharacter": "\\E09B",
"fontColor": "#cc3e44"
},
"_zip_1_light": {
"fontCharacter": "\\E09A",
"fontCharacter": "\\E09B",
"fontColor": "#627379"
},
"_zip_1": {
"fontCharacter": "\\E09A",
"fontCharacter": "\\E09B",
"fontColor": "#6d8086"
},
// {{SQL CARBON EDIT}}
@@ -1392,6 +1406,7 @@
"edn": "_clojure_1",
"cfc": "_coldfusion",
"cfm": "_coldfusion",
"litcoffee": "_coffee",
"config": "_config",
"cfg": "_config",
"conf": "_config",
@@ -1434,6 +1449,7 @@
"hxml": "_haxe_3",
"class": "_java",
"classpath": "_java",
"properties": "_java",
"js.map": "_javascript",
"spec.js": "_javascript_1",
"test.js": "_javascript_1",
@@ -1480,6 +1496,7 @@
"test.tsx": "_react_2",
"re": "_reasonml",
"r": "_R",
"rmd": "_rmd",
"erb": "_html_erb",
"erb.html": "_html_erb",
"html.erb": "_html_erb",
@@ -1507,6 +1524,7 @@
"vue": "_vue",
"wasm": "_wasm",
"wat": "_wat",
"pro": "_prolog",
"jar": "_zip",
"zip": "_zip_1",
"wgt": "_wgt",
@@ -1545,6 +1563,8 @@
"obj": "_svg_1",
"dae": "_svg_1",
"babelrc": "_babel",
"babelrc.js": "_babel",
"babelrc.cjs": "_babel",
"bowerrc": "_bower",
"dockerignore": "_docker_1",
"codeclimate.yml": "_code-climate",
@@ -1588,12 +1608,14 @@
"version.md": "_clock",
"version": "_clock",
"mvnw": "_maven",
"tsconfig.json": "_tsconfig",
"swagger.json": "_json_1",
"swagger.yml": "_json_1",
"swagger.yaml": "_json_1",
"mime.types": "_config",
"jenkinsfile": "_jenkins",
"babel.config.js": "_babel",
"babel.config.json": "_babel",
"babel.config.cjs": "_babel",
"bower.json": "_bower",
"docker-healthcheck": "_docker_2",
"docker-compose.yml": "_docker_3",
@@ -1606,6 +1628,7 @@
"gruntfile.babel.js": "_grunt",
"gruntfile.coffee": "_grunt",
"gulpfile": "_gulp",
"gulpfile.js": "_gulp",
"ionic.config.json": "_ionic",
"ionic.project": "_ionic",
"platformio.ini": "_platformio",
@@ -1649,7 +1672,6 @@
"groovy": "_grails",
"handlebars": "_mustache",
"html": "_html_3",
"properties": "_java",
"java": "_java",
"javascriptreact": "_react",
"javascript": "_javascript",
@@ -1699,7 +1721,9 @@
"todo": "_todo",
// {{SQL CARBON EDIT}}
"notebook": "notebook_dark",
"scmp": "scmp_dark"
"scmp": "scmp_dark",
"postcss": "_css",
"django-html": "_html_3"
},
"light": {
"file": "_default_light",
@@ -1719,6 +1743,7 @@
"edn": "_clojure_1_light",
"cfc": "_coldfusion_light",
"cfm": "_coldfusion_light",
"litcoffee": "_coffee_light",
"config": "_config_light",
"cfg": "_config_light",
"conf": "_config_light",
@@ -1761,6 +1786,7 @@
"hxml": "_haxe_3_light",
"class": "_java_light",
"classpath": "_java_light",
"properties": "_java_light",
"js.map": "_javascript_light",
"spec.js": "_javascript_1_light",
"test.js": "_javascript_1_light",
@@ -1807,6 +1833,7 @@
"test.tsx": "_react_2_light",
"re": "_reasonml_light",
"r": "_R_light",
"rmd": "_rmd_light",
"erb": "_html_erb_light",
"erb.html": "_html_erb_light",
"html.erb": "_html_erb_light",
@@ -1834,6 +1861,7 @@
"vue": "_vue_light",
"wasm": "_wasm_light",
"wat": "_wat_light",
"pro": "_prolog_light",
"jar": "_zip_light",
"zip": "_zip_1_light",
"wgt": "_wgt_light",
@@ -1872,6 +1900,8 @@
"obj": "_svg_1_light",
"dae": "_svg_1_light",
"babelrc": "_babel_light",
"babelrc.js": "_babel_light",
"babelrc.cjs": "_babel_light",
"bowerrc": "_bower_light",
"dockerignore": "_docker_1_light",
"codeclimate.yml": "_code-climate_light",
@@ -1919,7 +1949,6 @@
"groovy": "_grails_light",
"handlebars": "_mustache_light",
"html": "_html_3_light",
"properties": "_java_light",
"java": "_java_light",
"javascriptreact": "_react_light",
"javascript": "_javascript_light",
@@ -1968,7 +1997,9 @@
"vala": "_vala_light",
// {{SQL CARBON EDIT}}
"notebook": "notebook",
"scmp": "scmp"
"scmp": "scmp",
"postcss": "_css_light",
"django-html": "_html_3_light"
},
"fileNames": {
"mix": "_hex_light",
@@ -1981,12 +2012,14 @@
"version.md": "_clock_light",
"version": "_clock_light",
"mvnw": "_maven_light",
"tsconfig.json": "_tsconfig_light",
"swagger.json": "_json_1_light",
"swagger.yml": "_json_1_light",
"swagger.yaml": "_json_1_light",
"mime.types": "_config_light",
"jenkinsfile": "_jenkins_light",
"babel.config.js": "_babel_light",
"babel.config.json": "_babel_light",
"babel.config.cjs": "_babel_light",
"bower.json": "_bower_light",
"docker-healthcheck": "_docker_2_light",
"docker-compose.yml": "_docker_3_light",
@@ -1999,6 +2032,7 @@
"gruntfile.babel.js": "_grunt_light",
"gruntfile.coffee": "_grunt_light",
"gulpfile": "_gulp_light",
"gulpfile.js": "_gulp_light",
"ionic.config.json": "_ionic_light",
"ionic.project": "_ionic_light",
"platformio.ini": "_platformio_light",
@@ -2027,5 +2061,5 @@
"Schema Compare": "scmp"
}
},
"version": "https://github.com/jesseweed/seti-ui/commit/4b3e0a3d0ca8999430bc3aa9f2c8324e6922b3de"
"version": "https://github.com/jesseweed/seti-ui/commit/8f22764c37feb7f706465f5186132111a2401b6b"
}
@@ -317,6 +317,10 @@ export class AzureActiveDirectoryService {
}
private getCallbackEnvironment(callbackUri: vscode.Uri): string {
if (callbackUri.authority.endsWith('.workspaces.github.com')) {
return `${callbackUri.authority},`;
}
switch (callbackUri.authority) {
case 'online.visualstudio.com':
return 'vso,';
+3 -3
View File
@@ -76,15 +76,15 @@
"sudo-prompt": "9.1.1",
"v8-inspect-profiler": "^0.0.20",
"vscode-nsfw": "1.2.8",
"vscode-oniguruma": "1.3.0",
"vscode-oniguruma": "1.3.1",
"vscode-proxy-agent": "^0.5.2",
"vscode-ripgrep": "^1.5.8",
"vscode-sqlite3": "4.0.10",
"vscode-textmate": "5.1.1",
"xterm": "4.6.0-beta.38",
"xterm": "4.6.0-beta.44",
"xterm-addon-search": "0.7.0-beta.2",
"xterm-addon-unicode11": "0.2.0-beta.5",
"xterm-addon-web-links": "0.4.0-beta.5",
"xterm-addon-web-links": "0.4.0-beta.6",
"xterm-addon-webgl": "0.7.0-beta.10",
"yauzl": "^2.9.2",
"yazl": "^2.4.3",
+3 -3
View File
@@ -34,14 +34,14 @@
"slickgrid": "github:anthonydresser/SlickGrid#2.3.33",
"spdlog": "^0.11.1",
"vscode-nsfw": "1.2.8",
"vscode-oniguruma": "1.3.0",
"vscode-oniguruma": "1.3.1",
"vscode-proxy-agent": "^0.5.2",
"vscode-ripgrep": "^1.5.8",
"vscode-textmate": "5.1.1",
"xterm": "4.6.0-beta.38",
"xterm": "4.6.0-beta.44",
"xterm-addon-search": "0.7.0-beta.2",
"xterm-addon-unicode11": "0.2.0-beta.5",
"xterm-addon-web-links": "0.4.0-beta.5",
"xterm-addon-web-links": "0.4.0-beta.6",
"xterm-addon-webgl": "0.7.0-beta.10",
"yauzl": "^2.9.2",
"yazl": "^2.4.3",
+3 -3
View File
@@ -21,12 +21,12 @@
"sanitize-html": "^1.19.1",
"semver-umd": "^5.5.6",
"slickgrid": "github:anthonydresser/SlickGrid#2.3.33",
"vscode-oniguruma": "1.3.0",
"vscode-oniguruma": "1.3.1",
"vscode-textmate": "5.1.1",
"xterm": "4.6.0-beta.38",
"xterm": "4.6.0-beta.44",
"xterm-addon-search": "0.7.0-beta.2",
"xterm-addon-unicode11": "0.2.0-beta.5",
"xterm-addon-web-links": "0.4.0-beta.5",
"xterm-addon-web-links": "0.4.0-beta.6",
"xterm-addon-webgl": "0.7.0-beta.10",
"zone.js": "^0.8.4"
}
+12 -12
View File
@@ -338,10 +338,10 @@ util-deprecate@^1.0.1:
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
vscode-oniguruma@1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.3.0.tgz#6788a9db2f8b0781243b4eb8c7a1dd25f6c0e2c8"
integrity sha512-m4Br19v6XD4MRbVrgsLNSZgQrBzk1BCMCleL8+GrcoGxKEJJd62zOFcTaoQR3hCrSlLqoxWmJ7Cc0VieVV3iTQ==
vscode-oniguruma@1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.3.1.tgz#e2383879c3485b19f533ec34efea9d7a2b14be8f"
integrity sha512-gz6ZBofA7UXafVA+m2Yt2zHKgXC2qedArprIsHAPKByTkwq9l5y/izAGckqxYml7mSbYxTRTfdRwsFq3cwF4LQ==
vscode-textmate@5.1.1:
version "5.1.1"
@@ -363,20 +363,20 @@ xterm-addon-unicode11@0.2.0-beta.5:
resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.2.0-beta.5.tgz#5961850162df20b5e966166423cd6957ac2db298"
integrity sha512-IjnbBcyfS5JgJDXPO0W2nk/VBtGwx6GWE2snMC676z4DmAABUqPXfTzJKfUoWqoT6UcbxB0oIjDzykCfoRJp6Q==
xterm-addon-web-links@0.4.0-beta.5:
version "0.4.0-beta.5"
resolved "https://registry.yarnpkg.com/xterm-addon-web-links/-/xterm-addon-web-links-0.4.0-beta.5.tgz#523fd0a1c5668370d73e05019ed16eaf596894c8"
integrity sha512-Qe0idPpSokCNvGrthSBjdrOZrsgXwnLYbzuv0JoEec/A9HVcxKmZ+ktw7fOA2gT/zbcwtrA5FWrir3GlRHglCQ==
xterm-addon-web-links@0.4.0-beta.6:
version "0.4.0-beta.6"
resolved "https://registry.yarnpkg.com/xterm-addon-web-links/-/xterm-addon-web-links-0.4.0-beta.6.tgz#d159d4542eb9a02d57977fe7eb5f42f8ef2f27fa"
integrity sha512-dsQVD/EyVq8PtAYGh2PGQTCt009UipIfX6Q2SBDlz+W9x7IkXjhRxRaryMmLsBCca20qeVKwmbQ+ANhLi+nTaQ==
xterm-addon-webgl@0.7.0-beta.10:
version "0.7.0-beta.10"
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.7.0-beta.10.tgz#39fdb96351e97a1bf15f4c4c8944ba3d05cacee4"
integrity sha512-nQl/ASk+ck11aSrBZXb2a0tu+SNDnm89owBk/sAZeZzi5MHNo6bB8y2VTKNNC6D3i3aFouTz4VorYB25LUgNFg==
xterm@4.6.0-beta.38:
version "4.6.0-beta.38"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.6.0-beta.38.tgz#8472b168941500c3071aba482c2b5c6040951ec7"
integrity sha512-Q+nOalMD1MDGOqXdtkGZmOQqbSBU+71vhlX2RBwQoSpJa1QBrKDAhSlN/J+/XvouvVEtCiEFDeacF4EufMEIMg==
xterm@4.6.0-beta.44:
version "4.6.0-beta.44"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.6.0-beta.44.tgz#76b2a6b8e147595ab44aa752c0e721d935464615"
integrity sha512-vYtfz4spFcSKLEUpC6anH7TwDams71+k2wAtUzCJ47dNL2IrwYafcFsvGPm46QLTtq4M2Bp9rQo3R3V746yxNg==
zone.js@^0.8.4:
version "0.8.29"
+12 -12
View File
@@ -698,10 +698,10 @@ vscode-nsfw@1.2.8:
lodash.isundefined "^3.0.1"
nan "^2.10.0"
vscode-oniguruma@1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.3.0.tgz#6788a9db2f8b0781243b4eb8c7a1dd25f6c0e2c8"
integrity sha512-m4Br19v6XD4MRbVrgsLNSZgQrBzk1BCMCleL8+GrcoGxKEJJd62zOFcTaoQR3hCrSlLqoxWmJ7Cc0VieVV3iTQ==
vscode-oniguruma@1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.3.1.tgz#e2383879c3485b19f533ec34efea9d7a2b14be8f"
integrity sha512-gz6ZBofA7UXafVA+m2Yt2zHKgXC2qedArprIsHAPKByTkwq9l5y/izAGckqxYml7mSbYxTRTfdRwsFq3cwF4LQ==
vscode-proxy-agent@^0.5.2:
version "0.5.2"
@@ -750,20 +750,20 @@ xterm-addon-unicode11@0.2.0-beta.5:
resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.2.0-beta.5.tgz#5961850162df20b5e966166423cd6957ac2db298"
integrity sha512-IjnbBcyfS5JgJDXPO0W2nk/VBtGwx6GWE2snMC676z4DmAABUqPXfTzJKfUoWqoT6UcbxB0oIjDzykCfoRJp6Q==
xterm-addon-web-links@0.4.0-beta.5:
version "0.4.0-beta.5"
resolved "https://registry.yarnpkg.com/xterm-addon-web-links/-/xterm-addon-web-links-0.4.0-beta.5.tgz#523fd0a1c5668370d73e05019ed16eaf596894c8"
integrity sha512-Qe0idPpSokCNvGrthSBjdrOZrsgXwnLYbzuv0JoEec/A9HVcxKmZ+ktw7fOA2gT/zbcwtrA5FWrir3GlRHglCQ==
xterm-addon-web-links@0.4.0-beta.6:
version "0.4.0-beta.6"
resolved "https://registry.yarnpkg.com/xterm-addon-web-links/-/xterm-addon-web-links-0.4.0-beta.6.tgz#d159d4542eb9a02d57977fe7eb5f42f8ef2f27fa"
integrity sha512-dsQVD/EyVq8PtAYGh2PGQTCt009UipIfX6Q2SBDlz+W9x7IkXjhRxRaryMmLsBCca20qeVKwmbQ+ANhLi+nTaQ==
xterm-addon-webgl@0.7.0-beta.10:
version "0.7.0-beta.10"
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.7.0-beta.10.tgz#39fdb96351e97a1bf15f4c4c8944ba3d05cacee4"
integrity sha512-nQl/ASk+ck11aSrBZXb2a0tu+SNDnm89owBk/sAZeZzi5MHNo6bB8y2VTKNNC6D3i3aFouTz4VorYB25LUgNFg==
xterm@4.6.0-beta.38:
version "4.6.0-beta.38"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.6.0-beta.38.tgz#8472b168941500c3071aba482c2b5c6040951ec7"
integrity sha512-Q+nOalMD1MDGOqXdtkGZmOQqbSBU+71vhlX2RBwQoSpJa1QBrKDAhSlN/J+/XvouvVEtCiEFDeacF4EufMEIMg==
xterm@4.6.0-beta.44:
version "4.6.0-beta.44"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.6.0-beta.44.tgz#76b2a6b8e147595ab44aa752c0e721d935464615"
integrity sha512-vYtfz4spFcSKLEUpC6anH7TwDams71+k2wAtUzCJ47dNL2IrwYafcFsvGPm46QLTtq4M2Bp9rQo3R3V746yxNg==
yauzl@^2.9.2:
version "2.10.0"
+1
View File
@@ -9,6 +9,7 @@ if grep -qi Microsoft /proc/version && [ -z "$DONT_PROMPT_WSL_INSTALL" ]; then
read -e -p "Do you want to continue anyways ? [y/N] " YN
[[ $YN == "n" || $YN == "N" || $YN == "" ]] && exit 1
echo "To no longer see this prompt, start @@PRODNAME@@ with the environment variable DONT_PROMPT_WSL_INSTALL defined."
fi
+10 -8
View File
@@ -4,14 +4,16 @@ setlocal
pushd %~dp0\..
set VSCODEUSERDATADIR=%TEMP%\vscodeuserfolder-%RANDOM%-%TIME:~6,2%
set VSCODECRASHDIR=%~dp0\..\.build\crashes
:: Figure out which Electron to use for running tests
if "%INTEGRATION_TEST_ELECTRON_PATH%"=="" (
:: Run out of sources: no need to compile as code.sh takes care of it
:: Run out of sources: no need to compile as code.bat takes care of it
chcp 65001
set INTEGRATION_TEST_ELECTRON_PATH=.\scripts\code.bat
set VSCODE_BUILD_BUILTIN_EXTENSIONS_SILENCE_PLEASE=1
echo Storing crash reports into '%VSCODECRASHDIR%'.
echo Running integration tests out of sources.
) else (
:: Run from a built: need to compile all test extensions
@@ -29,8 +31,8 @@ if "%INTEGRATION_TEST_ELECTRON_PATH%"=="" (
:: Configuration for more verbose output
set VSCODE_CLI=1
set ELECTRON_ENABLE_LOGGING=1
set ELECTRON_ENABLE_STACK_DUMPING=1
echo Storing crash reports into '%VSCODECRASHDIR%'.
echo Running integration tests with '%INTEGRATION_TEST_ELECTRON_PATH%' as build.
)
@@ -41,19 +43,19 @@ if "%INTEGRATION_TEST_ELECTRON_PATH%"=="" (
:: Tests in the extension host
REM call "%INTEGRATION_TEST_ELECTRON_PATH%" %~dp0\..\extensions\vscode-api-tests\testWorkspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=%~dp0\..\extensions\vscode-api-tests --extensionTestsPath=%~dp0\..\extensions\vscode-api-tests\out\singlefolder-tests --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=%VSCODEUSERDATADIR%
REM call "%INTEGRATION_TEST_ELECTRON_PATH%" %~dp0\..\extensions\vscode-api-tests\testWorkspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=%~dp0\..\extensions\vscode-api-tests --extensionTestsPath=%~dp0\..\extensions\vscode-api-tests\out\singlefolder-tests --disable-telemetry --crash-reporter-directory=%VSCODECRASHDIR% --disable-updates --disable-extensions --user-data-dir=%VSCODEUSERDATADIR%
REM if %errorlevel% neq 0 exit /b %errorlevel%
REM call "%INTEGRATION_TEST_ELECTRON_PATH%" %~dp0\..\extensions\vscode-api-tests\testworkspace.code-workspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=%~dp0\..\extensions\vscode-api-tests --extensionTestsPath=%~dp0\..\extensions\vscode-api-tests\out\workspace-tests --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=%VSCODEUSERDATADIR%
REM call "%INTEGRATION_TEST_ELECTRON_PATH%" %~dp0\..\extensions\vscode-api-tests\testworkspace.code-workspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=%~dp0\..\extensions\vscode-api-tests --extensionTestsPath=%~dp0\..\extensions\vscode-api-tests\out\workspace-tests --disable-telemetry --crash-reporter-directory=%VSCODECRASHDIR% --disable-updates --disable-extensions --user-data-dir=%VSCODEUSERDATADIR%
REM if %errorlevel% neq 0 exit /b %errorlevel%
REM call "%INTEGRATION_TEST_ELECTRON_PATH%" %~dp0\..\extensions\vscode-colorize-tests\test --extensionDevelopmentPath=%~dp0\..\extensions\vscode-colorize-tests --extensionTestsPath=%~dp0\..\extensions\vscode-colorize-tests\out --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=%VSCODEUSERDATADIR%
REM call "%INTEGRATION_TEST_ELECTRON_PATH%" %~dp0\..\extensions\vscode-colorize-tests\test --extensionDevelopmentPath=%~dp0\..\extensions\vscode-colorize-tests --extensionTestsPath=%~dp0\..\extensions\vscode-colorize-tests\out --disable-telemetry --crash-reporter-directory=%VSCODECRASHDIR% --disable-updates --disable-extensions --user-data-dir=%VSCODEUSERDATADIR%
REM if %errorlevel% neq 0 exit /b %errorlevel%
REM call "%INTEGRATION_TEST_ELECTRON_PATH%" $%~dp0\..\extensions\markdown-language-features\out\test\test-fixtures --extensionDevelopmentPath=%~dp0\..\extensions\markdown-language-features --extensionTestsPath=%~dp0\..\extensions\markdown-language-features\out\test --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=%VSCODEUSERDATADIR% .
REM call "%INTEGRATION_TEST_ELECTRON_PATH%" $%~dp0\..\extensions\markdown-language-features\out\test\test-fixtures --extensionDevelopmentPath=%~dp0\..\extensions\markdown-language-features --extensionTestsPath=%~dp0\..\extensions\markdown-language-features\out\test --disable-telemetry --crash-reporter-directory=%VSCODECRASHDIR% --disable-updates --disable-extensions --user-data-dir=%VSCODEUSERDATADIR% .
REM if %errorlevel% neq 0 exit /b %errorlevel%
REM call "%INTEGRATION_TEST_ELECTRON_PATH%" $%~dp0\..\extensions\emmet\out\test\test-fixtures --extensionDevelopmentPath=%~dp0\..\extensions\emmet --extensionTestsPath=%~dp0\..\extensions\emmet\out\test --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=%VSCODEUSERDATADIR% .
REM call "%INTEGRATION_TEST_ELECTRON_PATH%" $%~dp0\..\extensions\emmet\out\test\test-fixtures --extensionDevelopmentPath=%~dp0\..\extensions\emmet --extensionTestsPath=%~dp0\..\extensions\emmet\out\test --disable-telemetry --crash-reporter-directory=%VSCODECRASHDIR% --disable-updates --disable-extensions --user-data-dir=%VSCODEUSERDATADIR% .
REM if %errorlevel% neq 0 exit /b %errorlevel%
call "%INTEGRATION_TEST_ELECTRON_PATH%" %~dp0\..\extensions\azurecore\test-fixtures --extensionDevelopmentPath=%~dp0\..\extensions\azurecore --extensionTestsPath=%~dp0\..\extensions\azurecore\out\test --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=%VSCODEUSERDATADIR%
@@ -62,7 +64,7 @@ if %errorlevel% neq 0 exit /b %errorlevel%
for /f "delims=" %%i in ('node -p "require('fs').realpathSync.native(require('os').tmpdir())"') do set TEMPDIR=%%i
set GITWORKSPACE=%TEMPDIR%\git-%RANDOM%
mkdir %GITWORKSPACE%
call "%INTEGRATION_TEST_ELECTRON_PATH%" %GITWORKSPACE% --extensionDevelopmentPath=%~dp0\..\extensions\git --extensionTestsPath=%~dp0\..\extensions\git\out\test --enable-proposed-api=vscode.git --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=%VSCODEUSERDATADIR%
call "%INTEGRATION_TEST_ELECTRON_PATH%" %GITWORKSPACE% --extensionDevelopmentPath=%~dp0\..\extensions\git --extensionTestsPath=%~dp0\..\extensions\git\out\test --enable-proposed-api=vscode.git --disable-telemetry --crash-reporter-directory=%VSCODECRASHDIR% --disable-updates --disable-extensions --user-data-dir=%VSCODEUSERDATADIR%
if %errorlevel% neq 0 exit /b %errorlevel%
:: Tests in commonJS (HTML, CSS, JSON language server tests...)
+10 -7
View File
@@ -10,6 +10,7 @@ else
fi
VSCODEUSERDATADIR=`mktemp -d 2>/dev/null`
VSCODECRASHDIR=$ROOT/.build/crashes
cd $ROOT
# Figure out which Electron to use for running tests
@@ -18,6 +19,7 @@ then
# Run out of sources: no need to compile as code.sh takes care of it
INTEGRATION_TEST_ELECTRON_PATH="./scripts/code.sh"
echo "Storing crash reports into '$VSCODECRASHDIR'."
echo "Running integration tests out of sources."
else
# Run from a built: need to compile all test extensions
@@ -38,6 +40,7 @@ else
export ELECTRON_ENABLE_STACK_DUMPING=1
export ELECTRON_ENABLE_LOGGING=1
echo "Storing crash reports into '$VSCODECRASHDIR'."
echo "Running integration tests with '$INTEGRATION_TEST_ELECTRON_PATH' as build."
fi
@@ -45,13 +48,13 @@ fi
./scripts/test.sh --runGlob **/*.integrationTest.js "$@"
# Tests in the extension host
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-notebook-tests/test --enable-proposed-api=vscode.vscode-notebook-tests --extensionDevelopmentPath=$ROOT/extensions/vscode-notebook-tests --extensionTestsPath=$ROOT/extensions/vscode-notebook-tests/out/ --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-api-tests/testWorkspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out/singlefolder-tests --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-api-tests/testworkspace.code-workspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out/workspace-tests --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-colorize-tests/test --extensionDevelopmentPath=$ROOT/extensions/vscode-colorize-tests --extensionTestsPath=$ROOT/extensions/vscode-colorize-tests/out --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/markdown-language-features/out/test/test-fixtures --extensionDevelopmentPath=$ROOT/extensions/markdown-language-features --extensionTestsPath=$ROOT/extensions/markdown-language-features/out/test --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/emmet/out/test/test-fixtures --extensionDevelopmentPath=$ROOT/extensions/emmet --extensionTestsPath=$ROOT/extensions/emmet/out/test --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $(mktemp -d 2>/dev/null) --enable-proposed-api=vscode.git --extensionDevelopmentPath=$ROOT/extensions/git --extensionTestsPath=$ROOT/extensions/git/out/test --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-notebook-tests/test --enable-proposed-api=vscode.vscode-notebook-tests --extensionDevelopmentPath=$ROOT/extensions/vscode-notebook-tests --extensionTestsPath=$ROOT/extensions/vscode-notebook-tests/out/ --disable-telemetry --crash-reporter-directory=$VSCODECRASHDIR --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-api-tests/testWorkspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out/singlefolder-tests --disable-telemetry --crash-reporter-directory=$VSCODECRASHDIR --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-api-tests/testworkspace.code-workspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out/workspace-tests --disable-telemetry --crash-reporter-directory=$VSCODECRASHDIR --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-colorize-tests/test --extensionDevelopmentPath=$ROOT/extensions/vscode-colorize-tests --extensionTestsPath=$ROOT/extensions/vscode-colorize-tests/out --disable-telemetry --crash-reporter-directory=$VSCODECRASHDIR --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/markdown-language-features/out/test/test-fixtures --extensionDevelopmentPath=$ROOT/extensions/markdown-language-features --extensionTestsPath=$ROOT/extensions/markdown-language-features/out/test --disable-telemetry --crash-reporter-directory=$VSCODECRASHDIR --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/emmet/out/test/test-fixtures --extensionDevelopmentPath=$ROOT/extensions/emmet --extensionTestsPath=$ROOT/extensions/emmet/out/test --disable-telemetry --crash-reporter-directory=$VSCODECRASHDIR --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $(mktemp -d 2>/dev/null) --enable-proposed-api=vscode.git --extensionDevelopmentPath=$ROOT/extensions/git --extensionTestsPath=$ROOT/extensions/git/out/test --disable-telemetry --crash-reporter-directory=$VSCODECRASHDIR --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR
"$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/azurecore/test-fixtures --extensionDevelopmentPath=$ROOT/extensions/azurecore --extensionTestsPath=$ROOT/extensions/azurecore/out/test --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR
+21 -1
View File
@@ -39,6 +39,25 @@ if (args['nogpu']) { // {{SQL CARBON EDIT}}
const userDataPath = getUserDataPath(args);
app.setPath('userData', userDataPath);
// Set temp directory based on crash-reporter-directory CLI argument
// The crash reporter will store crashes in temp folder so we need
// to change that location accordingly.
let crashReporterDirectory = args['crash-reporter-directory'];
if (crashReporterDirectory) {
crashReporterDirectory = path.normalize(crashReporterDirectory);
if (!fs.existsSync(crashReporterDirectory)) {
try {
fs.mkdirSync(crashReporterDirectory);
} catch (error) {
console.error(`The path '${crashReporterDirectory}' specified for --crash-reporter-directory does not seem to exist or cannot be created.`);
app.exit(1);
}
}
console.log(`Found --crash-reporter-directory argument. Setting temp directory to be '${crashReporterDirectory}'`);
app.setPath('temp', crashReporterDirectory);
}
// Set logs path before app 'ready' event if running portable
// to ensure that no 'logs' folder is created on disk at a
// location outside of the portable directory
@@ -336,7 +355,8 @@ function parseCLIArgs() {
'user-data-dir',
'locale',
'js-flags',
'max-memory'
'max-memory',
'crash-reporter-directory'
]
});
}
+12 -12
View File
@@ -477,27 +477,27 @@ export class ActionBar extends Disposable implements IActionRunner {
DOM.addClass(this.domNode, 'animated');
}
let previousKey: KeyCode;
let nextKey: KeyCode;
let previousKeys: KeyCode[];
let nextKeys: KeyCode[];
switch (this.options.orientation) {
case ActionsOrientation.HORIZONTAL:
previousKey = KeyCode.LeftArrow;
nextKey = KeyCode.RightArrow;
previousKeys = [KeyCode.LeftArrow, KeyCode.UpArrow];
nextKeys = [KeyCode.RightArrow, KeyCode.DownArrow];
break;
case ActionsOrientation.HORIZONTAL_REVERSE:
previousKey = KeyCode.RightArrow;
nextKey = KeyCode.LeftArrow;
previousKeys = [KeyCode.RightArrow, KeyCode.DownArrow];
nextKeys = [KeyCode.LeftArrow, KeyCode.UpArrow];
this.domNode.className += ' reverse';
break;
case ActionsOrientation.VERTICAL:
previousKey = KeyCode.UpArrow;
nextKey = KeyCode.DownArrow;
previousKeys = [KeyCode.LeftArrow, KeyCode.UpArrow];
nextKeys = [KeyCode.RightArrow, KeyCode.DownArrow];
this.domNode.className += ' vertical';
break;
case ActionsOrientation.VERTICAL_REVERSE:
previousKey = KeyCode.DownArrow;
nextKey = KeyCode.UpArrow;
previousKeys = [KeyCode.RightArrow, KeyCode.DownArrow];
nextKeys = [KeyCode.LeftArrow, KeyCode.UpArrow];
this.domNode.className += ' vertical reverse';
break;
}
@@ -506,9 +506,9 @@ export class ActionBar extends Disposable implements IActionRunner {
const event = new StandardKeyboardEvent(e);
let eventHandled = true;
if (event.equals(previousKey)) {
if (previousKeys && (event.equals(previousKeys[0]) || event.equals(previousKeys[1]))) {
this.focusPrevious();
} else if (event.equals(nextKey)) {
} else if (nextKeys && (event.equals(nextKeys[0]) || event.equals(nextKeys[1]))) {
this.focusNext();
} else if (event.equals(KeyCode.Escape)) {
this._onDidCancel.fire();
@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
.monaco-count-badge {
padding: 3px 5px;
padding: 3px 6px;
border-radius: 11px;
font-size: 11px;
min-width: 18px;
@@ -15,3 +15,8 @@
display: inline-block;
box-sizing: border-box;
}
.monaco-count-badge.long {
padding: 2px 3px;
border-radius: 2px;
}
+16 -1
View File
@@ -18,6 +18,7 @@ export interface IIndexTreeNode<T, TFilterData = void> extends ITreeNode<T, TFil
collapsible: boolean;
collapsed: boolean;
renderNodeCount: number;
visibility: TreeVisibility;
visible: boolean;
filterData: TFilterData | undefined;
}
@@ -95,6 +96,7 @@ export class IndexTreeModel<T extends Exclude<any, undefined>, TFilterData = voi
collapsible: false,
collapsed: false,
renderNodeCount: 0,
visibility: TreeVisibility.Visible,
visible: true,
filterData: undefined
};
@@ -185,6 +187,17 @@ export class IndexTreeModel<T extends Exclude<any, undefined>, TFilterData = voi
}
this._onDidSplice.fire({ insertedNodes: nodesToInsert, deletedNodes });
let node: IIndexTreeNode<T, TFilterData> | undefined = parentNode;
while (node) {
if (node.visibility === TreeVisibility.Recurse) {
this.refilter();
break;
}
node = node.parent;
}
}
rerender(location: number[]): void {
@@ -194,7 +207,7 @@ export class IndexTreeModel<T extends Exclude<any, undefined>, TFilterData = voi
const { node, listIndex, revealed } = this.getTreeNodeWithListIndex(location);
if (revealed) {
if (node.visible && revealed) {
this.list.splice(listIndex, 1, [node]);
}
}
@@ -355,11 +368,13 @@ export class IndexTreeModel<T extends Exclude<any, undefined>, TFilterData = voi
collapsible: typeof treeElement.collapsible === 'boolean' ? treeElement.collapsible : (typeof treeElement.collapsed !== 'undefined'),
collapsed: typeof treeElement.collapsed === 'undefined' ? this.collapseByDefault : treeElement.collapsed,
renderNodeCount: 1,
visibility: TreeVisibility.Visible,
visible: true,
filterData: undefined
};
const visibility = this._filterNode(node, parentVisibility);
node.visibility = visibility;
if (revealed) {
treeListElements.push(node);
+2 -2
View File
@@ -43,12 +43,12 @@ const _registry = new Registry();
export const iconRegistry: IIconRegistry = _registry;
export function registerIcon(id: string, def: Codicon) {
export function registerIcon(id: string, def: Codicon, description?: string) {
return new Codicon(id, def);
}
export class Codicon {
constructor(public readonly id: string, public readonly definition: Codicon | IconDefinition) {
constructor(public readonly id: string, public readonly definition: Codicon | IconDefinition, public description?: string) {
_registry.add(this);
}
public get classNames() { return 'codicon codicon-' + this.id; }
+1
View File
@@ -63,6 +63,7 @@ export interface IJSONSchema {
markdownEnumDescriptions?: string[];
markdownDescription?: string;
doNotSuggest?: boolean;
suggestSortText?: string;
allowComments?: boolean;
allowTrailingCommas?: boolean;
}
+27 -32
View File
@@ -580,9 +580,7 @@ export const enum Touch {
AsNew = 2
}
export class LinkedMap<K, V> implements Map<K, V>{
readonly [Symbol.toStringTag] = 'LinkedMap';
export class LinkedMap<K, V> {
private _map: Map<K, Item<K, V>>;
private _head: Item<K, V> | undefined;
@@ -634,7 +632,7 @@ export class LinkedMap<K, V> implements Map<K, V>{
return item.value;
}
set(key: K, value: V, touch: Touch = Touch.None): this {
set(key: K, value: V, touch: Touch = Touch.None): void {
let item = this._map.get(key);
if (item) {
item.value = value;
@@ -660,7 +658,6 @@ export class LinkedMap<K, V> implements Map<K, V>{
this._map.set(key, item);
this._size++;
}
return this;
}
delete(key: K): boolean {
@@ -704,8 +701,29 @@ export class LinkedMap<K, V> implements Map<K, V>{
}
}
keys(): IterableIterator<K> {
values(): V[] {
const result: V[] = [];
let current = this._head;
while (current) {
result.push(current.value);
current = current.next;
}
return result;
}
keys(): K[] {
const result: K[] = [];
let current = this._head;
while (current) {
result.push(current.key);
current = current.next;
}
return result;
}
/* VS Code / Monaco editor runs on es5 which has no Symbol.iterator
keys(): IterableIterator<K> {
const current = this._head;
const iterator: IterableIterator<K> = {
[Symbol.iterator]() {
return iterator;
@@ -724,7 +742,7 @@ export class LinkedMap<K, V> implements Map<K, V>{
}
values(): IterableIterator<V> {
let current = this._head;
const current = this._head;
const iterator: IterableIterator<V> = {
[Symbol.iterator]() {
return iterator;
@@ -741,29 +759,7 @@ export class LinkedMap<K, V> implements Map<K, V>{
};
return iterator;
}
entries(): IterableIterator<[K, V]> {
let current = this._head;
const iterator: IterableIterator<[K, V]> = {
[Symbol.iterator]() {
return iterator;
},
next(): IteratorResult<[K, V]> {
if (current) {
const result: IteratorResult<[K, V]> = { value: [current.key, current.value], done: false };
current = current.next;
return result;
} else {
return { value: undefined, done: true };
}
}
};
return iterator;
}
[Symbol.iterator](): IterableIterator<[K, V]> {
return this.entries();
}
*/
protected trimOld(newSize: number) {
if (newSize >= this.size) {
@@ -965,10 +961,9 @@ export class LRUCache<K, V> extends LinkedMap<K, V> {
return super.get(key, Touch.None);
}
set(key: K, value: V): this {
set(key: K, value: V): void {
super.set(key, value, Touch.AsNew);
this.checkTrim();
return this;
}
private checkTrim() {
@@ -97,10 +97,14 @@
align-self: center;
position: absolute;
right: 4px;
display: flex;
align-items: center;
}
.quick-input-count .monaco-count-badge {
vertical-align: middle;
padding: 2px 4px;
border-radius: 2px;
}
.quick-input-action {
@@ -108,9 +112,8 @@
}
.quick-input-action .monaco-text-button {
font-size: 85%;
font-size: 11px;
padding: 0 6px;
line-height: initial;
display: flex;
height: 100%;
align-items: center;
@@ -4,13 +4,14 @@
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { ITreeNode } from 'vs/base/browser/ui/tree/tree';
import { ITreeNode, ITreeFilter, TreeVisibility } from 'vs/base/browser/ui/tree/tree';
import { ISpliceable } from 'vs/base/common/sequence';
import { ObjectTreeModel } from 'vs/base/browser/ui/tree/objectTreeModel';
function toSpliceable<T>(arr: T[]): ISpliceable<T> {
return {
splice(start: number, deleteCount: number, elements: T[]): void {
// console.log(`splice (${start}, ${deleteCount}, ${elements.length} [${elements.join(', ')}] )`); // debugging
arr.splice(start, deleteCount, ...elements);
}
};
@@ -240,4 +241,35 @@ suite('ObjectTreeModel', function () {
model.expandTo(1000);
assert.deepEqual(toArray(list), [0, 10, 100, 1000, 11, 12, 1, 2]);
});
test('issue #95641', () => {
const list: ITreeNode<string>[] = [];
let fn = (_: string) => true;
const filter = new class implements ITreeFilter<string> {
filter(element: string, parentVisibility: TreeVisibility): TreeVisibility {
if (element === 'file') {
return TreeVisibility.Recurse;
}
return fn(element) ? TreeVisibility.Visible : parentVisibility;
}
};
const model = new ObjectTreeModel<string>('test', toSpliceable(list), { filter });
model.setChildren(null, [{ element: 'file', children: [{ element: 'hello' }] }]);
assert.deepEqual(toArray(list), ['file', 'hello']);
fn = (el: string) => el === 'world';
model.refilter();
assert.deepEqual(toArray(list), []);
model.setChildren('file', [{ element: 'world' }]);
assert.deepEqual(toArray(list), ['file', 'world']);
model.setChildren('file', [{ element: 'hello' }]);
assert.deepEqual(toArray(list), []);
model.setChildren('file', [{ element: 'world' }]);
assert.deepEqual(toArray(list), ['file', 'world']);
});
});
+29 -31
View File
@@ -13,8 +13,8 @@ suite('Map', () => {
let map = new LinkedMap<string, string>();
map.set('ak', 'av');
map.set('bk', 'bv');
assert.deepStrictEqual([...map.keys()], ['ak', 'bk']);
assert.deepStrictEqual([...map.values()], ['av', 'bv']);
assert.deepStrictEqual(map.keys(), ['ak', 'bk']);
assert.deepStrictEqual(map.values(), ['av', 'bv']);
assert.equal(map.first, 'av');
assert.equal(map.last, 'bv');
});
@@ -23,16 +23,16 @@ suite('Map', () => {
let map = new LinkedMap<string, string>();
map.set('ak', 'av');
map.set('ak', 'av', Touch.AsOld);
assert.deepStrictEqual([...map.keys()], ['ak']);
assert.deepStrictEqual([...map.values()], ['av']);
assert.deepStrictEqual(map.keys(), ['ak']);
assert.deepStrictEqual(map.values(), ['av']);
});
test('LinkedMap - Touch New one', () => {
let map = new LinkedMap<string, string>();
map.set('ak', 'av');
map.set('ak', 'av', Touch.AsNew);
assert.deepStrictEqual([...map.keys()], ['ak']);
assert.deepStrictEqual([...map.values()], ['av']);
assert.deepStrictEqual(map.keys(), ['ak']);
assert.deepStrictEqual(map.values(), ['av']);
});
test('LinkedMap - Touch Old two', () => {
@@ -40,8 +40,8 @@ suite('Map', () => {
map.set('ak', 'av');
map.set('bk', 'bv');
map.set('bk', 'bv', Touch.AsOld);
assert.deepStrictEqual([...map.keys()], ['bk', 'ak']);
assert.deepStrictEqual([...map.values()], ['bv', 'av']);
assert.deepStrictEqual(map.keys(), ['bk', 'ak']);
assert.deepStrictEqual(map.values(), ['bv', 'av']);
});
test('LinkedMap - Touch New two', () => {
@@ -49,8 +49,8 @@ suite('Map', () => {
map.set('ak', 'av');
map.set('bk', 'bv');
map.set('ak', 'av', Touch.AsNew);
assert.deepStrictEqual([...map.keys()], ['bk', 'ak']);
assert.deepStrictEqual([...map.values()], ['bv', 'av']);
assert.deepStrictEqual(map.keys(), ['bk', 'ak']);
assert.deepStrictEqual(map.values(), ['bv', 'av']);
});
test('LinkedMap - Touch Old from middle', () => {
@@ -59,8 +59,8 @@ suite('Map', () => {
map.set('bk', 'bv');
map.set('ck', 'cv');
map.set('bk', 'bv', Touch.AsOld);
assert.deepStrictEqual([...map.keys()], ['bk', 'ak', 'ck']);
assert.deepStrictEqual([...map.values()], ['bv', 'av', 'cv']);
assert.deepStrictEqual(map.keys(), ['bk', 'ak', 'ck']);
assert.deepStrictEqual(map.values(), ['bv', 'av', 'cv']);
});
test('LinkedMap - Touch New from middle', () => {
@@ -69,8 +69,8 @@ suite('Map', () => {
map.set('bk', 'bv');
map.set('ck', 'cv');
map.set('bk', 'bv', Touch.AsNew);
assert.deepStrictEqual([...map.keys()], ['ak', 'ck', 'bk']);
assert.deepStrictEqual([...map.values()], ['av', 'cv', 'bv']);
assert.deepStrictEqual(map.keys(), ['ak', 'ck', 'bk']);
assert.deepStrictEqual(map.values(), ['av', 'cv', 'bv']);
});
test('LinkedMap - basics', function () {
@@ -136,15 +136,13 @@ suite('Map', () => {
assert.strictEqual(cache.size, 5);
cache.set(6, 6);
assert.strictEqual(cache.size, 5);
assert.deepStrictEqual([...cache.keys()], [2, 3, 4, 5, 6]);
assert.deepStrictEqual(cache.keys(), [2, 3, 4, 5, 6]);
cache.set(7, 7);
assert.strictEqual(cache.size, 5);
assert.deepStrictEqual([...cache.keys()], [3, 4, 5, 6, 7]);
assert.deepStrictEqual(cache.keys(), [3, 4, 5, 6, 7]);
let values: number[] = [];
[3, 4, 5, 6, 7].forEach(key => values.push(cache.get(key)!));
assert.deepStrictEqual(values, [3, 4, 5, 6, 7]);
assert.deepEqual([...cache.entries()], [[3, 3], [4, 4], [5, 5], [6, 6], [7, 7]]);
});
test('LinkedMap - LRU Cache get', () => {
@@ -152,11 +150,11 @@ suite('Map', () => {
[1, 2, 3, 4, 5].forEach(value => cache.set(value, value));
assert.strictEqual(cache.size, 5);
assert.deepStrictEqual([...cache.keys()], [1, 2, 3, 4, 5]);
assert.deepStrictEqual(cache.keys(), [1, 2, 3, 4, 5]);
cache.get(3);
assert.deepStrictEqual([...cache.keys()], [1, 2, 4, 5, 3]);
assert.deepStrictEqual(cache.keys(), [1, 2, 4, 5, 3]);
cache.peek(4);
assert.deepStrictEqual([...cache.keys()], [1, 2, 4, 5, 3]);
assert.deepStrictEqual(cache.keys(), [1, 2, 4, 5, 3]);
let values: number[] = [];
[1, 2, 3, 4, 5].forEach(key => values.push(cache.get(key)!));
assert.deepStrictEqual(values, [1, 2, 3, 4, 5]);
@@ -171,7 +169,7 @@ suite('Map', () => {
assert.strictEqual(cache.size, 10);
cache.limit = 5;
assert.strictEqual(cache.size, 5);
assert.deepStrictEqual([...cache.keys()], [6, 7, 8, 9, 10]);
assert.deepStrictEqual(cache.keys(), [6, 7, 8, 9, 10]);
cache.limit = 20;
assert.strictEqual(cache.size, 5);
for (let i = 11; i <= 20; i++) {
@@ -183,7 +181,7 @@ suite('Map', () => {
values.push(cache.get(i)!);
assert.strictEqual(cache.get(i), i);
}
assert.deepStrictEqual([...cache.values()], values);
assert.deepStrictEqual(cache.values(), values);
});
test('LinkedMap - LRU Cache limit with ratio', () => {
@@ -195,11 +193,11 @@ suite('Map', () => {
assert.strictEqual(cache.size, 10);
cache.set(11, 11);
assert.strictEqual(cache.size, 5);
assert.deepStrictEqual([...cache.keys()], [7, 8, 9, 10, 11]);
assert.deepStrictEqual(cache.keys(), [7, 8, 9, 10, 11]);
let values: number[] = [];
[...cache.keys()].forEach(key => values.push(cache.get(key)!));
cache.keys().forEach(key => values.push(cache.get(key)!));
assert.deepStrictEqual(values, [7, 8, 9, 10, 11]);
assert.deepStrictEqual([...cache.values()], values);
assert.deepStrictEqual(cache.values(), values);
});
test('LinkedMap - toJSON / fromJSON', () => {
@@ -239,7 +237,7 @@ suite('Map', () => {
map.delete('1');
assert.equal(map.get('1'), undefined);
assert.equal(map.size, 0);
assert.equal([...map.keys()].length, 0);
assert.equal(map.keys().length, 0);
});
test('LinkedMap - delete Head', function () {
@@ -253,8 +251,8 @@ suite('Map', () => {
map.delete('1');
assert.equal(map.get('2'), 2);
assert.equal(map.size, 1);
assert.equal([...map.keys()].length, 1);
assert.equal([...map.keys()][0], 2);
assert.equal(map.keys().length, 1);
assert.equal(map.keys()[0], 2);
});
test('LinkedMap - delete Tail', function () {
@@ -268,8 +266,8 @@ suite('Map', () => {
map.delete('2');
assert.equal(map.get('1'), 1);
assert.equal(map.size, 1);
assert.equal([...map.keys()].length, 1);
assert.equal([...map.keys()][0], 1);
assert.equal(map.keys().length, 1);
assert.equal(map.keys()[0], 1);
});
@@ -31,84 +31,6 @@ function gestureChangeEventMerger(lastEvent: IThrottledGestureEvent | null, curr
return r;
}
/**
* Basically IE10 and IE11
*/
class MsPointerHandler extends MouseHandler implements IDisposable {
private _lastPointerType: string;
private _installGestureHandlerTimeout: number;
constructor(context: ViewContext, viewController: ViewController, viewHelper: IPointerHandlerHelper) {
super(context, viewController, viewHelper);
(this.viewHelper.linesContentDomNode.style as any).msTouchAction = 'none';
(this.viewHelper.linesContentDomNode.style as any).msContentZooming = 'none';
// TODO@Alex -> this expects that the view is added in 100 ms, might not be the case
// This handler should be added when the dom node is in the dom tree
this._installGestureHandlerTimeout = window.setTimeout(() => {
this._installGestureHandlerTimeout = -1;
if ((<any>window).MSGesture) {
const touchGesture = new MSGesture();
const penGesture = new MSGesture();
touchGesture.target = this.viewHelper.linesContentDomNode;
penGesture.target = this.viewHelper.linesContentDomNode;
this.viewHelper.linesContentDomNode.addEventListener(<any>'MSPointerDown', (e: MSPointerEvent) => {
// Circumvent IE11 breaking change in e.pointerType & TypeScript's stale definitions
const pointerType = <any>e.pointerType;
if (pointerType === ((<any>e).MSPOINTER_TYPE_MOUSE || 'mouse')) {
this._lastPointerType = 'mouse';
return;
} else if (pointerType === ((<any>e).MSPOINTER_TYPE_TOUCH || 'touch')) {
this._lastPointerType = 'touch';
touchGesture.addPointer(e.pointerId);
} else {
this._lastPointerType = 'pen';
penGesture.addPointer(e.pointerId);
}
});
this._register(dom.addDisposableThrottledListener<IThrottledGestureEvent, MSGestureEvent>(this.viewHelper.linesContentDomNode, 'MSGestureChange', (e) => this._onGestureChange(e), gestureChangeEventMerger));
this._register(dom.addDisposableListener(this.viewHelper.linesContentDomNode, 'MSGestureTap', (e) => this._onCaptureGestureTap(e), true));
}
}, 100);
this._lastPointerType = 'mouse';
}
public _onMouseDown(e: EditorMouseEvent): void {
if (this._lastPointerType === 'mouse') {
super._onMouseDown(e);
}
}
private _onCaptureGestureTap(rawEvent: MSGestureEvent): void {
const e = new EditorMouseEvent(<MouseEvent><any>rawEvent, this.viewHelper.viewDomNode);
const t = this._createMouseTarget(e, false);
if (t.position) {
this.viewController.moveTo(t.position);
}
// IE does not want to focus when coming in from the browser's address bar
if ((<any>e.browserEvent).fromElement) {
e.preventDefault();
this.viewHelper.focusTextArea();
} else {
// TODO@Alex -> cancel this is focus is lost
setTimeout(() => {
this.viewHelper.focusTextArea();
});
}
}
private _onGestureChange(e: IThrottledGestureEvent): void {
this._context.viewLayout.deltaScrollNow(-e.translationX, -e.translationY);
}
public dispose(): void {
window.clearTimeout(this._installGestureHandlerTimeout);
super.dispose();
}
}
/**
* Basically Edge but should be modified to handle any pointerEnabled, even without support of MSGesture
*/
@@ -302,9 +224,7 @@ export class PointerHandler extends Disposable {
constructor(context: ViewContext, viewController: ViewController, viewHelper: IPointerHandlerHelper) {
super();
if (window.navigator.msPointerEnabled) {
this.handler = this._register(new MsPointerHandler(context, viewController, viewHelper));
} else if ((platform.isIOS && BrowserFeatures.pointerEvents)) {
if ((platform.isIOS && BrowserFeatures.pointerEvents)) {
this.handler = this._register(new PointerEventHandler(context, viewController, viewHelper));
} else if ((<any>window).TouchEvent) {
this.handler = this._register(new TouchHandler(context, viewController, viewHelper));
@@ -111,7 +111,7 @@ export class EditorScrollbar extends ViewPart {
const minimap = options.get(EditorOption.minimap);
const side = minimap.side;
if (side === 'right') {
this.scrollbarDomNode.setWidth(layoutInfo.contentWidth + layoutInfo.minimapWidth);
this.scrollbarDomNode.setWidth(layoutInfo.contentWidth + layoutInfo.minimap.minimapWidth);
} else {
this.scrollbarDomNode.setWidth(layoutInfo.contentWidth);
}
@@ -104,30 +104,31 @@ class MinimapOptions {
const options = configuration.options;
const pixelRatio = options.get(EditorOption.pixelRatio);
const layoutInfo = options.get(EditorOption.layoutInfo);
const minimapLayout = layoutInfo.minimap;
const fontInfo = options.get(EditorOption.fontInfo);
const minimapOpts = options.get(EditorOption.minimap);
this.renderMinimap = layoutInfo.renderMinimap | 0;
this.renderMinimap = minimapLayout.renderMinimap;
this.size = minimapOpts.size;
this.minimapHeightIsEditorHeight = layoutInfo.minimapHeightIsEditorHeight;
this.minimapHeightIsEditorHeight = minimapLayout.minimapHeightIsEditorHeight;
this.scrollBeyondLastLine = options.get(EditorOption.scrollBeyondLastLine);
this.showSlider = minimapOpts.showSlider;
this.pixelRatio = pixelRatio;
this.typicalHalfwidthCharacterWidth = fontInfo.typicalHalfwidthCharacterWidth;
this.lineHeight = options.get(EditorOption.lineHeight);
this.minimapLeft = layoutInfo.minimapLeft;
this.minimapWidth = layoutInfo.minimapWidth;
this.minimapLeft = minimapLayout.minimapLeft;
this.minimapWidth = minimapLayout.minimapWidth;
this.minimapHeight = layoutInfo.height;
this.canvasInnerWidth = layoutInfo.minimapCanvasInnerWidth;
this.canvasInnerHeight = layoutInfo.minimapCanvasInnerHeight;
this.canvasOuterWidth = layoutInfo.minimapCanvasOuterWidth;
this.canvasOuterHeight = layoutInfo.minimapCanvasOuterHeight;
this.canvasInnerWidth = minimapLayout.minimapCanvasInnerWidth;
this.canvasInnerHeight = minimapLayout.minimapCanvasInnerHeight;
this.canvasOuterWidth = minimapLayout.minimapCanvasOuterWidth;
this.canvasOuterHeight = minimapLayout.minimapCanvasOuterHeight;
this.isSampling = layoutInfo.minimapIsSampling;
this.isSampling = minimapLayout.minimapIsSampling;
this.editorHeight = layoutInfo.height;
this.fontScale = layoutInfo.minimapScale;
this.minimapLineHeight = layoutInfo.minimapLineHeight;
this.fontScale = minimapLayout.minimapScale;
this.minimapLineHeight = minimapLayout.minimapLineHeight;
this.minimapCharWidth = Constants.BASE_CHAR_WIDTH * this.fontScale;
this.charRenderer = once(() => MinimapCharRendererFactory.create(this.fontScale, fontInfo.fontFamily));
@@ -262,7 +263,8 @@ class MinimapLayout {
const computedSliderRatio = (maxMinimapSliderTop) / (scrollHeight - viewportHeight);
const sliderTop = (scrollTop * computedSliderRatio);
const sliderNeeded = (maxMinimapSliderTop > 0);
return new MinimapLayout(scrollTop, scrollHeight, sliderNeeded, computedSliderRatio, sliderTop, sliderHeight, 1, lineCount);
const maxLinesFitting = Math.floor(options.canvasInnerHeight / options.minimapLineHeight);
return new MinimapLayout(scrollTop, scrollHeight, sliderNeeded, computedSliderRatio, sliderTop, sliderHeight, 1, Math.min(lineCount, maxLinesFitting));
}
// The visible line count in a viewport can change due to a number of reasons:
@@ -42,7 +42,7 @@ export class ViewOverlayWidgets extends ViewPart {
this._widgets = {};
this._verticalScrollbarWidth = layoutInfo.verticalScrollbarWidth;
this._minimapWidth = layoutInfo.minimapWidth;
this._minimapWidth = layoutInfo.minimap.minimapWidth;
this._horizontalScrollbarHeight = layoutInfo.horizontalScrollbarHeight;
this._editorHeight = layoutInfo.height;
this._editorWidth = layoutInfo.width;
@@ -68,7 +68,7 @@ export class ViewOverlayWidgets extends ViewPart {
const layoutInfo = options.get(EditorOption.layoutInfo);
this._verticalScrollbarWidth = layoutInfo.verticalScrollbarWidth;
this._minimapWidth = layoutInfo.minimapWidth;
this._minimapWidth = layoutInfo.minimap.minimapWidth;
this._horizontalScrollbarHeight = layoutInfo.horizontalScrollbarHeight;
this._editorHeight = layoutInfo.height;
this._editorWidth = layoutInfo.width;
@@ -58,10 +58,10 @@ export class ScrollDecorationViewPart extends ViewPart {
const options = this._context.configuration.options;
const layoutInfo = options.get(EditorOption.layoutInfo);
if (layoutInfo.renderMinimap === 0 || (layoutInfo.minimapWidth > 0 && layoutInfo.minimapLeft === 0)) {
if (layoutInfo.minimap.renderMinimap === 0 || (layoutInfo.minimap.minimapWidth > 0 && layoutInfo.minimap.minimapLeft === 0)) {
this._width = layoutInfo.width;
} else {
this._width = layoutInfo.width - layoutInfo.minimapWidth - layoutInfo.verticalScrollbarWidth;
this._width = layoutInfo.width - layoutInfo.minimap.minimapWidth - layoutInfo.verticalScrollbarWidth;
}
}
@@ -8,7 +8,7 @@ import { Emitter, Event } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
import * as objects from 'vs/base/common/objects';
import * as arrays from 'vs/base/common/arrays';
import { IEditorOptions, editorOptionsRegistry, ValidatedEditorOptions, IEnvironmentalOptions, IComputedEditorOptions, ConfigurationChangedEvent, EDITOR_MODEL_DEFAULTS, EditorOption, FindComputedEditorOptionValueById } from 'vs/editor/common/config/editorOptions';
import { IEditorOptions, editorOptionsRegistry, ValidatedEditorOptions, IEnvironmentalOptions, IComputedEditorOptions, ConfigurationChangedEvent, EDITOR_MODEL_DEFAULTS, EditorOption, FindComputedEditorOptionValueById, ComputeOptionsMemory } from 'vs/editor/common/config/editorOptions';
import { EditorZoom } from 'vs/editor/common/config/editorZoom';
import { BareFontInfo, FontInfo } from 'vs/editor/common/config/fontInfo';
import { IConfiguration, IDimension } from 'vs/editor/common/editorCommon';
@@ -284,6 +284,7 @@ export abstract class CommonEditorConfiguration extends Disposable implements IC
public readonly onDidChange: Event<ConfigurationChangedEvent> = this._onDidChange.event;
public readonly isSimpleWidget: boolean;
private _computeOptionsMemory: ComputeOptionsMemory;
public options!: ComputedEditorOptions;
private _isDominatedByLongLines: boolean;
@@ -299,6 +300,7 @@ export abstract class CommonEditorConfiguration extends Disposable implements IC
this.isSimpleWidget = isSimpleWidget;
this._isDominatedByLongLines = false;
this._computeOptionsMemory = new ComputeOptionsMemory();
this._viewLineCount = 1;
this._lineNumbersDigitCount = 1;
@@ -344,6 +346,7 @@ export abstract class CommonEditorConfiguration extends Disposable implements IC
const partialEnv = this._getEnvConfiguration();
const bareFontInfo = BareFontInfo.createFromValidatedSettings(this._validatedOptions, partialEnv.zoomLevel, this.isSimpleWidget);
const env: IEnvironmentalOptions = {
memory: this._computeOptionsMemory,
outerWidth: partialEnv.outerWidth,
outerHeight: partialEnv.outerHeight,
fontInfo: this.readConfiguration(bareFontInfo),
+334 -194
View File
@@ -693,6 +693,7 @@ export interface IComputedEditorOptions {
* @internal
*/
export interface IEnvironmentalOptions {
readonly memory: ComputeOptionsMemory | null;
readonly outerWidth: number;
readonly outerHeight: number;
readonly fontInfo: FontInfo;
@@ -706,6 +707,22 @@ export interface IEnvironmentalOptions {
readonly accessibilitySupport: AccessibilitySupport;
}
/**
* @internal
*/
export class ComputeOptionsMemory {
public stableMinimapLayoutInput: IMinimapLayoutInput | null;
public stableFitMaxMinimapScale: number;
public stableFitRemainingWidth: number;
constructor() {
this.stableMinimapLayoutInput = null;
this.stableFitMaxMinimapScale = 0;
this.stableFitRemainingWidth = 0;
}
}
export interface IEditorOption<K1 extends EditorOption, V> {
readonly id: K1;
readonly name: string;
@@ -1717,32 +1734,19 @@ export interface EditorLayoutInfo {
readonly contentWidth: number;
/**
* The position for the minimap
* Layout information for the minimap
*/
readonly minimapLeft: number;
/**
* The width of the minimap
*/
readonly minimapWidth: number;
readonly minimapHeightIsEditorHeight: boolean;
readonly minimapIsSampling: boolean;
readonly minimapScale: number;
readonly minimapLineHeight: number;
readonly minimapCanvasInnerWidth: number;
readonly minimapCanvasInnerHeight: number;
readonly minimapCanvasOuterWidth: number;
readonly minimapCanvasOuterHeight: number;
/**
* Minimap render type
*/
readonly renderMinimap: RenderMinimap;
readonly minimap: EditorMinimapLayoutInfo;
/**
* The number of columns (of typical characters) fitting on a viewport line.
*/
readonly viewportColumn: number;
readonly isWordWrapMinified: boolean;
readonly isViewportWrapping: boolean;
readonly wrappingColumn: number;
/**
* The width of the vertical scrollbar.
*/
@@ -1758,18 +1762,80 @@ export interface EditorLayoutInfo {
readonly overviewRuler: OverviewRulerPosition;
}
/**
* The internal layout details of the editor.
*/
export interface EditorMinimapLayoutInfo {
readonly renderMinimap: RenderMinimap;
readonly minimapLeft: number;
readonly minimapWidth: number;
readonly minimapHeightIsEditorHeight: boolean;
readonly minimapIsSampling: boolean;
readonly minimapScale: number;
readonly minimapLineHeight: number;
readonly minimapCanvasInnerWidth: number;
readonly minimapCanvasInnerHeight: number;
readonly minimapCanvasOuterWidth: number;
readonly minimapCanvasOuterHeight: number;
}
/**
* @internal
*/
export interface EditorLayoutInfoComputerEnv {
outerWidth: number;
outerHeight: number;
lineHeight: number;
viewLineCount: number;
lineNumbersDigitCount: number;
typicalHalfwidthCharacterWidth: number;
maxDigitWidth: number;
pixelRatio: number;
readonly memory: ComputeOptionsMemory | null;
readonly outerWidth: number;
readonly outerHeight: number;
readonly isDominatedByLongLines: boolean
readonly lineHeight: number;
readonly viewLineCount: number;
readonly lineNumbersDigitCount: number;
readonly typicalHalfwidthCharacterWidth: number;
readonly maxDigitWidth: number;
readonly pixelRatio: number;
}
/**
* @internal
*/
export interface IEditorLayoutComputerInput {
readonly outerWidth: number;
readonly outerHeight: number;
readonly isDominatedByLongLines: boolean
readonly lineHeight: number;
readonly lineNumbersDigitCount: number;
readonly typicalHalfwidthCharacterWidth: number;
readonly maxDigitWidth: number;
readonly pixelRatio: number;
readonly glyphMargin: boolean;
readonly lineDecorationsWidth: string | number;
readonly folding: boolean;
readonly minimap: Readonly<Required<IEditorMinimapOptions>>;
readonly scrollbar: InternalEditorScrollbarOptions;
readonly lineNumbers: InternalEditorRenderLineNumbersOptions;
readonly lineNumbersMinChars: number;
readonly scrollBeyondLastLine: boolean;
readonly wordWrap: 'wordWrapColumn' | 'on' | 'off' | 'bounded';
readonly wordWrapColumn: number;
readonly wordWrapMinified: boolean;
readonly accessibilitySupport: AccessibilitySupport;
}
/**
* @internal
*/
export interface IMinimapLayoutInput {
readonly outerWidth: number;
readonly outerHeight: number;
readonly lineHeight: number;
readonly typicalHalfwidthCharacterWidth: number;
readonly pixelRatio: number;
readonly scrollBeyondLastLine: boolean;
readonly minimap: Readonly<Required<IEditorMinimapOptions>>;
readonly verticalScrollbarWidth: number;
readonly viewLineCount: number;
readonly remainingWidth: number;
readonly isViewportWrapping: boolean;
}
/**
@@ -1780,14 +1846,22 @@ export class EditorLayoutInfoComputer extends ComputedEditorOption<EditorOption.
constructor() {
super(
EditorOption.layoutInfo,
[EditorOption.glyphMargin, EditorOption.lineDecorationsWidth, EditorOption.folding, EditorOption.minimap, EditorOption.scrollbar, EditorOption.lineNumbers]
[
EditorOption.glyphMargin, EditorOption.lineDecorationsWidth, EditorOption.folding,
EditorOption.minimap, EditorOption.scrollbar, EditorOption.lineNumbers,
EditorOption.lineNumbersMinChars, EditorOption.scrollBeyondLastLine,
EditorOption.wordWrap, EditorOption.wordWrapColumn, EditorOption.wordWrapMinified,
EditorOption.accessibilitySupport
]
);
}
public compute(env: IEnvironmentalOptions, options: IComputedEditorOptions, _: EditorLayoutInfo): EditorLayoutInfo {
return EditorLayoutInfoComputer.computeLayout(options, {
memory: env.memory,
outerWidth: env.outerWidth,
outerHeight: env.outerHeight,
isDominatedByLongLines: env.isDominatedByLongLines,
lineHeight: env.fontInfo.lineHeight,
viewLineCount: env.viewLineCount,
lineNumbersDigitCount: env.lineNumbersDigitCount,
@@ -1811,6 +1885,172 @@ export class EditorLayoutInfoComputer extends ComputedEditorOption<EditorOption.
return { typicalViewportLineCount, extraLinesBeyondLastLine, desiredRatio, minimapLineCount };
}
private static _computeMinimapLayout(input: IMinimapLayoutInput, memory: ComputeOptionsMemory): EditorMinimapLayoutInfo {
const outerWidth = input.outerWidth;
const outerHeight = input.outerHeight;
const pixelRatio = input.pixelRatio;
if (!input.minimap.enabled) {
return {
renderMinimap: RenderMinimap.None,
minimapLeft: 0,
minimapWidth: 0,
minimapHeightIsEditorHeight: false,
minimapIsSampling: false,
minimapScale: 1,
minimapLineHeight: 1,
minimapCanvasInnerWidth: 0,
minimapCanvasInnerHeight: Math.floor(pixelRatio * outerHeight),
minimapCanvasOuterWidth: 0,
minimapCanvasOuterHeight: outerHeight,
};
}
// Can use memory if only the `viewLineCount` and `remainingWidth` have changed
const stableMinimapLayoutInput = memory.stableMinimapLayoutInput;
const couldUseMemory = (
stableMinimapLayoutInput
// && input.outerWidth === lastMinimapLayoutInput.outerWidth !!! INTENTIONAL OMITTED
&& input.outerHeight === stableMinimapLayoutInput.outerHeight
&& input.lineHeight === stableMinimapLayoutInput.lineHeight
&& input.typicalHalfwidthCharacterWidth === stableMinimapLayoutInput.typicalHalfwidthCharacterWidth
&& input.pixelRatio === stableMinimapLayoutInput.pixelRatio
&& input.scrollBeyondLastLine === stableMinimapLayoutInput.scrollBeyondLastLine
&& input.minimap.enabled === stableMinimapLayoutInput.minimap.enabled
&& input.minimap.side === stableMinimapLayoutInput.minimap.side
&& input.minimap.size === stableMinimapLayoutInput.minimap.size
&& input.minimap.showSlider === stableMinimapLayoutInput.minimap.showSlider
&& input.minimap.renderCharacters === stableMinimapLayoutInput.minimap.renderCharacters
&& input.minimap.maxColumn === stableMinimapLayoutInput.minimap.maxColumn
&& input.minimap.scale === stableMinimapLayoutInput.minimap.scale
&& input.verticalScrollbarWidth === stableMinimapLayoutInput.verticalScrollbarWidth
// && input.viewLineCount === lastMinimapLayoutInput.viewLineCount !!! INTENTIONAL OMITTED
// && input.remainingWidth === lastMinimapLayoutInput.remainingWidth !!! INTENTIONAL OMITTED
&& input.isViewportWrapping === stableMinimapLayoutInput.isViewportWrapping
);
const lineHeight = input.lineHeight;
const typicalHalfwidthCharacterWidth = input.typicalHalfwidthCharacterWidth;
const scrollBeyondLastLine = input.scrollBeyondLastLine;
const minimapRenderCharacters = input.minimap.renderCharacters;
let minimapScale = (pixelRatio >= 2 ? Math.round(input.minimap.scale * 2) : input.minimap.scale);
const minimapMaxColumn = input.minimap.maxColumn;
const minimapSize = input.minimap.size;
const minimapSide = input.minimap.side;
const verticalScrollbarWidth = input.verticalScrollbarWidth;
const viewLineCount = input.viewLineCount;
const remainingWidth = input.remainingWidth;
const isViewportWrapping = input.isViewportWrapping;
const baseCharHeight = minimapRenderCharacters ? 2 : 3;
let minimapCanvasInnerHeight = Math.floor(pixelRatio * outerHeight);
const minimapCanvasOuterHeight = minimapCanvasInnerHeight / pixelRatio;
let minimapHeightIsEditorHeight = false;
let minimapIsSampling = false;
let minimapLineHeight = baseCharHeight * minimapScale;
let minimapCharWidth = minimapScale / pixelRatio;
let minimapWidthMultiplier: number = 1;
if (minimapSize === 'fill' || minimapSize === 'fit') {
const { typicalViewportLineCount, extraLinesBeyondLastLine, desiredRatio, minimapLineCount } = EditorLayoutInfoComputer.computeContainedMinimapLineCount({
viewLineCount: viewLineCount,
scrollBeyondLastLine: scrollBeyondLastLine,
height: outerHeight,
lineHeight: lineHeight,
pixelRatio: pixelRatio
});
// ratio is intentionally not part of the layout to avoid the layout changing all the time
// when doing sampling
const ratio = viewLineCount / minimapLineCount;
if (ratio > 1) {
minimapHeightIsEditorHeight = true;
minimapIsSampling = true;
minimapScale = 1;
minimapLineHeight = 1;
minimapCharWidth = minimapScale / pixelRatio;
} else {
let fitBecomesFill = false;
let maxMinimapScale = minimapScale + 1;
if (minimapSize === 'fit') {
const effectiveMinimapHeight = Math.ceil((viewLineCount + extraLinesBeyondLastLine) * minimapLineHeight);
if (isViewportWrapping && couldUseMemory && remainingWidth <= memory.stableFitRemainingWidth) {
// There is a loop when using `fit` and viewport wrapping:
// - view line count impacts minimap layout
// - minimap layout impacts viewport width
// - viewport width impacts view line count
// To break the loop, once we go to a smaller minimap scale, we try to stick with it.
fitBecomesFill = true;
maxMinimapScale = memory.stableFitMaxMinimapScale;
} else {
fitBecomesFill = (effectiveMinimapHeight > minimapCanvasInnerHeight);
if (isViewportWrapping && fitBecomesFill) {
// remember for next time
memory.stableMinimapLayoutInput = input;
memory.stableFitRemainingWidth = remainingWidth;
} else {
memory.stableMinimapLayoutInput = null;
memory.stableFitRemainingWidth = 0;
}
}
}
if (minimapSize === 'fill' || fitBecomesFill) {
minimapHeightIsEditorHeight = true;
const configuredMinimapScale = minimapScale;
minimapLineHeight = Math.min(lineHeight * pixelRatio, Math.max(1, Math.floor(1 / desiredRatio)));
minimapScale = Math.min(maxMinimapScale, Math.max(1, Math.floor(minimapLineHeight / baseCharHeight)));
if (minimapScale > configuredMinimapScale) {
minimapWidthMultiplier = Math.min(2, minimapScale / configuredMinimapScale);
}
minimapCharWidth = minimapScale / pixelRatio / minimapWidthMultiplier;
minimapCanvasInnerHeight = Math.ceil((Math.max(typicalViewportLineCount, viewLineCount + extraLinesBeyondLastLine)) * minimapLineHeight);
if (isViewportWrapping && fitBecomesFill) {
memory.stableFitMaxMinimapScale = minimapScale;
}
}
}
}
// Given:
// (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 - 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)
const minimapMaxWidth = Math.floor(minimapMaxColumn * minimapCharWidth);
const minimapWidth = Math.min(minimapMaxWidth, Math.max(0, Math.floor(((remainingWidth - verticalScrollbarWidth - 2) * minimapCharWidth) / (typicalHalfwidthCharacterWidth + minimapCharWidth))) + MINIMAP_GUTTER_WIDTH);
let minimapCanvasInnerWidth = Math.floor(pixelRatio * minimapWidth);
const minimapCanvasOuterWidth = minimapCanvasInnerWidth / pixelRatio;
minimapCanvasInnerWidth = Math.floor(minimapCanvasInnerWidth * minimapWidthMultiplier);
const renderMinimap = (minimapRenderCharacters ? RenderMinimap.Text : RenderMinimap.Blocks);
const minimapLeft = (minimapSide === 'left' ? 0 : (outerWidth - minimapWidth - verticalScrollbarWidth));
return {
renderMinimap,
minimapLeft,
minimapWidth,
minimapHeightIsEditorHeight,
minimapIsSampling,
minimapScale,
minimapLineHeight,
minimapCanvasInnerWidth,
minimapCanvasInnerHeight,
minimapCanvasOuterWidth,
minimapCanvasOuterHeight,
};
}
public static computeLayout(options: IComputedEditorOptions, env: EditorLayoutInfoComputerEnv): EditorLayoutInfo {
const outerWidth = env.outerWidth | 0;
const outerHeight = env.outerHeight | 0;
@@ -1819,24 +2059,25 @@ export class EditorLayoutInfoComputer extends ComputedEditorOption<EditorOption.
const typicalHalfwidthCharacterWidth = env.typicalHalfwidthCharacterWidth;
const maxDigitWidth = env.maxDigitWidth;
const pixelRatio = env.pixelRatio;
const viewLineCount = env.viewLineCount;
const wordWrap = options.get(EditorOption.wordWrap);
const wordWrapColumn = options.get(EditorOption.wordWrapColumn);
const wordWrapMinified = options.get(EditorOption.wordWrapMinified);
const accessibilitySupport = options.get(EditorOption.accessibilitySupport);
const isDominatedByLongLines = env.isDominatedByLongLines;
const showGlyphMargin = options.get(EditorOption.glyphMargin);
const showLineNumbers = (options.get(EditorOption.lineNumbers).renderType !== RenderLineNumbersType.Off);
const lineNumbersMinChars = options.get(EditorOption.lineNumbersMinChars) | 0;
const lineNumbersMinChars = options.get(EditorOption.lineNumbersMinChars);
const scrollBeyondLastLine = options.get(EditorOption.scrollBeyondLastLine);
const minimap = options.get(EditorOption.minimap);
const minimapEnabled = minimap.enabled;
const minimapSide = minimap.side;
const minimapRenderCharacters = minimap.renderCharacters;
let minimapScale = (pixelRatio >= 2 ? Math.round(minimap.scale * 2) : minimap.scale);
const minimapMaxColumn = minimap.maxColumn | 0;
const minimapSize = minimap.size;
const scrollbar = options.get(EditorOption.scrollbar);
const verticalScrollbarWidth = scrollbar.verticalScrollbarSize | 0;
const verticalScrollbarWidth = scrollbar.verticalScrollbarSize;
const verticalScrollbarHasArrows = scrollbar.verticalHasArrows;
const scrollbarArrowSize = scrollbar.arrowSize | 0;
const horizontalScrollbarHeight = scrollbar.horizontalScrollbarSize | 0;
const scrollbarArrowSize = scrollbar.arrowSize;
const horizontalScrollbarHeight = scrollbar.horizontalScrollbarSize;
const rawLineDecorationsWidth = options.get(EditorOption.lineDecorationsWidth);
const folding = options.get(EditorOption.folding);
@@ -1870,107 +2111,62 @@ export class EditorLayoutInfoComputer extends ComputedEditorOption<EditorOption.
const remainingWidth = outerWidth - glyphMarginWidth - lineNumbersWidth - lineDecorationsWidth;
const baseCharHeight = minimapRenderCharacters ? 2 : 3;
let renderMinimap: RenderMinimap;
let minimapLeft: number;
let minimapWidth: number;
let minimapCanvasInnerWidth: number;
let minimapCanvasInnerHeight = Math.floor(pixelRatio * outerHeight);
let minimapCanvasOuterWidth: number;
const minimapCanvasOuterHeight = minimapCanvasInnerHeight / pixelRatio;
let minimapHeightIsEditorHeight = false;
let minimapIsSampling = false;
let minimapLineHeight = baseCharHeight * minimapScale;
let contentWidth: number;
if (!minimapEnabled) {
minimapLeft = 0;
minimapWidth = 0;
minimapCanvasInnerWidth = 0;
minimapCanvasOuterWidth = 0;
minimapLineHeight = 1;
renderMinimap = RenderMinimap.None;
contentWidth = remainingWidth;
} else {
let minimapCharWidth = minimapScale / pixelRatio;
let minimapWidthMultiplier: number = 1;
let isWordWrapMinified = false;
let isViewportWrapping = false;
let wrappingColumn = -1;
if (minimapSize === 'fill' || minimapSize === 'fit') {
const viewLineCount = env.viewLineCount;
const { typicalViewportLineCount, extraLinesBeyondLastLine, desiredRatio, minimapLineCount } = EditorLayoutInfoComputer.computeContainedMinimapLineCount({
viewLineCount: viewLineCount,
scrollBeyondLastLine: scrollBeyondLastLine,
height: outerHeight,
if (accessibilitySupport !== AccessibilitySupport.Enabled) {
// See https://github.com/Microsoft/vscode/issues/27766
// Never enable wrapping when a screen reader is attached
// because arrow down etc. will not move the cursor in the way
// a screen reader expects.
if (wordWrapMinified && isDominatedByLongLines) {
// Force viewport width wrapping if model is dominated by long lines
isWordWrapMinified = true;
isViewportWrapping = true;
} else if (wordWrap === 'on' || wordWrap === 'bounded') {
isViewportWrapping = true;
} else if (wordWrap === 'wordWrapColumn') {
wrappingColumn = wordWrapColumn;
}
}
const minimapLayout = EditorLayoutInfoComputer._computeMinimapLayout({
outerWidth: outerWidth,
outerHeight: outerHeight,
lineHeight: lineHeight,
pixelRatio: pixelRatio
});
// ratio is intentionally not part of the layout to avoid the layout changing all the time
// when doing sampling
const ratio = viewLineCount / minimapLineCount;
typicalHalfwidthCharacterWidth: typicalHalfwidthCharacterWidth,
pixelRatio: pixelRatio,
scrollBeyondLastLine: scrollBeyondLastLine,
minimap: minimap,
verticalScrollbarWidth: verticalScrollbarWidth,
viewLineCount: viewLineCount,
remainingWidth: remainingWidth,
isViewportWrapping: isViewportWrapping,
}, env.memory || new ComputeOptionsMemory());
if (ratio > 1) {
minimapHeightIsEditorHeight = true;
minimapIsSampling = true;
minimapScale = 1;
minimapLineHeight = 1;
minimapCharWidth = minimapScale / pixelRatio;
} else {
const effectiveMinimapHeight = Math.ceil((viewLineCount + extraLinesBeyondLastLine) * minimapLineHeight);
if (minimapSize === 'fill' || effectiveMinimapHeight > minimapCanvasInnerHeight) {
minimapHeightIsEditorHeight = true;
const configuredFontScale = minimapScale;
minimapLineHeight = Math.min(lineHeight * pixelRatio, Math.max(1, Math.floor(1 / desiredRatio)));
minimapScale = Math.min(configuredFontScale + 1, Math.max(1, Math.floor(minimapLineHeight / baseCharHeight)));
if (minimapScale > configuredFontScale) {
minimapWidthMultiplier = Math.min(2, minimapScale / configuredFontScale);
}
minimapCharWidth = minimapScale / pixelRatio / minimapWidthMultiplier;
minimapCanvasInnerHeight = Math.ceil((Math.max(typicalViewportLineCount, viewLineCount + extraLinesBeyondLastLine)) * minimapLineHeight);
}
}
}
renderMinimap = minimapRenderCharacters ? RenderMinimap.Text : RenderMinimap.Blocks;
// Given:
// (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 - 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 - 2) * minimapCharWidth) / (typicalHalfwidthCharacterWidth + minimapCharWidth))) + MINIMAP_GUTTER_WIDTH;
let minimapColumns = minimapWidth / minimapCharWidth;
if (minimapColumns > minimapMaxColumn) {
minimapWidth = Math.floor(minimapMaxColumn * minimapCharWidth);
}
contentWidth = remainingWidth - minimapWidth;
if (minimapSide === 'left') {
minimapLeft = 0;
glyphMarginLeft += minimapWidth;
lineNumbersLeft += minimapWidth;
decorationsLeft += minimapWidth;
contentLeft += minimapWidth;
} else {
minimapLeft = outerWidth - minimapWidth - verticalScrollbarWidth;
}
minimapCanvasInnerWidth = Math.floor(pixelRatio * minimapWidth);
minimapCanvasOuterWidth = minimapCanvasInnerWidth / pixelRatio;
minimapCanvasInnerWidth = Math.floor(minimapCanvasInnerWidth * minimapWidthMultiplier);
if (minimapLayout.renderMinimap !== RenderMinimap.None && minimapLayout.minimapLeft === 0) {
// the minimap is rendered to the left, so move everything to the right
glyphMarginLeft += minimapLayout.minimapWidth;
lineNumbersLeft += minimapLayout.minimapWidth;
decorationsLeft += minimapLayout.minimapWidth;
contentLeft += minimapLayout.minimapWidth;
}
const contentWidth = remainingWidth - minimapLayout.minimapWidth;
// (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);
if (isViewportWrapping) {
// compute the actual wrappingColumn
wrappingColumn = Math.max(1, viewportColumn);
if (wordWrap === 'bounded') {
wrappingColumn = Math.min(wrappingColumn, wordWrapColumn);
}
}
return {
width: outerWidth,
height: outerHeight,
@@ -1987,20 +2183,14 @@ export class EditorLayoutInfoComputer extends ComputedEditorOption<EditorOption.
contentLeft: contentLeft,
contentWidth: contentWidth,
renderMinimap: renderMinimap,
minimapLeft: minimapLeft,
minimapWidth: minimapWidth,
minimapHeightIsEditorHeight: minimapHeightIsEditorHeight,
minimapIsSampling: minimapIsSampling,
minimapScale: minimapScale,
minimapLineHeight: minimapLineHeight,
minimapCanvasInnerWidth: minimapCanvasInnerWidth,
minimapCanvasInnerHeight: minimapCanvasInnerHeight,
minimapCanvasOuterWidth: minimapCanvasOuterWidth,
minimapCanvasOuterHeight: minimapCanvasOuterHeight,
minimap: minimapLayout,
viewportColumn: viewportColumn,
isWordWrapMinified: isWordWrapMinified,
isViewportWrapping: isViewportWrapping,
wrappingColumn: wrappingColumn,
verticalScrollbarWidth: verticalScrollbarWidth,
horizontalScrollbarHeight: horizontalScrollbarHeight,
@@ -3231,67 +3421,17 @@ export interface EditorWrappingInfo {
class EditorWrappingInfoComputer extends ComputedEditorOption<EditorOption.wrappingInfo, EditorWrappingInfo> {
constructor() {
super(EditorOption.wrappingInfo, [EditorOption.wordWrap, EditorOption.wordWrapColumn, EditorOption.wordWrapMinified, EditorOption.layoutInfo, EditorOption.accessibilitySupport]);
super(EditorOption.wrappingInfo, [EditorOption.layoutInfo]);
}
public compute(env: IEnvironmentalOptions, options: IComputedEditorOptions, _: EditorWrappingInfo): EditorWrappingInfo {
const wordWrap = options.get(EditorOption.wordWrap);
const wordWrapColumn = options.get(EditorOption.wordWrapColumn);
const wordWrapMinified = options.get(EditorOption.wordWrapMinified);
const layoutInfo = options.get(EditorOption.layoutInfo);
const accessibilitySupport = options.get(EditorOption.accessibilitySupport);
let bareWrappingInfo: { isWordWrapMinified: boolean; isViewportWrapping: boolean; wrappingColumn: number; } | null = null;
{
if (accessibilitySupport === AccessibilitySupport.Enabled) {
// See https://github.com/Microsoft/vscode/issues/27766
// Never enable wrapping when a screen reader is attached
// because arrow down etc. will not move the cursor in the way
// a screen reader expects.
bareWrappingInfo = {
isWordWrapMinified: false,
isViewportWrapping: false,
wrappingColumn: -1
};
} else if (wordWrapMinified && env.isDominatedByLongLines) {
// Force viewport width wrapping if model is dominated by long lines
bareWrappingInfo = {
isWordWrapMinified: true,
isViewportWrapping: true,
wrappingColumn: Math.max(1, layoutInfo.viewportColumn)
};
} else if (wordWrap === 'on') {
bareWrappingInfo = {
isWordWrapMinified: false,
isViewportWrapping: true,
wrappingColumn: Math.max(1, layoutInfo.viewportColumn)
};
} else if (wordWrap === 'bounded') {
bareWrappingInfo = {
isWordWrapMinified: false,
isViewportWrapping: true,
wrappingColumn: Math.min(Math.max(1, layoutInfo.viewportColumn), wordWrapColumn)
};
} else if (wordWrap === 'wordWrapColumn') {
bareWrappingInfo = {
isWordWrapMinified: false,
isViewportWrapping: false,
wrappingColumn: wordWrapColumn
};
} else {
bareWrappingInfo = {
isWordWrapMinified: false,
isViewportWrapping: false,
wrappingColumn: -1
};
}
}
return {
isDominatedByLongLines: env.isDominatedByLongLines,
isWordWrapMinified: bareWrappingInfo.isWordWrapMinified,
isViewportWrapping: bareWrappingInfo.isViewportWrapping,
wrappingColumn: bareWrappingInfo.wrappingColumn,
isWordWrapMinified: layoutInfo.isWordWrapMinified,
isViewportWrapping: layoutInfo.isViewportWrapping,
wrappingColumn: layoutInfo.wrappingColumn,
};
}
}
+2 -2
View File
@@ -701,7 +701,7 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
}
const editorWidth = layoutInfo.width;
const minimapWidth = layoutInfo.minimapWidth;
const minimapWidth = layoutInfo.minimap.minimapWidth;
let collapsedFindWidget = false;
let reducedFindWidget = false;
let narrowFindWidget = false;
@@ -1218,7 +1218,7 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
// 1. never resized before, double click should maximizes it
// 2. users resized it already but its width is the same as default
const layoutInfo = this._codeEditor.getLayoutInfo();
width = layoutInfo.width - 28 - layoutInfo.minimapWidth - 15;
width = layoutInfo.width - 28 - layoutInfo.minimap.minimapWidth - 15;
this._resized = true;
} else {
/**
@@ -254,13 +254,13 @@ export abstract class ZoneWidget implements IHorizontalSashLayoutProvider {
}
private _getWidth(info: EditorLayoutInfo): number {
return info.width - info.minimapWidth - info.verticalScrollbarWidth;
return info.width - info.minimap.minimapWidth - info.verticalScrollbarWidth;
}
private _getLeft(info: EditorLayoutInfo): number {
// If minimap is to the left, we move beyond it
if (info.minimapWidth > 0 && info.minimapLeft === 0) {
return info.minimapWidth;
if (info.minimap.minimapWidth > 0 && info.minimap.minimapLeft === 0) {
return info.minimap.minimapWidth;
}
return 0;
}
@@ -526,6 +526,6 @@ export abstract class ZoneWidget implements IHorizontalSashLayoutProvider {
getHorizontalSashWidth() {
const layoutInfo = this.editor.getLayoutInfo();
return layoutInfo.width - layoutInfo.minimapWidth;
return layoutInfo.width - layoutInfo.minimap.minimapWidth;
}
}
@@ -76,9 +76,16 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
};
options._write(EditorOption.lineNumbers, lineNumbersOptions);
options._write(EditorOption.wordWrap, 'off');
options._write(EditorOption.wordWrapColumn, 80);
options._write(EditorOption.wordWrapMinified, true);
options._write(EditorOption.accessibilitySupport, 'auto');
const actual = EditorLayoutInfoComputer.computeLayout(options, {
memory: null,
outerWidth: input.outerWidth,
outerHeight: input.outerHeight,
isDominatedByLongLines: false,
lineHeight: input.lineHeight,
viewLineCount: input.maxLineNumber || Math.pow(10, input.lineNumbersDigitCount) - 1,
lineNumbersDigitCount: input.lineNumbersDigitCount,
@@ -126,6 +133,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
contentLeft: 10,
contentWidth: 990,
minimap: {
renderMinimap: RenderMinimap.None,
minimapLeft: 0,
minimapWidth: 0,
@@ -137,7 +145,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
minimapCanvasInnerHeight: 800,
minimapCanvasOuterWidth: 0,
minimapCanvasOuterHeight: 800,
},
viewportColumn: 98,
isWordWrapMinified: false,
isViewportWrapping: false,
wrappingColumn: -1,
verticalScrollbarWidth: 0,
horizontalScrollbarHeight: 0,
@@ -188,6 +201,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
contentLeft: 10,
contentWidth: 990,
minimap: {
renderMinimap: RenderMinimap.None,
minimapLeft: 0,
minimapWidth: 0,
@@ -199,7 +213,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
minimapCanvasInnerHeight: 800,
minimapCanvasOuterWidth: 0,
minimapCanvasOuterHeight: 800,
},
viewportColumn: 97,
isWordWrapMinified: false,
isViewportWrapping: false,
wrappingColumn: -1,
verticalScrollbarWidth: 11,
horizontalScrollbarHeight: 12,
@@ -250,6 +269,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
contentLeft: 10,
contentWidth: 890,
minimap: {
renderMinimap: RenderMinimap.None,
minimapLeft: 0,
minimapWidth: 0,
@@ -261,7 +281,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
minimapCanvasInnerHeight: 800,
minimapCanvasOuterWidth: 0,
minimapCanvasOuterHeight: 800,
},
viewportColumn: 88,
isWordWrapMinified: false,
isViewportWrapping: false,
wrappingColumn: -1,
verticalScrollbarWidth: 0,
horizontalScrollbarHeight: 0,
@@ -312,6 +337,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
contentLeft: 10,
contentWidth: 890,
minimap: {
renderMinimap: RenderMinimap.None,
minimapLeft: 0,
minimapWidth: 0,
@@ -323,7 +349,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
minimapCanvasInnerHeight: 900,
minimapCanvasOuterWidth: 0,
minimapCanvasOuterHeight: 900,
},
viewportColumn: 88,
isWordWrapMinified: false,
isViewportWrapping: false,
wrappingColumn: -1,
verticalScrollbarWidth: 0,
horizontalScrollbarHeight: 0,
@@ -374,6 +405,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
contentLeft: 10,
contentWidth: 890,
minimap: {
renderMinimap: RenderMinimap.None,
minimapLeft: 0,
minimapWidth: 0,
@@ -385,7 +417,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
minimapCanvasInnerHeight: 900,
minimapCanvasOuterWidth: 0,
minimapCanvasOuterHeight: 900,
},
viewportColumn: 88,
isWordWrapMinified: false,
isViewportWrapping: false,
wrappingColumn: -1,
verticalScrollbarWidth: 0,
horizontalScrollbarHeight: 0,
@@ -436,6 +473,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
contentLeft: 60,
contentWidth: 840,
minimap: {
renderMinimap: RenderMinimap.None,
minimapLeft: 0,
minimapWidth: 0,
@@ -447,7 +485,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
minimapCanvasInnerHeight: 900,
minimapCanvasOuterWidth: 0,
minimapCanvasOuterHeight: 900,
},
viewportColumn: 83,
isWordWrapMinified: false,
isViewportWrapping: false,
wrappingColumn: -1,
verticalScrollbarWidth: 0,
horizontalScrollbarHeight: 0,
@@ -498,6 +541,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
contentLeft: 60,
contentWidth: 840,
minimap: {
renderMinimap: RenderMinimap.None,
minimapLeft: 0,
minimapWidth: 0,
@@ -509,7 +553,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
minimapCanvasInnerHeight: 900,
minimapCanvasOuterWidth: 0,
minimapCanvasOuterHeight: 900,
},
viewportColumn: 83,
isWordWrapMinified: false,
isViewportWrapping: false,
wrappingColumn: -1,
verticalScrollbarWidth: 0,
horizontalScrollbarHeight: 0,
@@ -560,6 +609,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
contentLeft: 70,
contentWidth: 830,
minimap: {
renderMinimap: RenderMinimap.None,
minimapLeft: 0,
minimapWidth: 0,
@@ -571,7 +621,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
minimapCanvasInnerHeight: 900,
minimapCanvasOuterWidth: 0,
minimapCanvasOuterHeight: 900,
},
viewportColumn: 82,
isWordWrapMinified: false,
isViewportWrapping: false,
wrappingColumn: -1,
verticalScrollbarWidth: 0,
horizontalScrollbarHeight: 0,
@@ -622,6 +677,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
contentLeft: 40,
contentWidth: 860,
minimap: {
renderMinimap: RenderMinimap.None,
minimapLeft: 0,
minimapWidth: 0,
@@ -633,7 +689,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
minimapCanvasInnerHeight: 900,
minimapCanvasOuterWidth: 0,
minimapCanvasOuterHeight: 900,
},
viewportColumn: 171,
isWordWrapMinified: false,
isViewportWrapping: false,
wrappingColumn: -1,
verticalScrollbarWidth: 0,
horizontalScrollbarHeight: 0,
@@ -684,6 +745,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
contentLeft: 40,
contentWidth: 860,
minimap: {
renderMinimap: RenderMinimap.None,
minimapLeft: 0,
minimapWidth: 0,
@@ -695,7 +757,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
minimapCanvasInnerHeight: 900,
minimapCanvasOuterWidth: 0,
minimapCanvasOuterHeight: 900,
},
viewportColumn: 169,
isWordWrapMinified: false,
isViewportWrapping: false,
wrappingColumn: -1,
verticalScrollbarWidth: 0,
horizontalScrollbarHeight: 0,
@@ -746,6 +813,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
contentLeft: 10,
contentWidth: 893,
minimap: {
renderMinimap: RenderMinimap.Text,
minimapLeft: 903,
minimapWidth: 97,
@@ -757,7 +825,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
minimapCanvasInnerHeight: 800,
minimapCanvasOuterWidth: 97,
minimapCanvasOuterHeight: 800,
},
viewportColumn: 89,
isWordWrapMinified: false,
isViewportWrapping: false,
wrappingColumn: -1,
verticalScrollbarWidth: 0,
horizontalScrollbarHeight: 0,
@@ -808,6 +881,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
contentLeft: 10,
contentWidth: 893,
minimap: {
renderMinimap: RenderMinimap.Text,
minimapLeft: 903,
minimapWidth: 97,
@@ -819,7 +893,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
minimapCanvasInnerHeight: 1600,
minimapCanvasOuterWidth: 97,
minimapCanvasOuterHeight: 800,
},
viewportColumn: 89,
isWordWrapMinified: false,
isViewportWrapping: false,
wrappingColumn: -1,
verticalScrollbarWidth: 0,
horizontalScrollbarHeight: 0,
@@ -870,6 +949,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
contentLeft: 10,
contentWidth: 935,
minimap: {
renderMinimap: RenderMinimap.Text,
minimapLeft: 945,
minimapWidth: 55,
@@ -881,7 +961,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
minimapCanvasInnerHeight: 3200,
minimapCanvasOuterWidth: 55,
minimapCanvasOuterHeight: 800,
},
viewportColumn: 93,
isWordWrapMinified: false,
isViewportWrapping: false,
wrappingColumn: -1,
verticalScrollbarWidth: 0,
horizontalScrollbarHeight: 0,
@@ -932,6 +1017,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
contentLeft: 65,
contentWidth: 935,
minimap: {
renderMinimap: RenderMinimap.Text,
minimapLeft: 0,
minimapWidth: 55,
@@ -943,7 +1029,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
minimapCanvasInnerHeight: 3200,
minimapCanvasOuterWidth: 55,
minimapCanvasOuterHeight: 800,
},
viewportColumn: 93,
isWordWrapMinified: false,
isViewportWrapping: false,
wrappingColumn: -1,
verticalScrollbarWidth: 0,
horizontalScrollbarHeight: 0,
@@ -996,6 +1087,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
contentLeft: 10,
contentWidth: 893,
minimap: {
renderMinimap: RenderMinimap.Text,
minimapLeft: 903,
minimapWidth: 97,
@@ -1007,7 +1099,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
minimapCanvasInnerHeight: 1560,
minimapCanvasOuterWidth: 97,
minimapCanvasOuterHeight: 800,
},
viewportColumn: 89,
isWordWrapMinified: false,
isViewportWrapping: false,
wrappingColumn: -1,
verticalScrollbarWidth: 0,
horizontalScrollbarHeight: 0,
@@ -1060,6 +1157,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
contentLeft: 10,
contentWidth: 935,
minimap: {
renderMinimap: RenderMinimap.Text,
minimapLeft: 945,
minimapWidth: 55,
@@ -1071,7 +1169,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
minimapCanvasInnerHeight: 1600,
minimapCanvasOuterWidth: 55,
minimapCanvasOuterHeight: 800,
},
viewportColumn: 93,
isWordWrapMinified: false,
isViewportWrapping: false,
wrappingColumn: -1,
verticalScrollbarWidth: 0,
horizontalScrollbarHeight: 0,
@@ -1124,6 +1227,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
contentLeft: 10,
contentWidth: 893,
minimap: {
renderMinimap: RenderMinimap.Text,
minimapLeft: 903,
minimapWidth: 97,
@@ -1135,7 +1239,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
minimapCanvasInnerHeight: 1600,
minimapCanvasOuterWidth: 97,
minimapCanvasOuterHeight: 800,
},
viewportColumn: 89,
isWordWrapMinified: false,
isViewportWrapping: false,
wrappingColumn: -1,
verticalScrollbarWidth: 0,
horizontalScrollbarHeight: 0,
@@ -1188,6 +1297,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
contentLeft: 10,
contentWidth: 935,
minimap: {
renderMinimap: RenderMinimap.Text,
minimapLeft: 945,
minimapWidth: 55,
@@ -1199,7 +1309,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
minimapCanvasInnerHeight: 1600,
minimapCanvasOuterWidth: 55,
minimapCanvasOuterHeight: 800,
},
viewportColumn: 93,
isWordWrapMinified: false,
isViewportWrapping: false,
wrappingColumn: -1,
verticalScrollbarWidth: 0,
horizontalScrollbarHeight: 0,
@@ -1250,6 +1365,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
contentLeft: 92,
contentWidth: 1018,
minimap: {
renderMinimap: RenderMinimap.Text,
minimapLeft: 1096,
minimapWidth: 91,
@@ -1261,7 +1377,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
minimapCanvasInnerHeight: 844,
minimapCanvasOuterWidth: 91,
minimapCanvasOuterHeight: 422,
},
viewportColumn: 83,
isWordWrapMinified: false,
isViewportWrapping: false,
wrappingColumn: -1,
verticalScrollbarWidth: 14,
horizontalScrollbarHeight: 10,
+22 -18
View File
@@ -3404,29 +3404,16 @@ declare namespace monaco.editor {
*/
readonly contentWidth: number;
/**
* The position for the minimap
* Layout information for the minimap
*/
readonly minimapLeft: number;
/**
* The width of the minimap
*/
readonly minimapWidth: number;
readonly minimapHeightIsEditorHeight: boolean;
readonly minimapIsSampling: boolean;
readonly minimapScale: number;
readonly minimapLineHeight: number;
readonly minimapCanvasInnerWidth: number;
readonly minimapCanvasInnerHeight: number;
readonly minimapCanvasOuterWidth: number;
readonly minimapCanvasOuterHeight: number;
/**
* Minimap render type
*/
readonly renderMinimap: RenderMinimap;
readonly minimap: EditorMinimapLayoutInfo;
/**
* The number of columns (of typical characters) fitting on a viewport line.
*/
readonly viewportColumn: number;
readonly isWordWrapMinified: boolean;
readonly isViewportWrapping: boolean;
readonly wrappingColumn: number;
/**
* The width of the vertical scrollbar.
*/
@@ -3441,6 +3428,23 @@ declare namespace monaco.editor {
readonly overviewRuler: OverviewRulerPosition;
}
/**
* The internal layout details of the editor.
*/
export interface EditorMinimapLayoutInfo {
readonly renderMinimap: RenderMinimap;
readonly minimapLeft: number;
readonly minimapWidth: number;
readonly minimapHeightIsEditorHeight: boolean;
readonly minimapIsSampling: boolean;
readonly minimapScale: number;
readonly minimapLineHeight: number;
readonly minimapCanvasInnerWidth: number;
readonly minimapCanvasInnerHeight: number;
readonly minimapCanvasOuterWidth: number;
readonly minimapCanvasOuterHeight: number;
}
/**
* Configuration options for editor lightbulb
*/
@@ -324,7 +324,8 @@ export class ConfigurationModelParser {
result[key] = this.filterByScope(properties[key], configurationProperties, false, scopes);
} else {
const scope = this.getScope(key, configurationProperties);
if (scopes.indexOf(scope) !== -1) {
// Load unregistered configurations always.
if (scope === undefined || scopes.indexOf(scope) !== -1) {
result[key] = properties[key];
}
}
@@ -332,9 +333,9 @@ export class ConfigurationModelParser {
return result;
}
private getScope(key: string, configurationProperties: { [qualifiedKey: string]: IConfigurationPropertySchema }): ConfigurationScope {
private getScope(key: string, configurationProperties: { [qualifiedKey: string]: IConfigurationPropertySchema }): ConfigurationScope | undefined {
const propertySchema = configurationProperties[key];
return propertySchema && typeof propertySchema.scope !== 'undefined' ? propertySchema.scope : ConfigurationScope.WINDOW;
return propertySchema ? typeof propertySchema.scope !== 'undefined' ? propertySchema.scope : ConfigurationScope.WINDOW : undefined;
}
}
@@ -5,7 +5,7 @@
import * as osLib from 'os';
import { virtualMachineHint } from 'vs/base/node/id';
import { IMachineInfo, WorkspaceStats, WorkspaceStatItem, PerformanceInfo, SystemInfo, IRemoteDiagnosticInfo, IRemoteDiagnosticError, isRemoteDiagnosticError, IWorkspaceInformation } from 'vs/platform/diagnostics/common/diagnostics';
import { readdir, stat, exists, readFile } from 'fs';
import { readdir, exists, readFile } from 'fs';
import { join, basename } from 'vs/base/common/path';
import { parse, ParseError, getNodeType } from 'vs/base/common/json';
import { listProcesses } from 'vs/base/node/ps';
@@ -17,6 +17,7 @@ import { ProcessItem } from 'vs/base/common/processes';
import { IMainProcessInfo } from 'vs/platform/launch/common/launch';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { Iterable } from 'vs/base/common/iterator';
export const ID = 'diagnosticsService';
export const IDiagnosticsService = createDecorator<IDiagnosticsService>(ID);
@@ -42,24 +43,31 @@ export interface ProcessInfo {
name: string;
}
export function collectWorkspaceStats(folder: string, filter: string[]): Promise<WorkspaceStats> {
const configFilePatterns = [
{ 'tag': 'grunt.js', 'pattern': /^gruntfile\.js$/i },
{ 'tag': 'gulp.js', 'pattern': /^gulpfile\.js$/i },
{ 'tag': 'tsconfig.json', 'pattern': /^tsconfig\.json$/i },
{ 'tag': 'package.json', 'pattern': /^package\.json$/i },
{ 'tag': 'jsconfig.json', 'pattern': /^jsconfig\.json$/i },
{ 'tag': 'tslint.json', 'pattern': /^tslint\.json$/i },
{ 'tag': 'eslint.json', 'pattern': /^eslint\.json$/i },
{ 'tag': 'tasks.json', 'pattern': /^tasks\.json$/i },
{ 'tag': 'launch.json', 'pattern': /^launch\.json$/i },
{ 'tag': 'settings.json', 'pattern': /^settings\.json$/i },
{ 'tag': 'webpack.config.js', 'pattern': /^webpack\.config\.js$/i },
{ 'tag': 'project.json', 'pattern': /^project\.json$/i },
{ 'tag': 'makefile', 'pattern': /^makefile$/i },
{ 'tag': 'sln', 'pattern': /^.+\.sln$/i },
{ 'tag': 'csproj', 'pattern': /^.+\.csproj$/i },
{ 'tag': 'cmake', 'pattern': /^.+\.cmake$/i }
interface ConfigFilePatterns {
tag: string;
filePattern: RegExp;
relativePathPattern?: RegExp;
}
export async function collectWorkspaceStats(folder: string, filter: string[]): Promise<WorkspaceStats> {
const configFilePatterns: ConfigFilePatterns[] = [
{ tag: 'grunt.js', filePattern: /^gruntfile\.js$/i },
{ tag: 'gulp.js', filePattern: /^gulpfile\.js$/i },
{ tag: 'tsconfig.json', filePattern: /^tsconfig\.json$/i },
{ tag: 'package.json', filePattern: /^package\.json$/i },
{ tag: 'jsconfig.json', filePattern: /^jsconfig\.json$/i },
{ tag: 'tslint.json', filePattern: /^tslint\.json$/i },
{ tag: 'eslint.json', filePattern: /^eslint\.json$/i },
{ tag: 'tasks.json', filePattern: /^tasks\.json$/i },
{ tag: 'launch.json', filePattern: /^launch\.json$/i },
{ tag: 'settings.json', filePattern: /^settings\.json$/i },
{ tag: 'webpack.config.js', filePattern: /^webpack\.config\.js$/i },
{ tag: 'project.json', filePattern: /^project\.json$/i },
{ tag: 'makefile', filePattern: /^makefile$/i },
{ tag: 'sln', filePattern: /^.+\.sln$/i },
{ tag: 'csproj', filePattern: /^.+\.csproj$/i },
{ tag: 'cmake', filePattern: /^.+\.cmake$/i },
{ tag: 'github-actions', filePattern: /^.+\.yml$/i, relativePathPattern: /^\.github(?:\/|\\)workflows$/i }
];
const fileTypes = new Map<string, number>();
@@ -67,23 +75,28 @@ export function collectWorkspaceStats(folder: string, filter: string[]): Promise
const MAX_FILES = 20000;
function walk(dir: string, filter: string[], token: { count: number, maxReached: boolean }, done: (allFiles: string[]) => void): void {
let results: string[] = [];
readdir(dir, async (err, files) => {
function collect(root: string, dir: string, filter: string[], token: { count: number, maxReached: boolean }): Promise<void> {
const relativePath = dir.substring(root.length + 1);
return new Promise(resolve => {
readdir(dir, { withFileTypes: true }, async (err, files) => {
// Ignore folders that can't be read
if (err) {
return done(results);
resolve();
return;
}
if (token.count > MAX_FILES) {
token.count += files.length;
token.maxReached = true;
return done(results);
resolve();
return;
}
let pending = files.length;
if (pending === 0) {
return done(results);
resolve();
return;
}
let filesToRead = files;
@@ -96,94 +109,57 @@ export function collectWorkspaceStats(folder: string, filter: string[]): Promise
token.count += files.length;
for (const file of filesToRead) {
stat(join(dir, file), (err, stats) => {
// Ignore files that can't be read
if (err) {
if (--pending === 0) {
return done(results);
if (file.isDirectory()) {
if (!filter.includes(file.name)) {
await collect(root, join(dir, file.name), filter, token);
}
} else {
if (stats.isDirectory()) {
if (filter.indexOf(file) === -1) {
walk(join(dir, file), filter, token, (res: string[]) => {
results = results.concat(res);
if (--pending === 0) {
return done(results);
}
});
} else {
if (--pending === 0) {
done(results);
}
resolve();
return;
}
} else {
results.push(file);
const index = file.name.lastIndexOf('.');
if (index >= 0) {
const fileType = file.name.substring(index + 1);
if (fileType) {
fileTypes.set(fileType, (fileTypes.get(fileType) ?? 0) + 1);
}
}
for (const configFile of configFilePatterns) {
if (configFile.relativePathPattern?.test(relativePath) !== false && configFile.filePattern.test(file.name)) {
configFiles.set(configFile.tag, (configFiles.get(configFile.tag) ?? 0) + 1);
}
}
if (--pending === 0) {
done(results);
resolve();
return;
}
}
}
});
}
});
}
const addFileType = (fileType: string) => {
if (fileTypes.has(fileType)) {
fileTypes.set(fileType, fileTypes.get(fileType)! + 1);
}
else {
fileTypes.set(fileType, 1);
}
};
const addConfigFiles = (fileName: string) => {
for (const each of configFilePatterns) {
if (each.pattern.test(fileName)) {
if (configFiles.has(each.tag)) {
configFiles.set(each.tag, configFiles.get(each.tag)! + 1);
} else {
configFiles.set(each.tag, 1);
}
}
}
};
const acceptFile = (name: string) => {
if (name.lastIndexOf('.') >= 0) {
const suffix: string | undefined = name.split('.').pop();
if (suffix) {
addFileType(suffix);
}
}
addConfigFiles(name);
};
const token: { count: number, maxReached: boolean } = { count: 0, maxReached: false };
return new Promise((resolve, reject) => {
walk(folder, filter, token, async (files) => {
files.forEach(acceptFile);
await collect(folder, folder, filter, token);
const launchConfigs = await collectLaunchConfigs(folder);
resolve({
return {
configFiles: asSortedItems(configFiles),
fileTypes: asSortedItems(fileTypes),
fileCount: token.count,
maxFilesReached: token.maxReached,
launchConfigFiles: launchConfigs
});
});
});
};
}
function asSortedItems(map: Map<string, number>): WorkspaceStatItem[] {
const a: WorkspaceStatItem[] = [];
map.forEach((value, index) => a.push({ name: index, count: value }));
return a.sort((a, b) => b.count - a.count);
function asSortedItems(items: Map<string, number>): WorkspaceStatItem[] {
return [
...Iterable.map(items.entries(), ([name, count]) => ({ name: name, count: count }))
].sort((a, b) => b.count - a.count);
}
export function getMachineInfo(): IMachineInfo {
@@ -540,11 +516,15 @@ export class DiagnosticsService implements IDiagnosticsService {
}
public async reportWorkspaceStats(workspace: IWorkspaceInformation): Promise<void> {
workspace.folders.forEach(folder => {
const folderUri = URI.revive(folder.uri);
if (folderUri.scheme === 'file') {
for (const { uri } of workspace.folders) {
const folderUri = URI.revive(uri);
if (folderUri.scheme !== 'file') {
continue;
}
const folder = folderUri.fsPath;
collectWorkspaceStats(folder, ['node_modules', '.git']).then(stats => {
try {
const stats = await collectWorkspaceStats(folder, ['node_modules', '.git']);
type WorkspaceStatsClassification = {
'workspace.id': { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
rendererSessionId: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
@@ -588,10 +568,9 @@ export class DiagnosticsService implements IDiagnosticsService {
count: e.count
});
});
}).catch(_ => {
} catch {
// Report nothing if collecting metadata fails.
});
}
});
}
}
}
}
+6
View File
@@ -170,6 +170,12 @@ export interface IEditorOptions {
*/
readonly pinned?: boolean;
/**
* An editor that is sticky moves to the beginning of the editors list within the group and will remain
* there unless explicitly closed. Operations such as "Close All" will not close sticky editors.
*/
readonly sticky?: boolean;
/**
* The index in the document stack where to insert the editor into when opening.
*/
+2
View File
@@ -62,6 +62,7 @@ export interface ParsedArgs {
'install-source'?: string;
'disable-updates'?: boolean;
'disable-crash-reporter'?: boolean;
'crash-reporter-directory'?: string;
'skip-add-to-recently-opened'?: boolean;
'max-memory'?: string;
'file-write'?: boolean;
@@ -186,6 +187,7 @@ export const OPTIONS: OptionDescriptions<Required<ParsedArgs>> = {
'disable-telemetry': { type: 'boolean' },
'disable-updates': { type: 'boolean' },
'disable-crash-reporter': { type: 'boolean' },
'crash-reporter-directory': { type: 'string' },
'disable-user-env-probe': { type: 'boolean' },
'skip-add-to-recently-opened': { type: 'boolean' },
'unity-launch': { type: 'boolean' },
@@ -253,6 +253,7 @@ export class EnvironmentService implements INativeEnvironmentService {
get disableUpdates(): boolean { return !!this._args['disable-updates']; }
get disableCrashReporter(): boolean { return !!this._args['disable-crash-reporter']; }
get crashReporterDirectory(): string | undefined { return this._args['crash-reporter-directory']; }
get driverHandle(): string | undefined { return this._args['driver']; }
get driverVerbose(): boolean { return !!this._args['driver-verbose']; }
+113
View File
@@ -5452,6 +5452,12 @@ declare module 'vscode' {
*/
readonly extensionPath: string;
/**
* Gets the extension's environment variable collection for this workspace, enabling changes
* to be applied to terminal environment variables.
*/
readonly environmentVariableCollection: EnvironmentVariableCollection;
/**
* Get the absolute path of a resource contained in the extension.
*
@@ -8257,6 +8263,113 @@ declare module 'vscode' {
readonly code: number | undefined;
}
/**
* A type of mutation that can be applied to an environment variable.
*/
export enum EnvironmentVariableMutatorType {
/**
* Replace the variable's existing value.
*/
Replace = 1,
/**
* Append to the end of the variable's existing value.
*/
Append = 2,
/**
* Prepend to the start of the variable's existing value.
*/
Prepend = 3
}
/**
* A type of mutation and its value to be applied to an environment variable.
*/
export interface EnvironmentVariableMutator {
/**
* The type of mutation that will occur to the variable.
*/
readonly type: EnvironmentVariableMutatorType;
/**
* The value to use for the variable.
*/
readonly value: string;
}
/**
* A collection of mutations that an extension can apply to a process environment.
*/
export interface EnvironmentVariableCollection {
/**
* Whether the collection should be cached for the workspace and applied to the terminal
* across window reloads. When true the collection will be active immediately such when the
* window reloads. Additionally, this API will return the cached version if it exists. The
* collection will be invalidated when the extension is uninstalled or when the collection
* is cleared. Defaults to true.
*/
persistent: boolean;
/**
* Replace an environment variable with a value.
*
* Note that an extension can only make a single change to any one variable, so this will
* overwrite any previous calls to replace, append or prepend.
*
* @param variable The variable to replace.
* @param value The value to replace the variable with.
*/
replace(variable: string, value: string): void;
/**
* Append a value to an environment variable.
*
* Note that an extension can only make a single change to any one variable, so this will
* overwrite any previous calls to replace, append or prepend.
*
* @param variable The variable to append to.
* @param value The value to append to the variable.
*/
append(variable: string, value: string): void;
/**
* Prepend a value to an environment variable.
*
* Note that an extension can only make a single change to any one variable, so this will
* overwrite any previous calls to replace, append or prepend.
*
* @param variable The variable to prepend.
* @param value The value to prepend to the variable.
*/
prepend(variable: string, value: string): void;
/**
* Gets the mutator that this collection applies to a variable, if any.
*
* @param variable The variable to get the mutator for.
*/
get(variable: string): EnvironmentVariableMutator | undefined;
/**
* Iterate over each mutator in this collection.
*
* @param callback Function to execute for each entry.
* @param thisArg The `this` context used when invoking the handler function.
*/
forEach(callback: (variable: string, mutator: EnvironmentVariableMutator, collection: EnvironmentVariableCollection) => any, thisArg?: any): void;
/**
* Deletes this collection's mutator for a variable.
*
* @param variable The variable to delete the mutator for.
*/
delete(variable: string): void;
/**
* Clears all mutators from this collection.
*/
clear(): void;
}
/**
* A location in the editor at which progress information can be shown. It depends on the
* location how progress is visually represented.
+37 -108
View File
@@ -930,103 +930,6 @@ declare module 'vscode' {
//#endregion
//#region Contribute to terminal environment https://github.com/microsoft/vscode/issues/46696
export enum EnvironmentVariableMutatorType {
/**
* Replace the variable's existing value.
*/
Replace = 1,
/**
* Append to the end of the variable's existing value.
*/
Append = 2,
/**
* Prepend to the start of the variable's existing value.
*/
Prepend = 3
}
export interface EnvironmentVariableMutator {
/**
* The type of mutation that will occur to the variable.
*/
readonly type: EnvironmentVariableMutatorType;
/**
* The value to use for the variable.
*/
readonly value: string;
}
/**
* A collection of mutations that an extension can apply to a process environment.
*/
export interface EnvironmentVariableCollection {
/**
* Whether the collection should be cached for the workspace and applied to the terminal
* across window reloads. When true the collection will be active immediately such when the
* window reloads. Additionally, this API will return the cached version if it exists. The
* collection will be invalidated when the extension is uninstalled or when the collection
* is cleared. Defaults to true.
*/
persistent: boolean;
/**
* Replace an environment variable with a value.
*
* Note that an extension can only make a single change to any one variable, so this will
* overwrite any previous calls to replace, append or prepend.
*/
replace(variable: string, value: string): void;
/**
* Append a value to an environment variable.
*
* Note that an extension can only make a single change to any one variable, so this will
* overwrite any previous calls to replace, append or prepend.
*/
append(variable: string, value: string): void;
/**
* Prepend a value to an environment variable.
*
* Note that an extension can only make a single change to any one variable, so this will
* overwrite any previous calls to replace, append or prepend.
*/
prepend(variable: string, value: string): void;
/**
* Gets the mutator that this collection applies to a variable, if any.
*/
get(variable: string): EnvironmentVariableMutator | undefined;
/**
* Iterate over each mutator in this collection.
*/
forEach(callback: (variable: string, mutator: EnvironmentVariableMutator, collection: EnvironmentVariableCollection) => any, thisArg?: any): void;
/**
* Deletes this collection's mutator for a variable.
*/
delete(variable: string): void;
/**
* Clears all mutators from this collection.
*/
clear(): void;
}
export interface ExtensionContext {
/**
* Gets the extension's environment variable collection for this workspace, enabling changes
* to be applied to terminal environment variables.
*/
readonly environmentVariableCollection: EnvironmentVariableCollection;
}
//#endregion
//#region @jrieken -> exclusive document filters
export interface DocumentFilter {
@@ -1737,12 +1640,6 @@ declare module 'vscode' {
edit(callback: (editBuilder: NotebookEditorCellEdit) => void): Thenable<boolean>;
}
export interface NotebookProvider {
resolveNotebook(editor: NotebookEditor): Promise<void>;
executeCell(document: NotebookDocument, cell: NotebookCell | undefined, token: CancellationToken): Promise<void>;
save(document: NotebookDocument): Promise<boolean>;
}
export interface NotebookOutputSelector {
type: string;
subTypes?: string[];
@@ -1805,11 +1702,6 @@ declare module 'vscode' {
provider: NotebookContentProvider
): Disposable;
export function registerNotebookProvider(
notebookType: string,
provider: NotebookProvider
): Disposable;
export function registerNotebookOutputRenderer(
type: string,
outputSelector: NotebookOutputSelector,
@@ -1839,6 +1731,43 @@ declare module 'vscode' {
//#endregion
//#region @connor4312 extension mode: https://github.com/microsoft/vscode/issues/95926
/**
* The ExtensionMode is provided on the `ExtensionContext` and indicates the
* mode the specific extension is running in.
*/
export enum ExtensionMode {
/**
* The extension is installed normally (for example, from the marketplace
* or VSIX) in VS Code.
*/
Release = 1,
/**
* The extension is running from an `--extensionDevelopmentPath` provided
* when launching VS Code.
*/
Development = 2,
/**
* The extension is running from an `--extensionDevelopmentPath` and
* the extension host is running unit tests.
*/
Test = 3,
}
export interface ExtensionContext {
/**
* The mode the extension is running in. This is specific to the current
* extension. One extension may be in `ExtensionMode.Development` while
* other extensions in the host run in `ExtensionMode.Release`.
*/
readonly extensionMode: ExtensionMode;
}
//#endregion
//#region https://github.com/microsoft/vscode/issues/39441
export interface CompletionItem {
@@ -8,7 +8,7 @@ import { MainContext, MainThreadNotebookShape, NotebookExtensionDescription, IEx
import { Disposable } from 'vs/base/common/lifecycle';
import { URI, UriComponents } from 'vs/base/common/uri';
import { INotebookService, IMainNotebookController } from 'vs/workbench/contrib/notebook/common/notebookService';
import { INotebookTextModel, INotebookMimeTypeSelector, NOTEBOOK_DISPLAY_ORDER, NotebookCellOutputsSplice, CellKind, NotebookDocumentMetadata, NotebookCellMetadata, ICellEditOperation, ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { INotebookTextModel, INotebookMimeTypeSelector, NOTEBOOK_DISPLAY_ORDER, NotebookCellOutputsSplice, NotebookDocumentMetadata, NotebookCellMetadata, ICellEditOperation, ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, CellEditType } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
@@ -84,7 +84,9 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
registerListeners() {
this._register(this._notebookService.onDidChangeActiveEditor(e => {
this._proxy.$updateActiveEditor(e.viewType, e.uri);
this._proxy.$acceptDocumentAndEditorsDelta({
newActiveEditor: e.uri
});
}));
const updateOrder = () => {
@@ -129,16 +131,6 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
return;
}
async $createNotebookDocument(handle: number, viewType: string, resource: UriComponents): Promise<void> {
let controller = this._notebookProviders.get(viewType);
if (controller) {
controller.createNotebookDocument(handle, viewType, resource);
}
return;
}
async $updateNotebookLanguages(viewType: string, resource: UriComponents, languages: string[]): Promise<void> {
let controller = this._notebookProviders.get(viewType);
@@ -163,11 +155,6 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
}
}
async resolveNotebook(viewType: string, uri: URI): Promise<number | undefined> {
let handle = await this._proxy.$resolveNotebook(viewType, uri);
return handle;
}
async $spliceNotebookCellOutputs(viewType: string, resource: UriComponents, cellHandle: number, splices: NotebookCellOutputsSplice[], renderers: number[]): Promise<void> {
let controller = this._notebookProviders.get(viewType);
controller?.spliceNotebookCellOutputs(resource, cellHandle, splices, renderers);
@@ -195,6 +182,7 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
export class MainThreadNotebookController implements IMainNotebookController {
private _mapping: Map<string, MainThreadNotebookDocument> = new Map();
static documentHandle: number = 0;
constructor(
private readonly _proxy: ExtHostNotebookShape,
@@ -203,26 +191,44 @@ export class MainThreadNotebookController implements IMainNotebookController {
) {
}
async resolveNotebook(viewType: string, uri: URI): Promise<NotebookTextModel | undefined> {
// TODO: resolve notebook should wait for all notebook document destory operations to finish.
async createNotebook(viewType: string, uri: URI, forBackup: boolean, forceReload: boolean): Promise<NotebookTextModel | undefined> {
let mainthreadNotebook = this._mapping.get(URI.from(uri).toString());
if (mainthreadNotebook) {
if (forceReload) {
const data = await this._proxy.$resolveNotebookData(viewType, uri);
if (!data) {
return undefined; // {{SQL CARBON EDIT}}
}
mainthreadNotebook.textModel.languages = data.languages;
mainthreadNotebook.textModel.metadata = data.metadata;
mainthreadNotebook.textModel.applyEdit(mainthreadNotebook.textModel.versionId, [
{ editType: CellEditType.Delete, count: mainthreadNotebook.textModel.cells.length, index: 0 },
{ editType: CellEditType.Insert, index: 0, cells: data.cells }
]);
}
return mainthreadNotebook.textModel;
}
let notebookHandle = await this._mainThreadNotebook.resolveNotebook(viewType, uri);
if (notebookHandle !== undefined) {
mainthreadNotebook = this._mapping.get(URI.from(uri).toString());
if (mainthreadNotebook && mainthreadNotebook.textModel.cells.length === 0) {
// it's empty, we should create an empty template one
const mainCell = mainthreadNotebook.textModel.createCellTextModel([''], mainthreadNotebook.textModel.languages.length ? mainthreadNotebook.textModel.languages[0] : '', CellKind.Code, [], undefined);
mainthreadNotebook.textModel.insertTemplateCell(mainCell);
}
return mainthreadNotebook?.textModel;
let document = new MainThreadNotebookDocument(this._proxy, MainThreadNotebookController.documentHandle++, viewType, uri);
await this.createNotebookDocument(document);
if (forBackup) {
return document.textModel;
}
return undefined;
// open notebook document
const data = await this._proxy.$resolveNotebookData(viewType, uri);
if (!data) {
return undefined; // {{SQL CARBON EDIT}}
}
document.textModel.languages = data.languages;
document.textModel.metadata = data.metadata;
document.textModel.initialize(data!.cells);
return document.textModel;
}
async tryApplyEdits(resource: UriComponents, modelVersionId: number, edits: ICellEditOperation[], renderers: number[]): Promise<boolean> {
@@ -250,12 +256,32 @@ export class MainThreadNotebookController implements IMainNotebookController {
this._proxy.$onDidReceiveMessage(uri, message);
}
// Methods for ExtHost
async createNotebookDocument(handle: number, viewType: string, resource: UriComponents): Promise<void> {
let document = new MainThreadNotebookDocument(this._proxy, handle, viewType, URI.revive(resource));
this._mapping.set(URI.revive(resource).toString(), document);
async createNotebookDocument(document: MainThreadNotebookDocument): Promise<void> {
this._mapping.set(document.uri.toString(), document);
await this._proxy.$acceptDocumentAndEditorsDelta({
addedDocuments: [{
viewType: document.viewType,
handle: document.handle,
uri: document.uri
}]
});
}
async removeNotebookDocument(notebook: INotebookTextModel): Promise<void> {
let document = this._mapping.get(URI.from(notebook.uri).toString());
if (!document) {
return;
}
await this._proxy.$acceptDocumentAndEditorsDelta({ removedDocuments: [notebook.uri] });
document.dispose();
this._mapping.delete(URI.from(notebook.uri).toString());
}
// Methods for ExtHost
updateLanguages(resource: UriComponents, languages: string[]) {
let document = this._mapping.get(URI.from(resource).toString());
document?.textModel.updateLanguages(languages);
@@ -280,21 +306,12 @@ export class MainThreadNotebookController implements IMainNotebookController {
return this._proxy.$executeNotebook(this._viewType, uri, handle, token);
}
async destoryNotebookDocument(notebook: INotebookTextModel): Promise<void> {
let document = this._mapping.get(URI.from(notebook.uri).toString());
if (!document) {
return;
}
let removeFromExtHost = await this._proxy.$destoryNotebookDocument(this._viewType, notebook.uri);
if (removeFromExtHost) {
document.dispose();
this._mapping.delete(URI.from(notebook.uri).toString());
}
}
async save(uri: URI, token: CancellationToken): Promise<boolean> {
return this._proxy.$saveNotebook(this._viewType, uri, token);
}
async saveAs(uri: URI, target: URI, token: CancellationToken): Promise<boolean> {
return this._proxy.$saveNotebookAs(this._viewType, uri, target, token);
}
}
@@ -368,6 +368,9 @@ class ViewsExtensionHandler implements IWorkbenchContribution {
}
private addViews(extensions: readonly IExtensionPointUser<ViewExtensionPointType>[]): void {
const viewIds: Set<string> = new Set<string>();
const allViewDescriptors: { views: IViewDescriptor[], viewContainer: ViewContainer }[] = [];
for (const extension of extensions) {
const { value, collector } = extension;
@@ -386,10 +389,9 @@ class ViewsExtensionHandler implements IWorkbenchContribution {
collector.warn(localize('ViewContainerDoesnotExist', "View container '{0}' does not exist and all views registered to it will be added to 'Explorer'.", entry.key));
}
const container = viewContainer || this.getDefaultViewContainer();
const viewIds: string[] = [];
const viewDescriptors = coalesce(entry.value.map((item, index) => {
// validate
if (viewIds.indexOf(item.id) !== -1) {
if (viewIds.has(item.id)) {
collector.error(localize('duplicateView1', "Cannot register multiple views with same id `{0}`", item.id));
return null;
}
@@ -421,12 +423,16 @@ class ViewsExtensionHandler implements IWorkbenchContribution {
remoteAuthority: item.remoteName || (<any>item).remoteAuthority // TODO@roblou - delete after remote extensions are updated
};
viewIds.push(viewDescriptor.id);
viewIds.add(viewDescriptor.id);
return viewDescriptor;
}));
this.viewsRegistry.registerViews(viewDescriptors, container);
allViewDescriptors.push({ viewContainer: container, views: viewDescriptors });
});
}
this.viewsRegistry.registerViews2(allViewDescriptors);
}
private getDefaultViewContainer(): ViewContainer {
@@ -931,10 +931,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
checkProposedApiEnabled(extension);
return extHostNotebook.onDidCloseNotebookDocument;
},
registerNotebookProvider: (viewType: string, provider: vscode.NotebookProvider) => {
checkProposedApiEnabled(extension);
return extHostNotebook.registerNotebookProvider(extension, viewType, provider);
},
registerNotebookContentProvider: (viewType: string, provider: vscode.NotebookContentProvider) => {
checkProposedApiEnabled(extension);
return extHostNotebook.registerNotebookContentProvider(extension, viewType, provider);
@@ -1015,6 +1011,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
EvaluatableExpression: extHostTypes.EvaluatableExpression,
EventEmitter: Emitter,
ExtensionKind: extHostTypes.ExtensionKind,
ExtensionMode: extHostTypes.ExtensionMode,
CustomExecution: extHostTypes.CustomExecution,
CustomExecution2: extHostTypes.CustomExecution,
FileChangeType: extHostTypes.FileChangeType,
@@ -51,7 +51,7 @@ import { TunnelDto } from 'vs/workbench/api/common/extHostTunnelService';
import { TunnelOptions } from 'vs/platform/remote/common/tunnel';
import { Timeline, TimelineChangeEvent, TimelineOptions, TimelineProviderDescriptor, InternalTimelineOptions } from 'vs/workbench/contrib/timeline/common/timeline';
import { revive } from 'vs/base/common/marshalling';
import { INotebookMimeTypeSelector, IOutput, INotebookDisplayOrder, NotebookCellMetadata, NotebookDocumentMetadata, ICellEditOperation, NotebookCellsChangedEvent } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { INotebookMimeTypeSelector, IOutput, INotebookDisplayOrder, NotebookCellMetadata, NotebookDocumentMetadata, ICellEditOperation, NotebookCellsChangedEvent, NotebookDataDto } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { CallHierarchyItem } from 'vs/workbench/contrib/callHierarchy/common/callHierarchy';
import { Dto } from 'vs/base/common/types';
import { ISerializableEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariable';
@@ -695,7 +695,6 @@ export interface MainThreadNotebookShape extends IDisposable {
$unregisterNotebookProvider(viewType: string): Promise<void>;
$registerNotebookRenderer(extension: NotebookExtensionDescription, type: string, selectors: INotebookMimeTypeSelector, handle: number, preloads: UriComponents[]): Promise<void>;
$unregisterNotebookRenderer(handle: number): Promise<void>;
$createNotebookDocument(handle: number, viewType: string, resource: UriComponents): Promise<void>;
$tryApplyEdits(viewType: string, resource: UriComponents, modelVersionId: number, edits: ICellEditOperation[], renderers: number[]): Promise<boolean>;
$updateNotebookLanguages(viewType: string, resource: UriComponents, languages: string[]): Promise<void>;
$updateNotebookMetadata(viewType: string, resource: UriComponents, metadata: NotebookDocumentMetadata): Promise<void>;
@@ -1542,16 +1541,31 @@ export interface INotebookEditorPropertiesChangeData {
selections: INotebookSelectionChangeEvent | null;
}
export interface INotebookModelAddedData {
uri: UriComponents;
handle: number;
// versionId: number;
viewType: string;
}
export interface INotebookDocumentsAndEditorsDelta {
removedDocuments?: UriComponents[];
addedDocuments?: INotebookModelAddedData[];
// removedEditors?: string[];
// addedEditors?: ITextEditorAddData[];
newActiveEditor?: UriComponents | null;
}
export interface ExtHostNotebookShape {
$resolveNotebook(viewType: string, uri: UriComponents): Promise<number | undefined>;
$resolveNotebookData(viewType: string, uri: UriComponents): Promise<NotebookDataDto | undefined>;
$executeNotebook(viewType: string, uri: UriComponents, cellHandle: number | undefined, token: CancellationToken): Promise<void>;
$saveNotebook(viewType: string, uri: UriComponents, token: CancellationToken): Promise<boolean>;
$updateActiveEditor(viewType: string, uri: UriComponents): Promise<void>;
$destoryNotebookDocument(viewType: string, uri: UriComponents): Promise<boolean>;
$saveNotebookAs(viewType: string, uri: UriComponents, target: UriComponents, token: CancellationToken): Promise<boolean>;
$acceptDisplayOrder(displayOrder: INotebookDisplayOrder): void;
$onDidReceiveMessage(uri: UriComponents, message: any): void;
$acceptModelChanged(uriComponents: UriComponents, event: NotebookCellsChangedEvent): void;
$acceptEditorPropertiesChanged(uriComponents: UriComponents, data: INotebookEditorPropertiesChangeData): void;
$acceptDocumentAndEditorsDelta(delta: INotebookDocumentsAndEditorsDelta): Promise<void>;
}
export interface ExtHostStorageShape {
@@ -25,7 +25,7 @@ import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensio
import { Schemas } from 'vs/base/common/network';
import { VSBuffer } from 'vs/base/common/buffer';
import { ExtensionMemento } from 'vs/workbench/api/common/extHostMemento';
import { RemoteAuthorityResolverError } from 'vs/workbench/api/common/extHostTypes';
import { RemoteAuthorityResolverError, ExtensionMode } from 'vs/workbench/api/common/extHostTypes';
import { ResolvedAuthority, ResolvedOptions, RemoteAuthorityResolverErrorCode } from 'vs/platform/remote/common/remoteAuthorityResolver';
import { IInstantiationService, createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
@@ -358,8 +358,12 @@ export abstract class AbstractExtHostExtensionService implements ExtHostExtensio
const globalState = new ExtensionMemento(extensionDescription.identifier.value, true, this._storage);
const workspaceState = new ExtensionMemento(extensionDescription.identifier.value, false, this._storage);
const extensionMode = extensionDescription.isUnderDevelopment
? (this._initData.environment.extensionTestsLocationURI ? ExtensionMode.Test : ExtensionMode.Development)
: ExtensionMode.Release;
this._logService.trace(`ExtensionService#loadExtensionContext ${extensionDescription.identifier.value}`);
return Promise.all([
globalState.whenReady,
workspaceState.whenReady,
@@ -376,10 +380,11 @@ export abstract class AbstractExtHostExtensionService implements ExtHostExtensio
get globalStoragePath() { return that._storagePath.globalValue(extensionDescription); },
asAbsolutePath(relativePath: string) { return path.join(extensionDescription.extensionLocation.fsPath, relativePath); },
get logPath() { return path.join(that._initData.logsLocation.fsPath, extensionDescription.identifier.value); },
get environmentVariableCollection() {
get extensionMode() {
checkProposedApiEnabled(extensionDescription);
return that._extHostTerminalService.getEnvironmentVariableCollection(extensionDescription);
}
return extensionMode;
},
get environmentVariableCollection() { return that._extHostTerminalService.getEnvironmentVariableCollection(extensionDescription); }
});
});
}
+157 -147
View File
@@ -10,10 +10,10 @@ import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecyc
import { ISplice } from 'vs/base/common/sequence';
import { URI, UriComponents } from 'vs/base/common/uri';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { CellKind, CellOutputKind, ExtHostNotebookShape, IMainContext, MainContext, MainThreadNotebookShape, NotebookCellOutputsSplice, MainThreadDocumentsShape, INotebookEditorPropertiesChangeData } from 'vs/workbench/api/common/extHost.protocol';
import { CellKind, CellOutputKind, ExtHostNotebookShape, IMainContext, MainContext, MainThreadNotebookShape, NotebookCellOutputsSplice, MainThreadDocumentsShape, INotebookEditorPropertiesChangeData, INotebookDocumentsAndEditorsDelta } from 'vs/workbench/api/common/extHost.protocol';
import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
import { CellEditType, CellUri, diff, ICellEditOperation, ICellInsertEdit, IErrorOutput, INotebookDisplayOrder, INotebookEditData, IOrderedMimeType, IStreamOutput, ITransformedDisplayOutputDto, mimeTypeSupportedByCore, NotebookCellsChangedEvent, NotebookCellsSplice2, sortMimeTypes, ICellDeleteEdit, notebookDocumentMetadataDefaults, NotebookCellsChangeType } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { CellEditType, CellUri, diff, ICellEditOperation, ICellInsertEdit, IErrorOutput, INotebookDisplayOrder, INotebookEditData, IOrderedMimeType, IStreamOutput, ITransformedDisplayOutputDto, mimeTypeSupportedByCore, NotebookCellsChangedEvent, NotebookCellsSplice2, sortMimeTypes, ICellDeleteEdit, notebookDocumentMetadataDefaults, NotebookCellsChangeType, NotebookDataDto } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { Disposable as VSCodeDisposable } from './extHostTypes';
import { CancellationToken } from 'vs/base/common/cancellation';
import { ExtHostDocumentData } from 'vs/workbench/api/common/extHostDocumentData';
@@ -345,8 +345,6 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo
transformMimeTypes(output: vscode.CellDisplayOutput): ITransformedDisplayOutputDto {
let mimeTypes = Object.keys(output.data);
// TODO@rebornix, the document display order might be assigned a bit later. We need to postpone sending the outputs to the core side.
let coreDisplayOrder = this.renderingHandler.outputDisplayOrder;
const sorted = sortMimeTypes(mimeTypes, coreDisplayOrder?.userOrder || [], this._displayOrder, coreDisplayOrder?.defaultOrder || []);
@@ -415,7 +413,7 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo
}
}
export class NotebookEditorCellEdit {
export class NotebookEditorCellEditBuilder implements vscode.NotebookEditorCellEdit {
private _finalized: boolean = false;
private readonly _documentVersionId: number;
private _collectedEdits: ICellEditOperation[] = [];
@@ -526,13 +524,13 @@ export class ExtHostNotebookEditor extends Disposable implements vscode.Notebook
}));
}
edit(callback: (editBuilder: NotebookEditorCellEdit) => void): Thenable<boolean> {
const edit = new NotebookEditorCellEdit(this);
edit(callback: (editBuilder: NotebookEditorCellEditBuilder) => void): Thenable<boolean> {
const edit = new NotebookEditorCellEditBuilder(this);
callback(edit);
return this._applyEdit(edit);
}
private _applyEdit(editBuilder: NotebookEditorCellEdit): Promise<boolean> {
private _applyEdit(editBuilder: NotebookEditorCellEditBuilder): Promise<boolean> {
const editData = editBuilder.finalize();
// return when there is nothing to do
@@ -625,7 +623,6 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
private static _handlePool: number = 0;
private readonly _proxy: MainThreadNotebookShape;
private readonly _notebookProviders = new Map<string, { readonly provider: vscode.NotebookProvider, readonly extension: IExtensionDescription; }>();
private readonly _notebookContentProviders = new Map<string, { readonly provider: vscode.NotebookContentProvider, readonly extension: IExtensionDescription; }>();
private readonly _documents = new Map<string, ExtHostNotebookDocument>();
private readonly _editors = new Map<string, { editor: ExtHostNotebookEditor, onDidReceiveMessage: Emitter<any>; }>();
@@ -706,31 +703,13 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
return matches;
}
registerNotebookProvider(
extension: IExtensionDescription,
viewType: string,
provider: vscode.NotebookProvider,
): vscode.Disposable {
if (this._notebookProviders.has(viewType)) {
throw new Error(`Notebook provider for '${viewType}' already registered`);
}
this._notebookProviders.set(viewType, { extension, provider });
this._proxy.$registerNotebookProvider({ id: extension.identifier, location: extension.extensionLocation }, viewType);
return new VSCodeDisposable(() => {
this._notebookProviders.delete(viewType);
this._proxy.$unregisterNotebookProvider(viewType);
});
}
registerNotebookContentProvider(
extension: IExtensionDescription,
viewType: string,
provider: vscode.NotebookContentProvider,
): vscode.Disposable {
if (this._notebookProviders.has(viewType)) {
if (this._notebookContentProviders.has(viewType)) {
throw new Error(`Notebook provider for '${viewType}' already registered`);
}
@@ -742,97 +721,99 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
});
}
async _resolveNotebookFromContentProvider(viewType: string, uri: UriComponents): Promise<number | undefined> {
async $resolveNotebookData(viewType: string, uri: UriComponents): Promise<NotebookDataDto | undefined> {
let provider = this._notebookContentProviders.get(viewType);
let document = this._documents.get(URI.revive(uri).toString());
if (provider) {
const revivedUri = URI.revive(uri);
if (!this._documents.has(revivedUri.toString())) {
let document = new ExtHostNotebookDocument(this._proxy, this._documentsAndEditors, viewType, revivedUri, this);
await this._proxy.$createNotebookDocument(
document.handle,
viewType,
uri
);
this._documents.set(revivedUri.toString(), document);
}
const onDidReceiveMessage = new Emitter<any>();
let editor = new ExtHostNotebookEditor(
viewType,
`${ExtHostNotebookController._handlePool++}`,
revivedUri,
this._proxy,
onDidReceiveMessage,
this._documents.get(revivedUri.toString())!,
this._documentsAndEditors
);
this._editors.set(revivedUri.toString(), { editor, onDidReceiveMessage });
const data = await provider.provider.openNotebook(revivedUri);
editor.document.languages = data.languages;
editor.document.metadata = {
if (provider && document) {
const rawCells = await provider.provider.openNotebook(URI.revive(uri));
const renderers = new Set<number>();
const dto = {
metadata: {
...notebookDocumentMetadataDefaults,
...data.metadata
};
...rawCells.metadata
},
languages: rawCells.languages,
cells: rawCells.cells.map(cell => {
let transformedOutputs = cell.outputs.map(output => {
if (output.outputKind === CellOutputKind.Rich) {
// TODO display string[]
const ret = this._transformMimeTypes(document!, (rawCells.metadata.displayOrder as string[]) || [], output);
await editor.edit(editBuilder => {
for (let i = 0; i < data.cells.length; i++) {
const cell = data.cells[i];
editBuilder.insert(0, cell.source, cell.language, cell.cellKind, cell.outputs, cell.metadata);
if (ret.orderedMimeTypes[ret.pickedMimeTypeIndex].isResolved) {
renderers.add(ret.orderedMimeTypes[ret.pickedMimeTypeIndex].rendererId!);
}
return ret;
} else {
return output as IStreamOutput | IErrorOutput;
}
});
this._onDidOpenNotebookDocument.fire(editor.document);
return editor.document.handle;
return {
language: cell.language,
cellKind: cell.cellKind,
metadata: cell.metadata,
source: cell.source,
outputs: transformedOutputs
};
})
};
return dto;
}
return undefined; // {{SQL CARBON EDIT}}
}
private _transformMimeTypes(document: ExtHostNotebookDocument, displayOrder: string[], output: vscode.CellDisplayOutput): ITransformedDisplayOutputDto {
let mimeTypes = Object.keys(output.data);
let coreDisplayOrder = this.outputDisplayOrder;
const sorted = sortMimeTypes(mimeTypes, coreDisplayOrder?.userOrder || [], displayOrder, coreDisplayOrder?.defaultOrder || []);
let orderMimeTypes: IOrderedMimeType[] = [];
sorted.forEach(mimeType => {
let handlers = this.findBestMatchedRenderer(mimeType);
if (handlers.length) {
let renderedOutput = handlers[0].render(document, output, mimeType);
orderMimeTypes.push({
mimeType: mimeType,
isResolved: true,
rendererId: handlers[0].handle,
output: renderedOutput
});
for (let i = 1; i < handlers.length; i++) {
orderMimeTypes.push({
mimeType: mimeType,
isResolved: false,
rendererId: handlers[i].handle
});
}
if (mimeTypeSupportedByCore(mimeType)) {
orderMimeTypes.push({
mimeType: mimeType,
isResolved: false,
rendererId: -1
});
}
} else {
return Promise.resolve(undefined);
}
orderMimeTypes.push({
mimeType: mimeType,
isResolved: false
});
}
});
async $resolveNotebook(viewType: string, uri: UriComponents): Promise<number | undefined> {
let notebookFromNotebookContentProvider = await this._resolveNotebookFromContentProvider(viewType, uri);
if (notebookFromNotebookContentProvider !== undefined) {
return notebookFromNotebookContentProvider;
}
let provider = this._notebookProviders.get(viewType);
if (provider) {
if (!this._documents.has(URI.revive(uri).toString())) {
let document = new ExtHostNotebookDocument(this._proxy, this._documentsAndEditors, viewType, URI.revive(uri), this);
await this._proxy.$createNotebookDocument(
document.handle,
viewType,
uri
);
this._documents.set(URI.revive(uri).toString(), document);
}
const onDidReceiveMessage = new Emitter<any>();
let editor = new ExtHostNotebookEditor(
viewType,
`${ExtHostNotebookController._handlePool++}`,
URI.revive(uri),
this._proxy,
onDidReceiveMessage,
this._documents.get(URI.revive(uri).toString())!,
this._documentsAndEditors
);
this._editors.set(URI.revive(uri).toString(), { editor, onDidReceiveMessage });
await provider.provider.resolveNotebook(editor);
// await editor.document.$updateCells();
return editor.document.handle;
}
return Promise.resolve(undefined);
return {
outputKind: output.outputKind,
data: output.data,
orderedMimeTypes: orderMimeTypes,
pickedMimeTypeIndex: 0
};
}
async $executeNotebook(viewType: string, uri: UriComponents, cellHandle: number | undefined, token: CancellationToken): Promise<void> {
@@ -847,15 +828,6 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
return this._notebookContentProviders.get(viewType)!.provider.executeCell(document, cell, token);
}
let provider = this._notebookProviders.get(viewType);
if (!provider) {
return;
}
let cell = cellHandle !== undefined ? document.getCell(cellHandle) : undefined;
return provider.provider.executeCell(document!, cell, token);
}
async $saveNotebook(viewType: string, uri: UriComponents, token: CancellationToken): Promise<boolean> {
@@ -874,46 +846,28 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
return true;
}
let provider = this._notebookProviders.get(viewType);
if (provider && document) {
return await provider.provider.save(document);
}
return false;
}
async $updateActiveEditor(viewType: string, uri: UriComponents): Promise<void> {
this._activeNotebookDocument = this._documents.get(URI.revive(uri).toString());
this._activeNotebookEditor = this._editors.get(URI.revive(uri).toString())?.editor;
}
async $destoryNotebookDocument(viewType: string, uri: UriComponents): Promise<boolean> {
let provider = this._notebookProviders.get(viewType);
if (!provider) {
return false;
}
async $saveNotebookAs(viewType: string, uri: UriComponents, target: UriComponents, token: CancellationToken): Promise<boolean> {
let document = this._documents.get(URI.revive(uri).toString());
if (document) {
document.dispose();
this._documents.delete(URI.revive(uri).toString());
this._onDidCloseNotebookDocument.fire(document);
if (!document) {
return false;
}
let editor = this._editors.get(URI.revive(uri).toString());
if (editor) {
editor.editor.dispose();
editor.onDidReceiveMessage.dispose();
this._editors.delete(URI.revive(uri).toString());
if (this._notebookContentProviders.has(viewType)) {
try {
await this._notebookContentProviders.get(viewType)!.provider.saveNotebookAs(URI.revive(target), document, token);
} catch (e) {
return false;
}
return true;
}
return false;
}
$acceptDisplayOrder(displayOrder: INotebookDisplayOrder): void {
this._outputDisplayOrder = displayOrder;
}
@@ -957,4 +911,60 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
}
}
}
async $acceptDocumentAndEditorsDelta(delta: INotebookDocumentsAndEditorsDelta) {
if (delta.removedDocuments) {
delta.removedDocuments.forEach((uri) => {
let document = this._documents.get(URI.revive(uri).toString());
if (document) {
document.dispose();
this._documents.delete(URI.revive(uri).toString());
this._onDidCloseNotebookDocument.fire(document);
}
let editor = this._editors.get(URI.revive(uri).toString());
if (editor) {
editor.editor.dispose();
editor.onDidReceiveMessage.dispose();
this._editors.delete(URI.revive(uri).toString());
}
});
}
if (delta.addedDocuments) {
delta.addedDocuments.forEach(modelData => {
const revivedUri = URI.revive(modelData.uri);
const viewType = modelData.viewType;
if (!this._documents.has(revivedUri.toString())) {
let document = new ExtHostNotebookDocument(this._proxy, this._documentsAndEditors, viewType, revivedUri, this);
this._documents.set(revivedUri.toString(), document);
}
const onDidReceiveMessage = new Emitter<any>();
const document = this._documents.get(revivedUri.toString())!;
let editor = new ExtHostNotebookEditor(
viewType,
`${ExtHostNotebookController._handlePool++}`,
revivedUri,
this._proxy,
onDidReceiveMessage,
document,
this._documentsAndEditors
);
this._onDidOpenNotebookDocument.fire(document);
// TODO, does it already exist?
this._editors.set(revivedUri.toString(), { editor, onDidReceiveMessage });
});
}
if (delta.newActiveEditor) {
this._activeNotebookDocument = this._documents.get(URI.revive(delta.newActiveEditor).toString());
this._activeNotebookEditor = this._editors.get(URI.revive(delta.newActiveEditor).toString())?.editor;
}
}
}
@@ -2742,3 +2742,27 @@ export class TimelineItem implements vscode.TimelineItem {
}
//#endregion Timeline
//#region ExtensionContext
export enum ExtensionMode {
/**
* The extension is installed normally (for example, from the marketplace
* or VSIX) in VS Code.
*/
Release = 1,
/**
* The extension is running from an `--extensionDevelopmentPath` provided
* when launching VS Code.
*/
Development = 2,
/**
* The extension is running from an `--extensionDevelopmentPath` and
* the extension host is running unit tests.
*/
Test = 3,
}
//#endregion ExtensionContext
@@ -37,7 +37,6 @@ namespace schema {
case 'debug/callstack/context': return MenuId.DebugCallStackContext;
case 'debug/toolbar': return MenuId.DebugToolBar;
case 'debug/toolBar': return MenuId.DebugToolBar;
case 'menuBar/file': return MenuId.MenubarFileMenu;
case 'menuBar/webNavigation': return MenuId.MenubarWebNavigationMenu;
case 'scm/title': return MenuId.SCMTitle;
case 'scm/sourceControl': return MenuId.SCMSourceControl;
@@ -70,7 +69,6 @@ namespace schema {
export function isProposedAPI(menuId: MenuId): boolean {
switch (menuId) {
case MenuId.StatusBarWindowIndicatorMenu:
case MenuId.MenubarFileMenu:
case MenuId.MenubarWebNavigationMenu:
return true;
}
@@ -230,13 +230,10 @@ export class ExtHostTerminalService extends BaseExtHostTerminalService {
public getEnvironmentVariableCollection(extension: IExtensionDescription): vscode.EnvironmentVariableCollection {
let collection = this._environmentVariableCollections.get(extension.identifier.value);
if (!collection) {
// TODO: Disable dispose
collection = new EnvironmentVariableCollection();
this._setEnvironmentVariableCollection(extension.identifier.value, collection);
}
return collection;
}
@@ -202,8 +202,9 @@ class NavigateDownAction extends BaseNavigationAction {
}
function findVisibleNeighbour(layoutService: IWorkbenchLayoutService, part: Parts, next: boolean): Parts {
const neighbour = part === Parts.EDITOR_PART ? (next ? Parts.STATUSBAR_PART : Parts.PANEL_PART) : part === Parts.STATUSBAR_PART ? (next ? Parts.SIDEBAR_PART : Parts.EDITOR_PART) :
part === Parts.SIDEBAR_PART ? (next ? Parts.PANEL_PART : Parts.STATUSBAR_PART) : part === Parts.PANEL_PART ? (next ? Parts.EDITOR_PART : Parts.SIDEBAR_PART) : Parts.EDITOR_PART;
const neighbour = part === Parts.EDITOR_PART ? (next ? Parts.STATUSBAR_PART : Parts.PANEL_PART) : part === Parts.STATUSBAR_PART ? (next ? Parts.ACTIVITYBAR_PART : Parts.EDITOR_PART) :
part === Parts.ACTIVITYBAR_PART ? (next ? Parts.SIDEBAR_PART : Parts.STATUSBAR_PART) : part === Parts.SIDEBAR_PART ? (next ? Parts.PANEL_PART : Parts.ACTIVITYBAR_PART) :
part === Parts.PANEL_PART ? (next ? Parts.EDITOR_PART : Parts.SIDEBAR_PART) : Parts.EDITOR_PART;
if (layoutService.isVisible(neighbour) || neighbour === Parts.EDITOR_PART) {
return neighbour;
}
@@ -212,8 +213,8 @@ function findVisibleNeighbour(layoutService: IWorkbenchLayoutService, part: Part
}
function focusNextOrPreviousPart(layoutService: IWorkbenchLayoutService, next: boolean): void {
const currentlyFocusedPart = layoutService.hasFocus(Parts.EDITOR_PART) ? Parts.EDITOR_PART : layoutService.hasFocus(Parts.STATUSBAR_PART) ? Parts.STATUSBAR_PART :
layoutService.hasFocus(Parts.SIDEBAR_PART) ? Parts.SIDEBAR_PART : layoutService.hasFocus(Parts.PANEL_PART) ? Parts.PANEL_PART : undefined;
const currentlyFocusedPart = layoutService.hasFocus(Parts.EDITOR_PART) ? Parts.EDITOR_PART : layoutService.hasFocus(Parts.ACTIVITYBAR_PART) ? Parts.ACTIVITYBAR_PART :
layoutService.hasFocus(Parts.STATUSBAR_PART) ? Parts.STATUSBAR_PART : layoutService.hasFocus(Parts.SIDEBAR_PART) ? Parts.SIDEBAR_PART : layoutService.hasFocus(Parts.PANEL_PART) ? Parts.PANEL_PART : undefined;
let partToFocus = Parts.EDITOR_PART;
if (currentlyFocusedPart) {
partToFocus = findVisibleNeighbour(layoutService, currentlyFocusedPart, next);
+24 -12
View File
@@ -11,7 +11,7 @@ import { IWindowOpenable } from 'vs/platform/windows/common/windows';
import { URI } from 'vs/base/common/uri';
import { ITextFileService, stringToSnapshot } from 'vs/workbench/services/textfile/common/textfiles';
import { Schemas } from 'vs/base/common/network';
import { IEditorViewState } from 'vs/editor/common/editorCommon';
import { ITextEditorOptions } from 'vs/platform/editor/common/editor';
import { DataTransfers, IDragAndDropData } from 'vs/base/browser/dnd';
import { DragMouseEvent } from 'vs/base/browser/mouseEvent';
import { normalizeDriveLetter } from 'vs/base/common/labels';
@@ -58,7 +58,7 @@ export interface IDraggedEditor extends IDraggedResource {
content?: string;
encoding?: string;
mode?: string;
viewState?: IEditorViewState;
options?: ITextEditorOptions;
}
export interface ISerializedDraggedEditor {
@@ -66,7 +66,7 @@ export interface ISerializedDraggedEditor {
content?: string;
encoding?: string;
mode?: string;
viewState?: IEditorViewState;
options?: ITextEditorOptions;
}
export const CodeDataTransfers = {
@@ -90,7 +90,7 @@ export function extractResources(e: DragEvent, externalOnly?: boolean): Array<ID
resources.push({
resource: URI.parse(draggedEditor.resource),
content: draggedEditor.content,
viewState: draggedEditor.viewState,
options: draggedEditor.options,
encoding: draggedEditor.encoding,
mode: draggedEditor.mode,
isExternal: false
@@ -202,9 +202,9 @@ export class ResourcesDropHandler {
encoding: (untitledOrFileResource as IDraggedEditor).encoding,
mode: (untitledOrFileResource as IDraggedEditor).mode,
options: {
...(untitledOrFileResource as IDraggedEditor).options,
pinned: true,
index: targetIndex,
viewState: (untitledOrFileResource as IDraggedEditor).viewState
index: targetIndex
}
}));
@@ -311,7 +311,7 @@ export class ResourcesDropHandler {
}
}
export function fillResourceDataTransfers(accessor: ServicesAccessor, resources: (URI | { resource: URI, isDirectory: boolean })[], event: DragMouseEvent | DragEvent): void {
export function fillResourceDataTransfers(accessor: ServicesAccessor, resources: (URI | { resource: URI, isDirectory: boolean })[], optionsCallback: ((resource: URI) => ITextEditorOptions) | undefined, event: DragMouseEvent | DragEvent): void {
if (resources.length === 0 || !event.dataTransfer) {
return;
}
@@ -346,20 +346,32 @@ export function fillResourceDataTransfers(accessor: ServicesAccessor, resources:
const draggedEditors: ISerializedDraggedEditor[] = [];
files.forEach(file => {
let options: ITextEditorOptions | undefined = undefined;
// Try to find editor view state from the visible editors that match given resource
let viewState: IEditorViewState | undefined = undefined;
// Use provided callback for editor options
if (typeof optionsCallback === 'function') {
options = optionsCallback(file.resource);
}
// Otherwise try to figure out the view state from opened editors that match
else {
options = {
viewState: (() => {
const textEditorControls = editorService.visibleTextEditorControls;
for (const textEditorControl of textEditorControls) {
if (isCodeEditor(textEditorControl)) {
const model = textEditorControl.getModel();
if (model?.uri?.toString() === file.resource.toString()) {
viewState = withNullAsUndefined(textEditorControl.saveViewState());
break;
return withNullAsUndefined(textEditorControl.saveViewState());
}
}
}
return undefined;
})()
};
}
// Try to find encoding and mode from text model
let encoding: string | undefined = undefined;
let mode: string | undefined = undefined;
@@ -378,7 +390,7 @@ export function fillResourceDataTransfers(accessor: ServicesAccessor, resources:
}
// Add as dragged editor
draggedEditors.push({ resource: file.resource.toString(), content, viewState, encoding, mode });
draggedEditors.push({ resource: file.resource.toString(), content, options, encoding, mode });
});
if (draggedEditors.length) {
+14 -2
View File
@@ -42,8 +42,21 @@ function toResource(props: IResourceLabelProps | undefined): URI | undefined {
}
export interface IResourceLabelOptions extends IIconLabelValueOptions {
/**
* A hint to the file kind of the resource.
*/
fileKind?: FileKind;
/**
* File decorations to use for the label.
*/
fileDecorations?: { colors: boolean, badges: boolean };
/**
* Will take the provided label as is and e.g. not override it for untitled files.
*/
forceLabel?: boolean;
}
export interface IFileLabelOptions extends IResourceLabelOptions {
@@ -368,7 +381,7 @@ class ResourceLabelWidget extends IconLabel {
/*const resource = toResource(label); {{SQL CARBON EDIT}} we don't want to special case untitled files
const isMasterDetail = label?.resource && !URI.isUri(label.resource);
if (!isMasterDetail && resource?.scheme === Schemas.untitled) {
if (!options.forceLabel && !isMasterDetail && resource?.scheme === Schemas.untitled) {
// Untitled labels are very dynamic because they may change
// whenever the content changes (unless a path is associated).
// As such we always ask the actual editor for it's name and
@@ -528,7 +541,6 @@ class ResourceLabelWidget extends IconLabel {
);
if (deco) {
this.renderDisposables.add(deco);
if (deco.tooltip) {
+5 -1
View File
@@ -177,6 +177,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
private backupFileService!: IBackupFileService;
private notificationService!: INotificationService;
private themeService!: IThemeService;
private activityBarService!: IActivityBarService;
protected readonly state = {
fullscreen: false,
@@ -260,8 +261,8 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
this.viewDescriptorService = accessor.get(IViewDescriptorService);
this.titleService = accessor.get(ITitleService);
this.notificationService = accessor.get(INotificationService);
this.activityBarService = accessor.get(IActivityBarService);
accessor.get(IStatusbarService); // not used, but called to ensure instantiated
accessor.get(IActivityBarService); // not used, but called to ensure instantiated
// Listeners
this.registerLayoutListeners();
@@ -846,6 +847,9 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
activeViewlet.focus();
}
break;
case Parts.ACTIVITYBAR_PART:
this.activityBarService.focusActivityBar();
break;
default:
// Status Bar, Activity Bar and Title Bar simply pass focus to container
const container = this.getContainer(part);
-3
View File
@@ -10,7 +10,6 @@
.monaco-workbench .part > .drop-block-overlay.visible {
visibility: visible;
opacity: 1;
}
.monaco-workbench .part > .drop-block-overlay {
@@ -18,10 +17,8 @@
top: 0;
width: 100%;
height: 100%;
backdrop-filter: brightness(97%) blur(2px);
visibility: hidden;
opacity: 0;
transition: opacity .5s, visibility .5s;
z-index: 10;
}
@@ -168,6 +168,10 @@ export class ActivitybarPart extends Part implements IActivityBarService {
this.registerListeners();
}
focusActivityBar(): void {
this.compositeBar.focus();
}
private registerListeners(): void {
// View Container Changes
@@ -66,8 +66,6 @@ export class CompositeDragAndDrop implements ICompositeDragAndDrop {
if (targetCompositeId) {
this.moveComposite(currentContainer.id, targetCompositeId, before);
}
this.openComposite(currentContainer.id, true);
}
}
@@ -255,6 +253,12 @@ export class CompositeBar extends Widget implements ICompositeBar {
return actionBarDiv;
}
focus(): void {
if (this.compositeSwitcherBar) {
this.compositeSwitcherBar.focus();
}
}
layout(dimension: Dimension): void {
this.dimension = dimension;
if (dimension.height === 0 || dimension.width === 0) {
@@ -275,8 +279,7 @@ export class CompositeBar extends Widget implements ICompositeBar {
// Add to the model
if (this.model.add(id, name, order)) {
this.computeSizes([this.model.findItem(id)]);
// Set timeout helps prevent flicker
setTimeout(() => this.updateCompositeSwitcher(), 0);
this.updateCompositeSwitcher();
}
}
@@ -548,11 +548,8 @@ export class CompositeActionViewItem extends ActivityActionViewItem {
if (e.eventData.dataTransfer) {
e.eventData.dataTransfer.effectAllowed = 'move';
}
// Trigger the action even on drag start to prevent clicks from failing that started a drag
if (!this.getAction().checked) {
this.getAction().run();
}
// Remove focus indicator when dragging
this.blur();
}
}));
@@ -19,6 +19,7 @@ import { MementoObject } from 'vs/workbench/common/memento';
import { isEqualOrParent, joinPath } from 'vs/base/common/resources';
import { isLinux } from 'vs/base/common/platform';
import { indexOfPath } from 'vs/base/common/extpath';
import { IDisposable } from 'vs/base/common/lifecycle';
/**
* The base class of editors in the workbench. Editors register themselves for specific editor inputs.
@@ -171,6 +172,7 @@ interface MapGroupToMemento<T> {
export class EditorMemento<T> implements IEditorMemento<T> {
private cache: LRUCache<string, MapGroupToMemento<T>> | undefined;
private cleanedUp = false;
private editorDisposables: Map<EditorInput, IDisposable> | undefined;
constructor(
public readonly id: string,
@@ -200,9 +202,18 @@ export class EditorMemento<T> implements IEditorMemento<T> {
// Automatically clear when editor input gets disposed if any
if (resourceOrEditor instanceof EditorInput) {
Event.once(resourceOrEditor.onDispose)(() => {
const editor = resourceOrEditor;
if (!this.editorDisposables) {
this.editorDisposables = new Map<EditorInput, IDisposable>();
}
if (!this.editorDisposables.has(editor)) {
this.editorDisposables.set(editor, Event.once(resourceOrEditor.onDispose)(() => {
this.clearEditorState(resource);
});
this.editorDisposables?.delete(editor);
}));
}
}
}
@@ -7,7 +7,7 @@ import { Registry } from 'vs/platform/registry/common/platform';
import * as nls from 'vs/nls';
import { URI, UriComponents } from 'vs/base/common/uri';
import { IEditorRegistry, EditorDescriptor, Extensions as EditorExtensions } from 'vs/workbench/browser/editor';
import { EditorInput, IEditorInputFactory, SideBySideEditorInput, IEditorInputFactoryRegistry, Extensions as EditorInputExtensions, TextCompareEditorActiveContext, EditorPinnedContext, EditorGroupEditorsCountContext } from 'vs/workbench/common/editor';
import { EditorInput, IEditorInputFactory, SideBySideEditorInput, IEditorInputFactoryRegistry, Extensions as EditorInputExtensions, TextCompareEditorActiveContext, EditorPinnedContext, EditorGroupEditorsCountContext, EditorStickyContext } from 'vs/workbench/common/editor';
import { TextResourceEditor } from 'vs/workbench/browser/parts/editor/textResourceEditor';
import { SideBySideEditor } from 'vs/workbench/browser/parts/editor/sideBySideEditor';
import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
@@ -433,6 +433,8 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCo
MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.CLOSE_SAVED_EDITORS_COMMAND_ID, title: nls.localize('closeAllSaved', "Close Saved") }, group: '1_close', order: 40 });
MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.CLOSE_EDITORS_IN_GROUP_COMMAND_ID, title: nls.localize('closeAll', "Close All") }, group: '1_close', order: 50 });
MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.KEEP_EDITOR_COMMAND_ID, title: nls.localize('keepOpen', "Keep Open"), precondition: EditorPinnedContext.toNegated() }, group: '3_preview', order: 10, when: ContextKeyExpr.has('config.workbench.editor.enablePreview') });
MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.PIN_EDITOR_COMMAND_ID, title: nls.localize('pin', "Pin") }, group: '3_preview', order: 20, when: ContextKeyExpr.and(EditorStickyContext.toNegated(), ContextKeyExpr.has('config.workbench.editor.showTabs')) });
MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.UNPIN_EDITOR_COMMAND_ID, title: nls.localize('unpin', "Unpin") }, group: '3_preview', order: 20, when: ContextKeyExpr.and(EditorStickyContext, ContextKeyExpr.has('config.workbench.editor.showTabs')) });
MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.SPLIT_EDITOR_UP, title: nls.localize('splitUp', "Split Up") }, group: '5_split', order: 10 });
MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.SPLIT_EDITOR_DOWN, title: nls.localize('splitDown', "Split Down") }, group: '5_split', order: 20 });
MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.SPLIT_EDITOR_LEFT, title: nls.localize('splitLeft', "Split Left") }, group: '5_split', order: 30 });
@@ -579,6 +581,8 @@ appendEditorToolItem(
// Editor Commands for Command Palette
const viewCategory = { value: nls.localize('view', "View"), original: 'View' };
MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: editorCommands.KEEP_EDITOR_COMMAND_ID, title: { value: nls.localize('keepEditor', "Keep Editor"), original: 'Keep Editor' }, category: viewCategory }, when: ContextKeyExpr.has('config.workbench.editor.enablePreview') });
MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: editorCommands.PIN_EDITOR_COMMAND_ID, title: { value: nls.localize('pinEditor', "Pin Editor"), original: 'Pin Editor' }, category: viewCategory }, when: ContextKeyExpr.has('config.workbench.editor.showTabs') });
MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: editorCommands.UNPIN_EDITOR_COMMAND_ID, title: { value: nls.localize('unpinEditor', "Unpin Editor"), original: 'Unpin Editor' }, category: viewCategory }, when: ContextKeyExpr.has('config.workbench.editor.showTabs') });
MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: editorCommands.CLOSE_EDITORS_IN_GROUP_COMMAND_ID, title: { value: nls.localize('closeEditorsInGroup', "Close All Editors in Group"), original: 'Close All Editors in Group' }, category: viewCategory } });
MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: editorCommands.CLOSE_SAVED_EDITORS_COMMAND_ID, title: { value: nls.localize('closeSavedEditors', "Close Saved Editors in Group"), original: 'Close Saved Editors in Group' }, category: viewCategory } });
MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: editorCommands.CLOSE_OTHER_EDITORS_IN_GROUP_COMMAND_ID, title: { value: nls.localize('closeOtherEditors', "Close Other Editors in Group"), original: 'Close Other Editors in Group' }, category: viewCategory } });
@@ -500,7 +500,7 @@ export class CloseLeftEditorsInGroupAction extends Action {
async run(context?: IEditorIdentifier): Promise<void> {
const { group, editor } = getTarget(this.editorService, this.editorGroupService, context);
if (group && editor) {
return group.closeEditors({ direction: CloseDirection.LEFT, except: editor });
return group.closeEditors({ direction: CloseDirection.LEFT, except: editor, excludeSticky: true });
}
}
}
@@ -514,7 +514,7 @@ function getTarget(editorService: IEditorService, editorGroupService: IEditorGro
return { group: editorGroupService.activeGroup, editor: editorGroupService.activeGroup.activeEditor };
}
export abstract class BaseCloseAllAction extends Action {
abstract class BaseCloseAllAction extends Action {
constructor(
id: string,
@@ -554,7 +554,7 @@ export abstract class BaseCloseAllAction extends Action {
// to bring each dirty editor to the front so that the user
// can review if the files should be changed or not.
await Promise.all(this.groupsToClose.map(async groupToClose => {
for (const editor of groupToClose.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE)) {
for (const editor of groupToClose.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE, { excludeSticky: this.excludeSticky })) {
if (editor.isDirty() && !editor.isSaving() /* ignore editors that are being saved */) {
return groupToClose.openEditor(editor);
}
@@ -566,7 +566,7 @@ export abstract class BaseCloseAllAction extends Action {
const dirtyEditorsToConfirm = new Set<string>();
const dirtyEditorsToAutoSave = new Set<IEditorInput>();
for (const editor of this.editorService.editors) {
for (const editor of this.editorService.getEditors(EditorsOrder.SEQUENTIAL, { excludeSticky: this.excludeSticky }).map(({ editor }) => editor)) {
if (!editor.isDirty() || editor.isSaving()) {
continue; // only interested in dirty editors (unless in the process of saving)
}
@@ -601,21 +601,29 @@ export abstract class BaseCloseAllAction extends Action {
confirmation = ConfirmResult.DONT_SAVE;
}
if (confirmation === ConfirmResult.CANCEL) {
// Handle result from asking user
let result: boolean | undefined = undefined;
switch (confirmation) {
case ConfirmResult.CANCEL:
return;
case ConfirmResult.DONT_SAVE:
result = await this.editorService.revertAll({ soft: true, includeUntitled: true, excludeSticky: this.excludeSticky });
break;
case ConfirmResult.SAVE:
result = await this.editorService.saveAll({ reason: saveReason, includeUntitled: true, excludeSticky: this.excludeSticky });
break;
}
if (confirmation === ConfirmResult.DONT_SAVE) {
await this.editorService.revertAll({ soft: true, includeUntitled: true });
} else {
await this.editorService.saveAll({ reason: saveReason, includeUntitled: true });
}
if (!this.workingCopyService.hasDirty) {
// Only continue to close editors if we either have no more dirty
// editors or the result from the save/revert was successful
if (!this.workingCopyService.hasDirty || result) {
return this.doCloseAll();
}
}
protected abstract get excludeSticky(): boolean;
protected abstract doCloseAll(): Promise<void>;
}
@@ -636,8 +644,12 @@ export class CloseAllEditorsAction extends BaseCloseAllAction {
super(id, label, Codicon.closeAll.classNames, workingCopyService, fileDialogService, editorGroupService, editorService, filesConfigurationService);
}
protected get excludeSticky(): boolean {
return true;
}
protected async doCloseAll(): Promise<void> {
await Promise.all(this.groupsToClose.map(g => g.closeAllEditors()));
await Promise.all(this.groupsToClose.map(group => group.closeAllEditors({ excludeSticky: true })));
}
}
@@ -658,6 +670,10 @@ export class CloseAllEditorGroupsAction extends BaseCloseAllAction {
super(id, label, undefined, workingCopyService, fileDialogService, editorGroupService, editorService, filesConfigurationService);
}
protected get excludeSticky(): boolean {
return false;
}
protected async doCloseAll(): Promise<void> {
await Promise.all(this.groupsToClose.map(group => group.closeAllEditors()));
@@ -680,12 +696,12 @@ export class CloseEditorsInOtherGroupsAction extends Action {
async run(context?: IEditorIdentifier): Promise<void> {
const groupToSkip = context ? this.editorGroupService.getGroup(context.groupId) : this.editorGroupService.activeGroup;
await Promise.all(this.editorGroupService.getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE).map(async g => {
if (groupToSkip && g.id === groupToSkip.id) {
await Promise.all(this.editorGroupService.getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE).map(async group => {
if (groupToSkip && group.id === groupToSkip.id) {
return;
}
return g.closeAllEditors();
return group.closeAllEditors({ excludeSticky: true });
}));
}
}
@@ -707,7 +723,7 @@ export class CloseEditorInAllGroupsAction extends Action {
async run(): Promise<void> {
const activeEditor = this.editorService.activeEditor;
if (activeEditor) {
await Promise.all(this.editorGroupService.getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE).map(g => g.closeEditor(activeEditor)));
await Promise.all(this.editorGroupService.getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE).map(group => group.closeEditor(activeEditor)));
}
}
}
@@ -7,7 +7,7 @@ import * as nls from 'vs/nls';
import * as types from 'vs/base/common/types';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { TextCompareEditorVisibleContext, EditorInput, IEditorIdentifier, IEditorCommandsContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, CloseDirection, IEditorInput, IVisibleEditorPane } from 'vs/workbench/common/editor';
import { TextCompareEditorVisibleContext, EditorInput, IEditorIdentifier, IEditorCommandsContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, CloseDirection, IEditorInput, IVisibleEditorPane, EditorStickyContext, EditorsOrder } from 'vs/workbench/common/editor';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { TextDiffEditor } from 'vs/workbench/browser/parts/editor/textDiffEditor';
@@ -37,6 +37,9 @@ export const LAYOUT_EDITOR_GROUPS_COMMAND_ID = 'layoutEditorGroups';
export const KEEP_EDITOR_COMMAND_ID = 'workbench.action.keepEditor';
export const SHOW_EDITORS_IN_GROUP = 'workbench.action.showEditorsInGroup';
export const PIN_EDITOR_COMMAND_ID = 'workbench.action.pinEditor';
export const UNPIN_EDITOR_COMMAND_ID = 'workbench.action.unpinEditor';
export const TOGGLE_DIFF_SIDE_BY_SIDE = 'toggle.diff.renderSideBySide';
export const GOTO_NEXT_CHANGE = 'workbench.action.compareEditor.nextChange';
export const GOTO_PREVIOUS_CHANGE = 'workbench.action.compareEditor.previousChange';
@@ -258,7 +261,7 @@ function registerDiffEditorCommands(): void {
function navigateInDiffEditor(accessor: ServicesAccessor, next: boolean): void {
const editorService = accessor.get(IEditorService);
const candidates = [editorService.activeEditorPane, ...editorService.visibleEditorPanes].filter(e => e instanceof TextDiffEditor);
const candidates = [editorService.activeEditorPane, ...editorService.visibleEditorPanes].filter(editor => editor instanceof TextDiffEditor);
if (candidates.length > 0) {
const navigator = (<TextDiffEditor>candidates[0]).getDiffNavigator();
@@ -491,7 +494,7 @@ function registerCloseEditorCommands() {
return Promise.all(distinct(contexts.map(c => c.groupId)).map(async groupId => {
const group = editorGroupService.getGroup(groupId);
if (group) {
return group.closeEditors({ savedOnly: true });
return group.closeEditors({ savedOnly: true, excludeSticky: true });
}
}));
}
@@ -514,7 +517,7 @@ function registerCloseEditorCommands() {
return Promise.all(distinctGroupIds.map(async groupId => {
const group = editorGroupService.getGroup(groupId);
if (group) {
return group.closeAllEditors();
return group.closeAllEditors({ excludeSticky: true });
}
}));
}
@@ -596,7 +599,8 @@ function registerCloseEditorCommands() {
const editors = contexts
.filter(context => context.groupId === groupId)
.map(context => typeof context.editorIndex === 'number' ? group.getEditorByIndex(context.editorIndex) : group.activeEditor);
const editorsToClose = group.editors.filter(e => editors.indexOf(e) === -1);
const editorsToClose = group.getEditors(EditorsOrder.SEQUENTIAL, { excludeSticky: true }).filter(editor => editors.indexOf(editor) === -1);
if (group.activeEditor) {
group.pinEditor(group.activeEditor);
@@ -622,7 +626,7 @@ function registerCloseEditorCommands() {
group.pinEditor(group.activeEditor);
}
return group.closeEditors({ direction: CloseDirection.RIGHT, except: editor });
return group.closeEditors({ direction: CloseDirection.RIGHT, except: editor, excludeSticky: true });
}
}
});
@@ -642,6 +646,36 @@ function registerCloseEditorCommands() {
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: PIN_EDITOR_COMMAND_ID,
weight: KeybindingWeight.WorkbenchContrib,
when: ContextKeyExpr.and(EditorStickyContext.toNegated(), ContextKeyExpr.has('config.workbench.editor.showTabs')),
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.Enter),
handler: async (accessor, resourceOrContext: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
const editorGroupService = accessor.get(IEditorGroupsService);
const { group, editor } = resolveCommandsContext(editorGroupService, getCommandsContext(resourceOrContext, context));
if (group && editor) {
return group.stickEditor(editor);
}
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: UNPIN_EDITOR_COMMAND_ID,
weight: KeybindingWeight.WorkbenchContrib,
when: ContextKeyExpr.and(EditorStickyContext, ContextKeyExpr.has('config.workbench.editor.showTabs')),
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.Enter),
handler: async (accessor, resourceOrContext: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
const editorGroupService = accessor.get(IEditorGroupsService);
const { group, editor } = resolveCommandsContext(editorGroupService, getCommandsContext(resourceOrContext, context));
if (group && editor) {
return group.unstickEditor(editor);
}
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: SHOW_EDITORS_IN_GROUP,
weight: KeybindingWeight.WorkbenchContrib,
@@ -266,7 +266,10 @@ class DropOverlay extends Themable {
}
// Open in target group
const options = getActiveTextEditorOptions(sourceGroup, draggedEditor.editor, EditorOptions.create({ pinned: true }));
const options = getActiveTextEditorOptions(sourceGroup, draggedEditor.editor, EditorOptions.create({
pinned: true, // always pin dropped editor
sticky: sourceGroup.isSticky(draggedEditor.editor) // preserve sticky state
}));
targetGroup.openEditor(draggedEditor.editor, options);
// Ensure target has focus
@@ -17,7 +17,7 @@ import { attachProgressBarStyler } from 'vs/platform/theme/common/styler';
import { IThemeService, registerThemingParticipant, Themable } from 'vs/platform/theme/common/themeService';
import { editorBackground, contrastBorder } from 'vs/platform/theme/common/colorRegistry';
import { EDITOR_GROUP_HEADER_TABS_BACKGROUND, EDITOR_GROUP_HEADER_NO_TABS_BACKGROUND, EDITOR_GROUP_EMPTY_BACKGROUND, EDITOR_GROUP_FOCUSED_EMPTY_BORDER, EDITOR_GROUP_HEADER_BORDER } from 'vs/workbench/common/theme';
import { IMoveEditorOptions, ICopyEditorOptions, ICloseEditorsFilter, IGroupChangeEvent, GroupChangeKind, GroupsOrder, ICloseEditorOptions } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IMoveEditorOptions, ICopyEditorOptions, ICloseEditorsFilter, IGroupChangeEvent, GroupChangeKind, GroupsOrder, ICloseEditorOptions, ICloseAllEditorsOptions } from 'vs/workbench/services/editor/common/editorGroupsService';
import { TabsTitleControl } from 'vs/workbench/browser/parts/editor/tabsTitleControl';
import { EditorControl } from 'vs/workbench/browser/parts/editor/editorControl';
import { IEditorProgressService } from 'vs/platform/progress/common/progress';
@@ -441,6 +441,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
}
options.pinned = this._group.isPinned(activeEditor); // preserve pinned state
options.sticky = this._group.isSticky(activeEditor); // preserve sticky state
options.preserveFocus = true; // handle focus after editor is opened
const activeElement = document.activeElement;
@@ -732,6 +733,10 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
return this._group.count;
}
get stickyCount(): number {
return this._group.stickyCount;
}
get activeEditorPane(): IVisibleEditorPane | undefined {
return this.editorControl ? withNullAsUndefined(this.editorControl.activeEditorPane) : undefined;
}
@@ -748,12 +753,16 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
return this._group.isPinned(editor);
}
isSticky(editorOrIndex: EditorInput | number): boolean {
return this._group.isSticky(editorOrIndex);
}
isActive(editor: EditorInput): boolean {
return this._group.isActive(editor);
}
getEditors(order: EditorsOrder): EditorInput[] {
return this._group.getEditors(order);
getEditors(order: EditorsOrder, options?: { excludeSticky?: boolean }): EditorInput[] {
return this._group.getEditors(order, options);
}
getEditorByIndex(index: number): EditorInput | undefined {
@@ -794,6 +803,43 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
}
}
stickEditor(candidate: EditorInput | undefined = this.activeEditor || undefined): void {
this.doStickEditor(candidate, true);
}
unstickEditor(candidate: EditorInput | undefined = this.activeEditor || undefined): void {
this.doStickEditor(candidate, false);
}
private doStickEditor(candidate: EditorInput | undefined, sticky: boolean): void {
if (candidate && this._group.isSticky(candidate) !== sticky) {
const oldIndexOfEditor = this.getIndexOfEditor(candidate);
// Update model
const editor = sticky ? this._group.stick(candidate) : this._group.unstick(candidate);
if (!editor) {
return;
}
// If the index of the editor changed, we need to forward this to
// title control and also make sure to emit this as an event
const newIndexOfEditor = this.getIndexOfEditor(editor);
if (newIndexOfEditor !== oldIndexOfEditor) {
this.titleAreaControl.moveEditor(editor, oldIndexOfEditor, newIndexOfEditor);
// Event
this._onDidGroupChange.fire({ kind: GroupChangeKind.EDITOR_MOVE, editor });
}
// Forward sticky state to title control
if (sticky) {
this.titleAreaControl.stickEditor(editor);
} else {
this.titleAreaControl.unstickEditor(editor);
}
}
}
invokeWithinContext<T>(fn: (accessor: ServicesAccessor) => T): T {
return this.scopedInstantiationService.invokeFunction(fn);
}
@@ -833,11 +879,19 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
// Determine options
const openEditorOptions: IEditorOpenOptions = {
index: options ? options.index : undefined,
pinned: !this.accessor.partOptions.enablePreview || editor.isDirty() || (options?.pinned ?? typeof options?.index === 'number'), // unless specified, prefer to pin when opening with index
pinned: options?.sticky || !this.accessor.partOptions.enablePreview || editor.isDirty() || (options?.pinned ?? typeof options?.index === 'number' /* unless specified, prefer to pin when opening with index */) || (typeof options?.index === 'number' && this._group.isSticky(options.index)),
sticky: options?.sticky || (typeof options?.index === 'number' && this._group.isSticky(options.index)),
active: this._group.count === 0 || !options || !options.inactive
};
if (!openEditorOptions.active && !openEditorOptions.pinned && this._group.activeEditor && this._group.isPreview(this._group.activeEditor)) {
if (options?.sticky && typeof options?.index === 'number' && !this._group.isSticky(options.index)) {
// Special case: we are to open an editor sticky but at an index that is not sticky
// In that case we prefer to open the editor at the index but not sticky. This enables
// to drag a sticky editor to an index that is not sticky to unstick it.
openEditorOptions.sticky = false;
}
if (!openEditorOptions.active && !openEditorOptions.pinned && this._group.activeEditor && !this._group.isPinned(this._group.activeEditor)) {
// Special case: we are to open an editor inactive and not pinned, but the current active
// editor is also not pinned, which means it will get replaced with this one. As such,
// the editor can only be active.
@@ -1095,8 +1149,11 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
// When moving an editor, try to preserve as much view state as possible by checking
// for the editor to be a text editor and creating the options accordingly if so
const options = getActiveTextEditorOptions(this, editor, EditorOptions.create(moveOptions));
options.pinned = true; // always pin moved editor
const options = getActiveTextEditorOptions(this, editor, EditorOptions.create({
...moveOptions,
pinned: true, // always pin moved editor
sticky: this._group.isSticky(editor) // preserve sticky state
}));
// A move to another group is an open first...
target.openEditor(editor, options);
@@ -1377,7 +1434,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
return;
}
const editors = this.getEditorsToClose(args);
const editors = this.doGetEditorsToClose(args);
// Check for dirty and veto
const veto = await this.handleDirtyClosing(editors.slice(0));
@@ -1389,31 +1446,31 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
this.doCloseEditors(editors, options);
}
private getEditorsToClose(editors: EditorInput[] | ICloseEditorsFilter): EditorInput[] {
if (Array.isArray(editors)) {
return editors;
private doGetEditorsToClose(args: EditorInput[] | ICloseEditorsFilter): EditorInput[] {
if (Array.isArray(args)) {
return args;
}
const filter = editors;
const filter = args;
const hasDirection = typeof filter.direction === 'number';
let editorsToClose = this._group.getEditors(hasDirection ? EditorsOrder.SEQUENTIAL : EditorsOrder.MOST_RECENTLY_ACTIVE); // in MRU order only if direction is not specified
let editorsToClose = this._group.getEditors(hasDirection ? EditorsOrder.SEQUENTIAL : EditorsOrder.MOST_RECENTLY_ACTIVE, filter); // in MRU order only if direction is not specified
// Filter: saved or saving only
if (filter.savedOnly) {
editorsToClose = editorsToClose.filter(e => !e.isDirty() || e.isSaving());
editorsToClose = editorsToClose.filter(editor => !editor.isDirty() || editor.isSaving());
}
// Filter: direction (left / right)
else if (hasDirection && filter.except) {
editorsToClose = (filter.direction === CloseDirection.LEFT) ?
editorsToClose.slice(0, this._group.indexOf(filter.except)) :
editorsToClose.slice(this._group.indexOf(filter.except) + 1);
editorsToClose.slice(0, this._group.indexOf(filter.except, editorsToClose)) :
editorsToClose.slice(this._group.indexOf(filter.except, editorsToClose) + 1);
}
// Filter: except
else if (filter.except) {
editorsToClose = editorsToClose.filter(e => !e.matches(filter.except));
editorsToClose = editorsToClose.filter(editor => !editor.matches(filter.except));
}
return editorsToClose;
@@ -1444,7 +1501,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
//#region closeAllEditors()
async closeAllEditors(): Promise<void> {
async closeAllEditors(options?: ICloseAllEditorsOptions): Promise<void> {
if (this.isEmpty) {
// If the group is empty and the request is to close all editors, we still close
@@ -1458,30 +1515,34 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
}
// Check for dirty and veto
const editors = this._group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE);
const veto = await this.handleDirtyClosing(editors.slice(0));
const veto = await this.handleDirtyClosing(this._group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE, options));
if (veto) {
return;
}
// Do close
this.doCloseAllEditors();
this.doCloseAllEditors(options);
}
private doCloseAllEditors(): void {
private doCloseAllEditors(options?: ICloseAllEditorsOptions): void {
// Close all inactive editors first
this.editors.forEach(editor => {
const editorsToClose: EditorInput[] = [];
this._group.getEditors(EditorsOrder.SEQUENTIAL, options).forEach(editor => {
if (!this.isActive(editor)) {
this.doCloseInactiveEditor(editor);
}
editorsToClose.push(editor);
});
// Close active editor last
// Close active editor last (unless we skip it, e.g. because it is sticky)
if (this.activeEditor && editorsToClose.includes(this.activeEditor)) {
this.doCloseActiveEditor();
}
// Forward to title control
this.titleAreaControl.closeAllEditors();
this.titleAreaControl.closeEditors(editorsToClose);
}
//#endregion
@@ -48,7 +48,7 @@ export class EditorsObserver extends Disposable {
}
get editors(): IEditorIdentifier[] {
return [...this.mostRecentEditorsMap.values()];
return this.mostRecentEditorsMap.values();
}
hasEditor(resource: URI): boolean {
@@ -283,7 +283,7 @@ export class EditorsObserver extends Disposable {
// Across all editor groups
else {
await this.doEnsureOpenedEditorsLimit(limit, [...this.mostRecentEditorsMap.values()], exclude);
await this.doEnsureOpenedEditorsLimit(limit, this.mostRecentEditorsMap.values(), exclude);
}
}
@@ -302,6 +302,10 @@ export class EditorsObserver extends Disposable {
return false; // never the editor that should be excluded
}
if (this.editorGroupsService.getGroup(groupId)?.isSticky(editor)) {
return false; // never sticky editors
}
return true;
});
@@ -342,7 +346,7 @@ export class EditorsObserver extends Disposable {
private serialize(): ISerializedEditorsList {
const registry = Registry.as<IEditorInputFactoryRegistry>(Extensions.EditorInputFactories);
const entries = [...this.mostRecentEditorsMap.values()];
const entries = this.mostRecentEditorsMap.values();
const mapGroupToSerializableEditorsOfGroup = new Map<IEditorGroup, IEditorInput[]>();
return {
@@ -63,8 +63,8 @@
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.has-icon-theme.close-button-right,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.has-icon-theme.close-button-off {
padding-left: 5px; /* reduce padding when we show icons and are in shrinking mode and tab close button is not left */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.has-icon-theme.close-button-off:not(.sticky) {
padding-left: 5px; /* reduce padding when we show icons and are in shrinking mode and tab close button is not left (unless sticky) */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fit {
@@ -82,6 +82,30 @@
max-width: -moz-fit-content;
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fit.sticky,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.sticky {
/** Sticky tabs do not scroll in case of overflow and are always above unsticky tabs which scroll under */
position: sticky;
z-index: 1;
/** Sticky tabs are even and never grow */
flex-basis: 0;
flex-grow: 0;
/** Sticky tabs have a fixed width of 38px */
width: 38px;
min-width: 38px;
max-width: 38px;
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container.disable-sticky-tabs > .tab.sizing-fit.sticky,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container.disable-sticky-tabs > .tab.sizing-shrink.sticky {
/** Disable sticky positions for sticky tabs if the available space is too little */
position: static;
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-left .action-label {
margin-right: 4px !important;
}
@@ -174,6 +198,10 @@
opacity: 0; /* when tab has the focus this shade breaks the tab border (fixes https://github.com/Microsoft/vscode/issues/57819) */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sticky:not(.has-icon-theme) .monaco-icon-label {
text-align: center; /* ensure that sticky tabs without icon have label centered */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fit .monaco-icon-label,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fit .monaco-icon-label > .monaco-icon-label-container {
overflow: visible; /* fixes https://github.com/Microsoft/vscode/issues/20182 */
@@ -210,8 +238,9 @@
overflow: visible; /* ...but still show the close button on hover, focus and when dirty */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off:not(.dirty) > .tab-close {
display: none; /* hide the close action bar when we are configured to hide it */
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off:not(.dirty) > .tab-close,
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off.sticky > .tab-close {
display: none; /* hide the close action bar when we are configured to hide it (unless dirty, but always when sticky) */
}
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.active > .tab-close .action-label, /* always show it for active tab */
@@ -257,8 +286,8 @@
padding-right: 10px; /* give a little bit more room if close button is off */
}
.monaco-workbench .part.editor > .content .editor-group-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 .editor-group-container > .title .tabs-container > .tab.sizing-shrink.close-button-off:not(.sticky) {
padding-right: 5px; /* we need less room when sizing is shrink (unless tab is sticky) */
}
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off.dirty-border-top > .tab-close,
@@ -136,10 +136,6 @@ export class NoTabsTitleControl extends TitleControl {
this.ifActiveEditorChanged(() => this.redraw());
}
closeAllEditors(): void {
this.redraw();
}
moveEditor(editor: IEditorInput, fromIndex: number, targetIndex: number): void {
this.ifActiveEditorChanged(() => this.redraw());
}
@@ -148,6 +144,14 @@ export class NoTabsTitleControl extends TitleControl {
this.ifEditorIsActive(editor, () => this.redraw());
}
stickEditor(editor: IEditorInput): void {
// Sticky editors are not presented any different with tabs disabled
}
unstickEditor(editor: IEditorInput): void {
// Sticky editors are not presented any different with tabs disabled
}
setActive(isActive: boolean): void {
this.redraw();
}
@@ -219,7 +223,6 @@ export class NoTabsTitleControl extends TitleControl {
}
}
private ifEditorIsActive(editor: IEditorInput, fn: () => void): void {
if (this.group.isActive(editor)) {
fn(); // only run if editor is current active
@@ -27,7 +27,7 @@ import { getOrSet } from 'vs/base/common/map';
import { IThemeService, registerThemingParticipant, IColorTheme, ICssStyleCollector, HIGH_CONTRAST } 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_BACKGROUND, 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, WORKBENCH_BACKGROUND, TAB_ACTIVE_BORDER_TOP, TAB_UNFOCUSED_ACTIVE_BORDER_TOP, TAB_ACTIVE_MODIFIED_BORDER, TAB_INACTIVE_MODIFIED_BORDER, TAB_UNFOCUSED_ACTIVE_MODIFIED_BORDER, TAB_UNFOCUSED_INACTIVE_MODIFIED_BORDER, TAB_UNFOCUSED_INACTIVE_BACKGROUND, TAB_HOVER_FOREGROUND, TAB_UNFOCUSED_HOVER_FOREGROUND, EDITOR_GROUP_HEADER_TABS_BORDER } from 'vs/workbench/common/theme';
import { activeContrastBorder, contrastBorder, editorBackground, breadcrumbsBackground } from 'vs/platform/theme/common/colorRegistry';
import { ResourcesDropHandler, fillResourceDataTransfers, DraggedEditorIdentifier, DraggedEditorGroupIdentifier, DragAndDropObserver } from 'vs/workbench/browser/dnd';
import { ResourcesDropHandler, DraggedEditorIdentifier, DraggedEditorGroupIdentifier, DragAndDropObserver } from 'vs/workbench/browser/dnd';
import { Color } from 'vs/base/common/color';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
@@ -67,6 +67,11 @@ export class TabsTitleControl extends TitleControl {
large: 10
};
private static readonly TAB_SIZES = {
sticky: 38,
fit: 120
};
private titleContainer: HTMLElement | undefined;
private tabsAndActionsContainer: HTMLElement | undefined;
private tabsContainer: HTMLElement | undefined;
@@ -392,10 +397,6 @@ export class TabsTitleControl extends TitleControl {
this.handleClosedEditors();
}
closeAllEditors(): void {
this.handleClosedEditors();
}
private handleClosedEditors(): void {
// There are tabs to show
@@ -453,7 +454,24 @@ export class TabsTitleControl extends TitleControl {
}
pinEditor(editor: IEditorInput): void {
this.withTab(editor, (editor, index, tabContainer, tabLabelWidget, tabLabel) => this.redrawLabel(editor, tabContainer, tabLabelWidget, tabLabel));
this.withTab(editor, (editor, index, tabContainer, tabLabelWidget, tabLabel) => this.redrawLabel(editor, index, tabContainer, tabLabelWidget, tabLabel));
}
stickEditor(editor: IEditorInput): void {
this.doHandleStickyEditorChange(editor);
}
unstickEditor(editor: IEditorInput): void {
this.doHandleStickyEditorChange(editor);
}
private doHandleStickyEditorChange(editor: IEditorInput): void {
// Update tab
this.withTab(editor, (editor, index, tabContainer, tabLabelWidget, tabLabel) => this.redrawTab(editor, index, tabContainer, tabLabelWidget, tabLabel));
// A change to the sticky state requires a layout to keep the active editor visible
this.layout(this.dimension);
}
setActive(isGroupActive: boolean): void {
@@ -487,7 +505,7 @@ export class TabsTitleControl extends TitleControl {
// As such we need to redraw each label
this.forEachTab((editor, index, tabContainer, tabLabelWidget, tabLabel) => {
this.redrawLabel(editor, tabContainer, tabLabelWidget, tabLabel);
this.redrawLabel(editor, index, tabContainer, tabLabelWidget, tabLabel);
});
// A change to a label requires a layout to keep the active editor visible
@@ -745,10 +763,7 @@ export class TabsTitleControl extends TitleControl {
}
// Apply some datatransfer types to allow for dragging the element outside of the application
const resource = toResource(editor, { supportSideBySide: SideBySideEditor.MASTER });
if (resource) {
this.instantiationService.invokeFunction(fillResourceDataTransfers, [resource], e);
}
this.doFillResourceDataTransfers(editor, e);
// Fixes https://github.com/Microsoft/vscode/issues/18733
addClass(tab, 'dragged');
@@ -1010,7 +1025,7 @@ export class TabsTitleControl extends TitleControl {
private redrawTab(editor: IEditorInput, index: number, tabContainer: HTMLElement, tabLabelWidget: IResourceLabel, tabLabel: IEditorInputLabel): void {
// Label
this.redrawLabel(editor, tabContainer, tabLabelWidget, tabLabel);
this.redrawLabel(editor, index, tabContainer, tabLabelWidget, tabLabel);
// Borders / Outline
const borderRightColor = (this.getColor(TAB_BORDER) || this.getColor(contrastBorder));
@@ -1018,10 +1033,12 @@ export class TabsTitleControl extends TitleControl {
tabContainer.style.outlineColor = this.getColor(activeContrastBorder) || '';
// Settings
const isTabSticky = this.group.isSticky(index);
const options = this.accessor.partOptions;
const tabCloseButton = isTabSticky ? 'off' /* treat sticky tabs as tabCloseButton: 'off' */ : options.tabCloseButton;
['off', 'left', 'right'].forEach(option => {
const domAction = options.tabCloseButton === option ? addClass : removeClass;
const domAction = tabCloseButton === option ? addClass : removeClass;
domAction(tabContainer, `close-button-${option}`);
});
@@ -1036,13 +1053,37 @@ export class TabsTitleControl extends TitleControl {
removeClass(tabContainer, 'has-icon-theme');
}
// Sticky Tabs need a position to remain at their location
// when scrolling to stay in view (requirement for position: sticky)
if (isTabSticky) {
addClass(tabContainer, 'sticky');
tabContainer.style.left = `${index * TabsTitleControl.TAB_SIZES.sticky}px`;
} else {
removeClass(tabContainer, 'sticky');
tabContainer.style.left = 'auto';
}
// Active / dirty state
this.redrawEditorActiveAndDirty(this.accessor.activeGroup === this.group, editor, tabContainer, tabLabelWidget);
}
private redrawLabel(editor: IEditorInput, tabContainer: HTMLElement, tabLabelWidget: IResourceLabel, tabLabel: IEditorInputLabel): void {
const name = tabLabel.name;
const description = tabLabel.description || '';
private redrawLabel(editor: IEditorInput, index: number, tabContainer: HTMLElement, tabLabelWidget: IResourceLabel, tabLabel: IEditorInputLabel): void {
const isTabSticky = this.group.isSticky(index);
// Unless tabs are sticky, show the full label and description
// Sticky tabs will only show an icon if icons are enabled
// or their first character of the name otherwise
let name: string | undefined;
let description: string;
if (isTabSticky) {
const isShowingIcons = this.accessor.partOptions.showIcons && !!this.accessor.partOptions.iconTheme;
name = isShowingIcons ? '' : tabLabel.name?.charAt(0).toUpperCase();
description = '';
} else {
name = tabLabel.name;
description = tabLabel.description || '';
}
const title = tabLabel.title || '';
if (tabLabel.ariaLabel) {
@@ -1056,7 +1097,7 @@ export class TabsTitleControl extends TitleControl {
// Label
tabLabelWidget.setResource(
{ name, description, resource: toResource(editor, { supportSideBySide: SideBySideEditor.BOTH }) },
{ title, extraClasses: ['tab-label'], italic: !this.group.isPinned(editor) }
{ title, extraClasses: ['tab-label'], italic: !this.group.isPinned(editor), forceLabel: isTabSticky }
);
this.setEditorTabColor(editor, tabContainer, this.group.isActive(editor)); // {{SQL CARBON EDIT}} -- Display the editor's tab color
@@ -1173,8 +1214,8 @@ export class TabsTitleControl extends TitleControl {
layout(dimension: Dimension | undefined): void {
this.dimension = dimension;
const activeTab = this.group.activeEditor ? this.getTab(this.group.activeEditor) : undefined;
if (!activeTab || !this.dimension) {
const activeTabAndIndex = this.group.activeEditor ? this.getTabAndIndex(this.group.activeEditor) : undefined;
if (!activeTabAndIndex || !this.dimension) {
return;
}
@@ -1192,20 +1233,66 @@ export class TabsTitleControl extends TitleControl {
}
private doLayout(dimension: Dimension): void {
const activeTab = this.group.activeEditor ? this.getTab(this.group.activeEditor) : undefined;
if (!activeTab) {
return;
const activeTabAndIndex = this.group.activeEditor ? this.getTabAndIndex(this.group.activeEditor) : undefined;
if (!activeTabAndIndex) {
return; // nothing to do if not editor opened
}
const [tabsContainer, tabsScrollbar] = assertAllDefined(this.tabsContainer, this.tabsScrollbar);
// Breadcrumbs
this.doLayoutBreadcrumbs(dimension);
// Tabs
const [activeTab, activeIndex] = activeTabAndIndex;
this.doLayoutTabs(activeTab, activeIndex);
}
private doLayoutBreadcrumbs(dimension: Dimension): void {
if (this.breadcrumbsControl && !this.breadcrumbsControl.isHidden()) {
const tabsScrollbar = assertIsDefined(this.tabsScrollbar);
this.breadcrumbsControl.layout({ width: dimension.width, height: BreadcrumbsControl.HEIGHT });
tabsScrollbar.getDomNode().style.height = `${dimension.height - BreadcrumbsControl.HEIGHT}px`;
}
}
const visibleContainerWidth = tabsContainer.offsetWidth;
const totalContainerWidth = tabsContainer.scrollWidth;
private doLayoutTabs(activeTab: HTMLElement, activeIndex: number): void {
const [tabsContainer, tabsScrollbar] = assertAllDefined(this.tabsContainer, this.tabsScrollbar);
//
// Synopsis
// - allTabsWidth: sum of all tab widths
// - stickyTabsWidth: sum of all sticky tab widths
// - visibleContainerWidth: size of tab container
// - availableContainerWidth: size of tab container minus size of sticky tabs
//
// [------------------------------ All tabs width ---------------------------------------]
// [------------------- Visible container width -------------------]
// [------ Available container width ------]
// [ Sticky A ][ Sticky B ][ Tab C ][ Tab D ][ Tab E ][ Tab F ][ Tab G ][ Tab H ][ Tab I ]
// Active Tab Width [-------]
// [------- Active Tab Pos X -------]
// [-- Sticky Tabs Width --]
//
const visibleTabsContainerWidth = tabsContainer.offsetWidth;
const allTabsWidth = tabsContainer.scrollWidth;
let stickyTabsWidth = this.group.stickyCount * TabsTitleControl.TAB_SIZES.sticky;
let activeTabSticky = this.group.isSticky(activeIndex);
let availableTabsContainerWidth = visibleTabsContainerWidth - stickyTabsWidth;
// Special case: we have sticky tabs but the available space for showing tabs
// is little enough that we need to disable sticky tabs sticky positioning
// so that tabs can be scrolled at naturally.
if (this.group.stickyCount > 0 && availableTabsContainerWidth < TabsTitleControl.TAB_SIZES.fit) {
addClass(tabsContainer, 'disable-sticky-tabs');
availableTabsContainerWidth = visibleTabsContainerWidth;
stickyTabsWidth = 0;
activeTabSticky = false;
} else {
removeClass(tabsContainer, 'disable-sticky-tabs');
}
let activeTabPosX: number | undefined;
let activeTabWidth: number | undefined;
@@ -1217,42 +1304,78 @@ export class TabsTitleControl extends TitleControl {
// Update scrollbar
tabsScrollbar.setScrollDimensions({
width: visibleContainerWidth,
scrollWidth: totalContainerWidth
width: visibleTabsContainerWidth,
scrollWidth: allTabsWidth
});
// Return now if we are blocked to reveal the active tab and clear flag
if (this.blockRevealActiveTab || typeof activeTabPosX !== 'number' || typeof activeTabWidth !== 'number') {
// We also return if the active tab is sticky because this means it is
// always visible anyway.
if (this.blockRevealActiveTab || typeof activeTabPosX !== 'number' || typeof activeTabWidth !== 'number' || activeTabSticky) {
this.blockRevealActiveTab = false;
return;
}
// Reveal the active one
const containerScrollPosX = tabsScrollbar.getScrollPosition().scrollLeft;
const activeTabFits = activeTabWidth <= visibleContainerWidth;
const tabsContainerScrollPosX = tabsScrollbar.getScrollPosition().scrollLeft;
const activeTabFits = activeTabWidth <= availableTabsContainerWidth;
const adjustedActiveTabPosX = activeTabPosX - stickyTabsWidth;
//
// Synopsis
// - adjustedActiveTabPosX: the adjusted tabPosX takes the width of sticky tabs into account
// conceptually the scrolling only begins after sticky tabs so in order to reveal a tab fully
// the actual position needs to be adjusted for sticky tabs.
//
// Tab is overflowing to the right: Scroll minimally until the element is fully visible to the right
// Note: only try to do this if we actually have enough width to give to show the tab fully!
if (activeTabFits && containerScrollPosX + visibleContainerWidth < activeTabPosX + activeTabWidth) {
//
// Example: Tab G should be made active and needs to be fully revealed as such.
//
// [-------------------------------- All tabs width -----------------------------------------]
// [-------------------- Visible container width --------------------]
// [----- Available container width -------]
// [ Sticky A ][ Sticky B ][ Tab C ][ Tab D ][ Tab E ][ Tab F ][ Tab G ][ Tab H ][ Tab I ]
// Active Tab Width [-------]
// [------- Active Tab Pos X -------]
// [-------- Adjusted Tab Pos X -------]
// [-- Sticky Tabs Width --]
//
//
if (activeTabFits && tabsContainerScrollPosX + availableTabsContainerWidth < adjustedActiveTabPosX + activeTabWidth) {
tabsScrollbar.setScrollPosition({
scrollLeft: containerScrollPosX + ((activeTabPosX + activeTabWidth) /* right corner of tab */ - (containerScrollPosX + visibleContainerWidth) /* right corner of view port */)
scrollLeft: tabsContainerScrollPosX + ((adjustedActiveTabPosX + activeTabWidth) /* right corner of tab */ - (tabsContainerScrollPosX + availableTabsContainerWidth) /* right corner of view port */)
});
}
// Tab is overlflowng to the left or does not fit: Scroll it into view to the left
else if (containerScrollPosX > activeTabPosX || !activeTabFits) {
//
// Tab is overlflowing to the left or does not fit: Scroll it into view to the left
//
// Example: Tab C should be made active and needs to be fully revealed as such.
//
// [----------------------------- All tabs width ----------------------------------------]
// [------------------ Visible container width ------------------]
// [----- Available container width -------]
// [ Sticky A ][ Sticky B ][ Tab C ][ Tab D ][ Tab E ][ Tab F ][ Tab G ][ Tab H ][ Tab I ]
// Active Tab Width [-------]
// [------- Active Tab Pos X -------]
// Adjusted Tab Pos X []
// [-- Sticky Tabs Width --]
//
//
else if (tabsContainerScrollPosX > adjustedActiveTabPosX || !activeTabFits) {
tabsScrollbar.setScrollPosition({
scrollLeft: activeTabPosX
scrollLeft: adjustedActiveTabPosX
});
}
}
private getTab(editor: IEditorInput): HTMLElement | undefined {
private getTabAndIndex(editor: IEditorInput): [HTMLElement, number /* index */] | undefined {
const editorIndex = this.group.getIndexOfEditor(editor);
if (editorIndex >= 0) {
const tabsContainer = assertIsDefined(this.tabsContainer);
return tabsContainer.children[editorIndex] as HTMLElement;
return [tabsContainer.children[editorIndex] as HTMLElement, editorIndex];
}
return undefined;
@@ -1494,11 +1617,11 @@ registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) =
// Adjust gradient for focused and unfocused hover background
const makeTabHoverBackgroundRule = (color: Color, colorDrag: Color, hasFocus = false) => `
.monaco-workbench .part.editor > .content:not(.dragged-over) .editor-group-container${hasFocus ? '.active' : ''} > .title .tabs-container > .tab.sizing-shrink:not(.dragged):hover > .tab-label::after {
.monaco-workbench .part.editor > .content:not(.dragged-over) .editor-group-container${hasFocus ? '.active' : ''} > .title .tabs-container > .tab.sizing-shrink:not(.dragged):not(.sticky):hover > .tab-label::after {
background: linear-gradient(to left, ${color}, transparent) !important;
}
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container${hasFocus ? '.active' : ''} > .title .tabs-container > .tab.sizing-shrink:not(.dragged):hover > .tab-label::after {
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container${hasFocus ? '.active' : ''} > .title .tabs-container > .tab.sizing-shrink:not(.dragged):not(.sticky):hover > .tab-label::after {
background: linear-gradient(to left, ${colorDrag}, transparent) !important;
}
`;
@@ -1521,19 +1644,19 @@ registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) =
if (editorDragAndDropBackground && adjustedTabDragBackground) {
const adjustedColorDrag = editorDragAndDropBackground.flatten(adjustedTabDragBackground);
collector.addRule(`
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container.active > .title .tabs-container > .tab.sizing-shrink.dragged-over:not(.active):not(.dragged) > .tab-label::after,
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container:not(.active) > .title .tabs-container > .tab.sizing-shrink.dragged-over:not(.dragged) > .tab-label::after {
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container.active > .title .tabs-container > .tab.sizing-shrink.dragged-over:not(.active):not(.dragged):not(.sticky) > .tab-label::after,
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container:not(.active) > .title .tabs-container > .tab.sizing-shrink.dragged-over:not(.dragged):not(.sticky) > .tab-label::after {
background: linear-gradient(to left, ${adjustedColorDrag}, transparent) !important;
}
`);
}
const makeTabBackgroundRule = (color: Color, colorDrag: Color, focused: boolean, active: boolean) => `
.monaco-workbench .part.editor > .content:not(.dragged-over) .editor-group-container${focused ? '.active' : ':not(.active)'} > .title .tabs-container > .tab.sizing-shrink${active ? '.active' : ''}:not(.dragged) > .tab-label::after {
.monaco-workbench .part.editor > .content:not(.dragged-over) .editor-group-container${focused ? '.active' : ':not(.active)'} > .title .tabs-container > .tab.sizing-shrink${active ? '.active' : ''}:not(.dragged):not(.sticky) > .tab-label::after {
background: linear-gradient(to left, ${color}, transparent);
}
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container${focused ? '.active' : ':not(.active)'} > .title .tabs-container > .tab.sizing-shrink${active ? '.active' : ''}:not(.dragged) > .tab-label::after {
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container${focused ? '.active' : ':not(.active)'} > .title .tabs-container > .tab.sizing-shrink${active ? '.active' : ''}:not(.dragged):not(.sticky) > .tab-label::after {
background: linear-gradient(to left, ${colorDrag}, transparent);
}
`;
@@ -181,7 +181,12 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditorPan
// because we are triggering another openEditor() call
// and do not control the initial intent that resulted
// in us now opening as binary.
const preservingOptions: IEditorOptions = { activation: EditorActivation.PRESERVE, pinned: this.group?.isPinned(input) };
const preservingOptions: IEditorOptions = {
activation: EditorActivation.PRESERVE,
pinned: this.group?.isPinned(input),
sticky: this.group?.isSticky(input)
};
if (options) {
options.overwrite(preservingOptions);
} else {
@@ -237,7 +242,7 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditorPan
if (isArray(error)) {
const errors = <Error[]>error;
return errors.some(e => this.isFileBinaryError(e));
return errors.some(error => this.isFileBinaryError(error));
}
return (<TextFileOperationError>error).textFileOperationResult === TextFileOperationResult.FILE_IS_BINARY;
@@ -3,6 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./media/titlecontrol';
import { applyDragImage, DataTransfers } from 'vs/base/browser/dnd';
import { addDisposableListener, Dimension, EventType } from 'vs/base/browser/dom';
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
@@ -12,8 +13,7 @@ import { IAction, IRunEvent, WorkbenchActionExecutedEvent, WorkbenchActionExecut
import * as arrays from 'vs/base/common/arrays';
import { ResolvedKeybinding } from 'vs/base/common/keyCodes';
import { dispose, DisposableStore } from 'vs/base/common/lifecycle';
import 'vs/css!./media/titlecontrol';
import { getCodeEditor } from 'vs/editor/browser/editorBrowser';
import { getCodeEditor, isCodeEditor } from 'vs/editor/browser/editorBrowser';
import { localize } from 'vs/nls';
import { createActionViewItem, createAndFillInActionBarActions, createAndFillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
import { ExecuteCommandAction, IMenu, IMenuService, MenuId } from 'vs/platform/actions/common/actions';
@@ -32,13 +32,14 @@ import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
import { BreadcrumbsConfig } from 'vs/workbench/browser/parts/editor/breadcrumbs';
import { BreadcrumbsControl, IBreadcrumbsControlOptions } from 'vs/workbench/browser/parts/editor/breadcrumbsControl';
import { EDITOR_TITLE_HEIGHT, IEditorGroupsAccessor, IEditorGroupView } from 'vs/workbench/browser/parts/editor/editor';
import { EditorCommandsContextActionRunner, IEditorCommandsContext, IEditorInput, toResource, IEditorPartOptions, SideBySideEditor, EditorPinnedContext } from 'vs/workbench/common/editor';
import { EditorCommandsContextActionRunner, IEditorCommandsContext, IEditorInput, toResource, IEditorPartOptions, SideBySideEditor, EditorPinnedContext, EditorStickyContext } from 'vs/workbench/common/editor';
import { ResourceContextKey } from 'vs/workbench/common/resources';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
import { IFileService } from 'vs/platform/files/common/files';
import { withNullAsUndefined, withUndefinedAsNull, assertIsDefined } from 'vs/base/common/types';
import { isFirefox } from 'vs/base/browser/browser';
import { ITextEditorOptions } from 'vs/platform/editor/common/editor';
export interface IToolbarActions {
primary: IAction[];
@@ -59,6 +60,7 @@ export abstract class TitleControl extends Themable {
private resourceContext: ResourceContextKey;
private editorPinnedContext: IContextKey<boolean>;
private editorStickyContext: IContextKey<boolean>;
private readonly editorToolBarMenuDisposables = this._register(new DisposableStore());
@@ -86,6 +88,7 @@ export abstract class TitleControl extends Themable {
this.resourceContext = this._register(instantiationService.createInstance(ResourceContextKey));
this.editorPinnedContext = EditorPinnedContext.bindTo(contextKeyService);
this.editorStickyContext = EditorStickyContext.bindTo(contextKeyService);
this.contextMenu = this._register(this.menuService.createMenu(MenuId.EditorTitleContext, this.contextKeyService));
@@ -222,6 +225,7 @@ export abstract class TitleControl extends Themable {
// Update contexts
this.resourceContext.set(this.group.activeEditor ? withUndefinedAsNull(toResource(this.group.activeEditor, { supportSideBySide: SideBySideEditor.MASTER })) : null);
this.editorPinnedContext.set(this.group.activeEditor ? this.group.isPinned(this.group.activeEditor) : false);
this.editorStickyContext.set(this.group.activeEditor ? this.group.isSticky(this.group.activeEditor) : false);
// Editor actions require the editor control to be there, so we retrieve it via service
const activeEditorPane = this.group.activeEditorPane;
@@ -266,10 +270,8 @@ export abstract class TitleControl extends Themable {
// If tabs are disabled, treat dragging as if an editor tab was dragged
let hasDataTransfer = false;
if (!this.accessor.partOptions.showTabs) {
const resource = this.group.activeEditor ? toResource(this.group.activeEditor, { supportSideBySide: SideBySideEditor.MASTER }) : null;
if (resource) {
this.instantiationService.invokeFunction(fillResourceDataTransfers, [resource], e);
hasDataTransfer = true;
if (this.group.activeEditor) {
hasDataTransfer = this.doFillResourceDataTransfers(this.group.activeEditor, e);
}
}
@@ -295,6 +297,31 @@ export abstract class TitleControl extends Themable {
}));
}
protected doFillResourceDataTransfers(editor: IEditorInput, e: DragEvent): boolean {
const resource = toResource(editor, { supportSideBySide: SideBySideEditor.MASTER });
if (!resource) {
return false;
}
const editorOptions: ITextEditorOptions = {
viewState: (() => {
if (this.group.activeEditor === editor) {
const activeControl = this.group.activeEditorPane?.getControl();
if (isCodeEditor(activeControl)) {
return withNullAsUndefined(activeControl.saveViewState());
}
}
return undefined;
})(),
sticky: this.group.isSticky(editor)
};
this.instantiationService.invokeFunction(fillResourceDataTransfers, [resource], () => editorOptions, e);
return true;
}
protected onContextMenu(editor: IEditorInput, e: Event, node: HTMLElement): void {
// Update contexts based on editor picked and remember previous to restore
@@ -302,6 +329,8 @@ export abstract class TitleControl extends Themable {
this.resourceContext.set(withUndefinedAsNull(toResource(editor, { supportSideBySide: SideBySideEditor.MASTER })));
const currentPinnedContext = !!this.editorPinnedContext.get();
this.editorPinnedContext.set(this.group.isPinned(editor));
const currentStickyContext = !!this.editorStickyContext.get();
this.editorStickyContext.set(this.group.isSticky(editor));
// Find target anchor
let anchor: HTMLElement | { x: number, y: number } = node;
@@ -325,6 +354,7 @@ export abstract class TitleControl extends Themable {
// restore previous contexts
this.resourceContext.set(currentResourceContext || null);
this.editorPinnedContext.set(currentPinnedContext);
this.editorStickyContext.set(currentStickyContext);
// restore focus to active group
this.accessor.activeGroup.focus();
@@ -351,12 +381,14 @@ export abstract class TitleControl extends Themable {
abstract closeEditors(editors: IEditorInput[]): void;
abstract closeAllEditors(): void;
abstract moveEditor(editor: IEditorInput, fromIndex: number, targetIndex: number): void;
abstract pinEditor(editor: IEditorInput): void;
abstract stickEditor(editor: IEditorInput): void;
abstract unstickEditor(editor: IEditorInput): void;
abstract setActive(isActive: boolean): void;
abstract updateEditorLabel(editor: IEditorInput): void;
@@ -207,7 +207,8 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
}
if (isActive) {
if (!activePanel) {
// Only try to open the panel if it has been created and visible
if (!activePanel && this.element && this.layoutService.isVisible(Parts.PANEL_PART)) {
this.doOpenPanel(panel.id);
}
@@ -22,7 +22,7 @@ import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/
import { contrastBorder } from 'vs/platform/theme/common/colorRegistry';
import { isThemeColor } from 'vs/editor/common/editorCommon';
import { Color } from 'vs/base/common/color';
import { addClass, EventHelper, createStyleSheet, addDisposableListener, addClasses, removeClass, EventType, hide, show, removeClasses } from 'vs/base/browser/dom';
import { addClass, EventHelper, createStyleSheet, addDisposableListener, addClasses, removeClass, EventType, hide, show, removeClasses, isAncestor } from 'vs/base/browser/dom';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { IStorageService, StorageScope, IWorkspaceStorageChangeEvent } from 'vs/platform/storage/common/storage';
import { Parts, IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
@@ -35,6 +35,11 @@ import { assertIsDefined } from 'vs/base/common/types';
import { Emitter } from 'vs/base/common/event';
import { Command } from 'vs/editor/common/modes';
import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { KeyCode } from 'vs/base/common/keyCodes';
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { ServicesAccessor } from 'vs/editor/browser/editorExtensions';
import { RawContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
interface IPendingStatusbarEntry {
id: string;
@@ -51,8 +56,11 @@ interface IStatusbarViewModelEntry {
alignment: StatusbarAlignment;
priority: number;
container: HTMLElement;
labelContainer: HTMLElement;
}
const CONTEXT_STATUS_BAR_FOCUSED = new RawContextKey<boolean>('statusBarFocused', false);
class StatusbarViewModel extends Disposable {
static readonly HIDDEN_ENTRIES_KEY = 'workbench.statusbar.hidden';
@@ -188,6 +196,40 @@ class StatusbarViewModel extends Disposable {
return this._entries.filter(entry => entry.alignment === alignment);
}
focusNextEntry(): void {
this.focusEntry(+1, 0);
}
focusPreviousEntry(): void {
this.focusEntry(-1, this.entries.length - 1);
}
private focusEntry(delta: number, restartPosition: number): void {
const getVisibleEntry = (start: number) => {
let indexToFocus = start;
let entry = (indexToFocus >= 0 && indexToFocus < this._entries.length) ? this._entries[indexToFocus] : undefined;
while (entry && this.isHidden(entry.id)) {
indexToFocus += delta;
entry = (indexToFocus >= 0 && indexToFocus < this._entries.length) ? this._entries[indexToFocus] : undefined;
}
return entry;
};
const focused = this._entries.find(entry => isAncestor(document.activeElement, entry.container));
if (focused) {
const entry = getVisibleEntry(this._entries.indexOf(focused) + delta);
if (entry) {
entry.labelContainer.focus();
return;
}
}
const entry = getVisibleEntry(restartPosition);
if (entry) {
entry.labelContainer.focus();
}
}
private updateVisibility(id: string, trigger: boolean): void;
private updateVisibility(entry: IStatusbarViewModelEntry, trigger: boolean): void;
private updateVisibility(arg1: string | IStatusbarViewModelEntry, trigger: boolean): void {
@@ -355,6 +397,7 @@ export class StatusbarPart extends Part implements IStatusbarService {
@IStorageService private readonly storageService: IStorageService,
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
@IContextMenuService private contextMenuService: IContextMenuService,
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService,
) {
super(Parts.STATUSBAR_PART, { hasTitle: false }, themeService, storageService, layoutService);
@@ -415,7 +458,7 @@ export class StatusbarPart extends Part implements IStatusbarService {
this.appendOneStatusbarEntry(itemContainer, alignment, priority);
// Add to view model
const viewModelEntry: IStatusbarViewModelEntry = { id, name, alignment, priority, container: itemContainer };
const viewModelEntry: IStatusbarViewModelEntry = { id, name, alignment, priority, container: itemContainer, labelContainer: item.labelContainer };
const viewModelEntryDispose = this.viewModel.add(viewModelEntry);
return {
@@ -442,9 +485,21 @@ export class StatusbarPart extends Part implements IStatusbarService {
}
}
focusNextEntry(): void {
this.viewModel.focusNextEntry();
}
focusPreviousEntry(): void {
this.viewModel.focusPreviousEntry();
}
createContentArea(parent: HTMLElement): HTMLElement {
this.element = parent;
// Track focus within container
const scopedContextKeyService = this.contextKeyService.createScoped(this.element);
CONTEXT_STATUS_BAR_FOCUSED.bindTo(scopedContextKeyService).set(true);
// Left items container
this.leftItemsContainer = document.createElement('div');
addClasses(this.leftItemsContainer, 'left-items', 'items-container');
@@ -645,13 +700,14 @@ class StatusbarEntryItem extends Disposable {
private entry!: IStatusbarEntry;
private labelContainer!: HTMLElement;
labelContainer!: HTMLElement;
private label!: CodiconLabel;
private readonly foregroundListener = this._register(new MutableDisposable());
private readonly backgroundListener = this._register(new MutableDisposable());
private readonly commandListener = this._register(new MutableDisposable());
private readonly commandMouseListener = this._register(new MutableDisposable());
private readonly commandKeyboardListener = this._register(new MutableDisposable());
constructor(
private container: HTMLElement,
@@ -711,11 +767,18 @@ class StatusbarEntryItem extends Disposable {
// Update: Command
if (!this.entry || entry.command !== this.entry.command) {
this.commandListener.clear();
this.commandMouseListener.clear();
this.commandKeyboardListener.clear();
const command = entry.command;
if (command) {
this.commandListener.value = addDisposableListener(this.labelContainer, EventType.CLICK, () => this.executeCommand(command));
this.commandMouseListener.value = addDisposableListener(this.labelContainer, EventType.CLICK, () => this.executeCommand(command));
this.commandKeyboardListener.value = addDisposableListener(this.labelContainer, EventType.KEY_UP, e => {
const event = new StandardKeyboardEvent(e);
if (event.equals(KeyCode.Space) || event.equals(KeyCode.Enter)) {
this.executeCommand(command);
}
});
removeClass(this.labelContainer, 'disabled');
} else {
@@ -814,7 +877,8 @@ class StatusbarEntryItem extends Disposable {
dispose(this.foregroundListener);
dispose(this.backgroundListener);
dispose(this.commandListener);
dispose(this.commandMouseListener);
dispose(this.commandKeyboardListener);
}
}
@@ -822,6 +886,7 @@ registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) =
const statusBarItemHoverBackground = theme.getColor(STATUS_BAR_ITEM_HOVER_BACKGROUND);
if (statusBarItemHoverBackground) {
collector.addRule(`.monaco-workbench .part.statusbar > .items-container > .statusbar-item a:hover { background-color: ${statusBarItemHoverBackground}; }`);
collector.addRule(`.monaco-workbench .part.statusbar > .items-container > .statusbar-item a:focus { background-color: ${statusBarItemHoverBackground}; }`);
}
const statusBarItemActiveBackground = theme.getColor(STATUS_BAR_ITEM_ACTIVE_BACKGROUND);
@@ -846,3 +911,27 @@ registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) =
});
registerSingleton(IStatusbarService, StatusbarPart);
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'workbench.statusBar.focusPrevious',
weight: KeybindingWeight.WorkbenchContrib,
primary: KeyCode.LeftArrow,
secondary: [KeyCode.UpArrow],
when: CONTEXT_STATUS_BAR_FOCUSED,
handler: (accessor: ServicesAccessor) => {
const statusBarService = accessor.get(IStatusbarService);
statusBarService.focusPreviousEntry();
}
});
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: 'workbench.statusBar.focusNext',
weight: KeybindingWeight.WorkbenchContrib,
primary: KeyCode.RightArrow,
secondary: [KeyCode.DownArrow],
when: CONTEXT_STATUS_BAR_FOCUSED,
handler: (accessor: ServicesAccessor) => {
const statusBarService = accessor.get(IStatusbarService);
statusBarService.focusNextEntry();
}
});
@@ -934,17 +934,21 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
getContextMenuActions(viewDescriptor?: IViewDescriptor): IAction[] {
const result: IAction[] = [];
let showHide = true;
if (!viewDescriptor && this.isViewMergedWithContainer()) {
viewDescriptor = this.viewDescriptorService.getViewDescriptorById(this.panes[0].id) || undefined;
showHide = false;
}
if (viewDescriptor) {
if (showHide) {
result.push(<IAction>{
id: `${viewDescriptor.id}.removeView`,
label: nls.localize('hideView', "Hide"),
enabled: viewDescriptor.canToggleVisibility,
run: () => this.toggleViewVisibility(viewDescriptor!.id)
});
}
const view = this.getView(viewDescriptor.id);
if (view) {
result.push(...view.getContextMenuActions());
@@ -955,7 +959,7 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
id: `${viewDescriptor.id}.toggleVisibility`,
label: viewDescriptor.name,
checked: this.viewContainerModel.isVisible(viewDescriptor.id),
enabled: viewDescriptor.canToggleVisibility,
enabled: viewDescriptor.canToggleVisibility && (!this.viewContainerModel.isVisible(viewDescriptor.id) || this.viewContainerModel.visibleViewDescriptors.length > 1),
run: () => this.toggleViewVisibility(viewDescriptor.id)
}));
@@ -127,15 +127,10 @@ export class ViewsService extends Disposable implements IViewsService {
this.deregisterViewletOrPanel(container, location);
}
for (const { container, location } of added) {
this.registerViewletOrPanel(container, location);
this.onDidRegisterViewContainer(container, location);
}
}
private onDidChangeContainerLocation(viewContainer: ViewContainer, from: ViewContainerLocation, to: ViewContainerLocation): void {
this.deregisterViewletOrPanel(viewContainer, from);
this.registerViewletOrPanel(viewContainer, to);
}
private onDidRegisterViewContainer(viewContainer: ViewContainer, viewContainerLocation: ViewContainerLocation): void {
this.registerViewletOrPanel(viewContainer, viewContainerLocation);
const viewContainerModel = this.viewDescriptorService.getViewContainerModel(viewContainer);
@@ -146,6 +141,11 @@ export class ViewsService extends Disposable implements IViewsService {
}));
}
private onDidChangeContainerLocation(viewContainer: ViewContainer, from: ViewContainerLocation, to: ViewContainerLocation): void {
this.deregisterViewletOrPanel(viewContainer, from);
this.registerViewletOrPanel(viewContainer, to);
}
private onViewDescriptorsAdded(views: ReadonlyArray<IViewDescriptor>, container: ViewContainer): void {
const location = this.viewDescriptorService.getViewContainerLocation(container);
if (location === null) {
+2 -2
View File
@@ -71,7 +71,7 @@ class BrowserMain extends Disposable {
services.storageService.store(Settings.WORKSPACE_FIRST_OPEN, !(firstOpen ?? false), StorageScope.WORKSPACE);
}
{ await domContentLoaded(); }
await domContentLoaded();
mark('willStartWorkbench');
// Base Theme
@@ -272,7 +272,7 @@ class BrowserMain extends Disposable {
if (!this.configuration.userDataProvider) {
const remoteUserDataUri = this.getRemoteUserDataUri();
if (remoteUserDataUri) {
this.configuration.userDataProvider = this._register(new FileUserDataProvider(remoteUserDataUri, joinPath(remoteUserDataUri, BACKUPS), remoteFileSystemProvider, environmentService));
this.configuration.userDataProvider = this._register(new FileUserDataProvider(remoteUserDataUri, joinPath(remoteUserDataUri, BACKUPS), remoteFileSystemProvider, environmentService, logService));
}
}
}
@@ -108,12 +108,12 @@ import { workbenchConfigurationNodeBase } from 'vs/workbench/common/configuratio
},
'workbench.editor.enablePreview': {
'type': 'boolean',
'description': nls.localize('enablePreview', "Controls whether opened editors show as preview. Preview editors are reused until they are pinned (e.g. via double click or editing) and show up with an italic font style."),
'description': nls.localize('enablePreview', "Controls whether opened editors show as preview. Preview editors are reused until they are explicitly set to be kept open (e.g. via double click or editing) and show up with an italic font style."),
'default': true
},
'workbench.editor.enablePreviewFromQuickOpen': {
'type': 'boolean',
'description': nls.localize('enablePreviewFromQuickOpen', "Controls whether editors opened from Quick Open show as preview. Preview editors are reused until they are pinned (e.g. via double click or editing)."),
'description': nls.localize('enablePreviewFromQuickOpen', "Controls whether editors opened from Quick Open show as preview. Preview editors are reused until they are explicitly set to be kept open (e.g. via double click or editing)."),
'default': true
},
'workbench.editor.closeOnFileDelete': {

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