mirror of
https://github.com/Microsoft/vscode
synced 2024-10-06 03:17:00 +00:00
Merge remote-tracking branch 'origin' into electron-19.x.y
This commit is contained in:
commit
7bc2706edd
6
.github/workflows/codeql.yml
vendored
6
.github/workflows/codeql.yml
vendored
|
@ -24,14 +24,14 @@ jobs:
|
|||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: javascript
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v1
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
|
@ -45,4 +45,4 @@ jobs:
|
|||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
||||
uses: github/codeql-action/analyze@v2
|
||||
|
|
2
.github/workflows/deep-classifier-runner.yml
vendored
2
.github/workflows/deep-classifier-runner.yml
vendored
|
@ -46,7 +46,7 @@ jobs:
|
|||
uses: ./actions/classifier-deep/apply/apply-labels
|
||||
with:
|
||||
configPath: classifier
|
||||
allowLabels: "needs more info|new release|error-telemetry|*english-please|translation-required"
|
||||
allowLabels: "info-needed|new release|error-telemetry|*english-please|translation-required"
|
||||
appInsightsKey: ${{secrets.TRIAGE_ACTIONS_APP_INSIGHTS}}
|
||||
manifestDbConnectionString: ${{secrets.MANIFEST_DB_CONNECTION_STRING}}
|
||||
token: ${{secrets.VSCODE_ISSUE_TRIAGE_BOT_PAT}}
|
||||
|
|
2
.github/workflows/english-please.yml
vendored
2
.github/workflows/english-please.yml
vendored
|
@ -24,6 +24,6 @@ jobs:
|
|||
token: ${{secrets.VSCODE_ISSUE_TRIAGE_BOT_PAT}}
|
||||
cognitiveServicesAPIKey: ${{secrets.AZURE_TEXT_TRANSLATOR_KEY}}
|
||||
nonEnglishLabel: "*english-please"
|
||||
needsMoreInfoLabel: "needs more info"
|
||||
needsMoreInfoLabel: "info-needed"
|
||||
translatorRequestedLabelPrefix: "translation-required-"
|
||||
translatorRequestedLabelColor: "c29cff"
|
||||
|
|
6
.github/workflows/needs-more-info-closer.yml
vendored
6
.github/workflows/needs-more-info-closer.yml
vendored
|
@ -1,4 +1,4 @@
|
|||
name: Needs More Info Closer
|
||||
name: info-needed Closer
|
||||
on:
|
||||
schedule:
|
||||
- cron: 20 11 * * * # 4:20am Redmond
|
||||
|
@ -17,12 +17,12 @@ jobs:
|
|||
ref: stable
|
||||
- name: Install Actions
|
||||
run: npm install --production --prefix ./actions
|
||||
- name: Run Needs More Info Closer
|
||||
- name: Run info-needed Closer
|
||||
uses: ./actions/needs-more-info-closer
|
||||
with:
|
||||
appInsightsKey: ${{secrets.TRIAGE_ACTIONS_APP_INSIGHTS}}
|
||||
token: ${{secrets.VSCODE_ISSUE_TRIAGE_BOT_PAT}}
|
||||
label: needs more info
|
||||
label: info-needed
|
||||
closeDays: 7
|
||||
additionalTeam: "cleidigh|usernamehw|gjsjohnmurray|IllusionMH"
|
||||
closeComment: "This issue has been closed automatically because it needs more information and has not had recent activity. See also our [issue reporting](https://aka.ms/vscodeissuereporting) guidelines.\n\nHappy Coding!"
|
||||
|
|
2
.github/workflows/on-label.yml
vendored
2
.github/workflows/on-label.yml
vendored
|
@ -85,6 +85,6 @@ jobs:
|
|||
token: ${{secrets.VSCODE_ISSUE_TRIAGE_BOT_PAT}}
|
||||
cognitiveServicesAPIKey: ${{secrets.AZURE_TEXT_TRANSLATOR_KEY}}
|
||||
nonEnglishLabel: "*english-please"
|
||||
needsMoreInfoLabel: "needs more info"
|
||||
needsMoreInfoLabel: "info-needed"
|
||||
translatorRequestedLabelPrefix: "translation-required-"
|
||||
translatorRequestedLabelColor: "c29cff"
|
||||
|
|
2
.github/workflows/on-open.yml
vendored
2
.github/workflows/on-open.yml
vendored
|
@ -59,6 +59,6 @@ jobs:
|
|||
appInsightsKey: ${{secrets.TRIAGE_ACTIONS_APP_INSIGHTS}}
|
||||
cognitiveServicesAPIKey: ${{secrets.AZURE_TEXT_TRANSLATOR_KEY}}
|
||||
nonEnglishLabel: "*english-please"
|
||||
needsMoreInfoLabel: "needs more info"
|
||||
needsMoreInfoLabel: "info-needed"
|
||||
translatorRequestedLabelPrefix: "translation-required-"
|
||||
translatorRequestedLabelColor: "c29cff"
|
||||
|
|
2
.vscode/notebooks/inbox.github-issues
vendored
2
.vscode/notebooks/inbox.github-issues
vendored
|
@ -7,7 +7,7 @@
|
|||
{
|
||||
"kind": 2,
|
||||
"language": "github-issues",
|
||||
"value": "$inbox -label:\"needs more info\" sort:created-desc"
|
||||
"value": "$inbox -label:\"info-needed\" sort:created-desc"
|
||||
},
|
||||
{
|
||||
"kind": 2,
|
||||
|
|
2
.vscode/notebooks/my-endgame.github-issues
vendored
2
.vscode/notebooks/my-endgame.github-issues
vendored
|
@ -147,7 +147,7 @@
|
|||
{
|
||||
"kind": 2,
|
||||
"language": "github-issues",
|
||||
"value": "$REPOS $MILESTONE -$MINE is:issue is:closed author:@me sort:updated-asc label:bug -label:unreleased -label:verified -label:z-author-verified -label:on-testplan -label:*duplicate -label:duplicate -label:invalid -label:*as-designed -label:error-telemetry -label:verification-steps-needed -label:needs-triage -label:verification-found"
|
||||
"value": "$REPOS $MILESTONE -$MINE is:issue is:closed author:@me sort:updated-asc label:bug -label:unreleased -label:verified -label:z-author-verified -label:on-testplan -label:*duplicate -label:duplicate -label:invalid -label:*as-designed -label:error-telemetry -label:verification-steps-needed -label:triage-needed -label:verification-found"
|
||||
},
|
||||
{
|
||||
"kind": 1,
|
||||
|
|
6
.vscode/notebooks/my-work.github-issues
vendored
6
.vscode/notebooks/my-work.github-issues
vendored
File diff suppressed because one or more lines are too long
|
@ -31,7 +31,7 @@ This project incorporates components from the projects listed below. The origina
|
|||
24. ionide/ionide-fsgrammar (https://github.com/ionide/ionide-fsgrammar)
|
||||
25. James-Yu/LaTeX-Workshop version 8.19.1 (https://github.com/James-Yu/LaTeX-Workshop)
|
||||
26. jeff-hykin/better-c-syntax version 1.13.2 (https://github.com/jeff-hykin/better-c-syntax)
|
||||
27. jeff-hykin/better-cpp-syntax version 1.15.17 (https://github.com/jeff-hykin/better-cpp-syntax)
|
||||
27. jeff-hykin/better-cpp-syntax version 1.15.18 (https://github.com/jeff-hykin/better-cpp-syntax)
|
||||
28. jeff-hykin/better-objc-syntax version 0.2.0 (https://github.com/jeff-hykin/better-objc-syntax)
|
||||
29. jeff-hykin/better-objcpp-syntax version 0.1.0 (https://github.com/jeff-hykin/better-objcpp-syntax)
|
||||
30. jlelong/vscode-latex-basics version 1.3.0 (https://github.com/jlelong/vscode-latex-basics)
|
||||
|
@ -47,7 +47,7 @@ This project incorporates components from the projects listed below. The origina
|
|||
40. microsoft/TypeScript-TmLanguage version 0.0.1 (https://github.com/microsoft/TypeScript-TmLanguage)
|
||||
41. microsoft/vscode-JSON.tmLanguage (https://github.com/microsoft/vscode-JSON.tmLanguage)
|
||||
42. microsoft/vscode-markdown-tm-grammar version 1.0.0 (https://github.com/microsoft/vscode-markdown-tm-grammar)
|
||||
43. microsoft/vscode-mssql version 1.10.1 (https://github.com/microsoft/vscode-mssql)
|
||||
43. microsoft/vscode-mssql version 1.16.0 (https://github.com/microsoft/vscode-mssql)
|
||||
44. mmims/language-batchfile version 0.7.6 (https://github.com/mmims/language-batchfile)
|
||||
45. NVIDIA/cuda-cpp-grammar (https://github.com/NVIDIA/cuda-cpp-grammar)
|
||||
46. PowerShell/EditorSyntax version 1.0.0 (https://github.com/PowerShell/EditorSyntax)
|
||||
|
@ -73,7 +73,7 @@ This project incorporates components from the projects listed below. The origina
|
|||
66. TypeScript-TmLanguage version 1.0.0 (https://github.com/microsoft/TypeScript-TmLanguage)
|
||||
67. Unicode version 12.0.0 (https://home.unicode.org/)
|
||||
68. vscode-codicons version 0.0.14 (https://github.com/microsoft/vscode-codicons)
|
||||
69. vscode-logfile-highlighter version 2.11.0 (https://github.com/emilast/vscode-logfile-highlighter)
|
||||
69. vscode-logfile-highlighter version 2.15.0 (https://github.com/emilast/vscode-logfile-highlighter)
|
||||
70. vscode-swift version 0.0.1 (https://github.com/owensd/vscode-swift)
|
||||
71. vscode-win32-app-container-tokens (https://github.com/microsoft/vscode-win32-app-container-tokens)
|
||||
72. Web Background Synchronization (https://github.com/WICG/background-sync)
|
||||
|
|
|
@ -93,12 +93,21 @@ steps:
|
|||
node build/azure-pipelines/common/computeNodeModulesCacheKey.js $VSCODE_ARCH $ENABLE_TERRAPIN > .build/yarnlockhash
|
||||
displayName: Prepare yarn cache flags
|
||||
|
||||
- task: Cache@2
|
||||
inputs:
|
||||
key: "nodeModules | $(Agent.OS) | .build/yarnlockhash"
|
||||
path: .build/node_modules_cache
|
||||
cacheHitVar: NODE_MODULES_RESTORED
|
||||
displayName: Restore node_modules cache
|
||||
- ${{ if eq(parameters.VSCODE_QUALITY, 'oss') }}:
|
||||
- task: Cache@2
|
||||
inputs:
|
||||
key: "genericNodeModules | $(Agent.OS) | .build/yarnlockhash"
|
||||
path: .build/node_modules_cache
|
||||
cacheHitVar: NODE_MODULES_RESTORED
|
||||
displayName: Restore node_modules cache
|
||||
|
||||
- ${{ if ne(parameters.VSCODE_QUALITY, 'oss') }}:
|
||||
- task: Cache@2
|
||||
inputs:
|
||||
key: "nodeModules | $(Agent.OS) | .build/yarnlockhash"
|
||||
path: .build/node_modules_cache
|
||||
cacheHitVar: NODE_MODULES_RESTORED
|
||||
displayName: Restore node_modules cache
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
|
|
|
@ -22,174 +22,168 @@ variables:
|
|||
- name: VSCODE_STEP_ON_IT
|
||||
value: false
|
||||
|
||||
stages:
|
||||
- ${{ if eq(variables['VSCODE_CIBUILD'], true) }}:
|
||||
- stage: MaintainNodeModulesCache
|
||||
displayName: Maintain node_modules cache
|
||||
jobs:
|
||||
- job: MaintainNodeModulesCache
|
||||
displayName: Maintain node_modules cache
|
||||
pool: vscode-1es-vscode-linux-20.04
|
||||
steps:
|
||||
- template: product-build-pr-cache.yml
|
||||
|
||||
jobs:
|
||||
- ${{ if ne(variables['VSCODE_CIBUILD'], true) }}:
|
||||
- stage: Compile
|
||||
- job: Compile
|
||||
displayName: Compile & Hygiene
|
||||
jobs:
|
||||
- job: Compile
|
||||
displayName: Compile & Hygiene
|
||||
pool: vscode-1es-vscode-linux-20.04
|
||||
variables:
|
||||
VSCODE_ARCH: x64
|
||||
steps:
|
||||
- template: product-compile.yml
|
||||
parameters:
|
||||
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
|
||||
pool: vscode-1es-vscode-linux-20.04
|
||||
timeoutInMinutes: 30
|
||||
variables:
|
||||
VSCODE_ARCH: x64
|
||||
steps:
|
||||
- template: product-compile.yml
|
||||
parameters:
|
||||
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
|
||||
|
||||
- stage: Test
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- job: Linuxx64UnitTest
|
||||
displayName: Linux (Unit Tests)
|
||||
pool: vscode-1es-vscode-linux-20.04
|
||||
# container: vscode-bionic-x64
|
||||
timeoutInMinutes: 60
|
||||
variables:
|
||||
VSCODE_ARCH: x64
|
||||
NPM_ARCH: x64
|
||||
DISPLAY: ":10"
|
||||
steps:
|
||||
- template: linux/product-build-linux-client.yml
|
||||
parameters:
|
||||
VSCODE_PUBLISH: ${{ variables.VSCODE_PUBLISH }}
|
||||
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
|
||||
VSCODE_RUN_UNIT_TESTS: true
|
||||
VSCODE_RUN_INTEGRATION_TESTS: false
|
||||
VSCODE_RUN_SMOKE_TESTS: false
|
||||
- job: Linuxx64IntegrationTest
|
||||
displayName: Linux (Integration Tests)
|
||||
pool: vscode-1es-vscode-linux-20.04
|
||||
# container: vscode-bionic-x64
|
||||
timeoutInMinutes: 60
|
||||
variables:
|
||||
VSCODE_ARCH: x64
|
||||
NPM_ARCH: x64
|
||||
DISPLAY: ":10"
|
||||
steps:
|
||||
- template: linux/product-build-linux-client.yml
|
||||
parameters:
|
||||
VSCODE_PUBLISH: ${{ variables.VSCODE_PUBLISH }}
|
||||
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
|
||||
VSCODE_RUN_UNIT_TESTS: false
|
||||
VSCODE_RUN_INTEGRATION_TESTS: true
|
||||
VSCODE_RUN_SMOKE_TESTS: false
|
||||
- job: Linuxx64SmokeTest
|
||||
displayName: Linux (Smoke Tests)
|
||||
pool: vscode-1es-vscode-linux-20.04
|
||||
# container: vscode-bionic-x64
|
||||
timeoutInMinutes: 60
|
||||
variables:
|
||||
VSCODE_ARCH: x64
|
||||
NPM_ARCH: x64
|
||||
DISPLAY: ":10"
|
||||
steps:
|
||||
- template: linux/product-build-linux-client.yml
|
||||
parameters:
|
||||
VSCODE_PUBLISH: ${{ variables.VSCODE_PUBLISH }}
|
||||
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
|
||||
VSCODE_RUN_UNIT_TESTS: false
|
||||
VSCODE_RUN_INTEGRATION_TESTS: false
|
||||
VSCODE_RUN_SMOKE_TESTS: true
|
||||
- job: Linuxx64UnitTest
|
||||
displayName: Linux (Unit Tests)
|
||||
pool: vscode-1es-vscode-linux-20.04
|
||||
timeoutInMinutes: 30
|
||||
variables:
|
||||
VSCODE_ARCH: x64
|
||||
NPM_ARCH: x64
|
||||
DISPLAY: ":10"
|
||||
steps:
|
||||
- template: linux/product-build-linux-client.yml
|
||||
parameters:
|
||||
VSCODE_PUBLISH: ${{ variables.VSCODE_PUBLISH }}
|
||||
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
|
||||
VSCODE_RUN_UNIT_TESTS: true
|
||||
VSCODE_RUN_INTEGRATION_TESTS: false
|
||||
VSCODE_RUN_SMOKE_TESTS: false
|
||||
|
||||
# - job: macOSUnitTest
|
||||
# displayName: macOS (Unit Tests)
|
||||
# pool:
|
||||
# vmImage: macOS-latest
|
||||
# timeoutInMinutes: 60
|
||||
# variables:
|
||||
# BUILDSECMON_OPT_IN: true
|
||||
# VSCODE_ARCH: x64
|
||||
# steps:
|
||||
# - template: darwin/product-build-darwin.yml
|
||||
# parameters:
|
||||
# VSCODE_PUBLISH: ${{ variables.VSCODE_PUBLISH }}
|
||||
# VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
|
||||
# VSCODE_RUN_UNIT_TESTS: true
|
||||
# VSCODE_RUN_INTEGRATION_TESTS: false
|
||||
# VSCODE_RUN_SMOKE_TESTS: false
|
||||
# - job: macOSIntegrationTest
|
||||
# displayName: macOS (Integration Tests)
|
||||
# pool:
|
||||
# vmImage: macOS-latest
|
||||
# timeoutInMinutes: 60
|
||||
# variables:
|
||||
# BUILDSECMON_OPT_IN: true
|
||||
# VSCODE_ARCH: x64
|
||||
# steps:
|
||||
# - template: darwin/product-build-darwin.yml
|
||||
# parameters:
|
||||
# VSCODE_PUBLISH: ${{ variables.VSCODE_PUBLISH }}
|
||||
# VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
|
||||
# VSCODE_RUN_UNIT_TESTS: false
|
||||
# VSCODE_RUN_INTEGRATION_TESTS: true
|
||||
# VSCODE_RUN_SMOKE_TESTS: false
|
||||
# - job: macOSSmokeTest
|
||||
# displayName: macOS (Smoke Tests)
|
||||
# pool:
|
||||
# vmImage: macOS-latest
|
||||
# timeoutInMinutes: 60
|
||||
# variables:
|
||||
# BUILDSECMON_OPT_IN: true
|
||||
# VSCODE_ARCH: x64
|
||||
# steps:
|
||||
# - template: darwin/product-build-darwin.yml
|
||||
# parameters:
|
||||
# VSCODE_PUBLISH: ${{ variables.VSCODE_PUBLISH }}
|
||||
# VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
|
||||
# VSCODE_RUN_UNIT_TESTS: false
|
||||
# VSCODE_RUN_INTEGRATION_TESTS: false
|
||||
# VSCODE_RUN_SMOKE_TESTS: true
|
||||
- job: Linuxx64IntegrationTest
|
||||
displayName: Linux (Integration Tests)
|
||||
pool: vscode-1es-vscode-linux-20.04
|
||||
timeoutInMinutes: 30
|
||||
variables:
|
||||
VSCODE_ARCH: x64
|
||||
NPM_ARCH: x64
|
||||
DISPLAY: ":10"
|
||||
steps:
|
||||
- template: linux/product-build-linux-client.yml
|
||||
parameters:
|
||||
VSCODE_PUBLISH: ${{ variables.VSCODE_PUBLISH }}
|
||||
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
|
||||
VSCODE_RUN_UNIT_TESTS: false
|
||||
VSCODE_RUN_INTEGRATION_TESTS: true
|
||||
VSCODE_RUN_SMOKE_TESTS: false
|
||||
|
||||
# - job: WindowsUnitTests
|
||||
# displayName: Windows (Unit Tests)
|
||||
# pool: vscode-1es-vscode-windows-2019
|
||||
# timeoutInMinutes: 60
|
||||
# variables:
|
||||
# VSCODE_ARCH: x64
|
||||
# steps:
|
||||
# - template: win32/product-build-win32.yml
|
||||
# parameters:
|
||||
# VSCODE_PUBLISH: ${{ variables.VSCODE_PUBLISH }}
|
||||
# VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
|
||||
# VSCODE_RUN_UNIT_TESTS: true
|
||||
# VSCODE_RUN_INTEGRATION_TESTS: false
|
||||
# VSCODE_RUN_SMOKE_TESTS: false
|
||||
# - job: WindowsIntegrationTests
|
||||
# displayName: Windows (Integration Tests)
|
||||
# pool: vscode-1es-vscode-windows-2019
|
||||
# timeoutInMinutes: 60
|
||||
# variables:
|
||||
# VSCODE_ARCH: x64
|
||||
# steps:
|
||||
# - template: win32/product-build-win32.yml
|
||||
# parameters:
|
||||
# VSCODE_PUBLISH: ${{ variables.VSCODE_PUBLISH }}
|
||||
# VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
|
||||
# VSCODE_RUN_UNIT_TESTS: false
|
||||
# VSCODE_RUN_INTEGRATION_TESTS: true
|
||||
# VSCODE_RUN_SMOKE_TESTS: false
|
||||
# - job: WindowsSmokeTests
|
||||
# displayName: Windows (Smoke Tests)
|
||||
# pool: vscode-1es-vscode-windows-2019
|
||||
# timeoutInMinutes: 60
|
||||
# variables:
|
||||
# VSCODE_ARCH: x64
|
||||
# steps:
|
||||
# - template: win32/product-build-win32.yml
|
||||
# parameters:
|
||||
# VSCODE_PUBLISH: ${{ variables.VSCODE_PUBLISH }}
|
||||
# VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
|
||||
# VSCODE_RUN_UNIT_TESTS: false
|
||||
# VSCODE_RUN_INTEGRATION_TESTS: false
|
||||
# VSCODE_RUN_SMOKE_TESTS: true
|
||||
- job: Linuxx64SmokeTest
|
||||
displayName: Linux (Smoke Tests)
|
||||
pool: vscode-1es-vscode-linux-20.04
|
||||
timeoutInMinutes: 30
|
||||
variables:
|
||||
VSCODE_ARCH: x64
|
||||
NPM_ARCH: x64
|
||||
DISPLAY: ":10"
|
||||
steps:
|
||||
- template: linux/product-build-linux-client.yml
|
||||
parameters:
|
||||
VSCODE_PUBLISH: ${{ variables.VSCODE_PUBLISH }}
|
||||
VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
|
||||
VSCODE_RUN_UNIT_TESTS: false
|
||||
VSCODE_RUN_INTEGRATION_TESTS: false
|
||||
VSCODE_RUN_SMOKE_TESTS: true
|
||||
|
||||
- ${{ if eq(variables['VSCODE_CIBUILD'], true) }}:
|
||||
- job: Linuxx64MaintainNodeModulesCache
|
||||
displayName: Linux (Maintain node_modules cache)
|
||||
pool: vscode-1es-vscode-linux-20.04
|
||||
timeoutInMinutes: 30
|
||||
variables:
|
||||
VSCODE_ARCH: x64
|
||||
steps:
|
||||
- template: product-build-pr-cache.yml
|
||||
|
||||
# - job: macOSUnitTest
|
||||
# displayName: macOS (Unit Tests)
|
||||
# pool:
|
||||
# vmImage: macOS-latest
|
||||
# timeoutInMinutes: 60
|
||||
# variables:
|
||||
# BUILDSECMON_OPT_IN: true
|
||||
# VSCODE_ARCH: x64
|
||||
# steps:
|
||||
# - template: darwin/product-build-darwin.yml
|
||||
# parameters:
|
||||
# VSCODE_PUBLISH: ${{ variables.VSCODE_PUBLISH }}
|
||||
# VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
|
||||
# VSCODE_RUN_UNIT_TESTS: true
|
||||
# VSCODE_RUN_INTEGRATION_TESTS: false
|
||||
# VSCODE_RUN_SMOKE_TESTS: false
|
||||
# - job: macOSIntegrationTest
|
||||
# displayName: macOS (Integration Tests)
|
||||
# pool:
|
||||
# vmImage: macOS-latest
|
||||
# timeoutInMinutes: 60
|
||||
# variables:
|
||||
# BUILDSECMON_OPT_IN: true
|
||||
# VSCODE_ARCH: x64
|
||||
# steps:
|
||||
# - template: darwin/product-build-darwin.yml
|
||||
# parameters:
|
||||
# VSCODE_PUBLISH: ${{ variables.VSCODE_PUBLISH }}
|
||||
# VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
|
||||
# VSCODE_RUN_UNIT_TESTS: false
|
||||
# VSCODE_RUN_INTEGRATION_TESTS: true
|
||||
# VSCODE_RUN_SMOKE_TESTS: false
|
||||
# - job: macOSSmokeTest
|
||||
# displayName: macOS (Smoke Tests)
|
||||
# pool:
|
||||
# vmImage: macOS-latest
|
||||
# timeoutInMinutes: 60
|
||||
# variables:
|
||||
# BUILDSECMON_OPT_IN: true
|
||||
# VSCODE_ARCH: x64
|
||||
# steps:
|
||||
# - template: darwin/product-build-darwin.yml
|
||||
# parameters:
|
||||
# VSCODE_PUBLISH: ${{ variables.VSCODE_PUBLISH }}
|
||||
# VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
|
||||
# VSCODE_RUN_UNIT_TESTS: false
|
||||
# VSCODE_RUN_INTEGRATION_TESTS: false
|
||||
# VSCODE_RUN_SMOKE_TESTS: true
|
||||
|
||||
# - job: WindowsUnitTests
|
||||
# displayName: Windows (Unit Tests)
|
||||
# pool: vscode-1es-vscode-windows-2019
|
||||
# timeoutInMinutes: 60
|
||||
# variables:
|
||||
# VSCODE_ARCH: x64
|
||||
# steps:
|
||||
# - template: win32/product-build-win32.yml
|
||||
# parameters:
|
||||
# VSCODE_PUBLISH: ${{ variables.VSCODE_PUBLISH }}
|
||||
# VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
|
||||
# VSCODE_RUN_UNIT_TESTS: true
|
||||
# VSCODE_RUN_INTEGRATION_TESTS: false
|
||||
# VSCODE_RUN_SMOKE_TESTS: false
|
||||
# - job: WindowsIntegrationTests
|
||||
# displayName: Windows (Integration Tests)
|
||||
# pool: vscode-1es-vscode-windows-2019
|
||||
# timeoutInMinutes: 60
|
||||
# variables:
|
||||
# VSCODE_ARCH: x64
|
||||
# steps:
|
||||
# - template: win32/product-build-win32.yml
|
||||
# parameters:
|
||||
# VSCODE_PUBLISH: ${{ variables.VSCODE_PUBLISH }}
|
||||
# VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
|
||||
# VSCODE_RUN_UNIT_TESTS: false
|
||||
# VSCODE_RUN_INTEGRATION_TESTS: true
|
||||
# VSCODE_RUN_SMOKE_TESTS: false
|
||||
# - job: WindowsSmokeTests
|
||||
# displayName: Windows (Smoke Tests)
|
||||
# pool: vscode-1es-vscode-windows-2019
|
||||
# timeoutInMinutes: 60
|
||||
# variables:
|
||||
# VSCODE_ARCH: x64
|
||||
# steps:
|
||||
# - template: win32/product-build-win32.yml
|
||||
# parameters:
|
||||
# VSCODE_PUBLISH: ${{ variables.VSCODE_PUBLISH }}
|
||||
# VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }}
|
||||
# VSCODE_RUN_UNIT_TESTS: false
|
||||
# VSCODE_RUN_INTEGRATION_TESTS: false
|
||||
# VSCODE_RUN_SMOKE_TESTS: true
|
||||
|
|
|
@ -399,6 +399,7 @@ const esbuildMediaScripts = [
|
|||
'markdown-language-features/esbuild-preview.js',
|
||||
'markdown-math/esbuild.js',
|
||||
'notebook-renderers/esbuild.js',
|
||||
'ipynb/esbuild.js',
|
||||
'simple-browser/esbuild-preview.js',
|
||||
];
|
||||
async function webpackExtensions(taskName, isWatch, webpackConfigLocations) {
|
||||
|
|
|
@ -486,6 +486,7 @@ const esbuildMediaScripts = [
|
|||
'markdown-language-features/esbuild-preview.js',
|
||||
'markdown-math/esbuild.js',
|
||||
'notebook-renderers/esbuild.js',
|
||||
'ipynb/esbuild.js',
|
||||
'simple-browser/esbuild-preview.js',
|
||||
];
|
||||
|
||||
|
|
|
@ -298,6 +298,10 @@
|
|||
"name": "vs/workbench/contrib/deprecatedExtensionMigrator",
|
||||
"project": "vscode-workbench"
|
||||
},
|
||||
{
|
||||
"name": "vs/workbench/contrib/bracketPairColorizer2Telemetry",
|
||||
"project": "vscode-workbench"
|
||||
},
|
||||
{
|
||||
"name": "vs/workbench/contrib/offline",
|
||||
"project": "vscode-workbench"
|
||||
|
|
|
@ -228,6 +228,12 @@ function getColor(node) {
|
|||
function setColor(node, color) {
|
||||
node.$$$color = color;
|
||||
}
|
||||
function markNeededSourceFile(node) {
|
||||
node.$$$neededSourceFile = true;
|
||||
}
|
||||
function isNeededSourceFile(node) {
|
||||
return Boolean(node.$$$neededSourceFile);
|
||||
}
|
||||
function nodeOrParentIsBlack(node) {
|
||||
while (node) {
|
||||
const color = getColor(node);
|
||||
|
@ -353,6 +359,19 @@ function markNodes(ts, languageService, options) {
|
|||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Return the parent of `node` which is an ImportDeclaration
|
||||
*/
|
||||
function findParentImportDeclaration(node) {
|
||||
let _node = node;
|
||||
do {
|
||||
if (ts.isImportDeclaration(_node)) {
|
||||
return _node;
|
||||
}
|
||||
_node = _node.parent;
|
||||
} while (_node);
|
||||
return null;
|
||||
}
|
||||
function enqueue_gray(node) {
|
||||
if (nodeOrParentIsBlack(node) || getColor(node) === 1 /* NodeColor.Gray */) {
|
||||
return;
|
||||
|
@ -420,6 +439,8 @@ function markNodes(ts, languageService, options) {
|
|||
console.warn(`Cannot find source file ${filename}`);
|
||||
return;
|
||||
}
|
||||
// This source file should survive even if it is empty
|
||||
markNeededSourceFile(sourceFile);
|
||||
enqueue_black(sourceFile);
|
||||
}
|
||||
function enqueueImport(node, importText) {
|
||||
|
@ -472,6 +493,10 @@ function markNodes(ts, languageService, options) {
|
|||
const [symbol, symbolImportNode] = getRealNodeSymbol(ts, checker, node);
|
||||
if (symbolImportNode) {
|
||||
setColor(symbolImportNode, 2 /* NodeColor.Black */);
|
||||
const importDeclarationNode = findParentImportDeclaration(symbolImportNode);
|
||||
if (importDeclarationNode && ts.isStringLiteral(importDeclarationNode.moduleSpecifier)) {
|
||||
enqueueImport(importDeclarationNode, importDeclarationNode.moduleSpecifier.text);
|
||||
}
|
||||
}
|
||||
if (isSymbolWithDeclarations(symbol) && !nodeIsInItsOwnDeclaration(nodeSourceFile, node, symbol)) {
|
||||
for (let i = 0, len = symbol.declarations.length; i < len; i++) {
|
||||
|
@ -663,11 +688,23 @@ function generateResult(ts, languageService, shakeLevel) {
|
|||
}
|
||||
if (getColor(sourceFile) !== 2 /* NodeColor.Black */) {
|
||||
if (!nodeOrChildIsBlack(sourceFile)) {
|
||||
// none of the elements are reachable => don't write this file at all!
|
||||
return;
|
||||
// none of the elements are reachable
|
||||
if (isNeededSourceFile(sourceFile)) {
|
||||
// this source file must be written, even if nothing is used from it
|
||||
// because there is an import somewhere for it.
|
||||
// However, TS complains with empty files with the error "x" is not a module,
|
||||
// so we will export a dummy variable
|
||||
result = 'export const __dummy = 0;';
|
||||
}
|
||||
else {
|
||||
// don't write this file at all!
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
sourceFile.forEachChild(writeMarkedNodes);
|
||||
result += sourceFile.endOfFileToken.getFullText(sourceFile);
|
||||
}
|
||||
sourceFile.forEachChild(writeMarkedNodes);
|
||||
result += sourceFile.endOfFileToken.getFullText(sourceFile);
|
||||
}
|
||||
else {
|
||||
result = text;
|
||||
|
|
|
@ -307,6 +307,12 @@ function getColor(node: ts.Node): NodeColor {
|
|||
function setColor(node: ts.Node, color: NodeColor): void {
|
||||
(<any>node).$$$color = color;
|
||||
}
|
||||
function markNeededSourceFile(node: ts.SourceFile): void {
|
||||
(<any>node).$$$neededSourceFile = true;
|
||||
}
|
||||
function isNeededSourceFile(node: ts.SourceFile): boolean {
|
||||
return Boolean((<any>node).$$$neededSourceFile);
|
||||
}
|
||||
function nodeOrParentIsBlack(node: ts.Node): boolean {
|
||||
while (node) {
|
||||
const color = getColor(node);
|
||||
|
@ -449,6 +455,20 @@ function markNodes(ts: typeof import('typescript'), languageService: ts.Language
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the parent of `node` which is an ImportDeclaration
|
||||
*/
|
||||
function findParentImportDeclaration(node: ts.Declaration): ts.ImportDeclaration | null {
|
||||
let _node: ts.Node = node;
|
||||
do {
|
||||
if (ts.isImportDeclaration(_node)) {
|
||||
return _node;
|
||||
}
|
||||
_node = _node.parent;
|
||||
} while (_node);
|
||||
return null;
|
||||
}
|
||||
|
||||
function enqueue_gray(node: ts.Node): void {
|
||||
if (nodeOrParentIsBlack(node) || getColor(node) === NodeColor.Gray) {
|
||||
return;
|
||||
|
@ -531,6 +551,8 @@ function markNodes(ts: typeof import('typescript'), languageService: ts.Language
|
|||
console.warn(`Cannot find source file ${filename}`);
|
||||
return;
|
||||
}
|
||||
// This source file should survive even if it is empty
|
||||
markNeededSourceFile(sourceFile);
|
||||
enqueue_black(sourceFile);
|
||||
}
|
||||
|
||||
|
@ -590,6 +612,10 @@ function markNodes(ts: typeof import('typescript'), languageService: ts.Language
|
|||
const [symbol, symbolImportNode] = getRealNodeSymbol(ts, checker, node);
|
||||
if (symbolImportNode) {
|
||||
setColor(symbolImportNode, NodeColor.Black);
|
||||
const importDeclarationNode = findParentImportDeclaration(symbolImportNode);
|
||||
if (importDeclarationNode && ts.isStringLiteral(importDeclarationNode.moduleSpecifier)) {
|
||||
enqueueImport(importDeclarationNode, importDeclarationNode.moduleSpecifier.text);
|
||||
}
|
||||
}
|
||||
|
||||
if (isSymbolWithDeclarations(symbol) && !nodeIsInItsOwnDeclaration(nodeSourceFile, node, symbol)) {
|
||||
|
@ -802,11 +828,21 @@ function generateResult(ts: typeof import('typescript'), languageService: ts.Lan
|
|||
|
||||
if (getColor(sourceFile) !== NodeColor.Black) {
|
||||
if (!nodeOrChildIsBlack(sourceFile)) {
|
||||
// none of the elements are reachable => don't write this file at all!
|
||||
return;
|
||||
// none of the elements are reachable
|
||||
if (isNeededSourceFile(sourceFile)) {
|
||||
// this source file must be written, even if nothing is used from it
|
||||
// because there is an import somewhere for it.
|
||||
// However, TS complains with empty files with the error "x" is not a module,
|
||||
// so we will export a dummy variable
|
||||
result = 'export const __dummy = 0;';
|
||||
} else {
|
||||
// don't write this file at all!
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
sourceFile.forEachChild(writeMarkedNodes);
|
||||
result += sourceFile.endOfFileToken.getFullText(sourceFile);
|
||||
}
|
||||
sourceFile.forEachChild(writeMarkedNodes);
|
||||
result += sourceFile.endOfFileToken.getFullText(sourceFile);
|
||||
} else {
|
||||
result = text;
|
||||
}
|
||||
|
|
|
@ -173,5 +173,32 @@
|
|||
"OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE",
|
||||
"SOFTWARE"
|
||||
]
|
||||
},
|
||||
{
|
||||
// Reason: Waiting for https://github.com/microsoft/vscode-markdown-languageservice/pull/9
|
||||
"name": "vscode-markdown-languageservice",
|
||||
"fullLicenseText": [
|
||||
"MIT License",
|
||||
"",
|
||||
"Copyright (c) Microsoft Corporation.",
|
||||
"",
|
||||
"Permission is hereby granted, free of charge, to any person obtaining a copy",
|
||||
"of this software and associated documentation files (the \"Software\"), to deal",
|
||||
"in the Software without restriction, including without limitation the rights",
|
||||
"to use, copy, modify, merge, publish, distribute, sublicense, and/or sell",
|
||||
"copies of the Software, and to permit persons to whom the Software is",
|
||||
"furnished to do so, subject to the following conditions:",
|
||||
"",
|
||||
"The above copyright notice and this permission notice shall be included in all",
|
||||
"copies or substantial portions of the Software.",
|
||||
"",
|
||||
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR",
|
||||
"IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,",
|
||||
"FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE",
|
||||
"AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER",
|
||||
"LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,",
|
||||
"OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE",
|
||||
"SOFTWARE"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -0,0 +1,189 @@
|
|||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"customizations": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"codespaces": {
|
||||
"type": "object",
|
||||
"description": "Customizations specific to GitHub Codespaces",
|
||||
"properties": {
|
||||
"repositories": {
|
||||
"type": "object",
|
||||
"description": "Configuration relative to the given repositories, following the format 'owner/repo'.\n A wildcard (*) is permitted for the repo name (eg: 'microsoft/*')",
|
||||
"patternProperties": {
|
||||
"^[a-zA-Z0-9-_.]+[.]*\/[a-zA-Z0-9-_*]+[.]*$": {
|
||||
"type": "object",
|
||||
"additionalProperties": true,
|
||||
"oneOf": [
|
||||
{
|
||||
"properties": {
|
||||
"permissions": {
|
||||
"type": "object",
|
||||
"description": "Additional repository permissions.\n See https://aka.ms/ghcs/multi-repo-auth for more info.",
|
||||
"additionalProperties": true,
|
||||
"anyOf": [
|
||||
{
|
||||
"properties": {
|
||||
"actions": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"checks": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"contents": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"deployments": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"discussions": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"issues": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"packages": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"read"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"pages": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"pull_requests": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"repository_projects": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"statuses": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"workflows": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"write"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"permissions": {
|
||||
"type": "string",
|
||||
"description": "Additional repository permissions.\n See https://aka.ms/ghcs/multi-repo-auth for more info.",
|
||||
"enum": [
|
||||
"read-all",
|
||||
"write-all"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"codespaces": {
|
||||
"type": "object",
|
||||
"additionalProperties": true,
|
||||
"description": "Codespaces-specific configuration.",
|
||||
"deprecated": true,
|
||||
"deprecationMessage": "Use 'customizations/codespaces' instead"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"customizations": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"vscode": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"extensions": {
|
||||
"type": "array",
|
||||
"description": "An array of extensions that should be installed into the container.",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"pattern": "^([a-z0-9A-Z][a-z0-9A-Z-]*)\\.([a-z0-9A-Z][a-z0-9A-Z-]*)(@(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?)?$",
|
||||
"errorMessage": "Expected format: '${publisher}.${name}' or '${publisher}.${name}@${version}'. Example: 'ms-dotnettools.csharp'."
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"$ref": "vscode://schemas/settings/machine",
|
||||
"description": "Machine specific settings that should be copied into the container. These are only copied when connecting to the container for the first time, rebuilding the container then triggers it again."
|
||||
},
|
||||
"devPort": {
|
||||
"type": "integer",
|
||||
"description": "The port VS Code can use to connect to its backend."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"extensions": {
|
||||
"type": "array",
|
||||
"description": "An array of extensions that should be installed into the container.",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"pattern": "^([a-z0-9A-Z][a-z0-9A-Z-]*)\\.([a-z0-9A-Z][a-z0-9A-Z-]*)((@(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?)|@prerelease)?$",
|
||||
"errorMessage": "Expected format: '${publisher}.${name}' or '${publisher}.${name}@${version}'. Example: 'ms-dotnettools.csharp'."
|
||||
},
|
||||
"deprecated": true,
|
||||
"deprecationMessage": "Use 'customizations/vscode/extensions' instead"
|
||||
},
|
||||
"settings": {
|
||||
"$ref": "vscode://schemas/settings/machine",
|
||||
"description": "Machine specific settings that should be copied into the container. These are only copied when connecting to the container for the first time, rebuilding the container then triggers it again.",
|
||||
"deprecated": true,
|
||||
"deprecationMessage": "Use 'customizations/vscode/settings' instead"
|
||||
},
|
||||
"devPort": {
|
||||
"type": "integer",
|
||||
"description": "The port VS Code can use to connect to its backend.",
|
||||
"deprecated": true,
|
||||
"deprecationMessage": "Use 'customizations/vscode/devPort' instead"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -65,6 +65,7 @@
|
|||
"emmet.showAbbreviationSuggestions": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"scope": "language-overridable",
|
||||
"markdownDescription": "%emmetShowAbbreviationSuggestions%"
|
||||
},
|
||||
"emmet.includeLanguages": {
|
||||
|
@ -125,6 +126,7 @@
|
|||
"emmet.triggerExpansionOnTab": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"scope": "language-overridable",
|
||||
"markdownDescription": "%emmetTriggerExpansionOnTab%"
|
||||
},
|
||||
"emmet.useInlineCompletions": {
|
||||
|
|
|
@ -95,18 +95,19 @@ export class ActionButtonCommand {
|
|||
return {
|
||||
command: this.getCommitActionButtonPrimaryCommand(),
|
||||
secondaryCommands: this.getCommitActionButtonSecondaryCommands(),
|
||||
enabled: this.state.repositoryHasChangesToCommit && !this.state.isCommitInProgress && !this.state.isMergeInProgress
|
||||
enabled: (this.state.repositoryHasChangesToCommit || this.state.isRebaseInProgress) && !this.state.isCommitInProgress && !this.state.isMergeInProgress
|
||||
};
|
||||
}
|
||||
|
||||
private getCommitActionButtonPrimaryCommand(): Command {
|
||||
let commandArg = '';
|
||||
let title = localize('scm button commit title', "{0} Commit", '$(check)');
|
||||
let tooltip = this.state.isCommitInProgress ? localize('scm button committing tooltip', "Committing Changes...") : localize('scm button commit tooltip', "Commit Changes");
|
||||
|
||||
// Rebase Continue
|
||||
if (this.state.isRebaseInProgress) {
|
||||
return { command: 'git.commit', title, tooltip, arguments: [this.repository.sourceControl, commandArg] };
|
||||
return {
|
||||
command: 'git.commit',
|
||||
title: localize('scm button continue title', "{0} Continue", '$(check)'),
|
||||
tooltip: this.state.isCommitInProgress ? localize('scm button continuing tooltip', "Continuing Rebase...") : localize('scm button continue tooltip', "Continue Rebase"),
|
||||
arguments: [this.repository.sourceControl, '']
|
||||
};
|
||||
}
|
||||
|
||||
// Commit
|
||||
|
@ -122,6 +123,10 @@ export class ActionButtonCommand {
|
|||
// Icon
|
||||
const icon = alwaysPrompt ? '$(lock)' : alwaysCommitToNewBranch ? '$(git-branch)' : undefined;
|
||||
|
||||
let commandArg = '';
|
||||
let title = localize('scm button commit title', "{0} Commit", icon ?? '$(check)');
|
||||
let tooltip = this.state.isCommitInProgress ? localize('scm button committing tooltip', "Committing Changes...") : localize('scm button commit tooltip', "Commit Changes");
|
||||
|
||||
// Title, tooltip
|
||||
switch (postCommitCommand) {
|
||||
case 'push': {
|
||||
|
|
|
@ -1558,6 +1558,8 @@ export class CommandCenter {
|
|||
// amend allows changing only the commit message
|
||||
&& !opts.amend
|
||||
&& !opts.empty
|
||||
// rebase not in progress
|
||||
&& repository.rebaseCommit === undefined
|
||||
) {
|
||||
const commitAnyway = localize('commit anyway', "Create Empty Commit");
|
||||
const answer = await window.showInformationMessage(localize('no changes', "There are no changes to commit."), commitAnyway);
|
||||
|
@ -1770,7 +1772,7 @@ export class CommandCenter {
|
|||
const shouldPrompt = config.get<boolean>('confirmEmptyCommits') === true;
|
||||
|
||||
if (shouldPrompt) {
|
||||
const message = localize('confirm emtpy commit', "Are you sure you want to create an empty commit?");
|
||||
const message = localize('confirm empty commit', "Are you sure you want to create an empty commit?");
|
||||
const yes = localize('yes', "Yes");
|
||||
const neverAgain = localize('yes never again', "Yes, Don't Show Again");
|
||||
const pick = await window.showWarningMessage(message, { modal: true }, yes, neverAgain);
|
||||
|
|
|
@ -9,9 +9,13 @@ import { publishRepository } from './publish';
|
|||
import { DisposableStore } from './util';
|
||||
import { getPermalink } from './links';
|
||||
|
||||
function getVscodeDevHost(): string {
|
||||
return `https://${vscode.env.appName.toLowerCase().includes('insiders') ? 'insiders.' : ''}vscode.dev/github`;
|
||||
}
|
||||
|
||||
async function copyVscodeDevLink(gitAPI: GitAPI, useSelection: boolean) {
|
||||
try {
|
||||
const permalink = getPermalink(gitAPI, useSelection, 'https://vscode.dev/github');
|
||||
const permalink = getPermalink(gitAPI, useSelection, getVscodeDevHost());
|
||||
if (permalink) {
|
||||
return vscode.env.clipboard.writeText(permalink);
|
||||
}
|
||||
|
@ -22,7 +26,7 @@ async function copyVscodeDevLink(gitAPI: GitAPI, useSelection: boolean) {
|
|||
|
||||
async function openVscodeDevLink(gitAPI: GitAPI): Promise<vscode.Uri | undefined> {
|
||||
try {
|
||||
const permalink = getPermalink(gitAPI, true, 'https://vscode.dev/github');
|
||||
const permalink = getPermalink(gitAPI, true, getVscodeDevHost());
|
||||
return permalink ? vscode.Uri.parse(permalink) : undefined;
|
||||
} catch (err) {
|
||||
vscode.window.showErrorMessage(err.message);
|
||||
|
|
|
@ -125,11 +125,11 @@ export function getPermalink(gitAPI: GitAPI, useSelection: boolean, hostPrefix?:
|
|||
return;
|
||||
}
|
||||
|
||||
const commitHash = gitRepo.state.HEAD?.commit;
|
||||
const commitHash = (gitRepo.state.HEAD?.ahead === 0) ? `/blob/${gitRepo.state.HEAD?.commit}` : '';
|
||||
const fileSegments = fileAndPosition.type === LinkType.File
|
||||
? (useSelection ? `${uri.path.substring(gitRepo.rootUri.path.length)}${rangeString(fileAndPosition.range)}` : '')
|
||||
: (useSelection ? `${uri.path.substring(gitRepo.rootUri.path.length)}${notebookCellRangeString(fileAndPosition.cellIndex, fileAndPosition.range)}` : '');
|
||||
|
||||
return `${hostPrefix}/${repo.owner}/${repo.repo}/blob/${commitHash
|
||||
return `${hostPrefix}/${repo.owner}/${repo.repo}${commitHash
|
||||
}${fileSegments}`;
|
||||
}
|
||||
|
|
1
extensions/ipynb/.gitignore
vendored
1
extensions/ipynb/.gitignore
vendored
|
@ -2,3 +2,4 @@ out
|
|||
dist
|
||||
node_modules
|
||||
*.vsix
|
||||
notebook-out
|
||||
|
|
|
@ -6,4 +6,4 @@ extension.webpack.config.js
|
|||
extension-browser.webpack.config.js
|
||||
yarn.lock
|
||||
.gitignore
|
||||
|
||||
esbuild.js
|
||||
|
|
|
@ -19,7 +19,7 @@ if (outputRootIndex >= 0) {
|
|||
}
|
||||
|
||||
const srcDir = path.join(__dirname, 'src');
|
||||
const outDir = path.join(outputRoot, 'out');
|
||||
const outDir = path.join(outputRoot, 'notebook-out');
|
||||
|
||||
async function build() {
|
||||
await esbuild.build({
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
"displayName": "Markdown it ipynb Cell Attachment renderer",
|
||||
"entrypoint": {
|
||||
"extends": "vscode.markdown-it-renderer",
|
||||
"path": "./out/cellAttachmentRenderer.js"
|
||||
"path": "./notebook-out/cellAttachmentRenderer.js"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
|
|
@ -22,11 +22,19 @@ export async function activate(ctx: RendererContext<void>) {
|
|||
md.renderer.rules.image = (tokens: MarkdownItToken[], idx: number, options, env, self) => {
|
||||
const token = tokens[idx];
|
||||
const src = token.attrGet('src');
|
||||
const attachments: Record<string, Record<string, string>> = env.outputItem.metadata?.custom?.attachments;
|
||||
const attachments: Record<string, Record<string, string>> = env.outputItem.metadata?.custom?.attachments; // this stores attachment entries for every image in the cell
|
||||
if (attachments && src) {
|
||||
const [attachmentKey, attachmentVal] = Object.entries(attachments[src.replace('attachment:', '')])[0];
|
||||
const b64Markdown = 'data:' + attachmentKey + ';base64,' + attachmentVal;
|
||||
token.attrSet('src', b64Markdown);
|
||||
const imageAttachment = attachments[src.replace('attachment:', '')];
|
||||
if (imageAttachment) {
|
||||
// objEntries will always be length 1, with objEntries[0] holding [0]=mime,[1]=b64
|
||||
// if length = 0, something is wrong with the attachment, mime/b64 weren't copied over
|
||||
const objEntries = Object.entries(imageAttachment);
|
||||
if (objEntries.length) {
|
||||
const [attachmentKey, attachmentVal] = objEntries[0];
|
||||
const b64Markdown = 'data:' + attachmentKey + ';base64,' + attachmentVal;
|
||||
token.attrSet('src', b64Markdown);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (original) {
|
||||
|
|
|
@ -12,7 +12,8 @@ cgmanifest.json
|
|||
yarn.lock
|
||||
preview-src/**
|
||||
webpack.config.js
|
||||
esbuild.js
|
||||
esbuild-notebook.js
|
||||
esbuild-preview.js
|
||||
.gitignore
|
||||
server/src/**
|
||||
server/extension.webpack.config.js
|
||||
|
|
|
@ -8,57 +8,108 @@ import MarkdownIt from 'markdown-it';
|
|||
import type * as MarkdownItToken from 'markdown-it/lib/token';
|
||||
import type { ActivationFunction } from 'vscode-notebook-renderer';
|
||||
|
||||
const allowedHtmlTags = Object.freeze([
|
||||
'a',
|
||||
'b',
|
||||
'blockquote',
|
||||
'br',
|
||||
'button',
|
||||
'caption',
|
||||
'center',
|
||||
'code',
|
||||
'col',
|
||||
'colgroup',
|
||||
'details',
|
||||
'div',
|
||||
'em',
|
||||
'font',
|
||||
'h1',
|
||||
'h2',
|
||||
'h3',
|
||||
'h4',
|
||||
'h5',
|
||||
'h6',
|
||||
'hr',
|
||||
'i',
|
||||
'img',
|
||||
'input',
|
||||
'kbd',
|
||||
'label',
|
||||
'li',
|
||||
'ol',
|
||||
'p',
|
||||
'pre',
|
||||
'select',
|
||||
'small',
|
||||
'span',
|
||||
'strong',
|
||||
'sub',
|
||||
'summary',
|
||||
'sup',
|
||||
'table',
|
||||
'tbody',
|
||||
'td',
|
||||
'textarea',
|
||||
'tfoot',
|
||||
'th',
|
||||
'thead',
|
||||
'tr',
|
||||
'tt',
|
||||
'u',
|
||||
'ul',
|
||||
'video',
|
||||
]);
|
||||
|
||||
const allowedSvgTags = Object.freeze([
|
||||
'svg',
|
||||
'a',
|
||||
'altglyph',
|
||||
'altglyphdef',
|
||||
'altglyphitem',
|
||||
'animatecolor',
|
||||
'animatemotion',
|
||||
'animatetransform',
|
||||
'circle',
|
||||
'clippath',
|
||||
'defs',
|
||||
'desc',
|
||||
'ellipse',
|
||||
'filter',
|
||||
'font',
|
||||
'g',
|
||||
'glyph',
|
||||
'glyphref',
|
||||
'hkern',
|
||||
'image',
|
||||
'line',
|
||||
'lineargradient',
|
||||
'marker',
|
||||
'mask',
|
||||
'metadata',
|
||||
'mpath',
|
||||
'path',
|
||||
'pattern',
|
||||
'polygon',
|
||||
'polyline',
|
||||
'radialgradient',
|
||||
'rect',
|
||||
'stop',
|
||||
'style',
|
||||
'switch',
|
||||
'symbol',
|
||||
'text',
|
||||
'textpath',
|
||||
'title',
|
||||
'tref',
|
||||
'tspan',
|
||||
'view',
|
||||
'vkern',
|
||||
]);
|
||||
|
||||
const sanitizerOptions: DOMPurify.Config = {
|
||||
ALLOWED_TAGS: [
|
||||
'a',
|
||||
'b',
|
||||
'blockquote',
|
||||
'br',
|
||||
'button',
|
||||
'caption',
|
||||
'center',
|
||||
'code',
|
||||
'col',
|
||||
'colgroup',
|
||||
'details',
|
||||
'div',
|
||||
'em',
|
||||
'font',
|
||||
'h1',
|
||||
'h2',
|
||||
'h3',
|
||||
'h4',
|
||||
'h5',
|
||||
'h6',
|
||||
'hr',
|
||||
'i',
|
||||
'img',
|
||||
'input',
|
||||
'kbd',
|
||||
'label',
|
||||
'li',
|
||||
'ol',
|
||||
'p',
|
||||
'pre',
|
||||
'select',
|
||||
'small',
|
||||
'span',
|
||||
'strong',
|
||||
'sub',
|
||||
'summary',
|
||||
'sup',
|
||||
'table',
|
||||
'tbody',
|
||||
'td',
|
||||
'textarea',
|
||||
'tfoot',
|
||||
'th',
|
||||
'thead',
|
||||
'tr',
|
||||
'tt',
|
||||
'u',
|
||||
'ul',
|
||||
'video',
|
||||
...allowedHtmlTags,
|
||||
...allowedSvgTags,
|
||||
],
|
||||
};
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
"configuration.markdown.links.openLocation.currentGroup": "Open links in the active editor group.",
|
||||
"configuration.markdown.links.openLocation.beside": "Open links beside the active editor.",
|
||||
"configuration.markdown.suggest.paths.enabled.description": "Enable/disable path suggestions for markdown links",
|
||||
"configuration.markdown.editor.drop.enabled": "Enable/disable dropping into the markdown editor to insert shift. Requires enabling `#workbench.editor.dropIntoEditor.enabled#`.",
|
||||
"configuration.markdown.editor.drop.enabled": "Enable/disable dropping into the markdown editor to insert shift. Requires enabling `#editor.dropIntoEditor.enabled#`.",
|
||||
"configuration.markdown.editor.pasteLinks.enabled": "Enable/disable pasting files into a Markdown editor inserts Markdown links. Requires enabling `#editor.experimental.pasteActions.enabled#`.",
|
||||
"configuration.markdown.experimental.validate.enabled.description": "Enable/disable all error reporting in Markdown files.",
|
||||
"configuration.markdown.experimental.validate.referenceLinks.enabled.description": "Validate reference links in Markdown files, e.g. `[link][ref]`. Requires enabling `#markdown.experimental.validate.enabled#`.",
|
||||
|
|
|
@ -11,7 +11,7 @@ import * as nls from 'vscode-nls';
|
|||
import { v4 as uuid } from 'uuid';
|
||||
import fetch, { Response } from 'node-fetch';
|
||||
import Logger from './logger';
|
||||
import { toBase64UrlEncoding } from './utils';
|
||||
import { isSupportedEnvironment, toBase64UrlEncoding } from './utils';
|
||||
import { sha256 } from './env/node/sha256';
|
||||
import { BetterTokenStorage, IDidChangeInOtherWindowEvent } from './betterSecretStorage';
|
||||
import { LoopbackAuthServer } from './authServer';
|
||||
|
@ -319,13 +319,7 @@ export class AzureActiveDirectoryService {
|
|||
}, 5000);
|
||||
}
|
||||
|
||||
const token = await this.exchangeCodeForToken(codeToExchange, codeVerifier, scopeData);
|
||||
if (token.expiresIn) {
|
||||
this.setSessionTimeout(token.sessionId, token.refreshToken, scopeData, token.expiresIn * AzureActiveDirectoryService.REFRESH_TIMEOUT_MODIFIER);
|
||||
}
|
||||
await this.setToken(token, scopeData);
|
||||
Logger.info(`Login successful for scopes: ${scopeData.scopeStr}`);
|
||||
const session = await this.convertToSession(token);
|
||||
const session = await this.exchangeCodeForSession(codeToExchange, codeVerifier, scopeData);
|
||||
return session;
|
||||
}
|
||||
|
||||
|
@ -355,9 +349,11 @@ export class AzureActiveDirectoryService {
|
|||
const uri = vscode.Uri.parse(`${signInUrl}?${oauthStartQuery.toString()}`);
|
||||
vscode.env.openExternal(uri);
|
||||
|
||||
let inputBox: vscode.InputBox | undefined;
|
||||
const timeoutPromise = new Promise((_: (value: vscode.AuthenticationSession) => void, reject) => {
|
||||
const wait = setTimeout(() => {
|
||||
clearTimeout(wait);
|
||||
inputBox?.dispose();
|
||||
reject('Login timed out.');
|
||||
}, 1000 * 60 * 5);
|
||||
});
|
||||
|
@ -369,7 +365,12 @@ export class AzureActiveDirectoryService {
|
|||
// before completing it.
|
||||
let existingPromise = this._codeExchangePromises.get(scopeData.scopeStr);
|
||||
if (!existingPromise) {
|
||||
existingPromise = this.handleCodeResponse(scopeData);
|
||||
if (isSupportedEnvironment(callbackUri)) {
|
||||
existingPromise = this.handleCodeResponse(scopeData);
|
||||
} else {
|
||||
inputBox = vscode.window.createInputBox();
|
||||
existingPromise = Promise.race([this.handleCodeInputBox(inputBox, codeVerifier, scopeData), this.handleCodeResponse(scopeData)]);
|
||||
}
|
||||
this._codeExchangePromises.set(scopeData.scopeStr, existingPromise);
|
||||
}
|
||||
|
||||
|
@ -659,13 +660,7 @@ export class AzureActiveDirectoryService {
|
|||
throw new Error('No available code verifier');
|
||||
}
|
||||
|
||||
const token = await this.exchangeCodeForToken(code, verifier, scopeData);
|
||||
if (token.expiresIn) {
|
||||
this.setSessionTimeout(token.sessionId, token.refreshToken, scopeData, token.expiresIn * AzureActiveDirectoryService.REFRESH_TIMEOUT_MODIFIER);
|
||||
}
|
||||
await this.setToken(token, scopeData);
|
||||
|
||||
const session = await this.convertToSession(token);
|
||||
const session = await this.exchangeCodeForSession(code, verifier, scopeData);
|
||||
resolve(session);
|
||||
} catch (err) {
|
||||
reject(err);
|
||||
|
@ -680,8 +675,33 @@ export class AzureActiveDirectoryService {
|
|||
});
|
||||
}
|
||||
|
||||
private async exchangeCodeForToken(code: string, codeVerifier: string, scopeData: IScopeData): Promise<IToken> {
|
||||
private async handleCodeInputBox(inputBox: vscode.InputBox, verifier: string, scopeData: IScopeData): Promise<vscode.AuthenticationSession> {
|
||||
inputBox.ignoreFocusOut = true;
|
||||
inputBox.title = localize('pasteCodeTitle', 'Microsoft Authentication');
|
||||
inputBox.prompt = localize('pasteCodePrompt', 'Provide the authorization code to complete the sign in flow.');
|
||||
inputBox.placeholder = localize('pasteCodePlaceholder', 'Paste authorization code here...');
|
||||
return new Promise((resolve: (value: vscode.AuthenticationSession) => void, reject) => {
|
||||
inputBox.show();
|
||||
inputBox.onDidAccept(async () => {
|
||||
const code = inputBox.value;
|
||||
if (code) {
|
||||
inputBox.dispose();
|
||||
const session = await this.exchangeCodeForSession(code, verifier, scopeData);
|
||||
resolve(session);
|
||||
}
|
||||
});
|
||||
inputBox.onDidHide(() => {
|
||||
if (!inputBox.value) {
|
||||
inputBox.dispose();
|
||||
reject('Cancelled');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private async exchangeCodeForSession(code: string, codeVerifier: string, scopeData: IScopeData): Promise<vscode.AuthenticationSession> {
|
||||
Logger.info(`Exchanging login code for token for scopes: ${scopeData.scopeStr}`);
|
||||
let token: IToken | undefined;
|
||||
try {
|
||||
const postData = querystring.stringify({
|
||||
grant_type: 'authorization_code',
|
||||
|
@ -698,11 +718,18 @@ export class AzureActiveDirectoryService {
|
|||
|
||||
const json = await this.fetchTokenResponse(endpoint, postData, scopeData);
|
||||
Logger.info(`Exchanging login code for token (for scopes: ${scopeData.scopeStr}) succeeded!`);
|
||||
return this.convertToTokenSync(json, scopeData);
|
||||
token = this.convertToTokenSync(json, scopeData);
|
||||
} catch (e) {
|
||||
Logger.error(`Error exchanging code for token (for scopes ${scopeData.scopeStr}): ${e}`);
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (token.expiresIn) {
|
||||
this.setSessionTimeout(token.sessionId, token.refreshToken, scopeData, token.expiresIn * AzureActiveDirectoryService.REFRESH_TIMEOUT_MODIFIER);
|
||||
}
|
||||
await this.setToken(token, scopeData);
|
||||
Logger.info(`Login successful for scopes: ${scopeData.scopeStr}`);
|
||||
return await this.convertToSession(token);
|
||||
}
|
||||
|
||||
private async fetchTokenResponse(endpoint: string, postData: string, scopeData: IScopeData): Promise<ITokenResponse> {
|
||||
|
|
|
@ -2,7 +2,40 @@
|
|||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import { env, UIKind, Uri } from 'vscode';
|
||||
|
||||
export function toBase64UrlEncoding(base64string: string) {
|
||||
return base64string.replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_'); // Need to use base64url encoding
|
||||
}
|
||||
|
||||
const LOCALHOST_ADDRESSES = ['localhost', '127.0.0.1', '0:0:0:0:0:0:0:1', '::1'];
|
||||
function isLocalhost(uri: Uri): boolean {
|
||||
if (!/^https?$/i.test(uri.scheme)) {
|
||||
return false;
|
||||
}
|
||||
const host = uri.authority.split(':')[0];
|
||||
return LOCALHOST_ADDRESSES.indexOf(host) >= 0;
|
||||
}
|
||||
|
||||
export function isSupportedEnvironment(uri: Uri): boolean {
|
||||
if (env.uiKind === UIKind.Desktop) {
|
||||
return true;
|
||||
}
|
||||
// local development (localhost:* or 127.0.0.1:*)
|
||||
if (isLocalhost(uri)) {
|
||||
return true;
|
||||
}
|
||||
// At this point we should only ever see https
|
||||
if (uri.scheme !== 'https') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
// vscode.dev & insiders.vscode.dev
|
||||
/(?:^|\.)vscode\.dev$/.test(uri.authority) ||
|
||||
// github.dev & codespaces
|
||||
/(?:^|\.)github\.dev$/.test(uri.authority) ||
|
||||
// github.dev/codespaces local setup (github.localhost)
|
||||
/(?:^|\.)github\.localhost$/.test(uri.authority)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -11,3 +11,4 @@ cgmanifest.json
|
|||
yarn.lock
|
||||
preview-src/**
|
||||
webpack.config.js
|
||||
esbuild-preview.js
|
||||
|
|
|
@ -45,7 +45,8 @@ const nonBuiltInLanguages = { // { fileNames, extensions }
|
|||
const inheritIconFromLanguage = {
|
||||
"jsonc": 'json',
|
||||
"postcss": 'css',
|
||||
"django-html": 'html'
|
||||
"django-html": 'html',
|
||||
"blade": 'php'
|
||||
}
|
||||
|
||||
const FROM_DISK = true; // set to true to take content from a repo checked out next to the vscode repo
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
"git": {
|
||||
"name": "seti-ui",
|
||||
"repositoryUrl": "https://github.com/jesseweed/seti-ui",
|
||||
"commitHash": "4dd6c27e1f5aed8068c2451dbaf0db3364545937"
|
||||
"commitHash": "2d10473b7575ec00c47eda751ea9caeec6b0b606"
|
||||
}
|
||||
},
|
||||
"version": "0.1.0"
|
||||
|
|
Binary file not shown.
|
@ -1694,6 +1694,7 @@
|
|||
"tf": "_terraform",
|
||||
"tf.json": "_terraform",
|
||||
"tfvars": "_terraform",
|
||||
"tfvars.json": "_terraform",
|
||||
"dtx": "_tex_2",
|
||||
"ins": "_tex_3",
|
||||
"toml": "_config",
|
||||
|
@ -1942,7 +1943,8 @@
|
|||
"vala": "_vala",
|
||||
"vue": "_vue",
|
||||
"postcss": "_css",
|
||||
"django-html": "_html_3"
|
||||
"django-html": "_html_3",
|
||||
"blade": "_php"
|
||||
},
|
||||
"light": {
|
||||
"file": "_default_light",
|
||||
|
@ -2093,6 +2095,7 @@
|
|||
"tf": "_terraform_light",
|
||||
"tf.json": "_terraform_light",
|
||||
"tfvars": "_terraform_light",
|
||||
"tfvars.json": "_terraform_light",
|
||||
"dtx": "_tex_2_light",
|
||||
"ins": "_tex_3_light",
|
||||
"toml": "_config_light",
|
||||
|
@ -2258,7 +2261,8 @@
|
|||
"vala": "_vala_light",
|
||||
"vue": "_vue_light",
|
||||
"postcss": "_css_light",
|
||||
"django-html": "_html_3_light"
|
||||
"django-html": "_html_3_light",
|
||||
"blade": "_php_light"
|
||||
},
|
||||
"fileNames": {
|
||||
"mix": "_hex_light",
|
||||
|
@ -2340,5 +2344,5 @@
|
|||
"npm-debug.log": "_npm_ignored_light"
|
||||
}
|
||||
},
|
||||
"version": "https://github.com/jesseweed/seti-ui/commit/4dd6c27e1f5aed8068c2451dbaf0db3364545937"
|
||||
"version": "https://github.com/jesseweed/seti-ui/commit/2d10473b7575ec00c47eda751ea9caeec6b0b606"
|
||||
}
|
|
@ -430,32 +430,29 @@ export default class TypeScriptServiceClient extends Disposable implements IType
|
|||
});
|
||||
|
||||
handle.onExit((data: TypeScriptServerExitEvent) => {
|
||||
const { code, signal } = data;
|
||||
this.error(`TSServer exited. Code: ${code}. Signal: ${signal}`);
|
||||
|
||||
// In practice, the exit code is an integer with no ties to any identity,
|
||||
// so it can be classified as SystemMetaData, rather than CallstackOrException.
|
||||
/* __GDPR__
|
||||
"tsserver.exitWithCode" : {
|
||||
"owner": "mjbvz",
|
||||
"code" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" },
|
||||
"signal" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" },
|
||||
"${include}": [
|
||||
"${TypeScriptCommonProperties}"
|
||||
]
|
||||
}
|
||||
*/
|
||||
this.logTelemetry('tsserver.exitWithCode', { code: code ?? undefined, signal: signal ?? undefined });
|
||||
|
||||
|
||||
if (this.token !== mytoken) {
|
||||
// this is coming from an old process
|
||||
return;
|
||||
}
|
||||
|
||||
const { code, signal } = data;
|
||||
|
||||
if (code === null || typeof code === 'undefined') {
|
||||
this.info(`TSServer exited. Signal: ${signal}`);
|
||||
} else {
|
||||
// In practice, the exit code is an integer with no ties to any identity,
|
||||
// so it can be classified as SystemMetaData, rather than CallstackOrException.
|
||||
this.error(`TSServer exited with code: ${code}. Signal: ${signal}`);
|
||||
/* __GDPR__
|
||||
"tsserver.exitWithCode" : {
|
||||
"owner": "mjbvz",
|
||||
"code" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" },
|
||||
"signal" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" },
|
||||
"${include}": [
|
||||
"${TypeScriptCommonProperties}"
|
||||
]
|
||||
}
|
||||
*/
|
||||
this.logTelemetry('tsserver.exitWithCode', { code, signal: signal ?? undefined });
|
||||
}
|
||||
|
||||
if (handle.tsServerLogFile) {
|
||||
this.info(`TSServer log file: ${handle.tsServerLogFile}`);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "code-oss-dev",
|
||||
"version": "1.70.0",
|
||||
"distro": "990065ff739688c0d4ad94e172eeccd6bd5ef124",
|
||||
"distro": "25c5a766dec5d762c3205176fec650c6964c7763",
|
||||
"author": {
|
||||
"name": "Microsoft Corporation"
|
||||
},
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
},
|
||||
{
|
||||
"name": "ms-vscode.js-debug",
|
||||
"version": "1.69.0",
|
||||
"version": "1.70.0",
|
||||
"repo": "https://github.com/microsoft/vscode-js-debug",
|
||||
"metadata": {
|
||||
"id": "25629058-ddac-4e17-abba-74678e126c5d",
|
||||
|
@ -61,7 +61,7 @@
|
|||
},
|
||||
{
|
||||
"name": "ms-vscode.vscode-js-profile-table",
|
||||
"version": "1.0.2",
|
||||
"version": "1.0.3",
|
||||
"repo": "https://github.com/microsoft/vscode-js-profile-visualizer",
|
||||
"metadata": {
|
||||
"id": "7e52b41b-71ad-457b-ab7e-0620f1fc4feb",
|
||||
|
|
|
@ -58,11 +58,9 @@ apps:
|
|||
command: electron-launch $SNAP/usr/share/@@NAME@@/bin/@@NAME@@ --no-sandbox
|
||||
common-id: @@NAME@@.desktop
|
||||
environment:
|
||||
DISABLE_WAYLAND: 1
|
||||
GSETTINGS_SCHEMA_DIR: $SNAP/usr/share/glib-2.0/schemas
|
||||
|
||||
url-handler:
|
||||
command: electron-launch $SNAP/usr/share/@@NAME@@/bin/@@NAME@@ --open-url --no-sandbox
|
||||
environment:
|
||||
DISABLE_WAYLAND: 1
|
||||
GSETTINGS_SCHEMA_DIR: $SNAP/usr/share/glib-2.0/schemas
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
"vs/base/browser/defaultWorkerFactory.ts",
|
||||
"vs/base/worker/workerMain.ts",
|
||||
"vs/editor/contrib/markdownRenderer/browser/markdownRenderer.ts",
|
||||
"vs/editor/contrib/stickyScroll/browser/stickyScroll.ts",
|
||||
"vs/editor/browser/view/domLineBreaksComputer.ts",
|
||||
"vs/editor/browser/view/viewLayer.ts",
|
||||
"vs/editor/browser/widget/diffEditorWidget.ts",
|
||||
|
|
|
@ -1869,9 +1869,11 @@ export function h(tag: string, ...args: [] | [attributes: { $: string } & Partia
|
|||
typeof cssValue === 'number' ? cssValue + 'px' : '' + cssValue
|
||||
);
|
||||
}
|
||||
continue;
|
||||
} else if (key === 'tabIndex') {
|
||||
el.tabIndex = value;
|
||||
} else {
|
||||
el.setAttribute(camelCaseToHyphenCase(key), value.toString());
|
||||
}
|
||||
el.setAttribute(camelCaseToHyphenCase(key), value.toString());
|
||||
}
|
||||
|
||||
result['root'] = el;
|
||||
|
|
|
@ -126,9 +126,22 @@ export class DropdownMenuActionViewItem extends BaseActionViewItem {
|
|||
};
|
||||
}
|
||||
|
||||
this.updateTooltip();
|
||||
this.updateEnabled();
|
||||
}
|
||||
|
||||
override getTooltip(): string | undefined {
|
||||
let title: string | null = null;
|
||||
|
||||
if (this.getAction().tooltip) {
|
||||
title = this.getAction().tooltip;
|
||||
} else if (this.getAction().label) {
|
||||
title = this.getAction().label;
|
||||
}
|
||||
|
||||
return title ?? undefined;
|
||||
}
|
||||
|
||||
override setActionContext(newContext: unknown): void {
|
||||
super.setActionContext(newContext);
|
||||
|
||||
|
|
|
@ -593,11 +593,11 @@ class FindFilter<T> implements ITreeFilter<T, FuzzyScore | LabelFuzzyScore>, IDi
|
|||
}
|
||||
|
||||
filter(element: T, parentVisibility: TreeVisibility): TreeFilterResult<FuzzyScore | LabelFuzzyScore> {
|
||||
let visibility = TreeVisibility.Visible;
|
||||
|
||||
if (this._filter) {
|
||||
const result = this._filter.filter(element, parentVisibility);
|
||||
|
||||
let visibility: TreeVisibility;
|
||||
|
||||
if (typeof result === 'boolean') {
|
||||
visibility = result ? TreeVisibility.Visible : TreeVisibility.Hidden;
|
||||
} else if (isFilterResult(result)) {
|
||||
|
@ -615,7 +615,7 @@ class FindFilter<T> implements ITreeFilter<T, FuzzyScore | LabelFuzzyScore>, IDi
|
|||
|
||||
if (!this._pattern) {
|
||||
this._matchCount++;
|
||||
return { data: FuzzyScore.Default, visibility: true };
|
||||
return { data: FuzzyScore.Default, visibility };
|
||||
}
|
||||
|
||||
const label = this.keyboardNavigationLabelProvider.getKeyboardNavigationLabel(element);
|
||||
|
@ -624,22 +624,22 @@ class FindFilter<T> implements ITreeFilter<T, FuzzyScore | LabelFuzzyScore>, IDi
|
|||
for (const l of labels) {
|
||||
const labelStr = l && l.toString();
|
||||
if (typeof labelStr === 'undefined') {
|
||||
return { data: FuzzyScore.Default, visibility: true };
|
||||
return { data: FuzzyScore.Default, visibility };
|
||||
}
|
||||
|
||||
const score = fuzzyScore(this._pattern, this._lowercasePattern, 0, labelStr, labelStr.toLowerCase(), 0, { firstMatchCanBeWeak: true, boostFullMatch: true });
|
||||
if (score) {
|
||||
this._matchCount++;
|
||||
return labels.length === 1 ?
|
||||
{ data: score, visibility: true } :
|
||||
{ data: { label: labelStr, score: score }, visibility: true };
|
||||
{ data: score, visibility } :
|
||||
{ data: { label: labelStr, score: score }, visibility };
|
||||
}
|
||||
}
|
||||
|
||||
if (this.tree.findMode === TreeFindMode.Filter) {
|
||||
return TreeVisibility.Recurse;
|
||||
} else {
|
||||
return { data: FuzzyScore.Default, visibility: true };
|
||||
return { data: FuzzyScore.Default, visibility };
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -685,7 +685,7 @@ export enum TreeFindMode {
|
|||
class FindWidget<T, TFilterData> extends Disposable {
|
||||
|
||||
private readonly elements = h('.monaco-tree-type-filter', [
|
||||
h('.monaco-tree-type-filter-grab.codicon.codicon-debug-gripper@grab'),
|
||||
h('.monaco-tree-type-filter-grab.codicon.codicon-debug-gripper@grab', { tabIndex: 0 }),
|
||||
h('.monaco-tree-type-filter-input@findInput'),
|
||||
h('.monaco-tree-type-filter-actionbar@actionbar'),
|
||||
]);
|
||||
|
@ -699,7 +699,7 @@ class FindWidget<T, TFilterData> extends Disposable {
|
|||
private readonly findInput: FindInput;
|
||||
private readonly actionbar: ActionBar;
|
||||
private width = 0;
|
||||
private right = 4;
|
||||
private right = 0;
|
||||
|
||||
readonly _onDidDisable = new Emitter<void>();
|
||||
readonly onDidDisable = this._onDidDisable.event;
|
||||
|
@ -772,6 +772,28 @@ class FindWidget<T, TFilterData> extends Disposable {
|
|||
}));
|
||||
}));
|
||||
|
||||
const onGrabKeyDown = this._register(Event.chain(this._register(new DomEmitter(this.elements.grab, 'keydown')).event))
|
||||
.map(e => new StandardKeyboardEvent(e))
|
||||
.event;
|
||||
|
||||
this._register(onGrabKeyDown((e): any => {
|
||||
let right: number | undefined;
|
||||
|
||||
if (e.keyCode === KeyCode.LeftArrow) {
|
||||
right = Number.POSITIVE_INFINITY;
|
||||
} else if (e.keyCode === KeyCode.RightArrow) {
|
||||
right = 0;
|
||||
} else if (e.keyCode === KeyCode.Space) {
|
||||
right = this.right === 0 ? Number.POSITIVE_INFINITY : 0;
|
||||
}
|
||||
|
||||
if (right !== undefined) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.right = right;
|
||||
this.layout();
|
||||
}
|
||||
}));
|
||||
|
||||
this.onDidChangeValue = this.findInput.onDidChange;
|
||||
this.style(options ?? {});
|
||||
|
@ -799,7 +821,7 @@ class FindWidget<T, TFilterData> extends Disposable {
|
|||
|
||||
layout(width: number = this.width): void {
|
||||
this.width = width;
|
||||
this.right = Math.min(Math.max(20, this.right), Math.max(20, width - 170));
|
||||
this.right = clamp(this.right, 0, Math.max(0, width - 212));
|
||||
this.elements.root.style.right = `${this.right}px`;
|
||||
}
|
||||
|
||||
|
@ -876,7 +898,8 @@ class FindController<T, TFilterData> implements IDisposable {
|
|||
return;
|
||||
}
|
||||
|
||||
this.widget = new FindWidget(this.view.getHTMLElement(), this.tree, this.contextViewProvider, this._mode, this.styles);
|
||||
this.mode = this.tree.options.defaultFindMode ?? TreeFindMode.Highlight;
|
||||
this.widget = new FindWidget(this.view.getHTMLElement(), this.tree, this.contextViewProvider, this.mode, this.styles);
|
||||
this.enabledDisposables.add(this.widget);
|
||||
|
||||
this.widget.onDidChangeValue(this.onDidChangeValue, this, this.enabledDisposables);
|
||||
|
@ -1022,6 +1045,7 @@ export interface IAbstractTreeOptions<T, TFilterData = void> extends IAbstractTr
|
|||
readonly filter?: ITreeFilter<T, TFilterData>;
|
||||
readonly dnd?: ITreeDragAndDrop<T>;
|
||||
readonly additionalScrollHeight?: number;
|
||||
readonly findWidgetEnabled?: boolean;
|
||||
}
|
||||
|
||||
function dfs<T, TFilterData>(node: ITreeNode<T, TFilterData>, fn: (node: ITreeNode<T, TFilterData>) => void): void {
|
||||
|
@ -1436,7 +1460,7 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
|
|||
onKeyDown.filter(e => e.keyCode === KeyCode.Space).on(this.onSpace, this, this.disposables);
|
||||
}
|
||||
|
||||
if (_options.keyboardNavigationLabelProvider && _options.contextViewProvider) {
|
||||
if ((_options.findWidgetEnabled ?? true) && _options.keyboardNavigationLabelProvider && _options.contextViewProvider) {
|
||||
this.findController = new FindController(this, this.model, this.view, filter!, _options.contextViewProvider);
|
||||
this.focusNavigationFilter = node => this.findController!.shouldAllowFocus(node);
|
||||
this.onDidChangeFindOpenState = this.findController.onDidChangeOpenState;
|
||||
|
|
|
@ -74,8 +74,9 @@
|
|||
display: flex;
|
||||
padding: 3px;
|
||||
transition: top 0.3s;
|
||||
width: 160px;
|
||||
max-width: 200px;
|
||||
z-index: 100;
|
||||
margin: 0 6px;
|
||||
}
|
||||
|
||||
.monaco-tree-type-filter.disabled {
|
||||
|
@ -87,6 +88,7 @@
|
|||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: grab;
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
.monaco-tree-type-filter-grab.grabbing {
|
||||
|
@ -98,12 +100,16 @@
|
|||
}
|
||||
|
||||
.monaco-tree-type-filter-input .monaco-inputbox {
|
||||
height: 26px;
|
||||
height: 23px;
|
||||
}
|
||||
|
||||
.monaco-tree-type-filter-input .monaco-inputbox > .ibwrapper > .input,
|
||||
.monaco-tree-type-filter-input .monaco-inputbox > .ibwrapper > .mirror {
|
||||
padding: 2px;
|
||||
padding: 2px 4px;
|
||||
}
|
||||
|
||||
.monaco-tree-type-filter-input .monaco-findInput > .controls {
|
||||
top: 2px;
|
||||
}
|
||||
|
||||
.monaco-tree-type-filter-actionbar {
|
||||
|
|
|
@ -8,7 +8,7 @@ import { onUnexpectedError } from 'vs/base/common/errors';
|
|||
import { once as onceFn } from 'vs/base/common/functional';
|
||||
import { combinedDisposable, Disposable, DisposableStore, IDisposable, SafeDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { LinkedList } from 'vs/base/common/linkedList';
|
||||
import { IObservable, IObserver } from 'vs/base/common/observableImpl/base';
|
||||
import { IObservable, IObserver } from 'vs/base/common/observable';
|
||||
import { StopWatch } from 'vs/base/common/stopwatch';
|
||||
|
||||
|
||||
|
|
|
@ -101,6 +101,11 @@ export namespace Schemas {
|
|||
* Scheme used vs live share
|
||||
*/
|
||||
export const vsls = 'vsls';
|
||||
|
||||
/**
|
||||
* Scheme used for the Source Control commit input's text document
|
||||
*/
|
||||
export const vscodeSourceControl = 'vscode-scm';
|
||||
}
|
||||
|
||||
export const connectionTokenCookieName = 'vscode-tkn';
|
||||
|
|
|
@ -275,9 +275,3 @@ export type UriDto<T> = { [K in keyof T]: T[K] extends URI
|
|||
export function assertNever(value: never, message = 'Unreachable'): never {
|
||||
throw new Error(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an object with all optional properties, requires at least one to be defined.
|
||||
* i.e. AtLeastOne<MyObject>;
|
||||
*/
|
||||
export type AtLeastOne<T, U = { [K in keyof T]: Pick<T, K> }> = Partial<T> & U[keyof U];
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
position: absolute;
|
||||
width: 600px;
|
||||
z-index: 2550;
|
||||
padding: 0 1px 1px 1px;
|
||||
left: 50%;
|
||||
margin-left: -300px;
|
||||
-webkit-app-region: no-drag;
|
||||
|
@ -151,6 +150,7 @@
|
|||
.quick-input-list {
|
||||
line-height: 22px;
|
||||
margin-top: 6px;
|
||||
padding: 0px 1px 1px 1px;
|
||||
}
|
||||
|
||||
.quick-input-widget.hidden-input .quick-input-list {
|
||||
|
|
|
@ -62,7 +62,7 @@ import { ICustomEndpointTelemetryService, ITelemetryService } from 'vs/platform/
|
|||
import { TelemetryAppenderChannel } from 'vs/platform/telemetry/common/telemetryIpc';
|
||||
import { TelemetryLogAppender } from 'vs/platform/telemetry/common/telemetryLogAppender';
|
||||
import { TelemetryService } from 'vs/platform/telemetry/common/telemetryService';
|
||||
import { supportsTelemetry, ITelemetryAppender, NullAppender, NullTelemetryService, getPiiPathsFromEnvironment } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
import { supportsTelemetry, ITelemetryAppender, NullAppender, NullTelemetryService, getPiiPathsFromEnvironment, isInternalTelemetry } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
import { CustomEndpointTelemetryService } from 'vs/platform/telemetry/node/customEndpointTelemetryService';
|
||||
import { LocalReconnectConstants, TerminalIpcChannels, TerminalSettingId } from 'vs/platform/terminal/common/terminal';
|
||||
import { ILocalPtyService } from 'vs/platform/terminal/electron-sandbox/terminal';
|
||||
|
@ -277,19 +277,20 @@ class SharedProcessMain extends Disposable {
|
|||
// Telemetry
|
||||
let telemetryService: ITelemetryService;
|
||||
const appenders: ITelemetryAppender[] = [];
|
||||
const internalTelemetry = isInternalTelemetry(productService, configurationService);
|
||||
if (supportsTelemetry(productService, environmentService)) {
|
||||
const logAppender = new TelemetryLogAppender(loggerService, environmentService);
|
||||
appenders.push(logAppender);
|
||||
const { installSourcePath } = environmentService;
|
||||
if (productService.aiConfig?.ariaKey) {
|
||||
const collectorAppender = new OneDataSystemWebAppender(configurationService, 'monacoworkbench', null, productService.aiConfig.ariaKey);
|
||||
const collectorAppender = new OneDataSystemWebAppender(internalTelemetry, 'monacoworkbench', null, productService.aiConfig.ariaKey);
|
||||
this._register(toDisposable(() => collectorAppender.flush())); // Ensure the 1DS appender is disposed so that it flushes remaining data
|
||||
appenders.push(collectorAppender);
|
||||
}
|
||||
|
||||
telemetryService = new TelemetryService({
|
||||
appenders,
|
||||
commonProperties: resolveCommonProperties(fileService, release(), hostname(), process.arch, productService.commit, productService.version, this.configuration.machineId, productService.msftInternalDomains, installSourcePath),
|
||||
commonProperties: resolveCommonProperties(fileService, release(), hostname(), process.arch, productService.commit, productService.version, this.configuration.machineId, internalTelemetry, installSourcePath),
|
||||
sendErrorTelemetry: true,
|
||||
piiPaths: getPiiPathsFromEnvironment(environmentService),
|
||||
}, configurationService, productService);
|
||||
|
|
|
@ -75,7 +75,7 @@ import { resolveCommonProperties } from 'vs/platform/telemetry/common/commonProp
|
|||
import { ITelemetryService, machineIdKey, TelemetryLevel } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { TelemetryAppenderClient } from 'vs/platform/telemetry/common/telemetryIpc';
|
||||
import { ITelemetryServiceConfig, TelemetryService } from 'vs/platform/telemetry/common/telemetryService';
|
||||
import { getPiiPathsFromEnvironment, getTelemetryLevel, NullTelemetryService, supportsTelemetry } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
import { getPiiPathsFromEnvironment, getTelemetryLevel, isInternalTelemetry, NullTelemetryService, supportsTelemetry } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
import { IUpdateService } from 'vs/platform/update/common/update';
|
||||
import { UpdateChannel } from 'vs/platform/update/common/updateIpc';
|
||||
import { DarwinUpdateService } from 'vs/platform/update/electron-main/updateService.darwin';
|
||||
|
@ -680,9 +680,10 @@ export class CodeApplication extends Disposable {
|
|||
|
||||
// Telemetry
|
||||
if (supportsTelemetry(this.productService, this.environmentMainService)) {
|
||||
const isInternal = isInternalTelemetry(this.productService, this.configurationService);
|
||||
const channel = getDelayedChannel(sharedProcessReady.then(client => client.getChannel('telemetryAppender')));
|
||||
const appender = new TelemetryAppenderClient(channel);
|
||||
const commonProperties = resolveCommonProperties(this.fileService, release(), hostname(), process.arch, this.productService.commit, this.productService.version, machineId, this.productService.msftInternalDomains, this.environmentMainService.installSourcePath);
|
||||
const commonProperties = resolveCommonProperties(this.fileService, release(), hostname(), process.arch, this.productService.commit, this.productService.version, machineId, isInternal, this.environmentMainService.installSourcePath);
|
||||
const piiPaths = getPiiPathsFromEnvironment(this.environmentMainService);
|
||||
const config: ITelemetryServiceConfig = { appenders: [appender], commonProperties, piiPaths, sendErrorTelemetry: true };
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src 'self' https: data: blob: vscode-remote-resource:; media-src 'self'; frame-src 'self' vscode-webview:; object-src 'self'; script-src 'self' 'unsafe-eval' blob:; style-src 'self' 'unsafe-inline'; connect-src 'self' https: ws:; font-src 'self' https: vscode-remote-resource:;">
|
||||
<meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script'; trusted-types amdLoader cellRendererEditorText defaultWorkerFactory diffEditorWidget editorGhostText domLineBreaksComputer editorViewLayer diffReview dompurify notebookRenderer safeInnerHtml standaloneColorizer tokenizeToString;">
|
||||
<meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script'; trusted-types amdLoader cellRendererEditorText defaultWorkerFactory diffEditorWidget stickyScrollViewLayer editorGhostText domLineBreaksComputer editorViewLayer diffReview dompurify notebookRenderer safeInnerHtml standaloneColorizer tokenizeToString;">
|
||||
</head>
|
||||
<body aria-label="">
|
||||
</body>
|
||||
|
|
|
@ -63,10 +63,6 @@ export async function main(argv: string[]): Promise<any> {
|
|||
|
||||
// Shell integration
|
||||
else if (args['locate-shell-integration-path']) {
|
||||
// Silently fail when the terminal is not VS Code's integrated terminal
|
||||
if (process.env['TERM_PROGRAM'] !== 'vscode') {
|
||||
return;
|
||||
}
|
||||
let file: string;
|
||||
switch (args['locate-shell-integration-path']) {
|
||||
// Usage: `[[ "$TERM_PROGRAM" == "vscode" ]] && . "$(code --locate-shell-integration-path bash)"`
|
||||
|
|
|
@ -52,7 +52,7 @@ import { StateService } from 'vs/platform/state/node/stateService';
|
|||
import { resolveCommonProperties } from 'vs/platform/telemetry/common/commonProperties';
|
||||
import { ITelemetryService, machineIdKey } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { ITelemetryServiceConfig, TelemetryService } from 'vs/platform/telemetry/common/telemetryService';
|
||||
import { supportsTelemetry, NullTelemetryService, getPiiPathsFromEnvironment } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
import { supportsTelemetry, NullTelemetryService, getPiiPathsFromEnvironment, isInternalTelemetry } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
import { OneDataSystemAppender } from 'vs/platform/telemetry/node/1dsAppender';
|
||||
import { buildTelemetryMessage } from 'vs/platform/telemetry/node/telemetry';
|
||||
import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity';
|
||||
|
@ -187,9 +187,10 @@ class CliMain extends Disposable {
|
|||
|
||||
// Telemetry
|
||||
const appenders: OneDataSystemAppender[] = [];
|
||||
const isInternal = isInternalTelemetry(productService, configurationService);
|
||||
if (supportsTelemetry(productService, environmentService)) {
|
||||
if (productService.aiConfig && productService.aiConfig.ariaKey) {
|
||||
appenders.push(new OneDataSystemAppender(configurationService, 'monacoworkbench', null, productService.aiConfig.ariaKey));
|
||||
appenders.push(new OneDataSystemAppender(isInternal, 'monacoworkbench', null, productService.aiConfig.ariaKey));
|
||||
}
|
||||
|
||||
const { installSourcePath } = environmentService;
|
||||
|
@ -208,7 +209,7 @@ class CliMain extends Disposable {
|
|||
}
|
||||
}
|
||||
|
||||
return resolveCommonProperties(fileService, release(), hostname(), process.arch, productService.commit, productService.version, machineId, productService.msftInternalDomains, installSourcePath);
|
||||
return resolveCommonProperties(fileService, release(), hostname(), process.arch, productService.commit, productService.version, machineId, isInternal, installSourcePath);
|
||||
})(),
|
||||
piiPaths: getPiiPathsFromEnvironment(environmentService)
|
||||
};
|
||||
|
|
|
@ -84,7 +84,7 @@ export namespace EditorScroll_ {
|
|||
\`\`\`
|
||||
* 'by': Unit to move. Default is computed based on 'to' value.
|
||||
\`\`\`
|
||||
'line', 'wrappedLine', 'page', 'halfPage'
|
||||
'line', 'wrappedLine', 'page', 'halfPage', 'editor'
|
||||
\`\`\`
|
||||
* 'value': Number of units to move. Default is '1'.
|
||||
* 'revealCursor': If 'true' reveals the cursor if it is outside view port.
|
||||
|
@ -100,7 +100,7 @@ export namespace EditorScroll_ {
|
|||
},
|
||||
'by': {
|
||||
'type': 'string',
|
||||
'enum': ['line', 'wrappedLine', 'page', 'halfPage']
|
||||
'enum': ['line', 'wrappedLine', 'page', 'halfPage', 'editor']
|
||||
},
|
||||
'value': {
|
||||
'type': 'number',
|
||||
|
@ -130,7 +130,8 @@ export namespace EditorScroll_ {
|
|||
Line: 'line',
|
||||
WrappedLine: 'wrappedLine',
|
||||
Page: 'page',
|
||||
HalfPage: 'halfPage'
|
||||
HalfPage: 'halfPage',
|
||||
Editor: 'editor'
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -172,6 +173,9 @@ export namespace EditorScroll_ {
|
|||
case RawUnit.HalfPage:
|
||||
unit = Unit.HalfPage;
|
||||
break;
|
||||
case RawUnit.Editor:
|
||||
unit = Unit.Editor;
|
||||
break;
|
||||
default:
|
||||
unit = Unit.WrappedLine;
|
||||
}
|
||||
|
@ -205,7 +209,8 @@ export namespace EditorScroll_ {
|
|||
Line = 1,
|
||||
WrappedLine = 2,
|
||||
Page = 3,
|
||||
HalfPage = 4
|
||||
HalfPage = 4,
|
||||
Editor = 5
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1279,6 +1284,14 @@ export namespace CoreNavigationCommands {
|
|||
return viewModel.viewLayout.getVerticalOffsetForLineNumber(viewPosition.lineNumber);
|
||||
}
|
||||
|
||||
if (args.unit === EditorScroll_.Unit.Editor) {
|
||||
let desiredTopModelLineNumber = 0;
|
||||
if (args.direction === EditorScroll_.Direction.Down) {
|
||||
desiredTopModelLineNumber = viewModel.model.getLineCount() - viewModel.cursorConfig.pageSize;
|
||||
}
|
||||
return viewModel.viewLayout.getVerticalOffsetForLineNumber(desiredTopModelLineNumber);
|
||||
}
|
||||
|
||||
let noOfLines: number;
|
||||
if (args.unit === EditorScroll_.Unit.Page) {
|
||||
noOfLines = viewModel.cursorConfig.pageSize * args.value;
|
||||
|
@ -1345,6 +1358,29 @@ export namespace CoreNavigationCommands {
|
|||
}
|
||||
});
|
||||
|
||||
export const ScrollEditorTop: CoreEditorCommand = registerEditorCommand(new class extends CoreEditorCommand {
|
||||
constructor() {
|
||||
super({
|
||||
id: 'scrollEditorTop',
|
||||
precondition: undefined,
|
||||
kbOpts: {
|
||||
weight: CORE_WEIGHT,
|
||||
kbExpr: EditorContextKeys.textInputFocus,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
runCoreEditorCommand(viewModel: IViewModel, args: any): void {
|
||||
EditorScroll._runEditorScroll(viewModel, args.source, {
|
||||
direction: EditorScroll_.Direction.Up,
|
||||
unit: EditorScroll_.Unit.Editor,
|
||||
value: 1,
|
||||
revealCursor: false,
|
||||
select: false
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
export const ScrollLineDown: CoreEditorCommand = registerEditorCommand(new class extends CoreEditorCommand {
|
||||
constructor() {
|
||||
super({
|
||||
|
@ -1396,6 +1432,29 @@ export namespace CoreNavigationCommands {
|
|||
}
|
||||
});
|
||||
|
||||
export const ScrollEditorBottom: CoreEditorCommand = registerEditorCommand(new class extends CoreEditorCommand {
|
||||
constructor() {
|
||||
super({
|
||||
id: 'scrollEditorBottom',
|
||||
precondition: undefined,
|
||||
kbOpts: {
|
||||
weight: CORE_WEIGHT,
|
||||
kbExpr: EditorContextKeys.textInputFocus,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
runCoreEditorCommand(viewModel: IViewModel, args: any): void {
|
||||
EditorScroll._runEditorScroll(viewModel, args.source, {
|
||||
direction: EditorScroll_.Direction.Down,
|
||||
unit: EditorScroll_.Unit.Editor,
|
||||
value: 1,
|
||||
revealCursor: false,
|
||||
select: false
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
class WordCommand extends CoreEditorCommand {
|
||||
|
||||
private readonly _inSelectionMode: boolean;
|
||||
|
|
|
@ -899,10 +899,15 @@ export interface ICodeEditor extends editorCommon.IEditor {
|
|||
getWhitespaces(): IEditorWhitespace[];
|
||||
|
||||
/**
|
||||
* Get the vertical position (top offset) for the line w.r.t. to the first line.
|
||||
* Get the vertical position (top offset) for the line's top w.r.t. to the first line.
|
||||
*/
|
||||
getTopForLineNumber(lineNumber: number): number;
|
||||
|
||||
/**
|
||||
* Get the vertical position (top offset) for the line's bottom w.r.t. to the first line.
|
||||
*/
|
||||
getBottomForLineNumber(lineNumber: number): number;
|
||||
|
||||
/**
|
||||
* Get the vertical position (top offset) for the position w.r.t. to the first line.
|
||||
*/
|
||||
|
|
|
@ -368,10 +368,15 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
|
|||
this._actions[internalAction.id] = internalAction;
|
||||
});
|
||||
|
||||
const isDropIntoEnabled = () => {
|
||||
return !this._configuration.options.get(EditorOption.readOnly)
|
||||
&& this._configuration.options.get(EditorOption.dropIntoEditor).enabled;
|
||||
};
|
||||
|
||||
this._register(new dom.DragAndDropObserver(this._domElement, {
|
||||
onDragEnter: () => undefined,
|
||||
onDragOver: e => {
|
||||
if (!this._configuration.options.get(EditorOption.enableDropIntoEditor)) {
|
||||
if (!isDropIntoEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -381,7 +386,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE
|
|||
}
|
||||
},
|
||||
onDrop: async e => {
|
||||
if (!this._configuration.options.get(EditorOption.enableDropIntoEditor)) {
|
||||
if (!isDropIntoEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -1189,7 +1189,7 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
|
|||
result.ariaLabel = options.originalAriaLabel;
|
||||
}
|
||||
result.readOnly = !this._options.originalEditable;
|
||||
result.enableDropIntoEditor = !result.readOnly;
|
||||
result.dropIntoEditor = { enabled: !result.readOnly };
|
||||
result.extraEditorClassName = 'original-in-monaco-diff-editor';
|
||||
return {
|
||||
...result,
|
||||
|
|
|
@ -169,6 +169,10 @@ export interface IEditorOptions {
|
|||
* Control the behavior and rendering of the scrollbars.
|
||||
*/
|
||||
scrollbar?: IEditorScrollbarOptions;
|
||||
/**
|
||||
* Control the behavior of experimental options
|
||||
*/
|
||||
experimental?: IEditorExperimentalOptions;
|
||||
/**
|
||||
* Control the behavior and rendering of the minimap.
|
||||
*/
|
||||
|
@ -661,11 +665,11 @@ export interface IEditorOptions {
|
|||
bracketPairColorization?: IBracketPairColorizationOptions;
|
||||
|
||||
/**
|
||||
* Enables dropping into the editor from an external source.
|
||||
* Controls dropping into the editor from an external source.
|
||||
*
|
||||
* This shows a preview of the drop location and triggers an `onDropIntoEditor` event.
|
||||
* When enabled, this shows a preview of the drop location and triggers an `onDropIntoEditor` event.
|
||||
*/
|
||||
enableDropIntoEditor?: boolean;
|
||||
dropIntoEditor?: IDropIntoEditorOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -876,7 +880,7 @@ function applyUpdate<T>(value: T | undefined, update: T): ApplyUpdateResult<T> {
|
|||
}
|
||||
if (Array.isArray(value) || Array.isArray(update)) {
|
||||
const arrayEquals = Array.isArray(value) && Array.isArray(update) && arrays.equals(value, update);
|
||||
return new ApplyUpdateResult(update, arrayEquals);
|
||||
return new ApplyUpdateResult(update, !arrayEquals);
|
||||
}
|
||||
let didChange = false;
|
||||
for (const key in update) {
|
||||
|
@ -2504,6 +2508,57 @@ class EditorLightbulb extends BaseEditorOption<EditorOption.lightbulb, IEditorLi
|
|||
|
||||
//#endregion
|
||||
|
||||
//#region experimental
|
||||
|
||||
export interface IEditorExperimentalOptions {
|
||||
/**
|
||||
* Configuration options for editor sticky scroll
|
||||
*/
|
||||
stickyScroll?: {
|
||||
/**
|
||||
* Enable the sticky scroll
|
||||
*/
|
||||
enabled?: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
export interface EditorExperimentalOptions {
|
||||
stickyScroll: {
|
||||
enabled: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
class EditorExperimental extends BaseEditorOption<EditorOption.experimental, IEditorExperimentalOptions, EditorExperimentalOptions> {
|
||||
|
||||
constructor() {
|
||||
const defaults: EditorExperimentalOptions = { stickyScroll: { enabled: false } };
|
||||
super(
|
||||
EditorOption.experimental, 'experimental', defaults,
|
||||
{
|
||||
'editor.experimental.stickyScroll.enabled': {
|
||||
type: 'boolean',
|
||||
default: defaults.stickyScroll.enabled,
|
||||
description: nls.localize('editor.experimental.stickyScroll', "Shows the nested current scopes during the scroll at the top of the editor.")
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public validate(_input: any): EditorExperimentalOptions {
|
||||
if (!_input || typeof _input !== 'object') {
|
||||
return this.defaultValue;
|
||||
}
|
||||
const input = _input as IEditorExperimentalOptions;
|
||||
return {
|
||||
stickyScroll: {
|
||||
enabled: boolean(input.stickyScroll?.enabled, this.defaultValue.stickyScroll.enabled)
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region inlayHints
|
||||
|
||||
/**
|
||||
|
@ -4387,6 +4442,53 @@ class EditorWrappingInfoComputer extends ComputedEditorOption<EditorOption.wrapp
|
|||
|
||||
//#endregion
|
||||
|
||||
//#region dropIntoEditor
|
||||
|
||||
/**
|
||||
* Configuration options for editor drop into behavior
|
||||
*/
|
||||
export interface IDropIntoEditorOptions {
|
||||
/**
|
||||
* Enable the dropping into editor.
|
||||
* Defaults to true.
|
||||
*/
|
||||
enabled?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export type EditorDropIntoEditorOptions = Readonly<Required<IDropIntoEditorOptions>>;
|
||||
|
||||
class EditorDropIntoEditor extends BaseEditorOption<EditorOption.dropIntoEditor, IDropIntoEditorOptions, EditorDropIntoEditorOptions> {
|
||||
|
||||
constructor() {
|
||||
const defaults: EditorDropIntoEditorOptions = { enabled: true };
|
||||
super(
|
||||
EditorOption.dropIntoEditor, 'dropIntoEditor', defaults,
|
||||
{
|
||||
'editor.dropIntoEditor.enabled': {
|
||||
type: 'boolean',
|
||||
default: defaults.enabled,
|
||||
markdownDescription: nls.localize('dropIntoEditor.enabled', "Controls whether you can drag and drop a file into a text editor by holding down `shift` (instead of opening the file in an editor)."),
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public validate(_input: any): EditorDropIntoEditorOptions {
|
||||
if (!_input || typeof _input !== 'object') {
|
||||
return this.defaultValue;
|
||||
}
|
||||
const input = _input as IDropIntoEditorOptions;
|
||||
return {
|
||||
enabled: boolean(input.enabled, this.defaultValue.enabled)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
const DEFAULT_WINDOWS_FONT_FAMILY = 'Consolas, \'Courier New\', monospace';
|
||||
const DEFAULT_MAC_FONT_FAMILY = 'Menlo, Monaco, \'Courier New\', monospace';
|
||||
const DEFAULT_LINUX_FONT_FAMILY = '\'Droid Sans Mono\', \'monospace\', monospace';
|
||||
|
@ -4449,8 +4551,9 @@ export const enum EditorOption {
|
|||
disableMonospaceOptimizations,
|
||||
domReadOnly,
|
||||
dragAndDrop,
|
||||
enableDropIntoEditor,
|
||||
dropIntoEditor,
|
||||
emptySelectionClipboard,
|
||||
experimental,
|
||||
extraEditorClassName,
|
||||
fastScrollSensitivity,
|
||||
find,
|
||||
|
@ -4758,9 +4861,8 @@ export const EditorOptions = {
|
|||
{ description: nls.localize('dragAndDrop', "Controls whether the editor should allow moving selections via drag and drop.") }
|
||||
)),
|
||||
emptySelectionClipboard: register(new EditorEmptySelectionClipboard()),
|
||||
enableDropIntoEditor: register(new EditorBooleanOption(
|
||||
EditorOption.enableDropIntoEditor, 'enableDropIntoEditor', true
|
||||
)),
|
||||
dropIntoEditor: register(new EditorDropIntoEditor()),
|
||||
experimental: register(new EditorExperimental()),
|
||||
extraEditorClassName: register(new EditorStringOption(
|
||||
EditorOption.extraEditorClassName, 'extraEditorClassName', '',
|
||||
)),
|
||||
|
|
|
@ -669,9 +669,6 @@ export interface CodeAction {
|
|||
disabled?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export const enum CodeActionTriggerType {
|
||||
Invoke = 1,
|
||||
Auto = 2,
|
||||
|
@ -1132,7 +1129,11 @@ export interface DocumentSymbolProvider {
|
|||
provideDocumentSymbols(model: model.ITextModel, token: CancellationToken): ProviderResult<DocumentSymbol[]>;
|
||||
}
|
||||
|
||||
export type TextEdit = { range: IRange; text: string; eol?: model.EndOfLineSequence };
|
||||
export interface TextEdit {
|
||||
range: IRange;
|
||||
text: string;
|
||||
eol?: model.EndOfLineSequence;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface used to format a model
|
||||
|
|
|
@ -528,13 +528,18 @@ export const enum TrackedRangeStickiness {
|
|||
* Text snapshot that works like an iterator.
|
||||
* Will try to return chunks of roughly ~64KB size.
|
||||
* Will return null when finished.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export interface ITextSnapshot {
|
||||
read(): string | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export function isITextSnapshot(obj: any): obj is ITextSnapshot {
|
||||
return (obj && typeof obj.read === 'function');
|
||||
}
|
||||
|
||||
/**
|
||||
* A model.
|
||||
*/
|
||||
|
@ -610,7 +615,7 @@ export interface ITextModel {
|
|||
/**
|
||||
* Replace the entire text buffer value contained in this model.
|
||||
*/
|
||||
setValue(newValue: string): void;
|
||||
setValue(newValue: string | ITextSnapshot): void;
|
||||
|
||||
/**
|
||||
* Get the text stored in this model.
|
||||
|
@ -624,7 +629,6 @@ export interface ITextModel {
|
|||
* Get the text stored in this model.
|
||||
* @param preserverBOM Preserve a BOM character if it was detected when the model was constructed.
|
||||
* @return The text snapshot (it is safe to consume it asynchronously).
|
||||
* @internal
|
||||
*/
|
||||
createSnapshot(preserveBOM?: boolean): ITextSnapshot;
|
||||
|
||||
|
|
|
@ -44,12 +44,8 @@ import { ITokenizationTextModelPart } from 'vs/editor/common/tokenizationTextMod
|
|||
import { IColorTheme, ThemeColor } from 'vs/platform/theme/common/themeService';
|
||||
import { IUndoRedoService, ResourceEditStackSnapshot } from 'vs/platform/undoRedo/common/undoRedo';
|
||||
|
||||
function createTextBufferBuilder() {
|
||||
return new PieceTreeTextBufferBuilder();
|
||||
}
|
||||
|
||||
export function createTextBufferFactory(text: string): model.ITextBufferFactory {
|
||||
const builder = createTextBufferBuilder();
|
||||
const builder = new PieceTreeTextBufferBuilder();
|
||||
builder.acceptChunk(text);
|
||||
return builder.finish();
|
||||
}
|
||||
|
@ -65,7 +61,7 @@ export function createTextBufferFactoryFromStream(stream: ITextStream): Promise<
|
|||
export function createTextBufferFactoryFromStream(stream: VSBufferReadableStream): Promise<model.ITextBufferFactory>;
|
||||
export function createTextBufferFactoryFromStream(stream: ITextStream | VSBufferReadableStream): Promise<model.ITextBufferFactory> {
|
||||
return new Promise<model.ITextBufferFactory>((resolve, reject) => {
|
||||
const builder = createTextBufferBuilder();
|
||||
const builder = new PieceTreeTextBufferBuilder();
|
||||
|
||||
let done = false;
|
||||
|
||||
|
@ -90,7 +86,7 @@ export function createTextBufferFactoryFromStream(stream: ITextStream | VSBuffer
|
|||
}
|
||||
|
||||
export function createTextBufferFactoryFromSnapshot(snapshot: model.ITextSnapshot): model.ITextBufferFactory {
|
||||
const builder = createTextBufferBuilder();
|
||||
const builder = new PieceTreeTextBufferBuilder();
|
||||
|
||||
let chunk: string | null;
|
||||
while (typeof (chunk = snapshot.read()) === 'string') {
|
||||
|
@ -100,8 +96,15 @@ export function createTextBufferFactoryFromSnapshot(snapshot: model.ITextSnapsho
|
|||
return builder.finish();
|
||||
}
|
||||
|
||||
export function createTextBuffer(value: string | model.ITextBufferFactory, defaultEOL: model.DefaultEndOfLine): { textBuffer: model.ITextBuffer; disposable: IDisposable } {
|
||||
const factory = (typeof value === 'string' ? createTextBufferFactory(value) : value);
|
||||
export function createTextBuffer(value: string | model.ITextBufferFactory | model.ITextSnapshot, defaultEOL: model.DefaultEndOfLine): { textBuffer: model.ITextBuffer; disposable: IDisposable } {
|
||||
let factory: model.ITextBufferFactory;
|
||||
if (typeof value === 'string') {
|
||||
factory = createTextBufferFactory(value);
|
||||
} else if (model.isITextSnapshot(value)) {
|
||||
factory = createTextBufferFactoryFromSnapshot(value);
|
||||
} else {
|
||||
factory = value;
|
||||
}
|
||||
return factory.create(defaultEOL);
|
||||
}
|
||||
|
||||
|
@ -424,7 +427,7 @@ export class TextModel extends Disposable implements model.ITextModel, IDecorati
|
|||
this._eventEmitter.fire(new InternalModelContentChangeEvent(rawChange, change));
|
||||
}
|
||||
|
||||
public setValue(value: string): void {
|
||||
public setValue(value: string | model.ITextSnapshot): void {
|
||||
this._assertNotDisposed();
|
||||
if (value === null) {
|
||||
// There's nothing to do
|
||||
|
|
|
@ -71,7 +71,6 @@ export function getIconClasses(modelService: IModelService, languageService: ILa
|
|||
return classes;
|
||||
}
|
||||
|
||||
|
||||
export function getIconClassesForLanguageId(languageId: string): string[] {
|
||||
return ['file-icon', `${cssEscape(languageId)}-lang-file-icon`];
|
||||
}
|
||||
|
|
|
@ -15,6 +15,11 @@ export enum AccessibilitySupport {
|
|||
Enabled = 2
|
||||
}
|
||||
|
||||
export enum CodeActionTriggerType {
|
||||
Invoke = 1,
|
||||
Auto = 2
|
||||
}
|
||||
|
||||
export enum CompletionItemInsertTextRule {
|
||||
/**
|
||||
* Adjust whitespace/indentation of multiline insert texts to
|
||||
|
@ -199,108 +204,109 @@ export enum EditorOption {
|
|||
disableMonospaceOptimizations = 29,
|
||||
domReadOnly = 30,
|
||||
dragAndDrop = 31,
|
||||
enableDropIntoEditor = 32,
|
||||
dropIntoEditor = 32,
|
||||
emptySelectionClipboard = 33,
|
||||
extraEditorClassName = 34,
|
||||
fastScrollSensitivity = 35,
|
||||
find = 36,
|
||||
fixedOverflowWidgets = 37,
|
||||
folding = 38,
|
||||
foldingStrategy = 39,
|
||||
foldingHighlight = 40,
|
||||
foldingImportsByDefault = 41,
|
||||
foldingMaximumRegions = 42,
|
||||
unfoldOnClickAfterEndOfLine = 43,
|
||||
fontFamily = 44,
|
||||
fontInfo = 45,
|
||||
fontLigatures = 46,
|
||||
fontSize = 47,
|
||||
fontWeight = 48,
|
||||
formatOnPaste = 49,
|
||||
formatOnType = 50,
|
||||
glyphMargin = 51,
|
||||
gotoLocation = 52,
|
||||
hideCursorInOverviewRuler = 53,
|
||||
hover = 54,
|
||||
inDiffEditor = 55,
|
||||
inlineSuggest = 56,
|
||||
letterSpacing = 57,
|
||||
lightbulb = 58,
|
||||
lineDecorationsWidth = 59,
|
||||
lineHeight = 60,
|
||||
lineNumbers = 61,
|
||||
lineNumbersMinChars = 62,
|
||||
linkedEditing = 63,
|
||||
links = 64,
|
||||
matchBrackets = 65,
|
||||
minimap = 66,
|
||||
mouseStyle = 67,
|
||||
mouseWheelScrollSensitivity = 68,
|
||||
mouseWheelZoom = 69,
|
||||
multiCursorMergeOverlapping = 70,
|
||||
multiCursorModifier = 71,
|
||||
multiCursorPaste = 72,
|
||||
occurrencesHighlight = 73,
|
||||
overviewRulerBorder = 74,
|
||||
overviewRulerLanes = 75,
|
||||
padding = 76,
|
||||
parameterHints = 77,
|
||||
peekWidgetDefaultFocus = 78,
|
||||
definitionLinkOpensInPeek = 79,
|
||||
quickSuggestions = 80,
|
||||
quickSuggestionsDelay = 81,
|
||||
readOnly = 82,
|
||||
renameOnType = 83,
|
||||
renderControlCharacters = 84,
|
||||
renderFinalNewline = 85,
|
||||
renderLineHighlight = 86,
|
||||
renderLineHighlightOnlyWhenFocus = 87,
|
||||
renderValidationDecorations = 88,
|
||||
renderWhitespace = 89,
|
||||
revealHorizontalRightPadding = 90,
|
||||
roundedSelection = 91,
|
||||
rulers = 92,
|
||||
scrollbar = 93,
|
||||
scrollBeyondLastColumn = 94,
|
||||
scrollBeyondLastLine = 95,
|
||||
scrollPredominantAxis = 96,
|
||||
selectionClipboard = 97,
|
||||
selectionHighlight = 98,
|
||||
selectOnLineNumbers = 99,
|
||||
showFoldingControls = 100,
|
||||
showUnused = 101,
|
||||
snippetSuggestions = 102,
|
||||
smartSelect = 103,
|
||||
smoothScrolling = 104,
|
||||
stickyTabStops = 105,
|
||||
stopRenderingLineAfter = 106,
|
||||
suggest = 107,
|
||||
suggestFontSize = 108,
|
||||
suggestLineHeight = 109,
|
||||
suggestOnTriggerCharacters = 110,
|
||||
suggestSelection = 111,
|
||||
tabCompletion = 112,
|
||||
tabIndex = 113,
|
||||
unicodeHighlighting = 114,
|
||||
unusualLineTerminators = 115,
|
||||
useShadowDOM = 116,
|
||||
useTabStops = 117,
|
||||
wordSeparators = 118,
|
||||
wordWrap = 119,
|
||||
wordWrapBreakAfterCharacters = 120,
|
||||
wordWrapBreakBeforeCharacters = 121,
|
||||
wordWrapColumn = 122,
|
||||
wordWrapOverride1 = 123,
|
||||
wordWrapOverride2 = 124,
|
||||
wrappingIndent = 125,
|
||||
wrappingStrategy = 126,
|
||||
showDeprecated = 127,
|
||||
inlayHints = 128,
|
||||
editorClassName = 129,
|
||||
pixelRatio = 130,
|
||||
tabFocusMode = 131,
|
||||
layoutInfo = 132,
|
||||
wrappingInfo = 133
|
||||
experimental = 34,
|
||||
extraEditorClassName = 35,
|
||||
fastScrollSensitivity = 36,
|
||||
find = 37,
|
||||
fixedOverflowWidgets = 38,
|
||||
folding = 39,
|
||||
foldingStrategy = 40,
|
||||
foldingHighlight = 41,
|
||||
foldingImportsByDefault = 42,
|
||||
foldingMaximumRegions = 43,
|
||||
unfoldOnClickAfterEndOfLine = 44,
|
||||
fontFamily = 45,
|
||||
fontInfo = 46,
|
||||
fontLigatures = 47,
|
||||
fontSize = 48,
|
||||
fontWeight = 49,
|
||||
formatOnPaste = 50,
|
||||
formatOnType = 51,
|
||||
glyphMargin = 52,
|
||||
gotoLocation = 53,
|
||||
hideCursorInOverviewRuler = 54,
|
||||
hover = 55,
|
||||
inDiffEditor = 56,
|
||||
inlineSuggest = 57,
|
||||
letterSpacing = 58,
|
||||
lightbulb = 59,
|
||||
lineDecorationsWidth = 60,
|
||||
lineHeight = 61,
|
||||
lineNumbers = 62,
|
||||
lineNumbersMinChars = 63,
|
||||
linkedEditing = 64,
|
||||
links = 65,
|
||||
matchBrackets = 66,
|
||||
minimap = 67,
|
||||
mouseStyle = 68,
|
||||
mouseWheelScrollSensitivity = 69,
|
||||
mouseWheelZoom = 70,
|
||||
multiCursorMergeOverlapping = 71,
|
||||
multiCursorModifier = 72,
|
||||
multiCursorPaste = 73,
|
||||
occurrencesHighlight = 74,
|
||||
overviewRulerBorder = 75,
|
||||
overviewRulerLanes = 76,
|
||||
padding = 77,
|
||||
parameterHints = 78,
|
||||
peekWidgetDefaultFocus = 79,
|
||||
definitionLinkOpensInPeek = 80,
|
||||
quickSuggestions = 81,
|
||||
quickSuggestionsDelay = 82,
|
||||
readOnly = 83,
|
||||
renameOnType = 84,
|
||||
renderControlCharacters = 85,
|
||||
renderFinalNewline = 86,
|
||||
renderLineHighlight = 87,
|
||||
renderLineHighlightOnlyWhenFocus = 88,
|
||||
renderValidationDecorations = 89,
|
||||
renderWhitespace = 90,
|
||||
revealHorizontalRightPadding = 91,
|
||||
roundedSelection = 92,
|
||||
rulers = 93,
|
||||
scrollbar = 94,
|
||||
scrollBeyondLastColumn = 95,
|
||||
scrollBeyondLastLine = 96,
|
||||
scrollPredominantAxis = 97,
|
||||
selectionClipboard = 98,
|
||||
selectionHighlight = 99,
|
||||
selectOnLineNumbers = 100,
|
||||
showFoldingControls = 101,
|
||||
showUnused = 102,
|
||||
snippetSuggestions = 103,
|
||||
smartSelect = 104,
|
||||
smoothScrolling = 105,
|
||||
stickyTabStops = 106,
|
||||
stopRenderingLineAfter = 107,
|
||||
suggest = 108,
|
||||
suggestFontSize = 109,
|
||||
suggestLineHeight = 110,
|
||||
suggestOnTriggerCharacters = 111,
|
||||
suggestSelection = 112,
|
||||
tabCompletion = 113,
|
||||
tabIndex = 114,
|
||||
unicodeHighlighting = 115,
|
||||
unusualLineTerminators = 116,
|
||||
useShadowDOM = 117,
|
||||
useTabStops = 118,
|
||||
wordSeparators = 119,
|
||||
wordWrap = 120,
|
||||
wordWrapBreakAfterCharacters = 121,
|
||||
wordWrapBreakBeforeCharacters = 122,
|
||||
wordWrapColumn = 123,
|
||||
wordWrapOverride1 = 124,
|
||||
wordWrapOverride2 = 125,
|
||||
wrappingIndent = 126,
|
||||
wrappingStrategy = 127,
|
||||
showDeprecated = 128,
|
||||
inlayHints = 129,
|
||||
editorClassName = 130,
|
||||
pixelRatio = 131,
|
||||
tabFocusMode = 132,
|
||||
layoutInfo = 133,
|
||||
wrappingInfo = 134
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -70,7 +70,7 @@ export class ViewportData {
|
|||
}
|
||||
|
||||
public getViewLineRenderingData(lineNumber: number): ViewLineRenderingData {
|
||||
return this._model.getViewLineRenderingData(this.visibleRange, lineNumber);
|
||||
return this._model.getViewportViewLineRenderingData(this.visibleRange, lineNumber);
|
||||
}
|
||||
|
||||
public getDecorationsInViewport(): ViewModelDecoration[] {
|
||||
|
|
|
@ -41,12 +41,15 @@ export interface IViewModel extends ICursorSimpleModel {
|
|||
onCompositionEnd(): void;
|
||||
|
||||
getDecorationsInViewport(visibleRange: Range): ViewModelDecoration[];
|
||||
getViewLineRenderingData(visibleRange: Range, lineNumber: number): ViewLineRenderingData;
|
||||
getViewportViewLineRenderingData(visibleRange: Range, lineNumber: number): ViewLineRenderingData;
|
||||
getViewLineRenderingData(lineNumber: number): ViewLineRenderingData;
|
||||
getViewLineData(lineNumber: number): ViewLineData;
|
||||
getMinimapLinesRenderingData(startLineNumber: number, endLineNumber: number, needed: boolean[]): MinimapLinesRenderingData;
|
||||
getCompletelyVisibleViewRange(): Range;
|
||||
getCompletelyVisibleViewRangeAtScrollTop(scrollTop: number): Range;
|
||||
|
||||
getHiddenAreas(): Range[];
|
||||
|
||||
getLineCount(): number;
|
||||
getLineContent(lineNumber: number): string;
|
||||
getLineLength(lineNumber: number): number;
|
||||
|
|
|
@ -100,17 +100,21 @@ export class ViewModelDecorations implements IDisposable {
|
|||
let cacheIsValid = (this._cachedModelDecorationsResolver !== null);
|
||||
cacheIsValid = cacheIsValid && (viewRange.equalsRange(this._cachedModelDecorationsResolverViewRange));
|
||||
if (!cacheIsValid) {
|
||||
this._cachedModelDecorationsResolver = this._getDecorationsViewportData(viewRange);
|
||||
this._cachedModelDecorationsResolver = this._getDecorationsInRange(viewRange);
|
||||
this._cachedModelDecorationsResolverViewRange = viewRange;
|
||||
}
|
||||
return this._cachedModelDecorationsResolver!;
|
||||
}
|
||||
|
||||
private _getDecorationsViewportData(viewportRange: Range): IDecorationsViewportData {
|
||||
const modelDecorations = this._linesCollection.getDecorationsInRange(viewportRange, this.editorId, filterValidationDecorations(this.configuration.options));
|
||||
public getInlineDecorationsOnLine(lineNumber: number): InlineDecoration[] {
|
||||
const range = new Range(lineNumber, this._linesCollection.getViewLineMinColumn(lineNumber), lineNumber, this._linesCollection.getViewLineMaxColumn(lineNumber));
|
||||
return this._getDecorationsInRange(range).inlineDecorations[0];
|
||||
}
|
||||
|
||||
const startLineNumber = viewportRange.startLineNumber;
|
||||
const endLineNumber = viewportRange.endLineNumber;
|
||||
private _getDecorationsInRange(viewRange: Range): IDecorationsViewportData {
|
||||
const modelDecorations = this._linesCollection.getDecorationsInRange(viewRange, this.editorId, filterValidationDecorations(this.configuration.options));
|
||||
const startLineNumber = viewRange.startLineNumber;
|
||||
const endLineNumber = viewRange.endLineNumber;
|
||||
|
||||
const decorationsInViewport: ViewModelDecoration[] = [];
|
||||
let decorationsInViewportLen = 0;
|
||||
|
|
|
@ -34,9 +34,9 @@ import { ViewLayout } from 'vs/editor/common/viewLayout/viewLayout';
|
|||
import { MinimapTokensColorTracker } from 'vs/editor/common/viewModel/minimapTokensColorTracker';
|
||||
import { ILineBreaksComputer, ILineBreaksComputerFactory, InjectedText } from 'vs/editor/common/modelLineProjectionData';
|
||||
import { ViewEventHandler } from 'vs/editor/common/viewEventHandler';
|
||||
import { ICoordinatesConverter, IViewModel, IWhitespaceChangeAccessor, MinimapLinesRenderingData, OverviewRulerDecorationsGroup, ViewLineData, ViewLineRenderingData, ViewModelDecoration } from 'vs/editor/common/viewModel';
|
||||
import { ICoordinatesConverter, InlineDecoration, IViewModel, IWhitespaceChangeAccessor, MinimapLinesRenderingData, OverviewRulerDecorationsGroup, ViewLineData, ViewLineRenderingData, ViewModelDecoration } from 'vs/editor/common/viewModel';
|
||||
import { ViewModelDecorations } from 'vs/editor/common/viewModel/viewModelDecorations';
|
||||
import { FocusChangedEvent, ModelContentChangedEvent, ModelDecorationsChangedEvent, ModelLanguageChangedEvent, ModelLanguageConfigurationChangedEvent, ModelOptionsChangedEvent, ModelTokensChangedEvent, OutgoingViewModelEvent, ReadOnlyEditAttemptEvent, ScrollChangedEvent, ViewModelEventDispatcher, ViewModelEventsCollector, ViewZonesChangedEvent } from 'vs/editor/common/viewModelEventDispatcher';
|
||||
import { FocusChangedEvent, HiddenAreasChangedEvent, ModelContentChangedEvent, ModelDecorationsChangedEvent, ModelLanguageChangedEvent, ModelLanguageConfigurationChangedEvent, ModelOptionsChangedEvent, ModelTokensChangedEvent, OutgoingViewModelEvent, ReadOnlyEditAttemptEvent, ScrollChangedEvent, ViewModelEventDispatcher, ViewModelEventsCollector, ViewZonesChangedEvent } from 'vs/editor/common/viewModelEventDispatcher';
|
||||
import { IViewModelLines, ViewModelLinesFromModelAsIs, ViewModelLinesFromProjectedModel } from 'vs/editor/common/viewModel/viewModelLines';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
|
||||
|
@ -485,7 +485,7 @@ export class ViewModel extends Disposable implements IViewModel {
|
|||
this._updateConfigurationViewLineCount.schedule();
|
||||
|
||||
if (lineMappingChanged) {
|
||||
this._eventDispatcher.emitOutgoingEvent(new ViewZonesChangedEvent());
|
||||
this._eventDispatcher.emitOutgoingEvent(new HiddenAreasChangedEvent());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -508,6 +508,10 @@ export class ViewModel extends Disposable implements IViewModel {
|
|||
return this._toModelVisibleRanges(visibleViewRange);
|
||||
}
|
||||
|
||||
public getHiddenAreas(): Range[] {
|
||||
return this._lines.getHiddenAreas();
|
||||
}
|
||||
|
||||
private _toModelVisibleRanges(visibleViewRange: Range): Range[] {
|
||||
const visibleRange = this.coordinatesConverter.convertViewRangeToModelRange(visibleViewRange);
|
||||
const hiddenAreas = this._lines.getHiddenAreas();
|
||||
|
@ -679,13 +683,22 @@ export class ViewModel extends Disposable implements IViewModel {
|
|||
return this._lines.getInjectedTextAt(viewPosition);
|
||||
}
|
||||
|
||||
public getViewLineRenderingData(visibleRange: Range, lineNumber: number): ViewLineRenderingData {
|
||||
public getViewportViewLineRenderingData(visibleRange: Range, lineNumber: number): ViewLineRenderingData {
|
||||
const allInlineDecorations = this._decorations.getDecorationsViewportData(visibleRange).inlineDecorations;
|
||||
const inlineDecorations = allInlineDecorations[lineNumber - visibleRange.startLineNumber];
|
||||
return this._getViewLineRenderingData(lineNumber, inlineDecorations);
|
||||
}
|
||||
|
||||
public getViewLineRenderingData(lineNumber: number): ViewLineRenderingData {
|
||||
const inlineDecorations = this._decorations.getInlineDecorationsOnLine(lineNumber);
|
||||
return this._getViewLineRenderingData(lineNumber, inlineDecorations);
|
||||
}
|
||||
|
||||
private _getViewLineRenderingData(lineNumber: number, inlineDecorations: InlineDecoration[]): ViewLineRenderingData {
|
||||
const mightContainRTL = this.model.mightContainRTL();
|
||||
const mightContainNonBasicASCII = this.model.mightContainNonBasicASCII();
|
||||
const tabSize = this.getTabSize();
|
||||
const lineData = this._lines.getViewLineData(lineNumber);
|
||||
const allInlineDecorations = this._decorations.getDecorationsViewportData(visibleRange).inlineDecorations;
|
||||
let inlineDecorations = allInlineDecorations[lineNumber - visibleRange.startLineNumber];
|
||||
|
||||
if (lineData.inlineDecorations) {
|
||||
inlineDecorations = [
|
||||
|
|
|
@ -151,6 +151,13 @@ export class QuickFixController extends Disposable implements IEditorContributio
|
|||
}
|
||||
}
|
||||
|
||||
public selectedOptionWithPreview() {
|
||||
if (this._ui.hasValue()) {
|
||||
this._ui.getValue().onPreviewEnter();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public showCodeActions(trigger: CodeActionTrigger, actions: CodeActionSet, at: IAnchor | IPosition) {
|
||||
return this._ui.getValue().showCodeActionList(trigger, actions, at, { includeDisabledActions: false, fromLightbulb: false });
|
||||
}
|
||||
|
@ -566,4 +573,16 @@ registerEditorCommand(new CodeActionContribution({
|
|||
}
|
||||
}));
|
||||
|
||||
registerEditorCommand(new CodeActionContribution({
|
||||
id: 'onEnterSelectCodeActionWithPreview',
|
||||
precondition: Context.Visible,
|
||||
handler(x) {
|
||||
x.selectedOptionWithPreview();
|
||||
},
|
||||
kbOpts: {
|
||||
weight: weight + 100000,
|
||||
primary: KeyMod.CtrlCmd | KeyCode.Enter,
|
||||
}
|
||||
}));
|
||||
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import { IAnchor } from 'vs/base/browser/ui/contextview/contextview';
|
||||
import { IListEvent, IListRenderer } from 'vs/base/browser/ui/list/list';
|
||||
import { IListEvent, IListMouseEvent, IListRenderer } from 'vs/base/browser/ui/list/list';
|
||||
import { List } from 'vs/base/browser/ui/list/listWidget';
|
||||
import { Action, IAction, Separator } from 'vs/base/common/actions';
|
||||
import { canceled } from 'vs/base/common/errors';
|
||||
|
@ -69,6 +69,7 @@ export interface ICodeActionMenuItem {
|
|||
decoratorRight?: string;
|
||||
isSeparator?: boolean;
|
||||
isEnabled: boolean;
|
||||
isDocumentation: boolean;
|
||||
index: number;
|
||||
disposables?: IDisposable[];
|
||||
}
|
||||
|
@ -93,6 +94,12 @@ const TEMPLATE_ID = 'codeActionWidget';
|
|||
const codeActionLineHeight = 26;
|
||||
|
||||
class CodeMenuRenderer implements IListRenderer<ICodeActionMenuItem, ICodeActionMenuTemplateData> {
|
||||
|
||||
constructor(
|
||||
private readonly acceptKeybindings: [string, string],
|
||||
@IKeybindingService private readonly keybindingService: IKeybindingService,
|
||||
) { }
|
||||
|
||||
get templateId(): string { return TEMPLATE_ID; }
|
||||
|
||||
renderTemplate(container: HTMLElement): ICodeActionMenuTemplateData {
|
||||
|
@ -114,6 +121,7 @@ class CodeMenuRenderer implements IListRenderer<ICodeActionMenuItem, ICodeAction
|
|||
|
||||
const isEnabled = element.isEnabled;
|
||||
const isSeparator = element.isSeparator;
|
||||
const isDocumentation = element.isDocumentation;
|
||||
|
||||
data.text.textContent = text;
|
||||
// data.detail.textContent = detail;
|
||||
|
@ -130,6 +138,15 @@ class CodeMenuRenderer implements IListRenderer<ICodeActionMenuItem, ICodeAction
|
|||
data.root.style.height = '10px';
|
||||
}
|
||||
|
||||
if (!isDocumentation) {
|
||||
const updateLabel = () => {
|
||||
const [accept, preview] = this.acceptKeybindings;
|
||||
data.root.title = localize({ key: 'label', comment: ['placeholders are keybindings, e.g "F2 to Refactor, Shift+F2 to Preview"'] }, "{0} to Refactor, {1} to Preview", this.keybindingService.lookupKeybinding(accept)?.getLabel(), this.keybindingService.lookupKeybinding(preview)?.getLabel());
|
||||
// data.root.title = this.keybindingService.lookupKeybinding(accept)?.getLabel() + ' to Refactor, ' + this.keybindingService.lookupKeybinding(preview)?.getLabel() + ' to Preview';
|
||||
};
|
||||
updateLabel();
|
||||
}
|
||||
|
||||
}
|
||||
disposeTemplate(templateData: ICodeActionMenuTemplateData): void {
|
||||
templateData.disposables = dispose(templateData.disposables);
|
||||
|
@ -144,8 +161,11 @@ export class CodeActionMenu extends Disposable implements IEditorContribution {
|
|||
private _ctxMenuWidgetVisible: IContextKey<boolean>;
|
||||
private viewItems: ICodeActionMenuItem[] = [];
|
||||
private focusedEnabledItem: number | undefined;
|
||||
private currSelectedItem: number = 0;
|
||||
private currSelectedItem: number | undefined;
|
||||
private hasSeperator: boolean = false;
|
||||
private block?: HTMLElement;
|
||||
|
||||
public static readonly documentationID: string = '_documentation';
|
||||
|
||||
public static readonly ID: string = 'editor.contrib.codeActionMenu';
|
||||
|
||||
|
@ -154,7 +174,7 @@ export class CodeActionMenu extends Disposable implements IEditorContribution {
|
|||
}
|
||||
|
||||
private readonly _keybindingResolver: CodeActionKeybindingResolver;
|
||||
private listRenderer: CodeMenuRenderer = new CodeMenuRenderer();
|
||||
private listRenderer: CodeMenuRenderer;
|
||||
|
||||
constructor(
|
||||
private readonly _editor: ICodeEditor,
|
||||
|
@ -175,6 +195,7 @@ export class CodeActionMenu extends Disposable implements IEditorContribution {
|
|||
});
|
||||
|
||||
this._ctxMenuWidgetVisible = Context.Visible.bindTo(this._contextKeyService);
|
||||
this.listRenderer = new CodeMenuRenderer([`onEnterSelectCodeAction`, `onEnterSelectCodeActionWithPreview`], keybindingService);
|
||||
}
|
||||
|
||||
get isVisible(): boolean {
|
||||
|
@ -192,17 +213,46 @@ export class CodeActionMenu extends Disposable implements IEditorContribution {
|
|||
e.elements.forEach(element => {
|
||||
if (element.isEnabled) {
|
||||
element.action.run();
|
||||
this.hideCodeActionWidget();
|
||||
}
|
||||
});
|
||||
this.hideCodeActionWidget();
|
||||
}
|
||||
}
|
||||
|
||||
private _onListHover(e: IListMouseEvent<ICodeActionMenuItem>): void {
|
||||
if (!e.element) {
|
||||
this.currSelectedItem = undefined;
|
||||
this.codeActionList.value?.setFocus([]);
|
||||
} else {
|
||||
if (e.element?.isEnabled) {
|
||||
this.codeActionList.value?.setFocus([e.element.index]);
|
||||
this.focusedEnabledItem = this.viewItems.indexOf(e.element);
|
||||
this.currSelectedItem = e.element.index;
|
||||
} else {
|
||||
this.currSelectedItem = undefined;
|
||||
this.codeActionList.value?.setFocus([e.element.index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private renderCodeActionMenuList(element: HTMLElement, inputArray: IAction[]): IDisposable {
|
||||
const renderDisposables = new DisposableStore();
|
||||
const renderMenu = document.createElement('div');
|
||||
|
||||
// Render invisible div to block mouse interaction in the rest of the UI
|
||||
const menuBlock = document.createElement('div');
|
||||
this.block = element.appendChild(menuBlock);
|
||||
this.block.classList.add('context-view-block');
|
||||
this.block.style.position = 'fixed';
|
||||
this.block.style.cursor = 'initial';
|
||||
this.block.style.left = '0';
|
||||
this.block.style.top = '0';
|
||||
this.block.style.width = '100%';
|
||||
this.block.style.height = '100%';
|
||||
this.block.style.zIndex = '-1';
|
||||
|
||||
renderDisposables.add(dom.addDisposableListener(this.block, dom.EventType.MOUSE_DOWN, e => e.stopPropagation()));
|
||||
|
||||
renderMenu.id = 'codeActionMenuWidget';
|
||||
renderMenu.classList.add('codeActionMenuWidget');
|
||||
|
||||
|
@ -221,6 +271,8 @@ export class CodeActionMenu extends Disposable implements IEditorContribution {
|
|||
}, [this.listRenderer], { keyboardSupport: false }
|
||||
);
|
||||
|
||||
renderDisposables.add(this.codeActionList.value.onMouseOver(e => this._onListHover(e)));
|
||||
renderDisposables.add(this.codeActionList.value.onDidChangeFocus(e => this.codeActionList.value?.domFocus()));
|
||||
renderDisposables.add(this.codeActionList.value.onDidChangeSelection(e => this._onListSelection(e)));
|
||||
renderDisposables.add(this._editor.onDidLayoutChange(e => this.hideCodeActionWidget()));
|
||||
|
||||
|
@ -228,11 +280,16 @@ export class CodeActionMenu extends Disposable implements IEditorContribution {
|
|||
// Populating the list widget and tracking enabled options.
|
||||
inputArray.forEach((item, index) => {
|
||||
const currIsSeparator = item.class === 'separator';
|
||||
let isDocumentation = false;
|
||||
if (item instanceof CodeActionAction) {
|
||||
isDocumentation = item.action.kind === CodeActionMenu.documentationID;
|
||||
}
|
||||
|
||||
if (currIsSeparator) {
|
||||
// set to true forever
|
||||
this.hasSeperator = true;
|
||||
}
|
||||
const menuItem = <ICodeActionMenuItem>{ title: item.label, detail: item.tooltip, action: inputArray[index], isEnabled: item.enabled, isSeparator: currIsSeparator, index };
|
||||
const menuItem = <ICodeActionMenuItem>{ title: item.label, detail: item.tooltip, action: inputArray[index], isEnabled: item.enabled, isSeparator: currIsSeparator, index, isDocumentation };
|
||||
if (item.enabled) {
|
||||
this.viewItems.push(menuItem);
|
||||
}
|
||||
|
@ -263,9 +320,13 @@ export class CodeActionMenu extends Disposable implements IEditorContribution {
|
|||
this.codeActionList.value?.layout(height, maxWidth);
|
||||
|
||||
// List selection
|
||||
this.focusedEnabledItem = 0;
|
||||
this.currSelectedItem = this.viewItems[0].index;
|
||||
this.codeActionList.value.setFocus([this.currSelectedItem]);
|
||||
if (this.viewItems.length < 1 || this.viewItems.every(item => item.isDocumentation)) {
|
||||
this.currSelectedItem = undefined;
|
||||
} else {
|
||||
this.focusedEnabledItem = 0;
|
||||
this.currSelectedItem = this.viewItems[0].index;
|
||||
this.codeActionList.value.setFocus([this.currSelectedItem]);
|
||||
}
|
||||
|
||||
// List Focus
|
||||
this.codeActionList.value.domFocus();
|
||||
|
@ -284,7 +345,7 @@ export class CodeActionMenu extends Disposable implements IEditorContribution {
|
|||
protected focusPrevious() {
|
||||
if (typeof this.focusedEnabledItem === 'undefined') {
|
||||
this.focusedEnabledItem = this.viewItems[0].index;
|
||||
} else if (this.viewItems.length <= 1) {
|
||||
} else if (this.viewItems.length < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -307,7 +368,7 @@ export class CodeActionMenu extends Disposable implements IEditorContribution {
|
|||
protected focusNext() {
|
||||
if (typeof this.focusedEnabledItem === 'undefined') {
|
||||
this.focusedEnabledItem = this.viewItems.length - 1;
|
||||
} else if (this.viewItems.length <= 1) {
|
||||
} else if (this.viewItems.length < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -333,7 +394,9 @@ export class CodeActionMenu extends Disposable implements IEditorContribution {
|
|||
}
|
||||
|
||||
public onEnterSet() {
|
||||
this.codeActionList.value?.setSelection([this.currSelectedItem]);
|
||||
if (typeof this.currSelectedItem === 'number') {
|
||||
this.codeActionList.value?.setSelection([this.currSelectedItem]);
|
||||
}
|
||||
}
|
||||
|
||||
override dispose() {
|
||||
|
@ -345,7 +408,7 @@ export class CodeActionMenu extends Disposable implements IEditorContribution {
|
|||
this.options = [];
|
||||
this.viewItems = [];
|
||||
this.focusedEnabledItem = 0;
|
||||
this.currSelectedItem = 0;
|
||||
this.currSelectedItem = undefined;
|
||||
this.hasSeperator = false;
|
||||
this._contextViewService.hideContextView({ source: this });
|
||||
}
|
||||
|
@ -455,6 +518,7 @@ export class CodeActionMenu extends Disposable implements IEditorContribution {
|
|||
result.push(new Separator(), ...allDocumentation.map(command => toCodeActionAction(new CodeActionItem({
|
||||
title: command.title,
|
||||
command: command,
|
||||
kind: CodeActionMenu.documentationID
|
||||
}, undefined))));
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ export class CodeActionUi extends Disposable {
|
|||
private readonly _codeActionWidget: Lazy<CodeActionMenu>;
|
||||
private readonly _lightBulbWidget: Lazy<LightBulbWidget>;
|
||||
private readonly _activeCodeActions = this._register(new MutableDisposable<CodeActionSet>());
|
||||
private previewOn: boolean = false;
|
||||
|
||||
#disposed = false;
|
||||
|
||||
|
@ -40,7 +41,12 @@ export class CodeActionUi extends Disposable {
|
|||
this._codeActionWidget = new Lazy(() => {
|
||||
return this._register(instantiationService.createInstance(CodeActionMenu, this._editor, {
|
||||
onSelectCodeAction: async (action, trigger) => {
|
||||
this.delegate.applyCodeAction(action, /* retrigger */ true, Boolean(trigger.preview));
|
||||
if (this.previewOn) {
|
||||
this.delegate.applyCodeAction(action, /* retrigger */ true, Boolean(this.previewOn));
|
||||
} else {
|
||||
this.delegate.applyCodeAction(action, /* retrigger */ true, Boolean(trigger.preview));
|
||||
}
|
||||
this.previewOn = false;
|
||||
}
|
||||
}));
|
||||
});
|
||||
|
@ -70,6 +76,11 @@ export class CodeActionUi extends Disposable {
|
|||
}
|
||||
}
|
||||
|
||||
public onPreviewEnter() {
|
||||
this.previewOn = true;
|
||||
this.onEnter();
|
||||
}
|
||||
|
||||
public navigateList(navUp: Boolean) {
|
||||
if (this._codeActionWidget.hasValue()) {
|
||||
if (navUp) {
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
border-color: none;
|
||||
background-color: var(--vscode-menu-background);
|
||||
color: var(--vscode-menu-foreground);
|
||||
box-shadow: rgb(0,0,0, 16%) 0px 2px 8px;
|
||||
}
|
||||
|
||||
.codeActionMenuWidget .monaco-list:not(.element-focused):focus:before {
|
||||
|
@ -29,10 +30,10 @@
|
|||
z-index: 5; /* make sure we are on top of the tree items */
|
||||
content: "";
|
||||
pointer-events: none; /* enable click through */
|
||||
outline: 0px solid; /* we still need to handle the empty tree or no focus item case */
|
||||
outline-width: 0px;
|
||||
outline-style: none;
|
||||
outline-offset: 0px;
|
||||
outline: 0px solid !important; /* we still need to handle the empty tree or no focus item case */
|
||||
outline-width: 0px !important;
|
||||
outline-style: none !important;
|
||||
outline-offset: 0px !important;
|
||||
}
|
||||
|
||||
.codeActionMenuWidget .monaco-list {
|
||||
|
|
|
@ -311,7 +311,7 @@ export class ContextMenuController implements IEditorContribution {
|
|||
|
||||
const actions: IAction[] = [];
|
||||
actions.push(createAction({
|
||||
label: nls.localize('context.minimap.showMinimap', "Show Minimap"),
|
||||
label: nls.localize('context.minimap.minimap', "Minimap"),
|
||||
checked: minimapOptions.enabled,
|
||||
run: () => {
|
||||
this._configurationService.updateValue(`editor.minimap.enabled`, !minimapOptions.enabled);
|
||||
|
|
|
@ -25,7 +25,6 @@ import { CodeEditorStateFlag, EditorStateCancellationTokenSource } from 'vs/edit
|
|||
import { performSnippetEdit } from 'vs/editor/contrib/snippet/browser/snippetController2';
|
||||
import { SnippetParser } from 'vs/editor/contrib/snippet/browser/snippetParser';
|
||||
import { localize } from 'vs/nls';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
|
||||
|
@ -37,7 +36,6 @@ export class DropIntoEditorController extends Disposable implements IEditorContr
|
|||
constructor(
|
||||
editor: ICodeEditor,
|
||||
@IBulkEditService private readonly _bulkEditService: IBulkEditService,
|
||||
@IConfigurationService private readonly _configurationService: IConfigurationService,
|
||||
@ILanguageFeaturesService private readonly _languageFeaturesService: ILanguageFeaturesService,
|
||||
@IProgressService private readonly _progressService: IProgressService,
|
||||
@IWorkspaceContextService workspaceContextService: IWorkspaceContextService,
|
||||
|
@ -46,22 +44,7 @@ export class DropIntoEditorController extends Disposable implements IEditorContr
|
|||
|
||||
this._register(editor.onDropIntoEditor(e => this.onDropIntoEditor(editor, e.position, e.event)));
|
||||
|
||||
|
||||
this._languageFeaturesService.documentOnDropEditProvider.register('*', new DefaultOnDropProvider(workspaceContextService));
|
||||
|
||||
this._register(this._configurationService.onDidChangeConfiguration(e => {
|
||||
if (e.affectsConfiguration('workbench.editor.dropIntoEditor.enabled')) {
|
||||
this.updateEditorOptions(editor);
|
||||
}
|
||||
}));
|
||||
|
||||
this.updateEditorOptions(editor);
|
||||
}
|
||||
|
||||
private updateEditorOptions(editor: ICodeEditor) {
|
||||
editor.updateOptions({
|
||||
enableDropIntoEditor: this._configurationService.getValue('workbench.editor.dropIntoEditor.enabled')
|
||||
});
|
||||
}
|
||||
|
||||
private async onDropIntoEditor(editor: ICodeEditor, position: IPosition, dragEvent: DragEvent) {
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
.monaco-editor .margin-view-overlays .codicon-folding-manual-collapsed,
|
||||
.monaco-editor .margin-view-overlays .codicon-folding-manual-expanded,
|
||||
.monaco-editor .margin-view-overlays .codicon-folding-expanded,
|
||||
.monaco-editor .margin-view-overlays .codicon-folding-collapsed {
|
||||
cursor: pointer;
|
||||
|
@ -17,6 +18,7 @@
|
|||
|
||||
.monaco-editor .margin-view-overlays:hover .codicon,
|
||||
.monaco-editor .margin-view-overlays .codicon.codicon-folding-collapsed,
|
||||
.monaco-editor .margin-view-overlays .codicon.codicon-folding-manual-collapsed,
|
||||
.monaco-editor .margin-view-overlays .codicon.alwaysShowFoldIcons {
|
||||
opacity: 1;
|
||||
}
|
||||
|
@ -29,3 +31,4 @@
|
|||
line-height: 1em;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,8 +31,8 @@ import { IContextKey, IContextKeyService, RawContextKey } from 'vs/platform/cont
|
|||
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { editorSelectionBackground, iconForeground, registerColor, transparent } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { registerThemingParticipant, ThemeIcon } from 'vs/platform/theme/common/themeService';
|
||||
import { foldingCollapsedIcon, FoldingDecorationProvider, foldingExpandedIcon, foldingManualIcon } from './foldingDecorations';
|
||||
import { FoldingRegion, FoldingRegions, FoldRange } from './foldingRanges';
|
||||
import { foldingCollapsedIcon, FoldingDecorationProvider, foldingExpandedIcon, foldingManualCollapsedIcon, foldingManualExpandedIcon } from './foldingDecorations';
|
||||
import { FoldingRegion, FoldingRegions, FoldRange, FoldSource, ILineRange } from './foldingRanges';
|
||||
import { SyntaxRangeProvider } from './syntaxRangeProvider';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
|
@ -222,7 +222,7 @@ export class FoldingController extends Disposable implements IEditorContribution
|
|||
}
|
||||
|
||||
this._currentModelHasFoldedImports = false;
|
||||
this.foldingModel = new FoldingModel(model, this.foldingDecorationProvider, this.triggerFoldingModelChanged.bind(this));
|
||||
this.foldingModel = new FoldingModel(model, this.foldingDecorationProvider);
|
||||
this.localToDispose.add(this.foldingModel);
|
||||
|
||||
this.hiddenRangeModel = new HiddenRangeModel(this.foldingModel);
|
||||
|
@ -293,7 +293,7 @@ export class FoldingController extends Disposable implements IEditorContribution
|
|||
this.triggerFoldingModelChanged();
|
||||
}
|
||||
|
||||
private triggerFoldingModelChanged() {
|
||||
public triggerFoldingModelChanged() {
|
||||
if (this.updateScheduler) {
|
||||
if (this.foldingRegionPromise) {
|
||||
this.foldingRegionPromise.cancel();
|
||||
|
@ -1066,17 +1066,17 @@ class GotoNextFoldAction extends FoldingAction<void> {
|
|||
}
|
||||
}
|
||||
|
||||
class FoldSelectedAction extends FoldingAction<void> {
|
||||
class FoldRangeFromSelectionAction extends FoldingAction<void> {
|
||||
|
||||
constructor() {
|
||||
super({
|
||||
id: 'editor.foldSelected',
|
||||
label: nls.localize('foldSelectedAction.label', "Fold Selected Lines"),
|
||||
alias: 'Fold Selected Lines',
|
||||
id: 'editor.createFoldingRangeFromSelection',
|
||||
label: nls.localize('createManualFoldRange.label', "Create Manual Folding Range from Selection"),
|
||||
alias: 'Create Folding Range from Selection',
|
||||
precondition: CONTEXT_FOLDING_ENABLED,
|
||||
kbOpts: {
|
||||
kbExpr: EditorContextKeys.editorTextFocus,
|
||||
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.Period),
|
||||
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.Comma),
|
||||
weight: KeybindingWeight.EditorContrib
|
||||
}
|
||||
});
|
||||
|
@ -1097,7 +1097,7 @@ class FoldSelectedAction extends FoldingAction<void> {
|
|||
endLineNumber: endLineNumber,
|
||||
type: undefined,
|
||||
isCollapsed: true,
|
||||
isManualSelection: true
|
||||
source: FoldSource.userDefined
|
||||
});
|
||||
editor.setSelection({
|
||||
startLineNumber: selection.startLineNumber,
|
||||
|
@ -1118,6 +1118,36 @@ class FoldSelectedAction extends FoldingAction<void> {
|
|||
}
|
||||
}
|
||||
|
||||
class RemoveFoldRangeFromSelectionAction extends FoldingAction<void> {
|
||||
|
||||
constructor() {
|
||||
super({
|
||||
id: 'editor.removeManualFoldingRanges',
|
||||
label: nls.localize('removeManualFoldingRanges.label', "Remove Manual Folding Ranges"),
|
||||
alias: 'Remove Manual Folding Ranges',
|
||||
precondition: CONTEXT_FOLDING_ENABLED,
|
||||
kbOpts: {
|
||||
kbExpr: EditorContextKeys.editorTextFocus,
|
||||
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.Period),
|
||||
weight: KeybindingWeight.EditorContrib
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
invoke(foldingController: FoldingController, foldingModel: FoldingModel, editor: ICodeEditor): void {
|
||||
const selections = editor.getSelections();
|
||||
if (selections) {
|
||||
const ranges: ILineRange[] = [];
|
||||
for (const selection of selections) {
|
||||
const { startLineNumber, endLineNumber } = selection;
|
||||
ranges.push(endLineNumber >= startLineNumber ? { startLineNumber, endLineNumber } : { endLineNumber, startLineNumber });
|
||||
}
|
||||
foldingModel.removeManualRanges(ranges);
|
||||
foldingController.triggerFoldingModelChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
registerEditorContribution(FoldingController.ID, FoldingController);
|
||||
registerEditorAction(UnfoldAction);
|
||||
|
@ -1135,7 +1165,8 @@ registerEditorAction(ToggleFoldAction);
|
|||
registerEditorAction(GotoParentFoldAction);
|
||||
registerEditorAction(GotoPreviousFoldAction);
|
||||
registerEditorAction(GotoNextFoldAction);
|
||||
registerEditorAction(FoldSelectedAction);
|
||||
registerEditorAction(FoldRangeFromSelectionAction);
|
||||
registerEditorAction(RemoveFoldRangeFromSelectionAction);
|
||||
|
||||
for (let i = 1; i <= 7; i++) {
|
||||
registerInstantiatedEditorAction(
|
||||
|
@ -1167,7 +1198,8 @@ registerThemingParticipant((theme, collector) => {
|
|||
collector.addRule(`
|
||||
.monaco-editor .cldr${ThemeIcon.asCSSSelector(foldingExpandedIcon)},
|
||||
.monaco-editor .cldr${ThemeIcon.asCSSSelector(foldingCollapsedIcon)},
|
||||
.monaco-editor .cldr${ThemeIcon.asCSSSelector(foldingManualIcon)} {
|
||||
.monaco-editor .cldr${ThemeIcon.asCSSSelector(foldingManualExpandedIcon)},
|
||||
.monaco-editor .cldr${ThemeIcon.asCSSSelector(foldingManualCollapsedIcon)} {
|
||||
color: ${editorFoldColor} !important;
|
||||
}
|
||||
`);
|
||||
|
|
|
@ -14,12 +14,14 @@ import { ThemeIcon } from 'vs/platform/theme/common/themeService';
|
|||
|
||||
export const foldingExpandedIcon = registerIcon('folding-expanded', Codicon.chevronDown, localize('foldingExpandedIcon', 'Icon for expanded ranges in the editor glyph margin.'));
|
||||
export const foldingCollapsedIcon = registerIcon('folding-collapsed', Codicon.chevronRight, localize('foldingCollapsedIcon', 'Icon for collapsed ranges in the editor glyph margin.'));
|
||||
export const foldingManualIcon = registerIcon('folding-manual', Codicon.ellipsis, localize('foldingManualIcon', 'Icon for manually collapsed ranges in the editor glyph margin.'));
|
||||
export const foldingManualCollapsedIcon = registerIcon('folding-manual-collapsed', foldingCollapsedIcon, localize('foldingManualCollapedIcon', 'Icon for manually collapsed ranges in the editor glyph margin.'));
|
||||
export const foldingManualExpandedIcon = registerIcon('folding-manual-expanded', foldingExpandedIcon, localize('foldingManualExpandedIcon', 'Icon for manually expanded ranges in the editor glyph margin.'));
|
||||
|
||||
export class FoldingDecorationProvider implements IDecorationProvider {
|
||||
|
||||
private static readonly COLLAPSED_VISUAL_DECORATION = ModelDecorationOptions.register({
|
||||
description: 'folding-collapsed-visual-decoration',
|
||||
stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,
|
||||
stickiness: TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges,
|
||||
afterContentClassName: 'inline-folded',
|
||||
isWholeLine: true,
|
||||
firstLineDecorationClassName: ThemeIcon.asClassName(foldingCollapsedIcon)
|
||||
|
@ -27,7 +29,7 @@ export class FoldingDecorationProvider implements IDecorationProvider {
|
|||
|
||||
private static readonly COLLAPSED_HIGHLIGHTED_VISUAL_DECORATION = ModelDecorationOptions.register({
|
||||
description: 'folding-collapsed-highlighted-visual-decoration',
|
||||
stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,
|
||||
stickiness: TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges,
|
||||
afterContentClassName: 'inline-folded',
|
||||
className: 'folded-background',
|
||||
isWholeLine: true,
|
||||
|
@ -36,19 +38,19 @@ export class FoldingDecorationProvider implements IDecorationProvider {
|
|||
|
||||
private static readonly MANUALLY_COLLAPSED_VISUAL_DECORATION = ModelDecorationOptions.register({
|
||||
description: 'folding-manually-collapsed-visual-decoration',
|
||||
stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,
|
||||
stickiness: TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges,
|
||||
afterContentClassName: 'inline-folded',
|
||||
isWholeLine: true,
|
||||
firstLineDecorationClassName: ThemeIcon.asClassName(foldingManualIcon)
|
||||
firstLineDecorationClassName: 'alwaysShowFoldIcons ' + ThemeIcon.asClassName(foldingExpandedIcon)
|
||||
});
|
||||
|
||||
private static readonly MANUALLY_COLLAPSED_HIGHLIGHTED_VISUAL_DECORATION = ModelDecorationOptions.register({
|
||||
description: 'folding-manually-collapsed-highlighted-visual-decoration',
|
||||
stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,
|
||||
stickiness: TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges,
|
||||
afterContentClassName: 'inline-folded',
|
||||
className: 'folded-background',
|
||||
isWholeLine: true,
|
||||
firstLineDecorationClassName: ThemeIcon.asClassName(foldingManualIcon)
|
||||
firstLineDecorationClassName: ThemeIcon.asClassName(foldingManualCollapsedIcon)
|
||||
});
|
||||
|
||||
private static readonly EXPANDED_AUTO_HIDE_VISUAL_DECORATION = ModelDecorationOptions.register({
|
||||
|
@ -65,6 +67,21 @@ export class FoldingDecorationProvider implements IDecorationProvider {
|
|||
firstLineDecorationClassName: 'alwaysShowFoldIcons ' + ThemeIcon.asClassName(foldingExpandedIcon)
|
||||
});
|
||||
|
||||
private static readonly MANUALLY_EXPANDED_VISUAL_DECORATION = ModelDecorationOptions.register({
|
||||
description: 'folding-manually-expanded-visual-decoration',
|
||||
stickiness: TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges,
|
||||
isWholeLine: true,
|
||||
firstLineDecorationClassName: 'alwaysShowFoldIcons ' + ThemeIcon.asClassName(foldingManualExpandedIcon)
|
||||
});
|
||||
|
||||
private static readonly MANUALLY_EXPANDED_AUTO_HIDE_VISUAL_DECORATION = ModelDecorationOptions.register({
|
||||
description: 'folding-manually-expanded-visual-decoration',
|
||||
stickiness: TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges,
|
||||
isWholeLine: true,
|
||||
firstLineDecorationClassName: ThemeIcon.asClassName(foldingManualExpandedIcon)
|
||||
});
|
||||
|
||||
|
||||
private static readonly HIDDEN_RANGE_DECORATION = ModelDecorationOptions.register({
|
||||
description: 'folding-hidden-range-decoration',
|
||||
stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges
|
||||
|
@ -77,19 +94,19 @@ export class FoldingDecorationProvider implements IDecorationProvider {
|
|||
constructor(private readonly editor: ICodeEditor) {
|
||||
}
|
||||
|
||||
getDecorationOption(isCollapsed: boolean, isHidden: boolean, isManualSelection: boolean): IModelDecorationOptions {
|
||||
getDecorationOption(isCollapsed: boolean, isHidden: boolean, isManual: boolean): IModelDecorationOptions {
|
||||
if (isHidden // is inside another collapsed region
|
||||
|| this.showFoldingControls === 'never' || (isManualSelection && !isCollapsed)) { //
|
||||
|| this.showFoldingControls === 'never') {
|
||||
return FoldingDecorationProvider.HIDDEN_RANGE_DECORATION;
|
||||
}
|
||||
if (isCollapsed) {
|
||||
return isManualSelection ?
|
||||
return isManual ?
|
||||
(this.showFoldingHighlights ? FoldingDecorationProvider.MANUALLY_COLLAPSED_HIGHLIGHTED_VISUAL_DECORATION : FoldingDecorationProvider.MANUALLY_COLLAPSED_VISUAL_DECORATION)
|
||||
: (this.showFoldingHighlights ? FoldingDecorationProvider.COLLAPSED_HIGHLIGHTED_VISUAL_DECORATION : FoldingDecorationProvider.COLLAPSED_VISUAL_DECORATION);
|
||||
} else if (this.showFoldingControls === 'mouseover') {
|
||||
return FoldingDecorationProvider.EXPANDED_AUTO_HIDE_VISUAL_DECORATION;
|
||||
return isManual ? FoldingDecorationProvider.MANUALLY_EXPANDED_AUTO_HIDE_VISUAL_DECORATION : FoldingDecorationProvider.EXPANDED_AUTO_HIDE_VISUAL_DECORATION;
|
||||
} else {
|
||||
return FoldingDecorationProvider.EXPANDED_VISUAL_DECORATION;
|
||||
return isManual ? FoldingDecorationProvider.MANUALLY_EXPANDED_VISUAL_DECORATION : FoldingDecorationProvider.EXPANDED_VISUAL_DECORATION;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { IModelDecorationOptions, IModelDecorationsChangeAccessor, IModelDeltaDecoration, ITextModel } from 'vs/editor/common/model';
|
||||
import { FoldingRegion, FoldingRegions, ILineRange, FoldRange } from './foldingRanges';
|
||||
import { FoldingRegion, FoldingRegions, ILineRange, FoldRange, FoldSource } from './foldingRanges';
|
||||
import { hash } from 'vs/base/common/hash';
|
||||
|
||||
export interface IDecorationProvider {
|
||||
getDecorationOption(isCollapsed: boolean, isHidden: boolean, isManualSelection: boolean): IModelDecorationOptions;
|
||||
getDecorationOption(isCollapsed: boolean, isHidden: boolean, isManual: boolean): IModelDecorationOptions;
|
||||
changeDecorations<T>(callback: (changeAccessor: IModelDecorationsChangeAccessor) => T): T | null;
|
||||
removeDecorations(decorationIds: string[]): void;
|
||||
}
|
||||
|
@ -21,6 +21,8 @@ export interface FoldingModelChangeEvent {
|
|||
|
||||
interface ILineMemento extends ILineRange {
|
||||
checksum?: number;
|
||||
isCollapsed?: boolean;
|
||||
source?: FoldSource;
|
||||
}
|
||||
|
||||
export type CollapseMemento = ILineMemento[];
|
||||
|
@ -28,7 +30,6 @@ export type CollapseMemento = ILineMemento[];
|
|||
export class FoldingModel {
|
||||
private readonly _textModel: ITextModel;
|
||||
private readonly _decorationProvider: IDecorationProvider;
|
||||
private readonly _triggerRecomputeRanges: (() => void) | undefined;
|
||||
|
||||
private _regions: FoldingRegions;
|
||||
private _editorDecorationIds: string[];
|
||||
|
@ -40,10 +41,9 @@ export class FoldingModel {
|
|||
public get textModel() { return this._textModel; }
|
||||
public get decorationProvider() { return this._decorationProvider; }
|
||||
|
||||
constructor(textModel: ITextModel, decorationProvider: IDecorationProvider, triggerRecomputeRanges?: () => void) {
|
||||
constructor(textModel: ITextModel, decorationProvider: IDecorationProvider) {
|
||||
this._textModel = textModel;
|
||||
this._decorationProvider = decorationProvider;
|
||||
this._triggerRecomputeRanges = triggerRecomputeRanges;
|
||||
this._regions = new FoldingRegions(new Uint32Array(0), new Uint32Array(0));
|
||||
this._editorDecorationIds = [];
|
||||
}
|
||||
|
@ -55,7 +55,6 @@ export class FoldingModel {
|
|||
toggledRegions = toggledRegions.sort((r1, r2) => r1.regionIndex - r2.regionIndex);
|
||||
|
||||
const processed: { [key: string]: boolean | undefined } = {};
|
||||
const manualExpanded = false;
|
||||
this._decorationProvider.changeDecorations(accessor => {
|
||||
let k = 0; // index from [0 ... this.regions.length]
|
||||
let dirtyRegionEndLine = -1; // end of the range where decorations need to be updated
|
||||
|
@ -64,9 +63,9 @@ export class FoldingModel {
|
|||
while (k < index) {
|
||||
const endLineNumber = this._regions.getEndLineNumber(k);
|
||||
const isCollapsed = this._regions.isCollapsed(k);
|
||||
const isManualSelection = this.regions.isManualSelection(k);
|
||||
if (endLineNumber <= dirtyRegionEndLine) {
|
||||
accessor.changeDecorationOptions(this._editorDecorationIds[k], this._decorationProvider.getDecorationOption(isCollapsed, endLineNumber <= lastHiddenLine, isManualSelection));
|
||||
const isManual = this.regions.getSource(k) !== FoldSource.provider;
|
||||
accessor.changeDecorationOptions(this._editorDecorationIds[k], this._decorationProvider.getDecorationOption(isCollapsed, endLineNumber <= lastHiddenLine, isManual));
|
||||
}
|
||||
if (isCollapsed && endLineNumber > lastHiddenLine) {
|
||||
lastHiddenLine = endLineNumber;
|
||||
|
@ -91,16 +90,30 @@ export class FoldingModel {
|
|||
updateDecorationsUntil(this._regions.length);
|
||||
});
|
||||
this._updateEventEmitter.fire({ model: this, collapseStateChanged: toggledRegions });
|
||||
if (manualExpanded && this._triggerRecomputeRanges) {
|
||||
// expanding a range which didn't originate from range provider might now enable ranges
|
||||
// from the provider which were previously dropped due to the collapsed range
|
||||
this._triggerRecomputeRanges();
|
||||
}
|
||||
|
||||
public removeManualRanges(ranges: ILineRange[]) {
|
||||
const newFoldingRanges: FoldRange[] = new Array();
|
||||
const intersects = (foldRange: FoldRange) => {
|
||||
for (const range of ranges) {
|
||||
if (!(range.startLineNumber > foldRange.endLineNumber || foldRange.startLineNumber > range.endLineNumber)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
for (let i = 0; i < this._regions.length; i++) {
|
||||
const foldRange = this._regions.toFoldRange(i);
|
||||
if (foldRange.source === FoldSource.provider || !intersects(foldRange)) {
|
||||
newFoldingRanges.push(foldRange);
|
||||
}
|
||||
}
|
||||
this.updatePost(FoldingRegions.fromFoldRanges(newFoldingRanges));
|
||||
}
|
||||
|
||||
public update(newRegions: FoldingRegions, blockedLineNumers: number[] = []): void {
|
||||
const hiddenRanges = this._currentHiddenRegions(blockedLineNumers);
|
||||
const newRanges = FoldingRegions.sanitizeAndMerge(newRegions, hiddenRanges, this._textModel.getLineCount());
|
||||
const foldedOrManualRanges = this._currentFoldedOrManualRanges(blockedLineNumers);
|
||||
const newRanges = FoldingRegions.sanitizeAndMerge(newRegions, foldedOrManualRanges, this._textModel.getLineCount());
|
||||
this.updatePost(FoldingRegions.fromFoldRanges(newRanges));
|
||||
}
|
||||
|
||||
|
@ -111,14 +124,14 @@ export class FoldingModel {
|
|||
const startLineNumber = newRegions.getStartLineNumber(index);
|
||||
const endLineNumber = newRegions.getEndLineNumber(index);
|
||||
const isCollapsed = newRegions.isCollapsed(index);
|
||||
const isManualSelection = newRegions.isManualSelection(index);
|
||||
const isManual = newRegions.getSource(index) !== FoldSource.provider;
|
||||
const decorationRange = {
|
||||
startLineNumber: startLineNumber,
|
||||
startColumn: this._textModel.getLineMaxColumn(startLineNumber),
|
||||
endLineNumber: endLineNumber,
|
||||
endColumn: this._textModel.getLineMaxColumn(endLineNumber) + 1
|
||||
};
|
||||
newEditorDecorations.push({ range: decorationRange, options: this._decorationProvider.getDecorationOption(isCollapsed, endLineNumber <= lastHiddenLine, isManualSelection) });
|
||||
newEditorDecorations.push({ range: decorationRange, options: this._decorationProvider.getDecorationOption(isCollapsed, endLineNumber <= lastHiddenLine, isManual) });
|
||||
if (isCollapsed && endLineNumber > lastHiddenLine) {
|
||||
lastHiddenLine = endLineNumber;
|
||||
}
|
||||
|
@ -128,7 +141,7 @@ export class FoldingModel {
|
|||
this._updateEventEmitter.fire({ model: this });
|
||||
}
|
||||
|
||||
private _currentHiddenRegions(blockedLineNumers: number[] = []): FoldRange[] {
|
||||
private _currentFoldedOrManualRanges(blockedLineNumers: number[] = []): FoldRange[] {
|
||||
|
||||
const isBlocked = (startLineNumber: number, endLineNumber: number) => {
|
||||
for (const blockedLineNumber of blockedLineNumers) {
|
||||
|
@ -139,42 +152,45 @@ export class FoldingModel {
|
|||
return false;
|
||||
};
|
||||
|
||||
const hiddenRanges: FoldRange[] = [];
|
||||
const foldedRanges: FoldRange[] = [];
|
||||
for (let i = 0, limit = this._regions.length; i < limit; i++) {
|
||||
if (this.regions.isCollapsed(i)) {
|
||||
const hiddenRange = this._regions.toFoldRange(i);
|
||||
let isCollapsed = this.regions.isCollapsed(i);
|
||||
const source = this.regions.getSource(i);
|
||||
if (isCollapsed || source !== FoldSource.provider) {
|
||||
const foldRange = this._regions.toFoldRange(i);
|
||||
const decRange = this._textModel.getDecorationRange(this._editorDecorationIds[i]);
|
||||
if (decRange
|
||||
&& !isBlocked(decRange.startLineNumber, decRange.endLineNumber)
|
||||
// if not same length user has modified it, skip and auto-expand
|
||||
&& decRange.endLineNumber - decRange.startLineNumber
|
||||
=== hiddenRange.endLineNumber - hiddenRange.startLineNumber) {
|
||||
hiddenRanges.push({
|
||||
if (decRange) {
|
||||
if (isCollapsed && (isBlocked(decRange.startLineNumber, decRange.endLineNumber) || decRange.endLineNumber - decRange.startLineNumber !== foldRange.endLineNumber - foldRange.startLineNumber)) {
|
||||
isCollapsed = false; // uncollapse is the range is blocked or there has been lines removed or added
|
||||
}
|
||||
foldedRanges.push({
|
||||
startLineNumber: decRange.startLineNumber,
|
||||
endLineNumber: decRange.endLineNumber,
|
||||
type: hiddenRange.type,
|
||||
isCollapsed: true,
|
||||
isManualSelection: hiddenRange.isManualSelection
|
||||
type: foldRange.type,
|
||||
isCollapsed,
|
||||
source
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hiddenRanges;
|
||||
return foldedRanges;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collapse state memento, for persistence only
|
||||
*/
|
||||
public getMemento(): CollapseMemento | undefined {
|
||||
const hiddenRegions = this._currentHiddenRegions();
|
||||
const foldedOrManualRanges = this._currentFoldedOrManualRanges();
|
||||
const result: ILineMemento[] = [];
|
||||
for (let i = 0, limit = hiddenRegions.length; i < limit; i++) {
|
||||
const range = hiddenRegions[i];
|
||||
for (let i = 0, limit = foldedOrManualRanges.length; i < limit; i++) {
|
||||
const range = foldedOrManualRanges[i];
|
||||
const checksum = this._getLinesChecksum(range.startLineNumber + 1, range.endLineNumber);
|
||||
result.push({
|
||||
startLineNumber: range.startLineNumber,
|
||||
endLineNumber: range.endLineNumber,
|
||||
isCollapsed: range.isCollapsed,
|
||||
source: range.source,
|
||||
checksum: checksum
|
||||
});
|
||||
}
|
||||
|
@ -188,7 +204,7 @@ export class FoldingModel {
|
|||
if (!Array.isArray(state)) {
|
||||
return;
|
||||
}
|
||||
const hiddenRanges: FoldRange[] = [];
|
||||
const rangesToRestore: FoldRange[] = [];
|
||||
const maxLineNumber = this._textModel.getLineCount();
|
||||
for (const range of state) {
|
||||
if (range.startLineNumber >= range.endLineNumber || range.startLineNumber < 1 || range.endLineNumber > maxLineNumber) {
|
||||
|
@ -196,17 +212,17 @@ export class FoldingModel {
|
|||
}
|
||||
const checksum = this._getLinesChecksum(range.startLineNumber + 1, range.endLineNumber);
|
||||
if (!range.checksum || checksum === range.checksum) {
|
||||
hiddenRanges.push({
|
||||
rangesToRestore.push({
|
||||
startLineNumber: range.startLineNumber,
|
||||
endLineNumber: range.endLineNumber,
|
||||
type: undefined,
|
||||
isCollapsed: true,
|
||||
isManualSelection: true // converts to false when provider sends a match
|
||||
isCollapsed: range.isCollapsed ?? true,
|
||||
source: range.source ?? FoldSource.provider
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const newRanges = FoldingRegions.sanitizeAndMerge(this._regions, hiddenRanges, maxLineNumber);
|
||||
const newRanges = FoldingRegions.sanitizeAndMerge(this._regions, rangesToRestore, maxLineNumber);
|
||||
this.updatePost(FoldingRegions.fromFoldRanges(newRanges));
|
||||
}
|
||||
|
||||
|
|
|
@ -8,12 +8,18 @@ export interface ILineRange {
|
|||
endLineNumber: number;
|
||||
}
|
||||
|
||||
export const enum FoldSource {
|
||||
provider = 0,
|
||||
userDefined = 1,
|
||||
recovered = 2
|
||||
}
|
||||
|
||||
export interface FoldRange {
|
||||
startLineNumber: number;
|
||||
endLineNumber: number;
|
||||
type: string | undefined;
|
||||
isCollapsed: boolean;
|
||||
isManualSelection: boolean;
|
||||
source: FoldSource;
|
||||
}
|
||||
|
||||
export const MAX_FOLDING_REGIONS = 0xFFFF;
|
||||
|
@ -21,11 +27,38 @@ export const MAX_LINE_NUMBER = 0xFFFFFF;
|
|||
|
||||
const MASK_INDENT = 0xFF000000;
|
||||
|
||||
class BitField {
|
||||
private readonly _states: Uint32Array;
|
||||
constructor(size: number) {
|
||||
const numWords = Math.ceil(size / 32);
|
||||
this._states = new Uint32Array(numWords);
|
||||
}
|
||||
|
||||
public get(index: number): boolean {
|
||||
const arrayIndex = (index / 32) | 0;
|
||||
const bit = index % 32;
|
||||
return (this._states[arrayIndex] & (1 << bit)) !== 0;
|
||||
}
|
||||
|
||||
public set(index: number, newState: boolean) {
|
||||
const arrayIndex = (index / 32) | 0;
|
||||
const bit = index % 32;
|
||||
const value = this._states[arrayIndex];
|
||||
if (newState) {
|
||||
this._states[arrayIndex] = value | (1 << bit);
|
||||
} else {
|
||||
this._states[arrayIndex] = value & ~(1 << bit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class FoldingRegions {
|
||||
private readonly _startIndexes: Uint32Array;
|
||||
private readonly _endIndexes: Uint32Array;
|
||||
private readonly _collapseStates: Uint32Array;
|
||||
private readonly _manualStates: Uint32Array;
|
||||
private readonly _collapseStates: BitField;
|
||||
private readonly _userDefinedStates: BitField;
|
||||
private readonly _recoveredStates: BitField;
|
||||
|
||||
private _parentsComputed: boolean;
|
||||
private readonly _types: Array<string | undefined> | undefined;
|
||||
|
||||
|
@ -35,9 +68,9 @@ export class FoldingRegions {
|
|||
}
|
||||
this._startIndexes = startIndexes;
|
||||
this._endIndexes = endIndexes;
|
||||
const numWords = Math.ceil(startIndexes.length / 32);
|
||||
this._collapseStates = new Uint32Array(numWords);
|
||||
this._manualStates = new Uint32Array(numWords);
|
||||
this._collapseStates = new BitField(startIndexes.length);
|
||||
this._userDefinedStates = new BitField(startIndexes.length);
|
||||
this._recoveredStates = new BitField(startIndexes.length);
|
||||
this._types = types;
|
||||
this._parentsComputed = false;
|
||||
}
|
||||
|
@ -88,36 +121,48 @@ export class FoldingRegions {
|
|||
}
|
||||
|
||||
public isCollapsed(index: number): boolean {
|
||||
const arrayIndex = (index / 32) | 0;
|
||||
const bit = index % 32;
|
||||
return (this._collapseStates[arrayIndex] & (1 << bit)) !== 0;
|
||||
return this._collapseStates.get(index);
|
||||
}
|
||||
|
||||
public setCollapsed(index: number, newState: boolean) {
|
||||
const arrayIndex = (index / 32) | 0;
|
||||
const bit = index % 32;
|
||||
const value = this._collapseStates[arrayIndex];
|
||||
if (newState) {
|
||||
this._collapseStates[arrayIndex] = value | (1 << bit);
|
||||
} else {
|
||||
this._collapseStates[arrayIndex] = value & ~(1 << bit);
|
||||
this._collapseStates.set(index, newState);
|
||||
}
|
||||
|
||||
private isUserDefined(index: number): boolean {
|
||||
return this._userDefinedStates.get(index);
|
||||
}
|
||||
|
||||
private setUserDefined(index: number, newState: boolean) {
|
||||
return this._userDefinedStates.set(index, newState);
|
||||
}
|
||||
|
||||
private isRecovered(index: number): boolean {
|
||||
return this._recoveredStates.get(index);
|
||||
}
|
||||
|
||||
private setRecovered(index: number, newState: boolean) {
|
||||
return this._recoveredStates.set(index, newState);
|
||||
}
|
||||
|
||||
public getSource(index: number): FoldSource {
|
||||
if (this.isUserDefined(index)) {
|
||||
return FoldSource.userDefined;
|
||||
} else if (this.isRecovered(index)) {
|
||||
return FoldSource.recovered;
|
||||
}
|
||||
return FoldSource.provider;
|
||||
}
|
||||
|
||||
public isManualSelection(index: number): boolean {
|
||||
const arrayIndex = (index / 32) | 0;
|
||||
const bit = index % 32;
|
||||
return (this._manualStates[arrayIndex] & (1 << bit)) !== 0;
|
||||
}
|
||||
|
||||
public setManualSelection(index: number, newState: boolean) {
|
||||
const arrayIndex = (index / 32) | 0;
|
||||
const bit = index % 32;
|
||||
const value = this._manualStates[arrayIndex];
|
||||
if (newState) {
|
||||
this._manualStates[arrayIndex] = value | (1 << bit);
|
||||
public setSource(index: number, source: FoldSource): void {
|
||||
if (source === FoldSource.userDefined) {
|
||||
this.setUserDefined(index, true);
|
||||
this.setRecovered(index, false);
|
||||
} else if (source === FoldSource.recovered) {
|
||||
this.setUserDefined(index, false);
|
||||
this.setRecovered(index, true);
|
||||
} else {
|
||||
this._manualStates[arrayIndex] = value & ~(1 << bit);
|
||||
this.setUserDefined(index, false);
|
||||
this.setRecovered(index, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -185,10 +230,16 @@ export class FoldingRegions {
|
|||
return -1;
|
||||
}
|
||||
|
||||
private readonly sourceAbbr = {
|
||||
[FoldSource.provider]: ' ',
|
||||
[FoldSource.userDefined]: 'u',
|
||||
[FoldSource.recovered]: 'r',
|
||||
};
|
||||
|
||||
public toString() {
|
||||
const res: string[] = [];
|
||||
for (let i = 0; i < this.length; i++) {
|
||||
res[i] = `[${this.isManualSelection(i) ? '*' : ' '}${this.isCollapsed(i) ? '+' : '-'}] ${this.getStartLineNumber(i)}/${this.getEndLineNumber(i)}`;
|
||||
res[i] = `[${this.sourceAbbr[this.getSource(i)]}${this.isCollapsed(i) ? '+' : '-'}] ${this.getStartLineNumber(i)}/${this.getEndLineNumber(i)}`;
|
||||
}
|
||||
return res.join(', ');
|
||||
}
|
||||
|
@ -199,7 +250,7 @@ export class FoldingRegions {
|
|||
endLineNumber: this._endIndexes[index] & MAX_LINE_NUMBER,
|
||||
type: this._types ? this._types[index] : undefined,
|
||||
isCollapsed: this.isCollapsed(index),
|
||||
isManualSelection: this.isManualSelection(index)
|
||||
source: this.getSource(index)
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -226,9 +277,7 @@ export class FoldingRegions {
|
|||
if (ranges[i].isCollapsed) {
|
||||
regions.setCollapsed(i, true);
|
||||
}
|
||||
if (ranges[i].isManualSelection) {
|
||||
regions.setManualSelection(i, true);
|
||||
}
|
||||
regions.setSource(i, ranges[i].source);
|
||||
}
|
||||
return regions;
|
||||
}
|
||||
|
@ -237,11 +286,10 @@ export class FoldingRegions {
|
|||
* Two inputs, each a FoldingRegions or a FoldRange[], are merged.
|
||||
* Each input must be pre-sorted on startLineNumber.
|
||||
* The first list is assumed to always include all regions currently defined by range providers.
|
||||
* The second list only contains hidden ranges.
|
||||
* The second list only contains the previously collapsed and all manual ranges.
|
||||
* If the line position matches, the range of the new range is taken, and the range is no longer manual
|
||||
* When an entry in one list overlaps an entry in the other, the second list's entry "wins" and
|
||||
* overlapping entries in the first list are discarded. With one exception: when there is just
|
||||
* one such second list entry and it is not manual it is discarded, on the assumption that
|
||||
* user editing has resulted in the range no longer existing.
|
||||
* overlapping entries in the first list are discarded.
|
||||
* Invalid entries are discarded. An entry is invalid if:
|
||||
* the start and end line numbers aren't a valid range of line numbers,
|
||||
* it is out of sequence or has the same start line as a preceding entry,
|
||||
|
@ -252,18 +300,6 @@ export class FoldingRegions {
|
|||
rangesB: FoldingRegions | FoldRange[],
|
||||
maxLineNumber: number | undefined): FoldRange[] {
|
||||
maxLineNumber = maxLineNumber ?? Number.MAX_VALUE;
|
||||
let result = this._trySanitizeAndMerge(1, rangesA, rangesB, maxLineNumber);
|
||||
if (!result) { // try again, converting hidden ranges to manually selected
|
||||
result = this._trySanitizeAndMerge(2, rangesA, rangesB, maxLineNumber);
|
||||
}
|
||||
return result!;
|
||||
}
|
||||
|
||||
private static _trySanitizeAndMerge(
|
||||
passNumber: number, // it can take two passes to get this done
|
||||
rangesA: FoldingRegions | FoldRange[],
|
||||
rangesB: FoldingRegions | FoldRange[],
|
||||
maxLineNumber: number): FoldRange[] | null {
|
||||
|
||||
const getIndexedFunction = (r: FoldingRegions | FoldRange[], limit: number) => {
|
||||
return Array.isArray(r)
|
||||
|
@ -281,41 +317,32 @@ export class FoldingRegions {
|
|||
let topStackedRange: FoldRange | undefined;
|
||||
let prevLineNumber = 0;
|
||||
const resultRanges: FoldRange[] = [];
|
||||
let numberAutoExpand = 0;
|
||||
|
||||
while (nextA || nextB) {
|
||||
|
||||
let useRange: FoldRange | undefined = undefined;
|
||||
if (nextB && (!nextA || nextA.startLineNumber >= nextB.startLineNumber)) {
|
||||
// nextB is next
|
||||
if (nextA
|
||||
&& nextA.startLineNumber === nextB.startLineNumber
|
||||
&& nextA.endLineNumber === nextB.endLineNumber) {
|
||||
// same range in both lists, merge the details
|
||||
useRange = nextB;
|
||||
useRange.isCollapsed = useRange.isCollapsed || nextA.isCollapsed;
|
||||
// next line removes manual flag when range provider has matching range
|
||||
useRange.isManualSelection = nextA.isManualSelection && nextB.isManualSelection;
|
||||
if (!useRange.type) {
|
||||
useRange.type = nextA.type;
|
||||
if (nextA && nextA.startLineNumber === nextB.startLineNumber) {
|
||||
if (nextB.source === FoldSource.userDefined) {
|
||||
// a user defined range (possibly unfolded)
|
||||
useRange = nextB;
|
||||
} else {
|
||||
// a previously folded range or a (possibly unfolded) recovered range
|
||||
useRange = nextA;
|
||||
useRange.isCollapsed = nextB.isCollapsed && nextA.endLineNumber === nextB.endLineNumber;
|
||||
useRange.source = FoldSource.provider;
|
||||
}
|
||||
nextA = getA(++indexA); // not necessary, just for speed
|
||||
} else if (nextB.isCollapsed && !nextB.isManualSelection && passNumber === 1) {
|
||||
if (++numberAutoExpand > 1) {
|
||||
// do second pass keeping these, assuming something like an unmatched /*
|
||||
return null;
|
||||
}
|
||||
// skip nextB (auto expand) by not setting useRange, assuming it was edited
|
||||
} else { // use nextB
|
||||
} else {
|
||||
useRange = nextB;
|
||||
if (useRange.isCollapsed) {
|
||||
// doesn't match nextA, convert to a manual selection if it wasn't already
|
||||
useRange.isManualSelection = true;
|
||||
if (nextB.isCollapsed && nextB.source === FoldSource.provider) {
|
||||
// a previously collapsed range
|
||||
useRange.source = FoldSource.recovered;
|
||||
}
|
||||
}
|
||||
nextB = getB(++indexB);
|
||||
} else {
|
||||
// nextA is next. The B set takes precedence and we sometimes need to look
|
||||
// nextA is next. The user folded B set takes precedence and we sometimes need to look
|
||||
// ahead in it to check for an upcoming conflict.
|
||||
let scanIndex = indexB;
|
||||
let prescanB = nextB;
|
||||
|
@ -324,8 +351,8 @@ export class FoldingRegions {
|
|||
useRange = nextA;
|
||||
break; // no conflict, use this nextA
|
||||
}
|
||||
if (prescanB.endLineNumber > nextA!.endLineNumber
|
||||
&& (!prescanB.isCollapsed || prescanB.isManualSelection || passNumber === 2)) {
|
||||
if (prescanB.source === FoldSource.userDefined && prescanB.endLineNumber > nextA!.endLineNumber) {
|
||||
// we found a user folded range, it wins
|
||||
break; // without setting nextResult, so this nextA gets skipped
|
||||
}
|
||||
prescanB = getB(++scanIndex);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
import * as assert from 'assert';
|
||||
import { FoldingMarkers } from 'vs/editor/common/languages/languageConfiguration';
|
||||
import { MAX_FOLDING_REGIONS, FoldRange, FoldingRegions } from 'vs/editor/contrib/folding/browser/foldingRanges';
|
||||
import { MAX_FOLDING_REGIONS, FoldRange, FoldingRegions, FoldSource } from 'vs/editor/contrib/folding/browser/foldingRanges';
|
||||
import { computeRanges } from 'vs/editor/contrib/folding/browser/indentRangeProvider';
|
||||
import { createTextModel } from 'vs/editor/test/common/testTextModel';
|
||||
|
||||
|
@ -16,20 +16,20 @@ const markers: FoldingMarkers = {
|
|||
|
||||
suite('FoldingRanges', () => {
|
||||
|
||||
const foldRange = (from: number, to: number, collapsed: boolean | undefined = undefined, manual: boolean | undefined = undefined, type: string | undefined = undefined) =>
|
||||
const foldRange = (from: number, to: number, collapsed: boolean | undefined = undefined, source: FoldSource = FoldSource.provider, type: string | undefined = undefined) =>
|
||||
<FoldRange>{
|
||||
startLineNumber: from,
|
||||
endLineNumber: to,
|
||||
type: type,
|
||||
isCollapsed: collapsed || false,
|
||||
isManualSelection: manual || false
|
||||
source
|
||||
};
|
||||
const assertEqualRanges = (range1: FoldRange, range2: FoldRange, msg: string) => {
|
||||
assert.strictEqual(range1.startLineNumber, range2.startLineNumber, msg + ' start');
|
||||
assert.strictEqual(range1.endLineNumber, range2.endLineNumber, msg + ' end');
|
||||
assert.strictEqual(range1.type, range2.type, msg + ' type');
|
||||
assert.strictEqual(range1.isCollapsed, range2.isCollapsed, msg + ' collapsed');
|
||||
assert.strictEqual(range1.isManualSelection, range2.isManualSelection, msg + ' manual');
|
||||
assert.strictEqual(range1.source, range2.source, msg + ' source');
|
||||
};
|
||||
|
||||
test('test max folding regions', () => {
|
||||
|
@ -122,110 +122,88 @@ suite('FoldingRanges', () => {
|
|||
test('sanitizeAndMerge1', () => {
|
||||
const regionSet1: FoldRange[] = [
|
||||
foldRange(0, 100), // invalid, should be removed
|
||||
foldRange(1, 100, false, false, 'A'), // valid
|
||||
foldRange(1, 100, false, false, 'Z'), // invalid, duplicate start
|
||||
foldRange(1, 100, false, FoldSource.provider, 'A'), // valid
|
||||
foldRange(1, 100, false, FoldSource.provider, 'Z'), // invalid, duplicate start
|
||||
foldRange(10, 10, false), // invalid, should be removed
|
||||
foldRange(20, 80, false, false, 'C1'), // valid inside 'B'
|
||||
foldRange(22, 80, true, false, 'D1'), // valid inside 'C1'
|
||||
foldRange(20, 80, false, FoldSource.provider, 'C1'), // valid inside 'B'
|
||||
foldRange(22, 80, true, FoldSource.provider, 'D1'), // valid inside 'C1'
|
||||
foldRange(90, 101), // invalid, should be removed
|
||||
];
|
||||
const regionSet2: FoldRange[] = [
|
||||
foldRange(2, 100, false, false, 'B'), // valid, inside 'A'
|
||||
foldRange(20, 80, true), // should merge with C1
|
||||
foldRange(18, 80, true), // invalid, out of order
|
||||
foldRange(21, 81, true, false, 'Z'), // invalid, overlapping
|
||||
foldRange(22, 80, false, false, 'D2'), // should merge with D1
|
||||
foldRange(21, 81, true, FoldSource.provider, 'Z'), // invalid, overlapping
|
||||
foldRange(22, 80, true, FoldSource.provider, 'D2'), // should merge with D1
|
||||
];
|
||||
let result = FoldingRegions.sanitizeAndMerge(regionSet1, regionSet2, 100);
|
||||
assert.strictEqual(result.length, 4, 'result length1');
|
||||
assertEqualRanges(result[0], foldRange(1, 100, false, false, 'A'), 'A1');
|
||||
assertEqualRanges(result[1], foldRange(2, 100, false, false, 'B'), 'B1');
|
||||
assertEqualRanges(result[2], foldRange(20, 80, true, false, 'C1'), 'C1');
|
||||
assertEqualRanges(result[3], foldRange(22, 80, true, false, 'D2'), 'D1');
|
||||
const regionClass1 = FoldingRegions.fromFoldRanges(regionSet1);
|
||||
const regionClass2 = FoldingRegions.fromFoldRanges(regionSet2);
|
||||
// same tests again with inputs as FoldingRegions instead of FoldRange[]
|
||||
result = FoldingRegions.sanitizeAndMerge(regionClass1, regionClass2, 100);
|
||||
assert.strictEqual(result.length, 4, 'result length2');
|
||||
assertEqualRanges(result[0], foldRange(1, 100, false, false, 'A'), 'A2');
|
||||
assertEqualRanges(result[1], foldRange(2, 100, false, false, 'B'), 'B2');
|
||||
assertEqualRanges(result[2], foldRange(20, 80, true, false, 'C1'), 'C2');
|
||||
assertEqualRanges(result[3], foldRange(22, 80, true, false, 'D2'), 'D2');
|
||||
const result = FoldingRegions.sanitizeAndMerge(regionSet1, regionSet2, 100);
|
||||
assert.strictEqual(result.length, 3, 'result length1');
|
||||
assertEqualRanges(result[0], foldRange(1, 100, false, FoldSource.provider, 'A'), 'A1');
|
||||
assertEqualRanges(result[1], foldRange(20, 80, true, FoldSource.provider, 'C1'), 'C1');
|
||||
assertEqualRanges(result[2], foldRange(22, 80, true, FoldSource.provider, 'D1'), 'D1');
|
||||
});
|
||||
|
||||
test('sanitizeAndMerge2', () => {
|
||||
const regionSet1: FoldRange[] = [
|
||||
foldRange(1, 100, false, false, 'a1'), // valid
|
||||
foldRange(2, 100, false, false, 'a2'), // valid
|
||||
foldRange(3, 19, false, false, 'a3'), // valid
|
||||
foldRange(20, 71, false, false, 'a4'), // overlaps b3
|
||||
foldRange(21, 29, false, false, 'a5'), // valid
|
||||
foldRange(81, 91, false, false, 'a6'), // overlaps b4
|
||||
foldRange(1, 100, false, FoldSource.provider, 'a1'), // valid
|
||||
foldRange(2, 100, false, FoldSource.provider, 'a2'), // valid
|
||||
foldRange(3, 19, false, FoldSource.provider, 'a3'), // valid
|
||||
foldRange(20, 71, false, FoldSource.provider, 'a4'), // overlaps b3
|
||||
foldRange(21, 29, false, FoldSource.provider, 'a5'), // valid
|
||||
foldRange(81, 91, false, FoldSource.provider, 'a6'), // overlaps b4
|
||||
];
|
||||
const regionSet2: FoldRange[] = [
|
||||
foldRange(30, 39, false, false, 'b1'), // valid
|
||||
foldRange(40, 49, false, false, 'b2'), // valid
|
||||
foldRange(50, 100, false, false, 'b3'), // overlaps a4
|
||||
foldRange(80, 90, false, false, 'b4'), // overlaps a6
|
||||
foldRange(92, 100, false, false, 'b5'), // valid
|
||||
foldRange(30, 39, true, FoldSource.provider, 'b1'), // valid, will be recovered
|
||||
foldRange(40, 49, true, FoldSource.userDefined, 'b2'), // valid
|
||||
foldRange(50, 100, true, FoldSource.userDefined, 'b3'), // overlaps a4
|
||||
foldRange(80, 90, true, FoldSource.userDefined, 'b4'), // overlaps a6
|
||||
foldRange(92, 100, true, FoldSource.userDefined, 'b5'), // valid
|
||||
];
|
||||
let result = FoldingRegions.sanitizeAndMerge(regionSet1, regionSet2, 100);
|
||||
const result = FoldingRegions.sanitizeAndMerge(regionSet1, regionSet2, 100);
|
||||
assert.strictEqual(result.length, 9, 'result length1');
|
||||
assertEqualRanges(result[0], foldRange(1, 100, false, false, 'a1'), 'P1');
|
||||
assertEqualRanges(result[1], foldRange(2, 100, false, false, 'a2'), 'P2');
|
||||
assertEqualRanges(result[2], foldRange(3, 19, false, false, 'a3'), 'P3');
|
||||
assertEqualRanges(result[3], foldRange(21, 29, false, false, 'a5'), 'P4');
|
||||
assertEqualRanges(result[4], foldRange(30, 39, false, false, 'b1'), 'P5');
|
||||
assertEqualRanges(result[5], foldRange(40, 49, false, false, 'b2'), 'P6');
|
||||
assertEqualRanges(result[6], foldRange(50, 100, false, false, 'b3'), 'P7');
|
||||
assertEqualRanges(result[7], foldRange(80, 90, false, false, 'b4'), 'P8');
|
||||
assertEqualRanges(result[8], foldRange(92, 100, false, false, 'b5'), 'P9');
|
||||
// reverse the two inputs
|
||||
result = FoldingRegions.sanitizeAndMerge(regionSet2, regionSet1, 100);
|
||||
assert.strictEqual(result.length, 9, 'result length2');
|
||||
assertEqualRanges(result[0], foldRange(1, 100, false, false, 'a1'), 'Q1');
|
||||
assertEqualRanges(result[1], foldRange(2, 100, false, false, 'a2'), 'Q2');
|
||||
assertEqualRanges(result[2], foldRange(3, 19, false, false, 'a3'), 'Q3');
|
||||
assertEqualRanges(result[3], foldRange(20, 71, false, false, 'a4'), 'Q4');
|
||||
assertEqualRanges(result[4], foldRange(21, 29, false, false, 'a5'), 'Q5');
|
||||
assertEqualRanges(result[5], foldRange(30, 39, false, false, 'b1'), 'Q6');
|
||||
assertEqualRanges(result[6], foldRange(40, 49, false, false, 'b2'), 'Q7');
|
||||
assertEqualRanges(result[7], foldRange(81, 91, false, false, 'a6'), 'Q8');
|
||||
assertEqualRanges(result[8], foldRange(92, 100, false, false, 'b5'), 'Q9');
|
||||
assertEqualRanges(result[0], foldRange(1, 100, false, FoldSource.provider, 'a1'), 'P1');
|
||||
assertEqualRanges(result[1], foldRange(2, 100, false, FoldSource.provider, 'a2'), 'P2');
|
||||
assertEqualRanges(result[2], foldRange(3, 19, false, FoldSource.provider, 'a3'), 'P3');
|
||||
assertEqualRanges(result[3], foldRange(21, 29, false, FoldSource.provider, 'a5'), 'P4');
|
||||
assertEqualRanges(result[4], foldRange(30, 39, true, FoldSource.recovered, 'b1'), 'P5');
|
||||
assertEqualRanges(result[5], foldRange(40, 49, true, FoldSource.userDefined, 'b2'), 'P6');
|
||||
assertEqualRanges(result[6], foldRange(50, 100, true, FoldSource.userDefined, 'b3'), 'P7');
|
||||
assertEqualRanges(result[7], foldRange(80, 90, true, FoldSource.userDefined, 'b4'), 'P8');
|
||||
assertEqualRanges(result[8], foldRange(92, 100, true, FoldSource.userDefined, 'b5'), 'P9');
|
||||
});
|
||||
|
||||
test('sanitizeAndMerge3', () => {
|
||||
const regionSet1: FoldRange[] = [
|
||||
foldRange(1, 100, false, false, 'a1'), // valid
|
||||
foldRange(10, 29, false, false, 'a2'), // matches manual hidden
|
||||
foldRange(35, 39, true, true, 'a3'), // valid
|
||||
foldRange(1, 100, false, FoldSource.provider, 'a1'), // valid
|
||||
foldRange(10, 29, false, FoldSource.provider, 'a2'), // matches manual hidden
|
||||
foldRange(35, 39, true, FoldSource.recovered, 'a3'), // valid
|
||||
];
|
||||
const regionSet2: FoldRange[] = [
|
||||
foldRange(10, 29, true, true, 'b1'), // matches a
|
||||
foldRange(20, 28, true, false, 'b2'), // should get dropped
|
||||
foldRange(30, 39, true, true, 'b3'), // should remain
|
||||
foldRange(10, 29, true, FoldSource.recovered, 'b1'), // matches a
|
||||
foldRange(20, 28, true, FoldSource.provider, 'b2'), // should remain
|
||||
foldRange(30, 39, true, FoldSource.recovered, 'b3'), // should remain
|
||||
];
|
||||
const result = FoldingRegions.sanitizeAndMerge(regionSet1, regionSet2, 100);
|
||||
assert.strictEqual(result.length, 4, 'result length3');
|
||||
assertEqualRanges(result[0], foldRange(1, 100, false, false, 'a1'), 'R1');
|
||||
assertEqualRanges(result[1], foldRange(10, 29, true, false, 'b1'), 'R2');
|
||||
assertEqualRanges(result[2], foldRange(30, 39, true, true, 'b3'), 'R3');
|
||||
assertEqualRanges(result[3], foldRange(35, 39, true, true, 'a3'), 'R4');
|
||||
assert.strictEqual(result.length, 5, 'result length3');
|
||||
assertEqualRanges(result[0], foldRange(1, 100, false, FoldSource.provider, 'a1'), 'R1');
|
||||
assertEqualRanges(result[1], foldRange(10, 29, true, FoldSource.provider, 'a2'), 'R2');
|
||||
assertEqualRanges(result[2], foldRange(20, 28, true, FoldSource.recovered, 'b2'), 'R3');
|
||||
assertEqualRanges(result[3], foldRange(30, 39, true, FoldSource.recovered, 'b3'), 'R3');
|
||||
assertEqualRanges(result[4], foldRange(35, 39, true, FoldSource.recovered, 'a3'), 'R4');
|
||||
});
|
||||
|
||||
test('sanitizeAndMerge4', () => {
|
||||
const regionSet1: FoldRange[] = [
|
||||
foldRange(1, 100, false, false, 'a1'), // valid
|
||||
foldRange(1, 100, false, FoldSource.provider, 'a1'), // valid
|
||||
];
|
||||
const regionSet2: FoldRange[] = [
|
||||
foldRange(20, 28, true, false, 'b1'), // hidden
|
||||
foldRange(30, 38, true, false, 'b2'), // hidden
|
||||
foldRange(20, 28, true, FoldSource.provider, 'b1'), // hidden
|
||||
foldRange(30, 38, true, FoldSource.provider, 'b2'), // hidden
|
||||
];
|
||||
const result = FoldingRegions.sanitizeAndMerge(regionSet1, regionSet2, 100);
|
||||
assert.strictEqual(result.length, 3, 'result length4');
|
||||
assertEqualRanges(result[0], foldRange(1, 100, false, false, 'a1'), 'R1');
|
||||
assertEqualRanges(result[1], foldRange(20, 28, true, true, 'b1'), 'R2');
|
||||
assertEqualRanges(result[2], foldRange(30, 38, true, true, 'b2'), 'R3');
|
||||
assertEqualRanges(result[0], foldRange(1, 100, false, FoldSource.provider, 'a1'), 'R1');
|
||||
assertEqualRanges(result[1], foldRange(20, 28, true, FoldSource.recovered, 'b1'), 'R2');
|
||||
assertEqualRanges(result[2], foldRange(30, 38, true, FoldSource.recovered, 'b2'), 'R3');
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -699,7 +699,7 @@ export async function provideInlineCompletions(
|
|||
}
|
||||
|
||||
for (const item of completions.items) {
|
||||
const range = item.range ? Range.lift(item.range) : defaultReplaceRange;
|
||||
let range = item.range ? Range.lift(item.range) : defaultReplaceRange;
|
||||
|
||||
if (range.startLineNumber !== range.endLineNumber) {
|
||||
// Ignore invalid ranges.
|
||||
|
@ -724,6 +724,12 @@ export async function provideInlineCompletions(
|
|||
model,
|
||||
languageConfigurationService
|
||||
);
|
||||
|
||||
// Modify range depending on if brackets are added or removed
|
||||
const diff = insertText.length - item.insertText.length;
|
||||
if (diff !== 0) {
|
||||
range = new Range(range.startLineNumber, range.startColumn, range.endLineNumber, range.endColumn + diff);
|
||||
}
|
||||
}
|
||||
|
||||
snippetInfo = undefined;
|
||||
|
|
408
src/vs/editor/contrib/stickyScroll/browser/stickyScroll.ts
Normal file
408
src/vs/editor/contrib/stickyScroll/browser/stickyScroll.ts
Normal file
|
@ -0,0 +1,408 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { IActiveCodeEditor, ICodeEditor, IOverlayWidget, IOverlayWidgetPosition } from 'vs/editor/browser/editorBrowser';
|
||||
import { registerEditorContribution } from 'vs/editor/browser/editorExtensions';
|
||||
import { IEditorContribution } from 'vs/editor/common/editorCommon';
|
||||
import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures';
|
||||
import { OutlineModel, OutlineElement } from 'vs/editor/contrib/documentSymbols/browser/outlineModel';
|
||||
import { CancellationToken, CancellationTokenSource, } from 'vs/base/common/cancellation';
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import { EditorOption } from 'vs/editor/common/config/editorOptions';
|
||||
import { createStringBuilder } from 'vs/editor/common/core/stringBuilder';
|
||||
import { RenderLineInput, renderViewLine } from 'vs/editor/common/viewLayout/viewLineRenderer';
|
||||
import { SymbolKind } from 'vs/editor/common/languages';
|
||||
import { LineDecoration } from 'vs/editor/common/viewLayout/lineDecorations';
|
||||
import { RunOnceScheduler } from 'vs/base/common/async';
|
||||
import { IModelTokensChangedEvent } from 'vs/editor/common/textModelEvents';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
|
||||
class StickyScrollController extends Disposable implements IEditorContribution {
|
||||
|
||||
static readonly ID = 'store.contrib.stickyScrollController';
|
||||
private readonly _editor: ICodeEditor;
|
||||
private readonly stickyScrollWidget: StickyScrollWidget;
|
||||
private readonly _languageFeaturesService: ILanguageFeaturesService;
|
||||
private readonly _sessionStore: DisposableStore = new DisposableStore();
|
||||
|
||||
private _ranges: [number, number, number][] = [];
|
||||
private _rangesVersionId: number = 0;
|
||||
private _cts: CancellationTokenSource | undefined;
|
||||
private readonly _updateSoon: RunOnceScheduler;
|
||||
|
||||
constructor(
|
||||
editor: ICodeEditor,
|
||||
@ILanguageFeaturesService _languageFeaturesService: ILanguageFeaturesService,
|
||||
) {
|
||||
super();
|
||||
this._editor = editor;
|
||||
this._languageFeaturesService = _languageFeaturesService;
|
||||
this.stickyScrollWidget = new StickyScrollWidget(this._editor);
|
||||
this._register(this._editor.onDidChangeConfiguration(e => {
|
||||
if (e.hasChanged(EditorOption.experimental)) {
|
||||
this.onConfigurationChange();
|
||||
}
|
||||
}));
|
||||
this._updateSoon = this._register(new RunOnceScheduler(() => this._update(true), 50));
|
||||
this.onConfigurationChange();
|
||||
}
|
||||
|
||||
private onConfigurationChange() {
|
||||
const options = this._editor.getOption(EditorOption.experimental);
|
||||
if (options.stickyScroll.enabled === false) {
|
||||
this.stickyScrollWidget.emptyRootNode();
|
||||
this._editor.removeOverlayWidget(this.stickyScrollWidget);
|
||||
this._sessionStore.clear();
|
||||
return;
|
||||
} else {
|
||||
this._editor.addOverlayWidget(this.stickyScrollWidget);
|
||||
this._sessionStore.add(this._editor.onDidChangeModel(() => this._update(true)));
|
||||
this._sessionStore.add(this._editor.onDidScrollChange(() => this._update(false)));
|
||||
this._sessionStore.add(this._editor.onDidChangeHiddenAreas(() => this._update(true)));
|
||||
this._sessionStore.add(this._editor.onDidChangeModelTokens((e) => this._onTokensChange(e)));
|
||||
this._sessionStore.add(this._editor.onDidChangeModelContent(() => this._updateSoon.schedule()));
|
||||
this._sessionStore.add(this._languageFeaturesService.documentSymbolProvider.onDidChange(() => this._update(true)));
|
||||
this._update(true);
|
||||
}
|
||||
}
|
||||
|
||||
private _needsUpdate(event: IModelTokensChangedEvent) {
|
||||
const stickyLineNumbers = this.stickyScrollWidget.getCurrentLines();
|
||||
for (const stickyLineNumber of stickyLineNumbers) {
|
||||
for (const range of event.ranges) {
|
||||
if (stickyLineNumber >= range.fromLineNumber && stickyLineNumber <= range.toLineNumber) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private _onTokensChange(event: IModelTokensChangedEvent) {
|
||||
if (this._needsUpdate(event)) {
|
||||
this._update(false);
|
||||
}
|
||||
}
|
||||
|
||||
private async _update(updateOutline: boolean = false): Promise<void> {
|
||||
if (updateOutline) {
|
||||
this._cts?.dispose(true);
|
||||
this._cts = new CancellationTokenSource();
|
||||
await this._updateOutlineModel(this._cts.token);
|
||||
}
|
||||
const hiddenRanges: Range[] | undefined = this._editor._getViewModel()?.getHiddenAreas();
|
||||
if (hiddenRanges) {
|
||||
for (const hiddenRange of hiddenRanges) {
|
||||
this._ranges = this._ranges.filter(range => { return !(range[0] >= hiddenRange.startLineNumber && range[1] <= hiddenRange.endLineNumber + 1); });
|
||||
}
|
||||
}
|
||||
this._renderStickyScroll();
|
||||
}
|
||||
|
||||
private _findLineRanges(outlineElement: OutlineElement, depth: number) {
|
||||
if (outlineElement?.children.size) {
|
||||
let didRecursion: boolean = false;
|
||||
for (const outline of outlineElement?.children.values()) {
|
||||
const kind: SymbolKind = outline.symbol.kind;
|
||||
if (kind === SymbolKind.Class || kind === SymbolKind.Constructor || kind === SymbolKind.Function || kind === SymbolKind.Interface || kind === SymbolKind.Method || kind === SymbolKind.Module) {
|
||||
didRecursion = true;
|
||||
this._findLineRanges(outline, depth + 1);
|
||||
}
|
||||
}
|
||||
if (!didRecursion) {
|
||||
this._addOutlineRanges(outlineElement, depth);
|
||||
}
|
||||
} else {
|
||||
this._addOutlineRanges(outlineElement, depth);
|
||||
}
|
||||
}
|
||||
|
||||
private _addOutlineRanges(outlineElement: OutlineElement, depth: number) {
|
||||
let currentStartLine: number | undefined = 0;
|
||||
let currentEndLine: number | undefined = 0;
|
||||
|
||||
while (outlineElement) {
|
||||
const kind: SymbolKind = outlineElement.symbol.kind;
|
||||
if (kind === SymbolKind.Class || kind === SymbolKind.Constructor || kind === SymbolKind.Function || kind === SymbolKind.Interface || kind === SymbolKind.Method || kind === SymbolKind.Module) {
|
||||
currentStartLine = outlineElement?.symbol.range.startLineNumber as number;
|
||||
currentEndLine = outlineElement?.symbol.range.endLineNumber as number;
|
||||
this._ranges.push([currentStartLine, currentEndLine, depth]);
|
||||
depth--;
|
||||
}
|
||||
if (outlineElement.parent instanceof OutlineElement) {
|
||||
outlineElement = outlineElement.parent;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async _updateOutlineModel(token: CancellationToken) {
|
||||
if (this._editor.hasModel()) {
|
||||
const model = this._editor.getModel();
|
||||
const modelVersionId = model.getVersionId();
|
||||
const outlineModel = await OutlineModel.create(this._languageFeaturesService.documentSymbolProvider, model, token);
|
||||
if (token.isCancellationRequested) {
|
||||
return;
|
||||
}
|
||||
this._ranges = [];
|
||||
this._rangesVersionId = modelVersionId;
|
||||
for (const outline of outlineModel.children.values()) {
|
||||
if (outline instanceof OutlineElement) {
|
||||
const kind: SymbolKind = outline.symbol.kind;
|
||||
if (kind === SymbolKind.Class || kind === SymbolKind.Constructor || kind === SymbolKind.Function || kind === SymbolKind.Interface || kind === SymbolKind.Method || kind === SymbolKind.Module) {
|
||||
this._findLineRanges(outline, 1);
|
||||
} else {
|
||||
this._findLineRanges(outline, 0);
|
||||
}
|
||||
}
|
||||
this._ranges = this._ranges.sort(function (a, b) {
|
||||
if (a[0] !== b[0]) {
|
||||
return a[0] - b[0];
|
||||
} else if (a[1] !== b[1]) {
|
||||
return b[1] - a[1];
|
||||
} else {
|
||||
return a[2] - b[2];
|
||||
}
|
||||
});
|
||||
let previous: number[] = [];
|
||||
for (const [index, arr] of this._ranges.entries()) {
|
||||
const [start, end, _depth] = arr;
|
||||
if (previous[0] === start && previous[1] === end) {
|
||||
this._ranges.splice(index, 1);
|
||||
} else {
|
||||
previous = arr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private _renderStickyScroll() {
|
||||
if (!(this._editor.hasModel())) {
|
||||
return;
|
||||
}
|
||||
const lineHeight: number = this._editor.getOption(EditorOption.lineHeight);
|
||||
const model = this._editor.getModel();
|
||||
if (this._rangesVersionId !== model.getVersionId()) {
|
||||
// Old _ranges not updated yet
|
||||
return;
|
||||
}
|
||||
const scrollTop = this._editor.getScrollTop();
|
||||
|
||||
this.stickyScrollWidget.emptyRootNode();
|
||||
const beginningLinesConsidered: Set<number> = new Set<number>();
|
||||
|
||||
for (const [index, arr] of this._ranges.entries()) {
|
||||
const [start, end, depth] = arr;
|
||||
if (end - start > 0 && model.getLineContent(start) !== '') {
|
||||
const topOfElementAtDepth = (depth - 1) * lineHeight;
|
||||
const bottomOfElementAtDepth = depth * lineHeight;
|
||||
|
||||
const bottomOfBeginningLine = this._editor.getBottomForLineNumber(start) - scrollTop;
|
||||
const topOfEndLine = this._editor.getTopForLineNumber(end) - scrollTop;
|
||||
const bottomOfEndLine = this._editor.getBottomForLineNumber(end) - scrollTop;
|
||||
|
||||
if (!beginningLinesConsidered.has(start)) {
|
||||
if (topOfElementAtDepth >= topOfEndLine - 1 && topOfElementAtDepth < bottomOfEndLine - 2) {
|
||||
beginningLinesConsidered.add(start);
|
||||
this.stickyScrollWidget.pushCodeLine(new StickyScrollCodeLine(start, depth, this._editor, -1, bottomOfEndLine - bottomOfElementAtDepth));
|
||||
break;
|
||||
}
|
||||
else if (bottomOfElementAtDepth > bottomOfBeginningLine && bottomOfElementAtDepth < bottomOfEndLine - 1) {
|
||||
beginningLinesConsidered.add(start);
|
||||
this.stickyScrollWidget.pushCodeLine(new StickyScrollCodeLine(start, depth, this._editor, 0, 0));
|
||||
}
|
||||
} else {
|
||||
this._ranges.splice(index, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.stickyScrollWidget.updateRootNode();
|
||||
}
|
||||
|
||||
override dispose(): void {
|
||||
super.dispose();
|
||||
this._sessionStore.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
const _ttPolicy = window.trustedTypes?.createPolicy('stickyScrollViewLayer', { createHTML: value => value });
|
||||
|
||||
class StickyScrollCodeLine {
|
||||
|
||||
public readonly effectiveLineHeight: number = 0;
|
||||
|
||||
constructor(private readonly _lineNumber: number, private readonly _depth: number, private readonly _editor: IActiveCodeEditor,
|
||||
private readonly _zIndex: number, private readonly _relativePosition: number) {
|
||||
this.effectiveLineHeight = this._editor.getOption(EditorOption.lineHeight) + this._relativePosition;
|
||||
}
|
||||
|
||||
get lineNumber() {
|
||||
return this._lineNumber;
|
||||
}
|
||||
|
||||
getDomNode() {
|
||||
|
||||
const root: HTMLElement = document.createElement('div');
|
||||
const viewModel = this._editor._getViewModel();
|
||||
const viewLineNumber = viewModel.coordinatesConverter.convertModelPositionToViewPosition(new Position(this._lineNumber, 1)).lineNumber;
|
||||
const lineRenderingData = viewModel.getViewLineRenderingData(viewLineNumber);
|
||||
|
||||
let actualInlineDecorations: LineDecoration[];
|
||||
try {
|
||||
actualInlineDecorations = LineDecoration.filter(lineRenderingData.inlineDecorations, viewLineNumber, lineRenderingData.minColumn, lineRenderingData.maxColumn);
|
||||
} catch (err) {
|
||||
actualInlineDecorations = [];
|
||||
}
|
||||
|
||||
const renderLineInput: RenderLineInput = new RenderLineInput(true, true, lineRenderingData.content, lineRenderingData.continuesWithWrappedLine,
|
||||
lineRenderingData.isBasicASCII, lineRenderingData.containsRTL, 0, lineRenderingData.tokens, actualInlineDecorations, lineRenderingData.tabSize,
|
||||
lineRenderingData.startVisibleColumn, 1, 1, 1, 100, 'none', true, true, null);
|
||||
|
||||
const sb = createStringBuilder(400);
|
||||
renderViewLine(renderLineInput, sb);
|
||||
|
||||
let newLine;
|
||||
if (_ttPolicy) {
|
||||
newLine = _ttPolicy.createHTML(sb.build() as string);
|
||||
} else {
|
||||
newLine = sb.build();
|
||||
}
|
||||
|
||||
const lineHTMLNode = document.createElement('span');
|
||||
lineHTMLNode.style.backgroundColor = `var(--vscode-editorStickyScroll-background)`;
|
||||
lineHTMLNode.style.overflow = 'hidden';
|
||||
lineHTMLNode.style.whiteSpace = 'nowrap';
|
||||
lineHTMLNode.style.display = 'inline-block';
|
||||
lineHTMLNode.style.lineHeight = this._editor.getOption(EditorOption.lineHeight).toString() + 'px';
|
||||
lineHTMLNode.innerHTML = newLine as string;
|
||||
|
||||
const lineNumberHTMLNode = document.createElement('span');
|
||||
lineNumberHTMLNode.style.width = this._editor.getLayoutInfo().contentLeft.toString() + 'px';
|
||||
lineNumberHTMLNode.style.backgroundColor = `var(--vscode-editorStickyScroll-background)`;
|
||||
lineNumberHTMLNode.style.color = 'var(--vscode-editorLineNumber-foreground)';
|
||||
lineNumberHTMLNode.style.display = 'inline-block';
|
||||
lineNumberHTMLNode.style.lineHeight = this._editor.getOption(EditorOption.lineHeight).toString() + 'px';
|
||||
|
||||
const innerLineNumberHTML = document.createElement('span');
|
||||
innerLineNumberHTML.innerText = this._lineNumber.toString();
|
||||
innerLineNumberHTML.style.paddingLeft = this._editor.getLayoutInfo().lineNumbersLeft.toString() + 'px';
|
||||
innerLineNumberHTML.style.width = this._editor.getLayoutInfo().lineNumbersWidth.toString() + 'px';
|
||||
innerLineNumberHTML.style.backgroundColor = `var(--vscode-editorStickyScroll-background)`;
|
||||
innerLineNumberHTML.style.textAlign = 'right';
|
||||
innerLineNumberHTML.style.float = 'left';
|
||||
innerLineNumberHTML.style.lineHeight = this._editor.getOption(EditorOption.lineHeight).toString() + 'px';
|
||||
lineNumberHTMLNode.appendChild(innerLineNumberHTML);
|
||||
|
||||
root.onclick = e => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
this._editor.revealPosition({ lineNumber: this._lineNumber - this._depth + 1, column: 1 });
|
||||
};
|
||||
|
||||
root.onmouseover = e => {
|
||||
innerLineNumberHTML.style.background = `var(--vscode-editorStickyScrollHover-background)`;
|
||||
lineHTMLNode.style.backgroundColor = `var(--vscode-editorStickyScrollHover-background)`;
|
||||
lineNumberHTMLNode.style.backgroundColor = `var(--vscode-editorStickyScrollHover-background)`;
|
||||
root.style.backgroundColor = `var(--vscode-editorStickyScrollHover-background)`;
|
||||
innerLineNumberHTML.style.cursor = `pointer`;
|
||||
lineHTMLNode.style.cursor = `pointer`;
|
||||
root.style.cursor = `pointer`;
|
||||
lineNumberHTMLNode.style.cursor = `pointer`;
|
||||
};
|
||||
root.onmouseleave = e => {
|
||||
innerLineNumberHTML.style.background = `var(--vscode-editorStickyScroll-background)`;
|
||||
lineHTMLNode.style.backgroundColor = `var(--vscode-editorStickyScroll-background)`;
|
||||
lineNumberHTMLNode.style.backgroundColor = `var(--vscode-editorStickyScroll-background)`;
|
||||
root.style.backgroundColor = `var(--vscode-editorStickyScroll-background)`;
|
||||
};
|
||||
|
||||
this._editor.applyFontInfo(lineHTMLNode);
|
||||
this._editor.applyFontInfo(innerLineNumberHTML);
|
||||
|
||||
root.appendChild(lineNumberHTMLNode);
|
||||
root.appendChild(lineHTMLNode);
|
||||
|
||||
root.style.zIndex = this._zIndex.toString();
|
||||
root.style.backgroundColor = `var(--vscode-editorStickyScroll-background)`;
|
||||
root.style.overflow = 'hidden';
|
||||
root.style.whiteSpace = 'nowrap';
|
||||
root.style.width = '100%';
|
||||
root.style.lineHeight = this._editor.getOption(EditorOption.lineHeight).toString() + 'px';
|
||||
root.style.height = this._editor.getOption(EditorOption.lineHeight).toString() + 'px';
|
||||
|
||||
// Special case for last line of sticky scroll
|
||||
if (this._relativePosition) {
|
||||
root.style.position = 'relative';
|
||||
root.style.top = this._relativePosition + 'px';
|
||||
root.style.width = '100%';
|
||||
}
|
||||
return root;
|
||||
}
|
||||
}
|
||||
|
||||
class StickyScrollWidget implements IOverlayWidget {
|
||||
|
||||
private readonly arrayOfCodeLines: StickyScrollCodeLine[] = [];
|
||||
private readonly rootDomNode: HTMLElement = document.createElement('div');
|
||||
|
||||
constructor(public readonly _editor: ICodeEditor) {
|
||||
this.rootDomNode = document.createElement('div');
|
||||
this.rootDomNode.style.width = '100%';
|
||||
this.rootDomNode.style.boxShadow = `var(--vscode-scrollbar-shadow) 0 6px 6px -6px`;
|
||||
}
|
||||
|
||||
get codeLineCount() {
|
||||
return this.arrayOfCodeLines.length;
|
||||
}
|
||||
|
||||
getCurrentLines(): number[] {
|
||||
const widgetLineRange: number[] = [];
|
||||
for (const codeLine of this.arrayOfCodeLines) {
|
||||
widgetLineRange.push(codeLine.lineNumber);
|
||||
}
|
||||
return widgetLineRange;
|
||||
}
|
||||
|
||||
pushCodeLine(codeLine: StickyScrollCodeLine) {
|
||||
this.arrayOfCodeLines.push(codeLine);
|
||||
}
|
||||
|
||||
updateRootNode() {
|
||||
let widgetHeight: number = 0;
|
||||
for (const line of this.arrayOfCodeLines) {
|
||||
widgetHeight += line.effectiveLineHeight;
|
||||
this.rootDomNode.appendChild(line.getDomNode());
|
||||
}
|
||||
this.rootDomNode.style.height = widgetHeight.toString() + 'px';
|
||||
}
|
||||
|
||||
emptyRootNode() {
|
||||
this.arrayOfCodeLines.length = 0;
|
||||
dom.clearNode(this.rootDomNode);
|
||||
}
|
||||
|
||||
getId(): string {
|
||||
return 'editor.contrib.stickyScrollWidget';
|
||||
}
|
||||
|
||||
getDomNode(): HTMLElement {
|
||||
this.rootDomNode.style.zIndex = '2';
|
||||
this.rootDomNode.style.backgroundColor = `var(--vscode-editorStickyScroll-background)`;
|
||||
return this.rootDomNode;
|
||||
}
|
||||
|
||||
getPosition(): IOverlayWidgetPosition | null {
|
||||
return {
|
||||
preference: null
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
registerEditorContribution(StickyScrollController.ID, StickyScrollController);
|
||||
|
|
@ -41,6 +41,7 @@ import 'vs/editor/contrib/links/browser/links';
|
|||
import 'vs/editor/contrib/multicursor/browser/multicursor';
|
||||
import 'vs/editor/contrib/parameterHints/browser/parameterHints';
|
||||
import 'vs/editor/contrib/rename/browser/rename';
|
||||
import 'vs/editor/contrib/stickyScroll/browser/stickyScroll';
|
||||
import 'vs/editor/contrib/smartSelect/browser/smartSelect';
|
||||
import 'vs/editor/contrib/snippet/browser/snippetController2';
|
||||
import 'vs/editor/contrib/suggest/browser/suggestController';
|
||||
|
|
|
@ -526,12 +526,13 @@ export function registerCodeActionProvider(languageSelector: LanguageSelector, p
|
|||
const languageFeaturesService = StandaloneServices.get(ILanguageFeaturesService);
|
||||
return languageFeaturesService.codeActionProvider.register(languageSelector, {
|
||||
providedCodeActionKinds: metadata?.providedCodeActionKinds,
|
||||
documentation: metadata?.documentation,
|
||||
provideCodeActions: (model: model.ITextModel, range: Range, context: languages.CodeActionContext, token: CancellationToken): languages.ProviderResult<languages.CodeActionList> => {
|
||||
const markerService = StandaloneServices.get(IMarkerService);
|
||||
const markers = markerService.read({ resource: model.uri }).filter(m => {
|
||||
return Range.areIntersectingOrTouching(m, range);
|
||||
});
|
||||
return provider.provideCodeActions(model, range, { markers, only: context.only }, token);
|
||||
return provider.provideCodeActions(model, range, { markers, only: context.only, trigger: context.trigger }, token);
|
||||
},
|
||||
resolveCodeAction: provider.resolveCodeAction
|
||||
});
|
||||
|
@ -664,6 +665,11 @@ export interface CodeActionContext {
|
|||
* Requested kind of actions to return.
|
||||
*/
|
||||
readonly only?: string;
|
||||
|
||||
/**
|
||||
* The reason why code actions were requested.
|
||||
*/
|
||||
readonly trigger: languages.CodeActionTriggerType;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -697,6 +703,8 @@ export interface CodeActionProviderMetadata {
|
|||
* such as `["quickfix.removeLine", "source.fixAll" ...]`.
|
||||
*/
|
||||
readonly providedCodeActionKinds?: readonly string[];
|
||||
|
||||
readonly documentation?: ReadonlyArray<{ readonly kind: string; readonly command: languages.Command }>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -753,6 +761,7 @@ export function createMonacoLanguagesAPI(): typeof monaco.languages {
|
|||
SignatureHelpTriggerKind: standaloneEnums.SignatureHelpTriggerKind,
|
||||
InlayHintKind: standaloneEnums.InlayHintKind,
|
||||
InlineCompletionTriggerKind: standaloneEnums.InlineCompletionTriggerKind,
|
||||
CodeActionTriggerType: standaloneEnums.CodeActionTriggerType,
|
||||
|
||||
// classes
|
||||
FoldingRangeKind: languages.FoldingRangeKind,
|
||||
|
|
|
@ -97,7 +97,7 @@ suite('ViewModelDecorations', () => {
|
|||
'dec14',
|
||||
]);
|
||||
|
||||
const inlineDecorations1 = viewModel.getViewLineRenderingData(
|
||||
const inlineDecorations1 = viewModel.getViewportViewLineRenderingData(
|
||||
new Range(1, viewModel.getLineMinColumn(1), 2, viewModel.getLineMaxColumn(2)),
|
||||
1
|
||||
).inlineDecorations;
|
||||
|
@ -118,7 +118,7 @@ suite('ViewModelDecorations', () => {
|
|||
new InlineDecoration(new Range(1, 2, 1, 2), 'b-dec5', InlineDecorationType.Before),
|
||||
]);
|
||||
|
||||
const inlineDecorations2 = viewModel.getViewLineRenderingData(
|
||||
const inlineDecorations2 = viewModel.getViewportViewLineRenderingData(
|
||||
new Range(2, viewModel.getLineMinColumn(2), 3, viewModel.getLineMaxColumn(3)),
|
||||
2
|
||||
).inlineDecorations;
|
||||
|
@ -148,7 +148,7 @@ suite('ViewModelDecorations', () => {
|
|||
new InlineDecoration(new Range(2, 3, 2, 3), 'b-dec12', InlineDecorationType.Before),
|
||||
]);
|
||||
|
||||
const inlineDecorations3 = viewModel.getViewLineRenderingData(
|
||||
const inlineDecorations3 = viewModel.getViewportViewLineRenderingData(
|
||||
new Range(2, viewModel.getLineMinColumn(2), 3, viewModel.getLineMaxColumn(3)),
|
||||
3
|
||||
).inlineDecorations;
|
||||
|
@ -198,13 +198,13 @@ suite('ViewModelDecorations', () => {
|
|||
).filter(x => Boolean(x.options.beforeContentClassName));
|
||||
assert.deepStrictEqual(decorations, []);
|
||||
|
||||
const inlineDecorations1 = viewModel.getViewLineRenderingData(
|
||||
const inlineDecorations1 = viewModel.getViewportViewLineRenderingData(
|
||||
new Range(2, viewModel.getLineMinColumn(2), 3, viewModel.getLineMaxColumn(3)),
|
||||
2
|
||||
).inlineDecorations;
|
||||
assert.deepStrictEqual(inlineDecorations1, []);
|
||||
|
||||
const inlineDecorations2 = viewModel.getViewLineRenderingData(
|
||||
const inlineDecorations2 = viewModel.getViewportViewLineRenderingData(
|
||||
new Range(2, viewModel.getLineMinColumn(2), 3, viewModel.getLineMaxColumn(3)),
|
||||
3
|
||||
).inlineDecorations;
|
||||
|
@ -229,7 +229,7 @@ suite('ViewModelDecorations', () => {
|
|||
);
|
||||
});
|
||||
|
||||
const inlineDecorations = viewModel.getViewLineRenderingData(
|
||||
const inlineDecorations = viewModel.getViewportViewLineRenderingData(
|
||||
new Range(1, 1, 1, 1),
|
||||
1
|
||||
).inlineDecorations;
|
||||
|
|
285
src/vs/monaco.d.ts
vendored
285
src/vs/monaco.d.ts
vendored
|
@ -1738,6 +1738,15 @@ declare namespace monaco.editor {
|
|||
GrowsOnlyWhenTypingAfter = 3
|
||||
}
|
||||
|
||||
/**
|
||||
* Text snapshot that works like an iterator.
|
||||
* Will try to return chunks of roughly ~64KB size.
|
||||
* Will return null when finished.
|
||||
*/
|
||||
export interface ITextSnapshot {
|
||||
read(): string | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* A model.
|
||||
*/
|
||||
|
@ -1769,7 +1778,7 @@ declare namespace monaco.editor {
|
|||
/**
|
||||
* Replace the entire text buffer value contained in this model.
|
||||
*/
|
||||
setValue(newValue: string): void;
|
||||
setValue(newValue: string | ITextSnapshot): void;
|
||||
/**
|
||||
* Get the text stored in this model.
|
||||
* @param eol The end of line character preference. Defaults to `EndOfLinePreference.TextDefined`.
|
||||
|
@ -1777,6 +1786,12 @@ declare namespace monaco.editor {
|
|||
* @return The text.
|
||||
*/
|
||||
getValue(eol?: EndOfLinePreference, preserveBOM?: boolean): string;
|
||||
/**
|
||||
* Get the text stored in this model.
|
||||
* @param preserverBOM Preserve a BOM character if it was detected when the model was constructed.
|
||||
* @return The text snapshot (it is safe to consume it asynchronously).
|
||||
*/
|
||||
createSnapshot(preserveBOM?: boolean): ITextSnapshot;
|
||||
/**
|
||||
* Get the length of the text stored in this model.
|
||||
*/
|
||||
|
@ -2931,6 +2946,10 @@ declare namespace monaco.editor {
|
|||
* Control the behavior and rendering of the scrollbars.
|
||||
*/
|
||||
scrollbar?: IEditorScrollbarOptions;
|
||||
/**
|
||||
* Control the behavior of experimental options
|
||||
*/
|
||||
experimental?: IEditorExperimentalOptions;
|
||||
/**
|
||||
* Control the behavior and rendering of the minimap.
|
||||
*/
|
||||
|
@ -3420,11 +3439,11 @@ declare namespace monaco.editor {
|
|||
*/
|
||||
bracketPairColorization?: IBracketPairColorizationOptions;
|
||||
/**
|
||||
* Enables dropping into the editor from an external source.
|
||||
* Controls dropping into the editor from an external source.
|
||||
*
|
||||
* This shows a preview of the drop location and triggers an `onDropIntoEditor` event.
|
||||
* When enabled, this shows a preview of the drop location and triggers an `onDropIntoEditor` event.
|
||||
*/
|
||||
enableDropIntoEditor?: boolean;
|
||||
dropIntoEditor?: IDropIntoEditorOptions;
|
||||
}
|
||||
|
||||
export interface IDiffEditorBaseOptions {
|
||||
|
@ -3789,6 +3808,24 @@ declare namespace monaco.editor {
|
|||
enabled?: boolean;
|
||||
}
|
||||
|
||||
export interface IEditorExperimentalOptions {
|
||||
/**
|
||||
* Configuration options for editor sticky scroll
|
||||
*/
|
||||
stickyScroll?: {
|
||||
/**
|
||||
* Enable the sticky scroll
|
||||
*/
|
||||
enabled?: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
export interface EditorExperimentalOptions {
|
||||
stickyScroll: {
|
||||
enabled: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration options for editor inlayHints
|
||||
*/
|
||||
|
@ -4301,6 +4338,17 @@ declare namespace monaco.editor {
|
|||
readonly wrappingColumn: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration options for editor drop into behavior
|
||||
*/
|
||||
export interface IDropIntoEditorOptions {
|
||||
/**
|
||||
* Enable the dropping into editor.
|
||||
* Defaults to true.
|
||||
*/
|
||||
enabled?: boolean;
|
||||
}
|
||||
|
||||
export enum EditorOption {
|
||||
acceptSuggestionOnCommitCharacter = 0,
|
||||
acceptSuggestionOnEnter = 1,
|
||||
|
@ -4334,108 +4382,109 @@ declare namespace monaco.editor {
|
|||
disableMonospaceOptimizations = 29,
|
||||
domReadOnly = 30,
|
||||
dragAndDrop = 31,
|
||||
enableDropIntoEditor = 32,
|
||||
dropIntoEditor = 32,
|
||||
emptySelectionClipboard = 33,
|
||||
extraEditorClassName = 34,
|
||||
fastScrollSensitivity = 35,
|
||||
find = 36,
|
||||
fixedOverflowWidgets = 37,
|
||||
folding = 38,
|
||||
foldingStrategy = 39,
|
||||
foldingHighlight = 40,
|
||||
foldingImportsByDefault = 41,
|
||||
foldingMaximumRegions = 42,
|
||||
unfoldOnClickAfterEndOfLine = 43,
|
||||
fontFamily = 44,
|
||||
fontInfo = 45,
|
||||
fontLigatures = 46,
|
||||
fontSize = 47,
|
||||
fontWeight = 48,
|
||||
formatOnPaste = 49,
|
||||
formatOnType = 50,
|
||||
glyphMargin = 51,
|
||||
gotoLocation = 52,
|
||||
hideCursorInOverviewRuler = 53,
|
||||
hover = 54,
|
||||
inDiffEditor = 55,
|
||||
inlineSuggest = 56,
|
||||
letterSpacing = 57,
|
||||
lightbulb = 58,
|
||||
lineDecorationsWidth = 59,
|
||||
lineHeight = 60,
|
||||
lineNumbers = 61,
|
||||
lineNumbersMinChars = 62,
|
||||
linkedEditing = 63,
|
||||
links = 64,
|
||||
matchBrackets = 65,
|
||||
minimap = 66,
|
||||
mouseStyle = 67,
|
||||
mouseWheelScrollSensitivity = 68,
|
||||
mouseWheelZoom = 69,
|
||||
multiCursorMergeOverlapping = 70,
|
||||
multiCursorModifier = 71,
|
||||
multiCursorPaste = 72,
|
||||
occurrencesHighlight = 73,
|
||||
overviewRulerBorder = 74,
|
||||
overviewRulerLanes = 75,
|
||||
padding = 76,
|
||||
parameterHints = 77,
|
||||
peekWidgetDefaultFocus = 78,
|
||||
definitionLinkOpensInPeek = 79,
|
||||
quickSuggestions = 80,
|
||||
quickSuggestionsDelay = 81,
|
||||
readOnly = 82,
|
||||
renameOnType = 83,
|
||||
renderControlCharacters = 84,
|
||||
renderFinalNewline = 85,
|
||||
renderLineHighlight = 86,
|
||||
renderLineHighlightOnlyWhenFocus = 87,
|
||||
renderValidationDecorations = 88,
|
||||
renderWhitespace = 89,
|
||||
revealHorizontalRightPadding = 90,
|
||||
roundedSelection = 91,
|
||||
rulers = 92,
|
||||
scrollbar = 93,
|
||||
scrollBeyondLastColumn = 94,
|
||||
scrollBeyondLastLine = 95,
|
||||
scrollPredominantAxis = 96,
|
||||
selectionClipboard = 97,
|
||||
selectionHighlight = 98,
|
||||
selectOnLineNumbers = 99,
|
||||
showFoldingControls = 100,
|
||||
showUnused = 101,
|
||||
snippetSuggestions = 102,
|
||||
smartSelect = 103,
|
||||
smoothScrolling = 104,
|
||||
stickyTabStops = 105,
|
||||
stopRenderingLineAfter = 106,
|
||||
suggest = 107,
|
||||
suggestFontSize = 108,
|
||||
suggestLineHeight = 109,
|
||||
suggestOnTriggerCharacters = 110,
|
||||
suggestSelection = 111,
|
||||
tabCompletion = 112,
|
||||
tabIndex = 113,
|
||||
unicodeHighlighting = 114,
|
||||
unusualLineTerminators = 115,
|
||||
useShadowDOM = 116,
|
||||
useTabStops = 117,
|
||||
wordSeparators = 118,
|
||||
wordWrap = 119,
|
||||
wordWrapBreakAfterCharacters = 120,
|
||||
wordWrapBreakBeforeCharacters = 121,
|
||||
wordWrapColumn = 122,
|
||||
wordWrapOverride1 = 123,
|
||||
wordWrapOverride2 = 124,
|
||||
wrappingIndent = 125,
|
||||
wrappingStrategy = 126,
|
||||
showDeprecated = 127,
|
||||
inlayHints = 128,
|
||||
editorClassName = 129,
|
||||
pixelRatio = 130,
|
||||
tabFocusMode = 131,
|
||||
layoutInfo = 132,
|
||||
wrappingInfo = 133
|
||||
experimental = 34,
|
||||
extraEditorClassName = 35,
|
||||
fastScrollSensitivity = 36,
|
||||
find = 37,
|
||||
fixedOverflowWidgets = 38,
|
||||
folding = 39,
|
||||
foldingStrategy = 40,
|
||||
foldingHighlight = 41,
|
||||
foldingImportsByDefault = 42,
|
||||
foldingMaximumRegions = 43,
|
||||
unfoldOnClickAfterEndOfLine = 44,
|
||||
fontFamily = 45,
|
||||
fontInfo = 46,
|
||||
fontLigatures = 47,
|
||||
fontSize = 48,
|
||||
fontWeight = 49,
|
||||
formatOnPaste = 50,
|
||||
formatOnType = 51,
|
||||
glyphMargin = 52,
|
||||
gotoLocation = 53,
|
||||
hideCursorInOverviewRuler = 54,
|
||||
hover = 55,
|
||||
inDiffEditor = 56,
|
||||
inlineSuggest = 57,
|
||||
letterSpacing = 58,
|
||||
lightbulb = 59,
|
||||
lineDecorationsWidth = 60,
|
||||
lineHeight = 61,
|
||||
lineNumbers = 62,
|
||||
lineNumbersMinChars = 63,
|
||||
linkedEditing = 64,
|
||||
links = 65,
|
||||
matchBrackets = 66,
|
||||
minimap = 67,
|
||||
mouseStyle = 68,
|
||||
mouseWheelScrollSensitivity = 69,
|
||||
mouseWheelZoom = 70,
|
||||
multiCursorMergeOverlapping = 71,
|
||||
multiCursorModifier = 72,
|
||||
multiCursorPaste = 73,
|
||||
occurrencesHighlight = 74,
|
||||
overviewRulerBorder = 75,
|
||||
overviewRulerLanes = 76,
|
||||
padding = 77,
|
||||
parameterHints = 78,
|
||||
peekWidgetDefaultFocus = 79,
|
||||
definitionLinkOpensInPeek = 80,
|
||||
quickSuggestions = 81,
|
||||
quickSuggestionsDelay = 82,
|
||||
readOnly = 83,
|
||||
renameOnType = 84,
|
||||
renderControlCharacters = 85,
|
||||
renderFinalNewline = 86,
|
||||
renderLineHighlight = 87,
|
||||
renderLineHighlightOnlyWhenFocus = 88,
|
||||
renderValidationDecorations = 89,
|
||||
renderWhitespace = 90,
|
||||
revealHorizontalRightPadding = 91,
|
||||
roundedSelection = 92,
|
||||
rulers = 93,
|
||||
scrollbar = 94,
|
||||
scrollBeyondLastColumn = 95,
|
||||
scrollBeyondLastLine = 96,
|
||||
scrollPredominantAxis = 97,
|
||||
selectionClipboard = 98,
|
||||
selectionHighlight = 99,
|
||||
selectOnLineNumbers = 100,
|
||||
showFoldingControls = 101,
|
||||
showUnused = 102,
|
||||
snippetSuggestions = 103,
|
||||
smartSelect = 104,
|
||||
smoothScrolling = 105,
|
||||
stickyTabStops = 106,
|
||||
stopRenderingLineAfter = 107,
|
||||
suggest = 108,
|
||||
suggestFontSize = 109,
|
||||
suggestLineHeight = 110,
|
||||
suggestOnTriggerCharacters = 111,
|
||||
suggestSelection = 112,
|
||||
tabCompletion = 113,
|
||||
tabIndex = 114,
|
||||
unicodeHighlighting = 115,
|
||||
unusualLineTerminators = 116,
|
||||
useShadowDOM = 117,
|
||||
useTabStops = 118,
|
||||
wordSeparators = 119,
|
||||
wordWrap = 120,
|
||||
wordWrapBreakAfterCharacters = 121,
|
||||
wordWrapBreakBeforeCharacters = 122,
|
||||
wordWrapColumn = 123,
|
||||
wordWrapOverride1 = 124,
|
||||
wordWrapOverride2 = 125,
|
||||
wrappingIndent = 126,
|
||||
wrappingStrategy = 127,
|
||||
showDeprecated = 128,
|
||||
inlayHints = 129,
|
||||
editorClassName = 130,
|
||||
pixelRatio = 131,
|
||||
tabFocusMode = 132,
|
||||
layoutInfo = 133,
|
||||
wrappingInfo = 134
|
||||
}
|
||||
|
||||
export const EditorOptions: {
|
||||
|
@ -4473,7 +4522,8 @@ declare namespace monaco.editor {
|
|||
domReadOnly: IEditorOption<EditorOption.domReadOnly, boolean>;
|
||||
dragAndDrop: IEditorOption<EditorOption.dragAndDrop, boolean>;
|
||||
emptySelectionClipboard: IEditorOption<EditorOption.emptySelectionClipboard, boolean>;
|
||||
enableDropIntoEditor: IEditorOption<EditorOption.enableDropIntoEditor, boolean>;
|
||||
dropIntoEditor: IEditorOption<EditorOption.dropIntoEditor, Readonly<Required<IDropIntoEditorOptions>>>;
|
||||
experimental: IEditorOption<EditorOption.experimental, EditorExperimentalOptions>;
|
||||
extraEditorClassName: IEditorOption<EditorOption.extraEditorClassName, string>;
|
||||
fastScrollSensitivity: IEditorOption<EditorOption.fastScrollSensitivity, number>;
|
||||
find: IEditorOption<EditorOption.find, Readonly<Required<IEditorFindOptions>>>;
|
||||
|
@ -5330,9 +5380,13 @@ declare namespace monaco.editor {
|
|||
*/
|
||||
getVisibleRanges(): Range[];
|
||||
/**
|
||||
* Get the vertical position (top offset) for the line w.r.t. to the first line.
|
||||
* Get the vertical position (top offset) for the line's top w.r.t. to the first line.
|
||||
*/
|
||||
getTopForLineNumber(lineNumber: number): number;
|
||||
/**
|
||||
* Get the vertical position (top offset) for the line's bottom w.r.t. to the first line.
|
||||
*/
|
||||
getBottomForLineNumber(lineNumber: number): number;
|
||||
/**
|
||||
* Get the vertical position (top offset) for the position w.r.t. to the first line.
|
||||
*/
|
||||
|
@ -5833,6 +5887,10 @@ declare namespace monaco.languages {
|
|||
* Requested kind of actions to return.
|
||||
*/
|
||||
readonly only?: string;
|
||||
/**
|
||||
* The reason why code actions were requested.
|
||||
*/
|
||||
readonly trigger: CodeActionTriggerType;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5863,6 +5921,10 @@ declare namespace monaco.languages {
|
|||
* such as `["quickfix.removeLine", "source.fixAll" ...]`.
|
||||
*/
|
||||
readonly providedCodeActionKinds?: readonly string[];
|
||||
readonly documentation?: ReadonlyArray<{
|
||||
readonly kind: string;
|
||||
readonly command: Command;
|
||||
}>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -6435,6 +6497,11 @@ declare namespace monaco.languages {
|
|||
disabled?: string;
|
||||
}
|
||||
|
||||
export enum CodeActionTriggerType {
|
||||
Invoke = 1,
|
||||
Auto = 2
|
||||
}
|
||||
|
||||
export interface CodeActionList extends IDisposable {
|
||||
readonly actions: ReadonlyArray<CodeAction>;
|
||||
}
|
||||
|
@ -6771,11 +6838,11 @@ declare namespace monaco.languages {
|
|||
provideDocumentSymbols(model: editor.ITextModel, token: CancellationToken): ProviderResult<DocumentSymbol[]>;
|
||||
}
|
||||
|
||||
export type TextEdit = {
|
||||
export interface TextEdit {
|
||||
range: IRange;
|
||||
text: string;
|
||||
eol?: editor.EndOfLineSequence;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface used to format a model
|
||||
|
|
|
@ -223,8 +223,8 @@ export class ExtensionManagementCLIService implements IExtensionManagementCLISer
|
|||
output.log(version ? localize('installing with version', "Installing extension '{0}' v{1}...", id, version) : localize('installing', "Installing extension '{0}'...", id));
|
||||
}
|
||||
|
||||
await this.extensionManagementService.installFromGallery(galleryExtension, { ...installOptions, installGivenVersion: !!version });
|
||||
output.log(localize('successInstall', "Extension '{0}' v{1} was successfully installed.", id, galleryExtension.version));
|
||||
const local = await this.extensionManagementService.installFromGallery(galleryExtension, { ...installOptions, installGivenVersion: !!version });
|
||||
output.log(localize('successInstall', "Extension '{0}' v{1} was successfully installed.", id, local.manifest.version));
|
||||
return manifest;
|
||||
} catch (error) {
|
||||
if (isCancellationError(error)) {
|
||||
|
|
|
@ -51,7 +51,7 @@ export interface ResourceLabelFormatter {
|
|||
}
|
||||
|
||||
export interface ResourceLabelFormatting {
|
||||
label: string | ((resource: URI) => string); // myLabel:/${path}
|
||||
label: string; // myLabel:/${path}
|
||||
separator: '/' | '\\' | '';
|
||||
tildify?: boolean;
|
||||
normalizeDriveLetter?: boolean;
|
||||
|
|
|
@ -125,6 +125,7 @@ export const WorkbenchTreeElementHasParent = new RawContextKey<boolean>('treeEle
|
|||
export const WorkbenchTreeElementCanExpand = new RawContextKey<boolean>('treeElementCanExpand', false);
|
||||
export const WorkbenchTreeElementHasChild = new RawContextKey<boolean>('treeElementHasChild', false);
|
||||
export const WorkbenchTreeFindOpen = new RawContextKey<boolean>('treeFindOpen', false);
|
||||
export const WorkbenchTreeSupportsFind = new RawContextKey<boolean>('treeSupportsFind', true);
|
||||
const WorkbenchListTypeNavigationModeKey = 'listTypeNavigationMode';
|
||||
|
||||
/**
|
||||
|
@ -189,7 +190,6 @@ class MultipleSelectionController<T> extends Disposable implements IMultipleSele
|
|||
|
||||
function toWorkbenchListOptions<T>(
|
||||
accessor: ServicesAccessor,
|
||||
container: HTMLElement,
|
||||
options: IListOptions<T>,
|
||||
): [IListOptions<T>, IDisposable] {
|
||||
const configurationService = accessor.get(IConfigurationService);
|
||||
|
@ -203,7 +203,7 @@ function toWorkbenchListOptions<T>(
|
|||
mouseWheelScrollSensitivity: configurationService.getValue<number>(mouseWheelScrollSensitivityKey),
|
||||
fastScrollSensitivity: configurationService.getValue<number>(fastScrollSensitivityKey),
|
||||
multipleSelectionController: options.multipleSelectionController ?? disposables.add(new MultipleSelectionController(configurationService)),
|
||||
keyboardNavigationEventFilter: createKeyboardNavigationEventFilter(container, keybindingService),
|
||||
keyboardNavigationEventFilter: createKeyboardNavigationEventFilter(keybindingService),
|
||||
};
|
||||
|
||||
return [result, disposables];
|
||||
|
@ -244,7 +244,7 @@ export class WorkbenchList<T> extends List<T> {
|
|||
@IInstantiationService instantiationService: IInstantiationService
|
||||
) {
|
||||
const horizontalScrolling = typeof options.horizontalScrolling !== 'undefined' ? options.horizontalScrolling : Boolean(configurationService.getValue(horizontalScrollingKey));
|
||||
const [workbenchListOptions, workbenchListOptionsDisposable] = instantiationService.invokeFunction(toWorkbenchListOptions, container, options);
|
||||
const [workbenchListOptions, workbenchListOptionsDisposable] = instantiationService.invokeFunction(toWorkbenchListOptions, options);
|
||||
|
||||
super(user, container, delegate, renderers,
|
||||
{
|
||||
|
@ -384,7 +384,7 @@ export class WorkbenchPagedList<T> extends PagedList<T> {
|
|||
@IInstantiationService instantiationService: IInstantiationService
|
||||
) {
|
||||
const horizontalScrolling = typeof options.horizontalScrolling !== 'undefined' ? options.horizontalScrolling : Boolean(configurationService.getValue(horizontalScrollingKey));
|
||||
const [workbenchListOptions, workbenchListOptionsDisposable] = instantiationService.invokeFunction(toWorkbenchListOptions, container, options);
|
||||
const [workbenchListOptions, workbenchListOptionsDisposable] = instantiationService.invokeFunction(toWorkbenchListOptions, options);
|
||||
super(user, container, delegate, renderers,
|
||||
{
|
||||
keyboardSupport: false,
|
||||
|
@ -517,7 +517,7 @@ export class WorkbenchTable<TRow> extends Table<TRow> {
|
|||
@IInstantiationService instantiationService: IInstantiationService
|
||||
) {
|
||||
const horizontalScrolling = typeof options.horizontalScrolling !== 'undefined' ? options.horizontalScrolling : Boolean(configurationService.getValue(horizontalScrollingKey));
|
||||
const [workbenchListOptions, workbenchListOptionsDisposable] = instantiationService.invokeFunction(toWorkbenchListOptions, container, options);
|
||||
const [workbenchListOptions, workbenchListOptionsDisposable] = instantiationService.invokeFunction(toWorkbenchListOptions, options);
|
||||
|
||||
super(user, container, delegate, columns, renderers,
|
||||
{
|
||||
|
@ -812,7 +812,7 @@ class TreeResourceNavigator<T, TFilterData> extends ResourceNavigator<T> {
|
|||
}
|
||||
}
|
||||
|
||||
function createKeyboardNavigationEventFilter(container: HTMLElement, keybindingService: IKeybindingService): IKeyboardNavigationEventFilter {
|
||||
function createKeyboardNavigationEventFilter(keybindingService: IKeybindingService): IKeyboardNavigationEventFilter {
|
||||
let inChord = false;
|
||||
|
||||
return event => {
|
||||
|
@ -825,7 +825,7 @@ function createKeyboardNavigationEventFilter(container: HTMLElement, keybindingS
|
|||
return false;
|
||||
}
|
||||
|
||||
const result = keybindingService.softDispatch(event, container);
|
||||
const result = keybindingService.softDispatch(event, event.target);
|
||||
|
||||
if (result?.enterChord) {
|
||||
inChord = true;
|
||||
|
@ -862,7 +862,7 @@ export class WorkbenchObjectTree<T extends NonNullable<any>, TFilterData = void>
|
|||
@IThemeService themeService: IThemeService,
|
||||
@IConfigurationService configurationService: IConfigurationService
|
||||
) {
|
||||
const { options: treeOptions, getTypeNavigationMode, disposable } = instantiationService.invokeFunction(workbenchTreeDataPreamble, container, options as any);
|
||||
const { options: treeOptions, getTypeNavigationMode, disposable } = instantiationService.invokeFunction(workbenchTreeDataPreamble, options as any);
|
||||
super(user, container, delegate, renderers, treeOptions);
|
||||
this.disposables.add(disposable);
|
||||
this.internals = new WorkbenchTreeInternals(this, options, getTypeNavigationMode, options.overrideStyles, contextKeyService, listService, themeService, configurationService);
|
||||
|
@ -903,7 +903,7 @@ export class WorkbenchCompressibleObjectTree<T extends NonNullable<any>, TFilter
|
|||
@IThemeService themeService: IThemeService,
|
||||
@IConfigurationService configurationService: IConfigurationService
|
||||
) {
|
||||
const { options: treeOptions, getTypeNavigationMode, disposable } = instantiationService.invokeFunction(workbenchTreeDataPreamble, container, options as any);
|
||||
const { options: treeOptions, getTypeNavigationMode, disposable } = instantiationService.invokeFunction(workbenchTreeDataPreamble, options as any);
|
||||
super(user, container, delegate, renderers, treeOptions);
|
||||
this.disposables.add(disposable);
|
||||
this.internals = new WorkbenchTreeInternals(this, options, getTypeNavigationMode, options.overrideStyles, contextKeyService, listService, themeService, configurationService);
|
||||
|
@ -950,7 +950,7 @@ export class WorkbenchDataTree<TInput, T, TFilterData = void> extends DataTree<T
|
|||
@IThemeService themeService: IThemeService,
|
||||
@IConfigurationService configurationService: IConfigurationService
|
||||
) {
|
||||
const { options: treeOptions, getTypeNavigationMode, disposable } = instantiationService.invokeFunction(workbenchTreeDataPreamble, container, options as any);
|
||||
const { options: treeOptions, getTypeNavigationMode, disposable } = instantiationService.invokeFunction(workbenchTreeDataPreamble, options as any);
|
||||
super(user, container, delegate, renderers, dataSource, treeOptions);
|
||||
this.disposables.add(disposable);
|
||||
this.internals = new WorkbenchTreeInternals(this, options, getTypeNavigationMode, options.overrideStyles, contextKeyService, listService, themeService, configurationService);
|
||||
|
@ -997,7 +997,7 @@ export class WorkbenchAsyncDataTree<TInput, T, TFilterData = void> extends Async
|
|||
@IThemeService themeService: IThemeService,
|
||||
@IConfigurationService configurationService: IConfigurationService
|
||||
) {
|
||||
const { options: treeOptions, getTypeNavigationMode, disposable } = instantiationService.invokeFunction(workbenchTreeDataPreamble, container, options as any);
|
||||
const { options: treeOptions, getTypeNavigationMode, disposable } = instantiationService.invokeFunction(workbenchTreeDataPreamble, options as any);
|
||||
super(user, container, delegate, renderers, dataSource, treeOptions);
|
||||
this.disposables.add(disposable);
|
||||
this.internals = new WorkbenchTreeInternals(this, options, getTypeNavigationMode, options.overrideStyles, contextKeyService, listService, themeService, configurationService);
|
||||
|
@ -1042,7 +1042,7 @@ export class WorkbenchCompressibleAsyncDataTree<TInput, T, TFilterData = void> e
|
|||
@IThemeService themeService: IThemeService,
|
||||
@IConfigurationService configurationService: IConfigurationService
|
||||
) {
|
||||
const { options: treeOptions, getTypeNavigationMode, disposable } = instantiationService.invokeFunction(workbenchTreeDataPreamble, container, options as any);
|
||||
const { options: treeOptions, getTypeNavigationMode, disposable } = instantiationService.invokeFunction(workbenchTreeDataPreamble, options as any);
|
||||
super(user, container, virtualDelegate, compressionDelegate, renderers, dataSource, treeOptions);
|
||||
this.disposables.add(disposable);
|
||||
this.internals = new WorkbenchTreeInternals(this, options, getTypeNavigationMode, options.overrideStyles, contextKeyService, listService, themeService, configurationService);
|
||||
|
@ -1077,11 +1077,9 @@ function getDefaultTreeFindMode(configurationService: IConfigurationService) {
|
|||
|
||||
function workbenchTreeDataPreamble<T, TFilterData, TOptions extends IAbstractTreeOptions<T, TFilterData> | IAsyncDataTreeOptions<T, TFilterData>>(
|
||||
accessor: ServicesAccessor,
|
||||
container: HTMLElement,
|
||||
options: TOptions,
|
||||
): { options: TOptions; getTypeNavigationMode: () => TypeNavigationMode | undefined; disposable: IDisposable } {
|
||||
const configurationService = accessor.get(IConfigurationService);
|
||||
const keybindingService = accessor.get(IKeybindingService);
|
||||
const contextViewService = accessor.get(IContextViewService);
|
||||
const contextKeyService = accessor.get(IContextKeyService);
|
||||
const instantiationService = accessor.get(IInstantiationService);
|
||||
|
@ -1107,7 +1105,7 @@ function workbenchTreeDataPreamble<T, TFilterData, TOptions extends IAbstractTre
|
|||
};
|
||||
|
||||
const horizontalScrolling = options.horizontalScrolling !== undefined ? options.horizontalScrolling : Boolean(configurationService.getValue(horizontalScrollingKey));
|
||||
const [workbenchListOptions, disposable] = instantiationService.invokeFunction(toWorkbenchListOptions, container, options);
|
||||
const [workbenchListOptions, disposable] = instantiationService.invokeFunction(toWorkbenchListOptions, options);
|
||||
const additionalScrollHeight = options.additionalScrollHeight;
|
||||
|
||||
return {
|
||||
|
@ -1122,7 +1120,6 @@ function workbenchTreeDataPreamble<T, TFilterData, TOptions extends IAbstractTre
|
|||
smoothScrolling: Boolean(configurationService.getValue(listSmoothScrolling)),
|
||||
defaultFindMode: getDefaultTreeFindMode(configurationService),
|
||||
horizontalScrolling,
|
||||
keyboardNavigationEventFilter: createKeyboardNavigationEventFilter(container, keybindingService),
|
||||
additionalScrollHeight,
|
||||
hideTwistiesOfChildlessElements: options.hideTwistiesOfChildlessElements,
|
||||
expandOnlyOnTwistieClick: options.expandOnlyOnTwistieClick ?? (configurationService.getValue<'singleClick' | 'doubleClick'>(treeExpandMode) === 'doubleClick'),
|
||||
|
@ -1147,6 +1144,7 @@ class WorkbenchTreeInternals<TInput, T, TFilterData> {
|
|||
private treeElementCanExpand: IContextKey<boolean>;
|
||||
private treeElementHasChild: IContextKey<boolean>;
|
||||
private treeFindOpen: IContextKey<boolean>;
|
||||
private treeSupportFindWidget: IContextKey<boolean>;
|
||||
private _useAltAsMultipleSelectionModifier: boolean;
|
||||
private disposables: IDisposable[] = [];
|
||||
private styler: IDisposable | undefined;
|
||||
|
@ -1180,7 +1178,10 @@ class WorkbenchTreeInternals<TInput, T, TFilterData> {
|
|||
this.treeElementHasParent = WorkbenchTreeElementHasParent.bindTo(this.contextKeyService);
|
||||
this.treeElementCanExpand = WorkbenchTreeElementCanExpand.bindTo(this.contextKeyService);
|
||||
this.treeElementHasChild = WorkbenchTreeElementHasChild.bindTo(this.contextKeyService);
|
||||
|
||||
this.treeFindOpen = WorkbenchTreeFindOpen.bindTo(this.contextKeyService);
|
||||
this.treeSupportFindWidget = WorkbenchTreeSupportsFind.bindTo(this.contextKeyService);
|
||||
this.treeSupportFindWidget.set(options.findWidgetEnabled ?? true);
|
||||
|
||||
this._useAltAsMultipleSelectionModifier = useAltAsMultipleSelectionModifier(configurationService);
|
||||
|
||||
|
|
|
@ -103,7 +103,7 @@ class MarkerStats implements MarkerStatistics {
|
|||
const result: MarkerStatistics = { errors: 0, warnings: 0, infos: 0, unknowns: 0 };
|
||||
|
||||
// TODO this is a hack
|
||||
if (resource.scheme === Schemas.inMemory || resource.scheme === Schemas.walkThrough || resource.scheme === Schemas.walkThroughSnippet) {
|
||||
if (resource.scheme === Schemas.inMemory || resource.scheme === Schemas.walkThrough || resource.scheme === Schemas.walkThroughSnippet || resource.scheme === Schemas.vscodeSourceControl) {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -417,30 +417,48 @@ export interface IAddressProvider {
|
|||
}
|
||||
|
||||
export async function connectRemoteAgentManagement(options: IConnectionOptions, remoteAuthority: string, clientId: string): Promise<ManagementPersistentConnection> {
|
||||
try {
|
||||
const reconnectionToken = generateUuid();
|
||||
const simpleOptions = await resolveConnectionOptions(options, reconnectionToken, null);
|
||||
const { protocol } = await doConnectRemoteAgentManagement(simpleOptions, CancellationToken.None);
|
||||
return new ManagementPersistentConnection(options, remoteAuthority, clientId, reconnectionToken, protocol);
|
||||
} catch (err) {
|
||||
options.logService.error(`[remote-connection] An error occurred in the very first connect attempt, it will be treated as a permanent error! Error:`);
|
||||
options.logService.error(err);
|
||||
PersistentConnection.triggerPermanentFailure(0, 0, RemoteAuthorityResolverError.isHandled(err));
|
||||
throw err;
|
||||
}
|
||||
return createInitialConnection(
|
||||
options,
|
||||
async (simpleOptions) => {
|
||||
const { protocol } = await doConnectRemoteAgentManagement(simpleOptions, CancellationToken.None);
|
||||
return new ManagementPersistentConnection(options, remoteAuthority, clientId, simpleOptions.reconnectionToken, protocol);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export async function connectRemoteAgentExtensionHost(options: IConnectionOptions, startArguments: IRemoteExtensionHostStartParams): Promise<ExtensionHostPersistentConnection> {
|
||||
try {
|
||||
const reconnectionToken = generateUuid();
|
||||
const simpleOptions = await resolveConnectionOptions(options, reconnectionToken, null);
|
||||
const { protocol, debugPort } = await doConnectRemoteAgentExtensionHost(simpleOptions, startArguments, CancellationToken.None);
|
||||
return new ExtensionHostPersistentConnection(options, startArguments, reconnectionToken, protocol, debugPort);
|
||||
} catch (err) {
|
||||
options.logService.error(`[remote-connection] An error occurred in the very first connect attempt, it will be treated as a permanent error! Error:`);
|
||||
options.logService.error(err);
|
||||
PersistentConnection.triggerPermanentFailure(0, 0, RemoteAuthorityResolverError.isHandled(err));
|
||||
throw err;
|
||||
return createInitialConnection(
|
||||
options,
|
||||
async (simpleOptions) => {
|
||||
const { protocol, debugPort } = await doConnectRemoteAgentExtensionHost(simpleOptions, startArguments, CancellationToken.None);
|
||||
return new ExtensionHostPersistentConnection(options, startArguments, simpleOptions.reconnectionToken, protocol, debugPort);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Will attempt to connect 5 times. If it fails 5 consecutive times, it will give up.
|
||||
*/
|
||||
async function createInitialConnection<T extends PersistentConnection>(options: IConnectionOptions, connectionFactory: (simpleOptions: ISimpleConnectionOptions) => Promise<T>): Promise<T> {
|
||||
const MAX_ATTEMPTS = 5;
|
||||
|
||||
for (let attempt = 1; ; attempt++) {
|
||||
try {
|
||||
const reconnectionToken = generateUuid();
|
||||
const simpleOptions = await resolveConnectionOptions(options, reconnectionToken, null);
|
||||
const result = await connectionFactory(simpleOptions);
|
||||
return result;
|
||||
} catch (err) {
|
||||
if (attempt < MAX_ATTEMPTS) {
|
||||
options.logService.error(`[remote-connection][attempt ${attempt}] An error occurred in initial connection! Will retry... Error:`);
|
||||
options.logService.error(err);
|
||||
} else {
|
||||
options.logService.error(`[remote-connection][attempt ${attempt}] An error occurred in initial connection! It will be treated as a permanent error. Error:`);
|
||||
options.logService.error(err);
|
||||
PersistentConnection.triggerPermanentFailure(0, 0, RemoteAuthorityResolverError.isHandled(err));
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ import { parse as parseUrl } from 'url';
|
|||
import { Promises } from 'vs/base/common/async';
|
||||
import { streamToBufferReadableStream } from 'vs/base/common/buffer';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { canceled } from 'vs/base/common/errors';
|
||||
import { CancellationError } from 'vs/base/common/errors';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import * as streams from 'vs/base/common/stream';
|
||||
import { isBoolean, isNumber } from 'vs/base/common/types';
|
||||
|
@ -170,7 +170,7 @@ export class RequestService extends Disposable implements IRequestService {
|
|||
|
||||
token.onCancellationRequested(() => {
|
||||
req.abort();
|
||||
e(canceled());
|
||||
e(new CancellationError());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -4,18 +4,17 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import type { AppInsightsCore } from '@microsoft/1ds-core-js';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { AbstractOneDataSystemAppender } from 'vs/platform/telemetry/common/1dsAppender';
|
||||
|
||||
|
||||
export class OneDataSystemWebAppender extends AbstractOneDataSystemAppender {
|
||||
constructor(
|
||||
configurationService: IConfigurationService | undefined,
|
||||
isInternalTelemetry: boolean,
|
||||
eventPrefix: string,
|
||||
defaultData: { [key: string]: any } | null,
|
||||
iKeyOrClientFactory: string | (() => AppInsightsCore), // allow factory function for testing
|
||||
) {
|
||||
super(configurationService, eventPrefix, defaultData, iKeyOrClientFactory);
|
||||
super(isInternalTelemetry, eventPrefix, defaultData, iKeyOrClientFactory);
|
||||
|
||||
// If we cannot fetch the endpoint it means it is down and we should not send any telemetry.
|
||||
// This is most likely due to ad blockers
|
||||
|
|
|
@ -7,7 +7,6 @@ import type { AppInsightsCore, IExtendedConfiguration } from '@microsoft/1ds-cor
|
|||
import type { IChannelConfiguration, IXHROverride, PostChannel } from '@microsoft/1ds-post-js';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { mixin } from 'vs/base/common/objects';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { ITelemetryAppender, validateTelemetryData } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
|
||||
const endpointUrl = 'https://mobile.events.data.microsoft.com/OneCollector/1.0';
|
||||
|
@ -63,7 +62,7 @@ export abstract class AbstractOneDataSystemAppender implements ITelemetryAppende
|
|||
protected readonly endPointUrl = endpointUrl;
|
||||
|
||||
constructor(
|
||||
private readonly _configurationService: IConfigurationService | undefined,
|
||||
private readonly _isInternalTelemetry: boolean,
|
||||
private _eventPrefix: string,
|
||||
private _defaultData: { [key: string]: any } | null,
|
||||
iKeyOrClientFactory: string | (() => AppInsightsCore), // allow factory function for testing
|
||||
|
@ -92,8 +91,7 @@ export abstract class AbstractOneDataSystemAppender implements ITelemetryAppende
|
|||
}
|
||||
|
||||
if (!this._asyncAiCore) {
|
||||
const isInternal = this._configurationService?.getValue<boolean>('telemetry.internalTesting');
|
||||
this._asyncAiCore = getClient(this._aiCoreOrKey, isInternal, this._xhrOverride);
|
||||
this._asyncAiCore = getClient(this._aiCoreOrKey, this._isInternalTelemetry, this._xhrOverride);
|
||||
}
|
||||
|
||||
this._asyncAiCore.then(
|
||||
|
|
|
@ -25,7 +25,7 @@ export async function resolveCommonProperties(
|
|||
commit: string | undefined,
|
||||
version: string | undefined,
|
||||
machineId: string | undefined,
|
||||
msftInternalDomains: string[] | undefined,
|
||||
isInternalTelemetry: boolean,
|
||||
installSourcePath: string,
|
||||
product?: string
|
||||
): Promise<{ [name: string]: string | boolean | undefined }> {
|
||||
|
@ -50,10 +50,9 @@ export async function resolveCommonProperties(
|
|||
// __GDPR__COMMON__ "common.product" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }
|
||||
result['common.product'] = product || 'desktop';
|
||||
|
||||
const msftInternal = verifyMicrosoftInternalDomain(msftInternalDomains || []);
|
||||
if (msftInternal) {
|
||||
if (isInternalTelemetry) {
|
||||
// __GDPR__COMMON__ "common.msftInternal" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }
|
||||
result['common.msftInternal'] = msftInternal;
|
||||
result['common.msftInternal'] = isInternalTelemetry;
|
||||
}
|
||||
|
||||
// dynamic properties which value differs on each call
|
||||
|
|
|
@ -11,6 +11,7 @@ import { URI } from 'vs/base/common/uri';
|
|||
import { ConfigurationTarget, ConfigurationTargetToString, IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { verifyMicrosoftInternalDomain } from 'vs/platform/telemetry/common/commonProperties';
|
||||
import { ClassifiedEvent, GDPRClassification, StrictPropertyCheck } from 'vs/platform/telemetry/common/gdprTypings';
|
||||
import { ICustomEndpointTelemetryService, ITelemetryData, ITelemetryEndpoint, ITelemetryInfo, ITelemetryService, TelemetryConfiguration, TelemetryLevel, TELEMETRY_OLD_SETTING_ID, TELEMETRY_SETTING_ID } from 'vs/platform/telemetry/common/telemetry';
|
||||
|
||||
|
@ -252,6 +253,18 @@ function flatKeys(result: string[], prefix: string, value: { [key: string]: any
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not this is an internal user
|
||||
* @param productService The product service
|
||||
* @param configService The config servivce
|
||||
* @returns true if internal, false otherwise
|
||||
*/
|
||||
export function isInternalTelemetry(productService: IProductService, configService: IConfigurationService) {
|
||||
const msftInternalDomains = productService.msftInternalDomains || [];
|
||||
const internalTesting = configService.getValue<boolean>('telemetry.internalTesting');
|
||||
return verifyMicrosoftInternalDomain(msftInternalDomains) || internalTesting;
|
||||
}
|
||||
|
||||
interface IPathEnvironment {
|
||||
appRoot: string;
|
||||
extensionsPath: string;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue