Archived
Merge from vscode 7653d836944892f83ce9e1f95c1204bafa1aec31
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/microsoft/vscode-github-triage-actions/master/classifier/apply/apply-labels/classifier-config.schema.json",
|
||||
"assignees": {
|
||||
"JacksonKearl": {
|
||||
"assign": true
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
"search-editor": {
|
||||
"applyLabel": true,
|
||||
"assign": [
|
||||
"JacksonKearl"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
{
|
||||
perform: true,
|
||||
alwaysRequireAssignee: false,
|
||||
labelsRequiringAssignee: [],
|
||||
defaultLabel: 'Triage: Needed',
|
||||
defaultAssignee: '',
|
||||
autoAssignees: {
|
||||
Area - Acquisition: [],
|
||||
Area - Azure: [],
|
||||
Area - Backup\Restore: [],
|
||||
Area - Charting\Insights: [],
|
||||
Area - Connection: [ charles-gagnon ],
|
||||
Area - DacFX: [],
|
||||
Area - Dashboard: [],
|
||||
Area - Data Explorer: [],
|
||||
Area - Edit Data: [],
|
||||
Area - Extensibility: [],
|
||||
Area - External Table: [],
|
||||
Area - Fundamentals: [],
|
||||
Area - Language Service: [ charles-gagnon ],
|
||||
Area - Localization: [],
|
||||
Area - Notebooks: [ chlafreniere ],
|
||||
Area - Performance: [],
|
||||
Area - Query Editor: [ anthonydresser ],
|
||||
Area - Query Plan: [],
|
||||
Area - Reliability: [],
|
||||
Area - Resource Deployment: [],
|
||||
Area - Schema Compare: [],
|
||||
Area - Shell: [],
|
||||
Area - SQL Agent: [],
|
||||
Area - SQL Import: [],
|
||||
Area - SQL Profiler: [],
|
||||
Area - SQL 2019: [],
|
||||
Area - SSMS Integration: []
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
name: "Classifier: Apply"
|
||||
on:
|
||||
schedule:
|
||||
- cron: 0,30 * * * *
|
||||
|
||||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Actions
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: 'microsoft/vscode-github-triage-actions'
|
||||
ref: v15
|
||||
path: ./actions
|
||||
- name: Install Actions
|
||||
run: npm install --production --prefix ./actions
|
||||
- name: Install Additional Dependencies
|
||||
# Pulls in a bunch of other packages that arent needed for the rest of the actions
|
||||
run: npm install @azure/storage-blob@12
|
||||
- name: "Run Classifier: Scraper"
|
||||
uses: ./actions/classifier/apply/fetch-issues
|
||||
with:
|
||||
# slightly overlapping to protect against issues slipping through the cracks if a run is delayed
|
||||
from: 45
|
||||
until: 5
|
||||
blobContainerName: classifier-models
|
||||
blobStorageKey: ${{secrets.AZURE_BLOB_STORAGE_CONNECTION_STRING}}
|
||||
- name: Set up Python 3.7
|
||||
uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: 3.7
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install --upgrade numpy scipy scikit-learn joblib nltk
|
||||
- name: "Run Classifier: Generator"
|
||||
run: python ./actions/classifier/apply/generate-labels/main.py
|
||||
- name: "Run Classifier: Labeler"
|
||||
uses: ./actions/classifier/apply/apply-labels
|
||||
with:
|
||||
config-path: classifier
|
||||
token: ${{secrets.VSCODE_ISSUE_TRIAGE_BOT_PAT}}
|
||||
Vendored
+19
@@ -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'
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -795,8 +796,8 @@ function getRealNodeSymbol(checker: ts.TypeChecker, node: ts.Node): [ts.Symbol |
|
||||
|
||||
let symbol = (
|
||||
ts.isShorthandPropertyAssignment(node)
|
||||
? checker.getShorthandAssignmentValueSymbol(node)
|
||||
: checker.getSymbolAtLocation(node)
|
||||
? checker.getShorthandAssignmentValueSymbol(node)
|
||||
: checker.getSymbolAtLocation(node)
|
||||
);
|
||||
|
||||
let importNode: ts.Declaration | null = null;
|
||||
|
||||
@@ -409,6 +409,11 @@
|
||||
"command": "git.timeline.copyCommitMessage",
|
||||
"title": "%command.timelineCopyCommitMessage%",
|
||||
"category": "Git"
|
||||
},
|
||||
{
|
||||
"command": "git.rebaseAbort",
|
||||
"title": "%command.rebaseAbort%",
|
||||
"category": "Git"
|
||||
}
|
||||
],
|
||||
"keybindings": [
|
||||
|
||||
@@ -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...",
|
||||
|
||||
@@ -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[]) => {
|
||||
|
||||
@@ -1333,6 +1333,10 @@ export class Repository {
|
||||
}
|
||||
}
|
||||
|
||||
async rebaseAbort(): Promise<void> {
|
||||
await this.run(['rebase', '--abort']);
|
||||
}
|
||||
|
||||
async rebaseContinue(): Promise<void> {
|
||||
const args = ['rebase', '--continue'];
|
||||
|
||||
|
||||
@@ -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') {
|
||||
return workspace.openTextDocument(uri).then(doc => {
|
||||
schemaDocuments[uri.toString()] = true;
|
||||
return doc.getText();
|
||||
}, error => {
|
||||
return Promise.reject(error);
|
||||
});
|
||||
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,16 +303,61 @@ 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)}`);
|
||||
});
|
||||
|
||||
function updateFormatterRegistration() {
|
||||
const formatEnabled = workspace.getConfiguration().get(SettingIds.enableFormatter);
|
||||
if (!formatEnabled && rangeFormatting) {
|
||||
rangeFormatting.dispose();
|
||||
rangeFormatting = undefined;
|
||||
} else if (formatEnabled && !rangeFormatting) {
|
||||
rangeFormatting = languages.registerDocumentRangeFormattingEditProvider(documentSelector, {
|
||||
provideDocumentRangeFormattingEdits(document: TextDocument, range: Range, options: FormattingOptions, token: CancellationToken): ProviderResult<TextEdit[]> {
|
||||
const params: DocumentRangeFormattingParams = {
|
||||
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document),
|
||||
range: client.code2ProtocolConverter.asRange(range),
|
||||
options: client.code2ProtocolConverter.asFormattingOptions(options)
|
||||
};
|
||||
return client.sendRequest(DocumentRangeFormattingRequest.type, params, token).then(
|
||||
client.protocol2CodeConverter.asTextEdits,
|
||||
(error) => {
|
||||
client.logFailedRequest(DocumentRangeFormattingRequest.type, error);
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
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 = {
|
||||
@@ -316,30 +370,6 @@ export function activate(context: ExtensionContext) {
|
||||
languages.setLanguageConfiguration('json', languageConfiguration);
|
||||
languages.setLanguageConfiguration('jsonc', languageConfiguration);
|
||||
|
||||
function updateFormatterRegistration() {
|
||||
const formatEnabled = workspace.getConfiguration().get('json.format.enable');
|
||||
if (!formatEnabled && rangeFormatting) {
|
||||
rangeFormatting.dispose();
|
||||
rangeFormatting = undefined;
|
||||
} else if (formatEnabled && !rangeFormatting) {
|
||||
rangeFormatting = languages.registerDocumentRangeFormattingEditProvider(documentSelector, {
|
||||
provideDocumentRangeFormattingEdits(document: TextDocument, range: Range, options: FormattingOptions, token: CancellationToken): ProviderResult<TextEdit[]> {
|
||||
const params: DocumentRangeFormattingParams = {
|
||||
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document),
|
||||
range: client.code2ProtocolConverter.asRange(range),
|
||||
options: client.code2ProtocolConverter.asFormattingOptions(options)
|
||||
};
|
||||
return client.sendRequest(DocumentRangeFormattingRequest.type, params, token).then(
|
||||
client.protocol2CodeConverter.asTextEdits,
|
||||
(error) => {
|
||||
client.logFailedRequest(DocumentRangeFormattingRequest.type, error);
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,7 +95,13 @@
|
||||
"type": "number",
|
||||
"default": 5000,
|
||||
"description": "%json.maxItemsComputed.desc%"
|
||||
}
|
||||
},
|
||||
"json.schemaDownload.enable": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "%json.enableSchemaDownload.desc%",
|
||||
"tags": ["usesOnlineServices"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"configurationDefaults": {
|
||||
|
||||
@@ -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,8 +10,8 @@ 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
|
||||
let nonBuiltInLanguages = { // { fileNames, extensions }
|
||||
// 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'] },
|
||||
"elm": { extensions: ['elm'] },
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
@@ -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
@@ -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",
|
||||
|
||||
@@ -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
@@ -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
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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,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
@@ -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'
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -14,4 +14,9 @@
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
|
||||
.monaco-count-badge.long {
|
||||
padding: 2px 3px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -63,6 +63,7 @@ export interface IJSONSchema {
|
||||
markdownEnumDescriptions?: string[];
|
||||
markdownDescription?: string;
|
||||
doNotSuggest?: boolean;
|
||||
suggestSortText?: string;
|
||||
allowComments?: boolean;
|
||||
allowTrailingCommas?: boolean;
|
||||
}
|
||||
|
||||
+29
-34
@@ -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,13 +701,34 @@ 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;
|
||||
},
|
||||
next(): IteratorResult<K> {
|
||||
next():IteratorResult<K> {
|
||||
if (current) {
|
||||
const result = { value: current.key, done: false };
|
||||
current = current.next;
|
||||
@@ -724,12 +742,12 @@ 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;
|
||||
},
|
||||
next(): IteratorResult<V> {
|
||||
next():IteratorResult<V> {
|
||||
if (current) {
|
||||
const result = { value: current.value, done: false };
|
||||
current = current.next;
|
||||
@@ -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']);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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,
|
||||
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 {
|
||||
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);
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
const minimapLayout = EditorLayoutInfoComputer._computeMinimapLayout({
|
||||
outerWidth: outerWidth,
|
||||
outerHeight: outerHeight,
|
||||
lineHeight: lineHeight,
|
||||
typicalHalfwidthCharacterWidth: typicalHalfwidthCharacterWidth,
|
||||
pixelRatio: pixelRatio,
|
||||
scrollBeyondLastLine: scrollBeyondLastLine,
|
||||
minimap: minimap,
|
||||
verticalScrollbarWidth: verticalScrollbarWidth,
|
||||
viewLineCount: viewLineCount,
|
||||
remainingWidth: remainingWidth,
|
||||
isViewportWrapping: isViewportWrapping,
|
||||
}, env.memory || new ComputeOptionsMemory());
|
||||
|
||||
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,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,18 +133,24 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
contentLeft: 10,
|
||||
contentWidth: 990,
|
||||
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
minimapWidth: 0,
|
||||
minimapHeightIsEditorHeight: false,
|
||||
minimapIsSampling: false,
|
||||
minimapScale: 1,
|
||||
minimapLineHeight: 1,
|
||||
minimapCanvasInnerWidth: 0,
|
||||
minimapCanvasInnerHeight: 800,
|
||||
minimapCanvasOuterWidth: 0,
|
||||
minimapCanvasOuterHeight: 800,
|
||||
minimap: {
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
minimapWidth: 0,
|
||||
minimapHeightIsEditorHeight: false,
|
||||
minimapIsSampling: false,
|
||||
minimapScale: 1,
|
||||
minimapLineHeight: 1,
|
||||
minimapCanvasInnerWidth: 0,
|
||||
minimapCanvasInnerHeight: 800,
|
||||
minimapCanvasOuterWidth: 0,
|
||||
minimapCanvasOuterHeight: 800,
|
||||
},
|
||||
|
||||
viewportColumn: 98,
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: -1,
|
||||
|
||||
verticalScrollbarWidth: 0,
|
||||
horizontalScrollbarHeight: 0,
|
||||
@@ -188,18 +201,24 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
contentLeft: 10,
|
||||
contentWidth: 990,
|
||||
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
minimapWidth: 0,
|
||||
minimapHeightIsEditorHeight: false,
|
||||
minimapIsSampling: false,
|
||||
minimapScale: 1,
|
||||
minimapLineHeight: 1,
|
||||
minimapCanvasInnerWidth: 0,
|
||||
minimapCanvasInnerHeight: 800,
|
||||
minimapCanvasOuterWidth: 0,
|
||||
minimapCanvasOuterHeight: 800,
|
||||
minimap: {
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
minimapWidth: 0,
|
||||
minimapHeightIsEditorHeight: false,
|
||||
minimapIsSampling: false,
|
||||
minimapScale: 1,
|
||||
minimapLineHeight: 1,
|
||||
minimapCanvasInnerWidth: 0,
|
||||
minimapCanvasInnerHeight: 800,
|
||||
minimapCanvasOuterWidth: 0,
|
||||
minimapCanvasOuterHeight: 800,
|
||||
},
|
||||
|
||||
viewportColumn: 97,
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: -1,
|
||||
|
||||
verticalScrollbarWidth: 11,
|
||||
horizontalScrollbarHeight: 12,
|
||||
@@ -250,18 +269,24 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
contentLeft: 10,
|
||||
contentWidth: 890,
|
||||
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
minimapWidth: 0,
|
||||
minimapHeightIsEditorHeight: false,
|
||||
minimapIsSampling: false,
|
||||
minimapScale: 1,
|
||||
minimapLineHeight: 1,
|
||||
minimapCanvasInnerWidth: 0,
|
||||
minimapCanvasInnerHeight: 800,
|
||||
minimapCanvasOuterWidth: 0,
|
||||
minimapCanvasOuterHeight: 800,
|
||||
minimap: {
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
minimapWidth: 0,
|
||||
minimapHeightIsEditorHeight: false,
|
||||
minimapIsSampling: false,
|
||||
minimapScale: 1,
|
||||
minimapLineHeight: 1,
|
||||
minimapCanvasInnerWidth: 0,
|
||||
minimapCanvasInnerHeight: 800,
|
||||
minimapCanvasOuterWidth: 0,
|
||||
minimapCanvasOuterHeight: 800,
|
||||
},
|
||||
|
||||
viewportColumn: 88,
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: -1,
|
||||
|
||||
verticalScrollbarWidth: 0,
|
||||
horizontalScrollbarHeight: 0,
|
||||
@@ -312,18 +337,24 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
contentLeft: 10,
|
||||
contentWidth: 890,
|
||||
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
minimapWidth: 0,
|
||||
minimapHeightIsEditorHeight: false,
|
||||
minimapIsSampling: false,
|
||||
minimapScale: 1,
|
||||
minimapLineHeight: 1,
|
||||
minimapCanvasInnerWidth: 0,
|
||||
minimapCanvasInnerHeight: 900,
|
||||
minimapCanvasOuterWidth: 0,
|
||||
minimapCanvasOuterHeight: 900,
|
||||
minimap: {
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
minimapWidth: 0,
|
||||
minimapHeightIsEditorHeight: false,
|
||||
minimapIsSampling: false,
|
||||
minimapScale: 1,
|
||||
minimapLineHeight: 1,
|
||||
minimapCanvasInnerWidth: 0,
|
||||
minimapCanvasInnerHeight: 900,
|
||||
minimapCanvasOuterWidth: 0,
|
||||
minimapCanvasOuterHeight: 900,
|
||||
},
|
||||
|
||||
viewportColumn: 88,
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: -1,
|
||||
|
||||
verticalScrollbarWidth: 0,
|
||||
horizontalScrollbarHeight: 0,
|
||||
@@ -374,18 +405,24 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
contentLeft: 10,
|
||||
contentWidth: 890,
|
||||
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
minimapWidth: 0,
|
||||
minimapHeightIsEditorHeight: false,
|
||||
minimapIsSampling: false,
|
||||
minimapScale: 1,
|
||||
minimapLineHeight: 1,
|
||||
minimapCanvasInnerWidth: 0,
|
||||
minimapCanvasInnerHeight: 900,
|
||||
minimapCanvasOuterWidth: 0,
|
||||
minimapCanvasOuterHeight: 900,
|
||||
minimap: {
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
minimapWidth: 0,
|
||||
minimapHeightIsEditorHeight: false,
|
||||
minimapIsSampling: false,
|
||||
minimapScale: 1,
|
||||
minimapLineHeight: 1,
|
||||
minimapCanvasInnerWidth: 0,
|
||||
minimapCanvasInnerHeight: 900,
|
||||
minimapCanvasOuterWidth: 0,
|
||||
minimapCanvasOuterHeight: 900,
|
||||
},
|
||||
|
||||
viewportColumn: 88,
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: -1,
|
||||
|
||||
verticalScrollbarWidth: 0,
|
||||
horizontalScrollbarHeight: 0,
|
||||
@@ -436,18 +473,24 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
contentLeft: 60,
|
||||
contentWidth: 840,
|
||||
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
minimapWidth: 0,
|
||||
minimapHeightIsEditorHeight: false,
|
||||
minimapIsSampling: false,
|
||||
minimapScale: 1,
|
||||
minimapLineHeight: 1,
|
||||
minimapCanvasInnerWidth: 0,
|
||||
minimapCanvasInnerHeight: 900,
|
||||
minimapCanvasOuterWidth: 0,
|
||||
minimapCanvasOuterHeight: 900,
|
||||
minimap: {
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
minimapWidth: 0,
|
||||
minimapHeightIsEditorHeight: false,
|
||||
minimapIsSampling: false,
|
||||
minimapScale: 1,
|
||||
minimapLineHeight: 1,
|
||||
minimapCanvasInnerWidth: 0,
|
||||
minimapCanvasInnerHeight: 900,
|
||||
minimapCanvasOuterWidth: 0,
|
||||
minimapCanvasOuterHeight: 900,
|
||||
},
|
||||
|
||||
viewportColumn: 83,
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: -1,
|
||||
|
||||
verticalScrollbarWidth: 0,
|
||||
horizontalScrollbarHeight: 0,
|
||||
@@ -498,18 +541,24 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
contentLeft: 60,
|
||||
contentWidth: 840,
|
||||
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
minimapWidth: 0,
|
||||
minimapHeightIsEditorHeight: false,
|
||||
minimapIsSampling: false,
|
||||
minimapScale: 1,
|
||||
minimapLineHeight: 1,
|
||||
minimapCanvasInnerWidth: 0,
|
||||
minimapCanvasInnerHeight: 900,
|
||||
minimapCanvasOuterWidth: 0,
|
||||
minimapCanvasOuterHeight: 900,
|
||||
minimap: {
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
minimapWidth: 0,
|
||||
minimapHeightIsEditorHeight: false,
|
||||
minimapIsSampling: false,
|
||||
minimapScale: 1,
|
||||
minimapLineHeight: 1,
|
||||
minimapCanvasInnerWidth: 0,
|
||||
minimapCanvasInnerHeight: 900,
|
||||
minimapCanvasOuterWidth: 0,
|
||||
minimapCanvasOuterHeight: 900,
|
||||
},
|
||||
|
||||
viewportColumn: 83,
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: -1,
|
||||
|
||||
verticalScrollbarWidth: 0,
|
||||
horizontalScrollbarHeight: 0,
|
||||
@@ -560,18 +609,24 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
contentLeft: 70,
|
||||
contentWidth: 830,
|
||||
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
minimapWidth: 0,
|
||||
minimapHeightIsEditorHeight: false,
|
||||
minimapIsSampling: false,
|
||||
minimapScale: 1,
|
||||
minimapLineHeight: 1,
|
||||
minimapCanvasInnerWidth: 0,
|
||||
minimapCanvasInnerHeight: 900,
|
||||
minimapCanvasOuterWidth: 0,
|
||||
minimapCanvasOuterHeight: 900,
|
||||
minimap: {
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
minimapWidth: 0,
|
||||
minimapHeightIsEditorHeight: false,
|
||||
minimapIsSampling: false,
|
||||
minimapScale: 1,
|
||||
minimapLineHeight: 1,
|
||||
minimapCanvasInnerWidth: 0,
|
||||
minimapCanvasInnerHeight: 900,
|
||||
minimapCanvasOuterWidth: 0,
|
||||
minimapCanvasOuterHeight: 900,
|
||||
},
|
||||
|
||||
viewportColumn: 82,
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: -1,
|
||||
|
||||
verticalScrollbarWidth: 0,
|
||||
horizontalScrollbarHeight: 0,
|
||||
@@ -622,18 +677,24 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
contentLeft: 40,
|
||||
contentWidth: 860,
|
||||
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
minimapWidth: 0,
|
||||
minimapHeightIsEditorHeight: false,
|
||||
minimapIsSampling: false,
|
||||
minimapScale: 1,
|
||||
minimapLineHeight: 1,
|
||||
minimapCanvasInnerWidth: 0,
|
||||
minimapCanvasInnerHeight: 900,
|
||||
minimapCanvasOuterWidth: 0,
|
||||
minimapCanvasOuterHeight: 900,
|
||||
minimap: {
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
minimapWidth: 0,
|
||||
minimapHeightIsEditorHeight: false,
|
||||
minimapIsSampling: false,
|
||||
minimapScale: 1,
|
||||
minimapLineHeight: 1,
|
||||
minimapCanvasInnerWidth: 0,
|
||||
minimapCanvasInnerHeight: 900,
|
||||
minimapCanvasOuterWidth: 0,
|
||||
minimapCanvasOuterHeight: 900,
|
||||
},
|
||||
|
||||
viewportColumn: 171,
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: -1,
|
||||
|
||||
verticalScrollbarWidth: 0,
|
||||
horizontalScrollbarHeight: 0,
|
||||
@@ -684,18 +745,24 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
contentLeft: 40,
|
||||
contentWidth: 860,
|
||||
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
minimapWidth: 0,
|
||||
minimapHeightIsEditorHeight: false,
|
||||
minimapIsSampling: false,
|
||||
minimapScale: 1,
|
||||
minimapLineHeight: 1,
|
||||
minimapCanvasInnerWidth: 0,
|
||||
minimapCanvasInnerHeight: 900,
|
||||
minimapCanvasOuterWidth: 0,
|
||||
minimapCanvasOuterHeight: 900,
|
||||
minimap: {
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
minimapWidth: 0,
|
||||
minimapHeightIsEditorHeight: false,
|
||||
minimapIsSampling: false,
|
||||
minimapScale: 1,
|
||||
minimapLineHeight: 1,
|
||||
minimapCanvasInnerWidth: 0,
|
||||
minimapCanvasInnerHeight: 900,
|
||||
minimapCanvasOuterWidth: 0,
|
||||
minimapCanvasOuterHeight: 900,
|
||||
},
|
||||
|
||||
viewportColumn: 169,
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: -1,
|
||||
|
||||
verticalScrollbarWidth: 0,
|
||||
horizontalScrollbarHeight: 0,
|
||||
@@ -746,18 +813,24 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
contentLeft: 10,
|
||||
contentWidth: 893,
|
||||
|
||||
renderMinimap: RenderMinimap.Text,
|
||||
minimapLeft: 903,
|
||||
minimapWidth: 97,
|
||||
minimapHeightIsEditorHeight: false,
|
||||
minimapIsSampling: false,
|
||||
minimapScale: 1,
|
||||
minimapLineHeight: 2,
|
||||
minimapCanvasInnerWidth: 97,
|
||||
minimapCanvasInnerHeight: 800,
|
||||
minimapCanvasOuterWidth: 97,
|
||||
minimapCanvasOuterHeight: 800,
|
||||
minimap: {
|
||||
renderMinimap: RenderMinimap.Text,
|
||||
minimapLeft: 903,
|
||||
minimapWidth: 97,
|
||||
minimapHeightIsEditorHeight: false,
|
||||
minimapIsSampling: false,
|
||||
minimapScale: 1,
|
||||
minimapLineHeight: 2,
|
||||
minimapCanvasInnerWidth: 97,
|
||||
minimapCanvasInnerHeight: 800,
|
||||
minimapCanvasOuterWidth: 97,
|
||||
minimapCanvasOuterHeight: 800,
|
||||
},
|
||||
|
||||
viewportColumn: 89,
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: -1,
|
||||
|
||||
verticalScrollbarWidth: 0,
|
||||
horizontalScrollbarHeight: 0,
|
||||
@@ -808,18 +881,24 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
contentLeft: 10,
|
||||
contentWidth: 893,
|
||||
|
||||
renderMinimap: RenderMinimap.Text,
|
||||
minimapLeft: 903,
|
||||
minimapWidth: 97,
|
||||
minimapHeightIsEditorHeight: false,
|
||||
minimapIsSampling: false,
|
||||
minimapScale: 2,
|
||||
minimapLineHeight: 4,
|
||||
minimapCanvasInnerWidth: 194,
|
||||
minimapCanvasInnerHeight: 1600,
|
||||
minimapCanvasOuterWidth: 97,
|
||||
minimapCanvasOuterHeight: 800,
|
||||
minimap: {
|
||||
renderMinimap: RenderMinimap.Text,
|
||||
minimapLeft: 903,
|
||||
minimapWidth: 97,
|
||||
minimapHeightIsEditorHeight: false,
|
||||
minimapIsSampling: false,
|
||||
minimapScale: 2,
|
||||
minimapLineHeight: 4,
|
||||
minimapCanvasInnerWidth: 194,
|
||||
minimapCanvasInnerHeight: 1600,
|
||||
minimapCanvasOuterWidth: 97,
|
||||
minimapCanvasOuterHeight: 800,
|
||||
},
|
||||
|
||||
viewportColumn: 89,
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: -1,
|
||||
|
||||
verticalScrollbarWidth: 0,
|
||||
horizontalScrollbarHeight: 0,
|
||||
@@ -870,18 +949,24 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
contentLeft: 10,
|
||||
contentWidth: 935,
|
||||
|
||||
renderMinimap: RenderMinimap.Text,
|
||||
minimapLeft: 945,
|
||||
minimapWidth: 55,
|
||||
minimapHeightIsEditorHeight: false,
|
||||
minimapIsSampling: false,
|
||||
minimapScale: 2,
|
||||
minimapLineHeight: 4,
|
||||
minimapCanvasInnerWidth: 220,
|
||||
minimapCanvasInnerHeight: 3200,
|
||||
minimapCanvasOuterWidth: 55,
|
||||
minimapCanvasOuterHeight: 800,
|
||||
minimap: {
|
||||
renderMinimap: RenderMinimap.Text,
|
||||
minimapLeft: 945,
|
||||
minimapWidth: 55,
|
||||
minimapHeightIsEditorHeight: false,
|
||||
minimapIsSampling: false,
|
||||
minimapScale: 2,
|
||||
minimapLineHeight: 4,
|
||||
minimapCanvasInnerWidth: 220,
|
||||
minimapCanvasInnerHeight: 3200,
|
||||
minimapCanvasOuterWidth: 55,
|
||||
minimapCanvasOuterHeight: 800,
|
||||
},
|
||||
|
||||
viewportColumn: 93,
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: -1,
|
||||
|
||||
verticalScrollbarWidth: 0,
|
||||
horizontalScrollbarHeight: 0,
|
||||
@@ -932,18 +1017,24 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
contentLeft: 65,
|
||||
contentWidth: 935,
|
||||
|
||||
renderMinimap: RenderMinimap.Text,
|
||||
minimapLeft: 0,
|
||||
minimapWidth: 55,
|
||||
minimapHeightIsEditorHeight: false,
|
||||
minimapIsSampling: false,
|
||||
minimapScale: 2,
|
||||
minimapLineHeight: 4,
|
||||
minimapCanvasInnerWidth: 220,
|
||||
minimapCanvasInnerHeight: 3200,
|
||||
minimapCanvasOuterWidth: 55,
|
||||
minimapCanvasOuterHeight: 800,
|
||||
minimap: {
|
||||
renderMinimap: RenderMinimap.Text,
|
||||
minimapLeft: 0,
|
||||
minimapWidth: 55,
|
||||
minimapHeightIsEditorHeight: false,
|
||||
minimapIsSampling: false,
|
||||
minimapScale: 2,
|
||||
minimapLineHeight: 4,
|
||||
minimapCanvasInnerWidth: 220,
|
||||
minimapCanvasInnerHeight: 3200,
|
||||
minimapCanvasOuterWidth: 55,
|
||||
minimapCanvasOuterHeight: 800,
|
||||
},
|
||||
|
||||
viewportColumn: 93,
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: -1,
|
||||
|
||||
verticalScrollbarWidth: 0,
|
||||
horizontalScrollbarHeight: 0,
|
||||
@@ -996,18 +1087,24 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
contentLeft: 10,
|
||||
contentWidth: 893,
|
||||
|
||||
renderMinimap: RenderMinimap.Text,
|
||||
minimapLeft: 903,
|
||||
minimapWidth: 97,
|
||||
minimapHeightIsEditorHeight: true,
|
||||
minimapIsSampling: false,
|
||||
minimapScale: 3,
|
||||
minimapLineHeight: 13,
|
||||
minimapCanvasInnerWidth: 291,
|
||||
minimapCanvasInnerHeight: 1560,
|
||||
minimapCanvasOuterWidth: 97,
|
||||
minimapCanvasOuterHeight: 800,
|
||||
minimap: {
|
||||
renderMinimap: RenderMinimap.Text,
|
||||
minimapLeft: 903,
|
||||
minimapWidth: 97,
|
||||
minimapHeightIsEditorHeight: true,
|
||||
minimapIsSampling: false,
|
||||
minimapScale: 3,
|
||||
minimapLineHeight: 13,
|
||||
minimapCanvasInnerWidth: 291,
|
||||
minimapCanvasInnerHeight: 1560,
|
||||
minimapCanvasOuterWidth: 97,
|
||||
minimapCanvasOuterHeight: 800,
|
||||
},
|
||||
|
||||
viewportColumn: 89,
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: -1,
|
||||
|
||||
verticalScrollbarWidth: 0,
|
||||
horizontalScrollbarHeight: 0,
|
||||
@@ -1060,18 +1157,24 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
contentLeft: 10,
|
||||
contentWidth: 935,
|
||||
|
||||
renderMinimap: RenderMinimap.Text,
|
||||
minimapLeft: 945,
|
||||
minimapWidth: 55,
|
||||
minimapHeightIsEditorHeight: true,
|
||||
minimapIsSampling: true,
|
||||
minimapScale: 1,
|
||||
minimapLineHeight: 1,
|
||||
minimapCanvasInnerWidth: 110,
|
||||
minimapCanvasInnerHeight: 1600,
|
||||
minimapCanvasOuterWidth: 55,
|
||||
minimapCanvasOuterHeight: 800,
|
||||
minimap: {
|
||||
renderMinimap: RenderMinimap.Text,
|
||||
minimapLeft: 945,
|
||||
minimapWidth: 55,
|
||||
minimapHeightIsEditorHeight: true,
|
||||
minimapIsSampling: true,
|
||||
minimapScale: 1,
|
||||
minimapLineHeight: 1,
|
||||
minimapCanvasInnerWidth: 110,
|
||||
minimapCanvasInnerHeight: 1600,
|
||||
minimapCanvasOuterWidth: 55,
|
||||
minimapCanvasOuterHeight: 800,
|
||||
},
|
||||
|
||||
viewportColumn: 93,
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: -1,
|
||||
|
||||
verticalScrollbarWidth: 0,
|
||||
horizontalScrollbarHeight: 0,
|
||||
@@ -1124,18 +1227,24 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
contentLeft: 10,
|
||||
contentWidth: 893,
|
||||
|
||||
renderMinimap: RenderMinimap.Text,
|
||||
minimapLeft: 903,
|
||||
minimapWidth: 97,
|
||||
minimapHeightIsEditorHeight: false,
|
||||
minimapIsSampling: false,
|
||||
minimapScale: 2,
|
||||
minimapLineHeight: 4,
|
||||
minimapCanvasInnerWidth: 194,
|
||||
minimapCanvasInnerHeight: 1600,
|
||||
minimapCanvasOuterWidth: 97,
|
||||
minimapCanvasOuterHeight: 800,
|
||||
minimap: {
|
||||
renderMinimap: RenderMinimap.Text,
|
||||
minimapLeft: 903,
|
||||
minimapWidth: 97,
|
||||
minimapHeightIsEditorHeight: false,
|
||||
minimapIsSampling: false,
|
||||
minimapScale: 2,
|
||||
minimapLineHeight: 4,
|
||||
minimapCanvasInnerWidth: 194,
|
||||
minimapCanvasInnerHeight: 1600,
|
||||
minimapCanvasOuterWidth: 97,
|
||||
minimapCanvasOuterHeight: 800,
|
||||
},
|
||||
|
||||
viewportColumn: 89,
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: -1,
|
||||
|
||||
verticalScrollbarWidth: 0,
|
||||
horizontalScrollbarHeight: 0,
|
||||
@@ -1188,18 +1297,24 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
contentLeft: 10,
|
||||
contentWidth: 935,
|
||||
|
||||
renderMinimap: RenderMinimap.Text,
|
||||
minimapLeft: 945,
|
||||
minimapWidth: 55,
|
||||
minimapHeightIsEditorHeight: true,
|
||||
minimapIsSampling: true,
|
||||
minimapScale: 1,
|
||||
minimapLineHeight: 1,
|
||||
minimapCanvasInnerWidth: 110,
|
||||
minimapCanvasInnerHeight: 1600,
|
||||
minimapCanvasOuterWidth: 55,
|
||||
minimapCanvasOuterHeight: 800,
|
||||
minimap: {
|
||||
renderMinimap: RenderMinimap.Text,
|
||||
minimapLeft: 945,
|
||||
minimapWidth: 55,
|
||||
minimapHeightIsEditorHeight: true,
|
||||
minimapIsSampling: true,
|
||||
minimapScale: 1,
|
||||
minimapLineHeight: 1,
|
||||
minimapCanvasInnerWidth: 110,
|
||||
minimapCanvasInnerHeight: 1600,
|
||||
minimapCanvasOuterWidth: 55,
|
||||
minimapCanvasOuterHeight: 800,
|
||||
},
|
||||
|
||||
viewportColumn: 93,
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: -1,
|
||||
|
||||
verticalScrollbarWidth: 0,
|
||||
horizontalScrollbarHeight: 0,
|
||||
@@ -1250,18 +1365,24 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
contentLeft: 92,
|
||||
contentWidth: 1018,
|
||||
|
||||
renderMinimap: RenderMinimap.Text,
|
||||
minimapLeft: 1096,
|
||||
minimapWidth: 91,
|
||||
minimapHeightIsEditorHeight: false,
|
||||
minimapIsSampling: false,
|
||||
minimapScale: 2,
|
||||
minimapLineHeight: 4,
|
||||
minimapCanvasInnerWidth: 182,
|
||||
minimapCanvasInnerHeight: 844,
|
||||
minimapCanvasOuterWidth: 91,
|
||||
minimapCanvasOuterHeight: 422,
|
||||
minimap: {
|
||||
renderMinimap: RenderMinimap.Text,
|
||||
minimapLeft: 1096,
|
||||
minimapWidth: 91,
|
||||
minimapHeightIsEditorHeight: false,
|
||||
minimapIsSampling: false,
|
||||
minimapScale: 2,
|
||||
minimapLineHeight: 4,
|
||||
minimapCanvasInnerWidth: 182,
|
||||
minimapCanvasInnerHeight: 844,
|
||||
minimapCanvasOuterWidth: 91,
|
||||
minimapCanvasOuterHeight: 422,
|
||||
},
|
||||
|
||||
viewportColumn: 83,
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: -1,
|
||||
|
||||
verticalScrollbarWidth: 14,
|
||||
horizontalScrollbarHeight: 10,
|
||||
|
||||
Vendored
+22
-18
@@ -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,123 +75,91 @@ 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) => {
|
||||
// Ignore folders that can't be read
|
||||
if (err) {
|
||||
return done(results);
|
||||
}
|
||||
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) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
if (token.count > MAX_FILES) {
|
||||
token.count += files.length;
|
||||
token.maxReached = true;
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
let pending = files.length;
|
||||
if (pending === 0) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
let filesToRead = files;
|
||||
if (token.count + files.length > MAX_FILES) {
|
||||
token.maxReached = true;
|
||||
pending = MAX_FILES - token.count;
|
||||
filesToRead = files.slice(0, pending);
|
||||
}
|
||||
|
||||
if (token.count > MAX_FILES) {
|
||||
token.count += files.length;
|
||||
token.maxReached = true;
|
||||
return done(results);
|
||||
}
|
||||
|
||||
let pending = files.length;
|
||||
if (pending === 0) {
|
||||
return done(results);
|
||||
}
|
||||
for (const file of filesToRead) {
|
||||
if (file.isDirectory()) {
|
||||
if (!filter.includes(file.name)) {
|
||||
await collect(root, join(dir, file.name), filter, token);
|
||||
}
|
||||
|
||||
let filesToRead = files;
|
||||
if (token.count + files.length > MAX_FILES) {
|
||||
token.maxReached = true;
|
||||
pending = MAX_FILES - token.count;
|
||||
filesToRead = files.slice(0, pending);
|
||||
}
|
||||
|
||||
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);
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
results.push(file);
|
||||
|
||||
if (--pending === 0) {
|
||||
done(results);
|
||||
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) {
|
||||
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);
|
||||
|
||||
const launchConfigs = await collectLaunchConfigs(folder);
|
||||
|
||||
resolve({
|
||||
configFiles: asSortedItems(configFiles),
|
||||
fileTypes: asSortedItems(fileTypes),
|
||||
fileCount: token.count,
|
||||
maxFilesReached: token.maxReached,
|
||||
launchConfigFiles: launchConfigs
|
||||
});
|
||||
});
|
||||
});
|
||||
await collect(folder, folder, filter, token);
|
||||
const launchConfigs = await collectLaunchConfigs(folder);
|
||||
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,58 +516,61 @@ 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') {
|
||||
const folder = folderUri.fsPath;
|
||||
collectWorkspaceStats(folder, ['node_modules', '.git']).then(stats => {
|
||||
type WorkspaceStatsClassification = {
|
||||
'workspace.id': { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
|
||||
rendererSessionId: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
|
||||
};
|
||||
type WorkspaceStatsEvent = {
|
||||
'workspace.id': string | undefined;
|
||||
rendererSessionId: string;
|
||||
};
|
||||
this.telemetryService.publicLog2<WorkspaceStatsEvent, WorkspaceStatsClassification>('workspace.stats', {
|
||||
'workspace.id': workspace.telemetryId,
|
||||
rendererSessionId: workspace.rendererSessionId
|
||||
});
|
||||
type WorkspaceStatsFileClassification = {
|
||||
rendererSessionId: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
|
||||
type: { classification: 'SystemMetaData', purpose: 'FeatureInsight', isMeasurement: true };
|
||||
count: { classification: 'SystemMetaData', purpose: 'FeatureInsight', isMeasurement: true };
|
||||
};
|
||||
type WorkspaceStatsFileEvent = {
|
||||
rendererSessionId: string;
|
||||
type: string;
|
||||
count: number;
|
||||
};
|
||||
stats.fileTypes.forEach(e => {
|
||||
this.telemetryService.publicLog2<WorkspaceStatsFileEvent, WorkspaceStatsFileClassification>('workspace.stats.file', {
|
||||
rendererSessionId: workspace.rendererSessionId,
|
||||
type: e.name,
|
||||
count: e.count
|
||||
});
|
||||
});
|
||||
stats.launchConfigFiles.forEach(e => {
|
||||
this.telemetryService.publicLog2<WorkspaceStatsFileEvent, WorkspaceStatsFileClassification>('workspace.stats.launchConfigFile', {
|
||||
rendererSessionId: workspace.rendererSessionId,
|
||||
type: e.name,
|
||||
count: e.count
|
||||
});
|
||||
});
|
||||
stats.configFiles.forEach(e => {
|
||||
this.telemetryService.publicLog2<WorkspaceStatsFileEvent, WorkspaceStatsFileClassification>('workspace.stats.configFiles', {
|
||||
rendererSessionId: workspace.rendererSessionId,
|
||||
type: e.name,
|
||||
count: e.count
|
||||
});
|
||||
});
|
||||
}).catch(_ => {
|
||||
// Report nothing if collecting metadata fails.
|
||||
});
|
||||
for (const { uri } of workspace.folders) {
|
||||
const folderUri = URI.revive(uri);
|
||||
if (folderUri.scheme !== 'file') {
|
||||
continue;
|
||||
}
|
||||
});
|
||||
|
||||
const folder = folderUri.fsPath;
|
||||
try {
|
||||
const stats = await collectWorkspaceStats(folder, ['node_modules', '.git']);
|
||||
type WorkspaceStatsClassification = {
|
||||
'workspace.id': { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
|
||||
rendererSessionId: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
|
||||
};
|
||||
type WorkspaceStatsEvent = {
|
||||
'workspace.id': string | undefined;
|
||||
rendererSessionId: string;
|
||||
};
|
||||
this.telemetryService.publicLog2<WorkspaceStatsEvent, WorkspaceStatsClassification>('workspace.stats', {
|
||||
'workspace.id': workspace.telemetryId,
|
||||
rendererSessionId: workspace.rendererSessionId
|
||||
});
|
||||
type WorkspaceStatsFileClassification = {
|
||||
rendererSessionId: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
|
||||
type: { classification: 'SystemMetaData', purpose: 'FeatureInsight', isMeasurement: true };
|
||||
count: { classification: 'SystemMetaData', purpose: 'FeatureInsight', isMeasurement: true };
|
||||
};
|
||||
type WorkspaceStatsFileEvent = {
|
||||
rendererSessionId: string;
|
||||
type: string;
|
||||
count: number;
|
||||
};
|
||||
stats.fileTypes.forEach(e => {
|
||||
this.telemetryService.publicLog2<WorkspaceStatsFileEvent, WorkspaceStatsFileClassification>('workspace.stats.file', {
|
||||
rendererSessionId: workspace.rendererSessionId,
|
||||
type: e.name,
|
||||
count: e.count
|
||||
});
|
||||
});
|
||||
stats.launchConfigFiles.forEach(e => {
|
||||
this.telemetryService.publicLog2<WorkspaceStatsFileEvent, WorkspaceStatsFileClassification>('workspace.stats.launchConfigFile', {
|
||||
rendererSessionId: workspace.rendererSessionId,
|
||||
type: e.name,
|
||||
count: e.count
|
||||
});
|
||||
});
|
||||
stats.configFiles.forEach(e => {
|
||||
this.telemetryService.publicLog2<WorkspaceStatsFileEvent, WorkspaceStatsFileClassification>('workspace.stats.configFiles', {
|
||||
rendererSessionId: workspace.rendererSessionId,
|
||||
type: e.name,
|
||||
count: e.count
|
||||
});
|
||||
});
|
||||
} catch {
|
||||
// Report nothing if collecting metadata fails.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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']; }
|
||||
|
||||
Vendored
+113
@@ -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.
|
||||
|
||||
Vendored
+37
-108
@@ -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); }
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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
|
||||
);
|
||||
if (provider && document) {
|
||||
const rawCells = await provider.provider.openNotebook(URI.revive(uri));
|
||||
const renderers = new Set<number>();
|
||||
const dto = {
|
||||
metadata: {
|
||||
...notebookDocumentMetadataDefaults,
|
||||
...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);
|
||||
|
||||
this._documents.set(revivedUri.toString(), document);
|
||||
}
|
||||
if (ret.orderedMimeTypes[ret.pickedMimeTypeIndex].isResolved) {
|
||||
renderers.add(ret.orderedMimeTypes[ret.pickedMimeTypeIndex].rendererId!);
|
||||
}
|
||||
return ret;
|
||||
} else {
|
||||
return output as IStreamOutput | IErrorOutput;
|
||||
}
|
||||
});
|
||||
|
||||
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 = {
|
||||
...notebookDocumentMetadataDefaults,
|
||||
...data.metadata
|
||||
return {
|
||||
language: cell.language,
|
||||
cellKind: cell.cellKind,
|
||||
metadata: cell.metadata,
|
||||
source: cell.source,
|
||||
outputs: transformedOutputs
|
||||
};
|
||||
})
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
});
|
||||
|
||||
this._onDidOpenNotebookDocument.fire(editor.document);
|
||||
return editor.document.handle;
|
||||
} else {
|
||||
return Promise.resolve(undefined);
|
||||
return dto;
|
||||
}
|
||||
|
||||
return undefined; // {{SQL CARBON EDIT}}
|
||||
}
|
||||
|
||||
async $resolveNotebook(viewType: string, uri: UriComponents): Promise<number | undefined> {
|
||||
let notebookFromNotebookContentProvider = await this._resolveNotebookFromContentProvider(viewType, uri);
|
||||
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 || []);
|
||||
|
||||
if (notebookFromNotebookContentProvider !== undefined) {
|
||||
return notebookFromNotebookContentProvider;
|
||||
}
|
||||
let orderMimeTypes: IOrderedMimeType[] = [];
|
||||
|
||||
let provider = this._notebookProviders.get(viewType);
|
||||
sorted.forEach(mimeType => {
|
||||
let handlers = this.findBestMatchedRenderer(mimeType);
|
||||
|
||||
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
|
||||
);
|
||||
if (handlers.length) {
|
||||
let renderedOutput = handlers[0].render(document, output, mimeType);
|
||||
|
||||
this._documents.set(URI.revive(uri).toString(), document);
|
||||
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 {
|
||||
orderMimeTypes.push({
|
||||
mimeType: mimeType,
|
||||
isResolved: false
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
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,44 +846,26 @@ 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) {
|
||||
async $saveNotebookAs(viewType: string, uri: UriComponents, target: UriComponents, token: CancellationToken): Promise<boolean> {
|
||||
let document = this._documents.get(URI.revive(uri).toString());
|
||||
if (!document) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let document = this._documents.get(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;
|
||||
}
|
||||
|
||||
if (document) {
|
||||
document.dispose();
|
||||
this._documents.delete(URI.revive(uri).toString());
|
||||
this._onDidCloseNotebookDocument.fire(document);
|
||||
return true;
|
||||
}
|
||||
|
||||
let editor = this._editors.get(URI.revive(uri).toString());
|
||||
|
||||
if (editor) {
|
||||
editor.editor.dispose();
|
||||
editor.onDidReceiveMessage.dispose();
|
||||
this._editors.delete(URI.revive(uri).toString());
|
||||
}
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
$acceptDisplayOrder(displayOrder: INotebookDisplayOrder): void {
|
||||
@@ -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);
|
||||
|
||||
@@ -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,18 +346,30 @@ 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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
// 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()) {
|
||||
return withNullAsUndefined(textEditorControl.saveViewState());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
})()
|
||||
};
|
||||
}
|
||||
|
||||
// Try to find encoding and mode from text model
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)(() => {
|
||||
this.clearEditorState(resource);
|
||||
});
|
||||
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) {
|
||||
return;
|
||||
// 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
|
||||
this.doCloseActiveEditor();
|
||||
// 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,14 +238,15 @@
|
||||
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 */
|
||||
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab > .tab-close .action-label:focus, /* always show it on focus */
|
||||
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab:hover > .tab-close .action-label, /* always show it on hover */
|
||||
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.active:hover > .tab-close .action-label, /* always show it on hover */
|
||||
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.active:hover > .tab-close .action-label, /* always show it on hover */
|
||||
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.dirty > .tab-close .action-label { /* always show it for dirty tabs */
|
||||
opacity: 1;
|
||||
}
|
||||
@@ -233,10 +262,10 @@
|
||||
content: "\ea71"; /* use `circle-filled` icon unicode */
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active > .tab-close .action-label, /* show dimmed for inactive group */
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active > .tab-close .action-label, /* show dimmed for inactive group */
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.active:hover > .tab-close .action-label, /* show dimmed for inactive group */
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.dirty > .tab-close .action-label, /* show dimmed for inactive group */
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab:hover > .tab-close .action-label { /* show dimmed for inactive group */
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab:hover > .tab-close .action-label { /* show dimmed for inactive group */
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
result.push(<IAction>{
|
||||
id: `${viewDescriptor.id}.removeView`,
|
||||
label: nls.localize('hideView', "Hide"),
|
||||
enabled: viewDescriptor.canToggleVisibility,
|
||||
run: () => this.toggleViewVisibility(viewDescriptor!.id)
|
||||
});
|
||||
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)
|
||||
}));
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user