Merge from vscode 2e5312cd61ff99c570299ecc122c52584265eda2

This commit is contained in:
ADS Merger
2020-04-23 02:50:35 +00:00
committed by Anthony Dresser
parent 3603f55d97
commit 7f1d8fc32f
659 changed files with 22709 additions and 12497 deletions

30
.github/workflows/english-please.yml vendored Normal file
View File

@@ -0,0 +1,30 @@
name: English Please
on:
issues:
types: [edited]
# also make changes in ./on-label.yml and ./on-open.yml
jobs:
main:
runs-on: ubuntu-latest
steps:
- name: Checkout Actions
if: contains(github.event.issue.labels.*.name, '*english-please')
uses: actions/checkout@v2
with:
repository: 'microsoft/vscode-github-triage-actions'
ref: v7
path: ./actions
- name: Install Actions
if: contains(github.event.issue.labels.*.name, '*english-please')
run: npm install --production --prefix ./actions
- name: Run English Please
if: contains(github.event.issue.labels.*.name, '*english-please')
uses: ./actions/english-please
with:
token: ${{secrets.VSCODE_ISSUE_TRIAGE_BOT_PAT}}
cognitiveServicesAPIKey: ${{secrets.AZURE_TEXT_TRANSLATOR_KEY}}
nonEnglishLabel: "*english-please"
needsMoreInfoLabel: "needs more info"
translatorRequestedLabelPrefix: "translation-required-"
translatorRequestedLabelColor: "c29cff"

49
.vscode/launch.json vendored
View File

@@ -14,18 +14,26 @@
{ {
"type": "node", "type": "node",
"request": "attach", "request": "attach",
"restart": true,
"name": "Attach to Extension Host", "name": "Attach to Extension Host",
"timeout": 30000,
"port": 5870, "port": 5870,
"outFiles": [ "outFiles": [
"${workspaceFolder}/out/**/*.js" "${workspaceFolder}/out/**/*.js"
] ],
"presentation": {
"hidden": true
}
}, },
{ {
"type": "chrome", "type": "pwa-chrome",
"request": "attach", "request": "attach",
"name": "Attach to Shared Process", "name": "Attach to Shared Process",
"port": 9222, "port": 9222,
"urlFilter": "*" "urlFilter": "*sharedProcess.html*",
"presentation": {
"hidden": true
}
}, },
{ {
"type": "node", "type": "node",
@@ -67,9 +75,10 @@
"port": 9222 "port": 9222
}, },
{ {
"type": "chrome", "type": "pwa-chrome",
"request": "launch", "request": "launch",
"name": "Launch azuredatastudio", "name": "Launch azuredatastudio",
"browserLaunchLocation": "workspace",
"windows": { "windows": {
"runtimeExecutable": "${workspaceFolder}/scripts/sql.bat" "runtimeExecutable": "${workspaceFolder}/scripts/sql.bat"
}, },
@@ -97,25 +106,7 @@
"outFiles": [ "outFiles": [
"${workspaceFolder}/out/**/*.js" "${workspaceFolder}/out/**/*.js"
], ],
}, "browserLaunchLocation": "workspace"
{
"type": "node",
"request": "launch",
"name": "Launch ADS (Main Process)",
"runtimeExecutable": "${workspaceFolder}/scripts/sql.sh",
"windows": {
"runtimeExecutable": "${workspaceFolder}/scripts/sql.bat",
},
"runtimeArgs": [
"--no-cached-data"
],
"outFiles": [
"${workspaceFolder}/out/**/*.js"
],
"presentation": {
"group": "2_launch",
"order": 1
}
}, },
{ {
"type": "chrome", "type": "chrome",
@@ -150,7 +141,7 @@
"web" "web"
], ],
"presentation": { "presentation": {
"group": "2_launch", "group": "0_vscode",
"order": 2 "order": 2
} }
}, },
@@ -161,7 +152,7 @@
"url": "http://localhost:8080", "url": "http://localhost:8080",
"preLaunchTask": "Run web", "preLaunchTask": "Run web",
"presentation": { "presentation": {
"group": "2_launch", "group": "0_vscode",
"order": 3 "order": 3
} }
}, },
@@ -270,13 +261,15 @@
] ]
}, },
{ {
"name": "Debug azuredatastudio Main and Renderer", "name": "Azure Data Studio",
"configurations": [ "configurations": [
"Launch azuredatastudio", "Launch azuredatastudio",
"Attach to Main Process" "Attach to Main Process",
"Attach to Extension Host",
"Attach to Shared Process",
], ],
"presentation": { "presentation": {
"group": "1_vscode", "group": "0_vscode",
"order": 1 "order": 1
} }
}, },

View File

@@ -2,7 +2,7 @@
# Flags: CaseSensitive WordMatch # Flags: CaseSensitive WordMatch
# ContextLines: 2 # ContextLines: 2
9 results - 4 files 10 results - 4 files
src/vs/base/common/arrays.ts: src/vs/base/common/arrays.ts:
401 401
@@ -24,17 +24,17 @@ src/vs/base/common/arrays.ts:
564 export function find<T>(arr: ArrayLike<T>, predicate: (value: T, index: number, arr: ArrayLike<T>) => any): T | undefined { 564 export function find<T>(arr: ArrayLike<T>, predicate: (value: T, index: number, arr: ArrayLike<T>) => any): T | undefined {
src/vs/base/common/map.ts: src/vs/base/common/map.ts:
9 11
10 /** 12 /**
11: * @deprecated ES6: use `[...SetOrMap.values()]` 13: * @deprecated ES6: use `[...SetOrMap.values()]`
12 */ 14 */
13 export function values<V = any>(set: Set<V>): V[]; 15 export function values<V = any>(set: Set<V>): V[];
20 22
21 /** 23 /**
22: * @deprecated ES6: use `[...map.keys()]` 24: * @deprecated ES6: use `[...map.keys()]`
23 */ 25 */
24 export function keys<K, V>(map: Map<K, V>): K[] { 26 export function keys<K, V>(map: Map<K, V>): K[] {
src/vs/base/common/objects.ts: src/vs/base/common/objects.ts:
115 115
@@ -61,3 +61,9 @@ src/vs/base/common/strings.ts:
169: * @deprecated ES6: use `String.endsWith` 169: * @deprecated ES6: use `String.endsWith`
170 */ 170 */
171 export function endsWith(haystack: string, needle: string): boolean { 171 export function endsWith(haystack: string, needle: string): boolean {
853
854 /**
855: * @deprecated ES6
856 */
857 export function repeat(s: string, count: number): string {

View File

@@ -72,5 +72,6 @@
"files.insertFinalNewline": true, "files.insertFinalNewline": true,
"[typescript]": { "[typescript]": {
"editor.defaultFormatter": "vscode.typescript-language-features" "editor.defaultFormatter": "vscode.typescript-language-features"
} },
"typescript.tsc.autoDetect": "off"
} }

12
.vscode/tasks.json vendored
View File

@@ -3,7 +3,7 @@
"tasks": [ "tasks": [
{ {
"type": "npm", "type": "npm",
"script": "watch", "script": "watchd",
"label": "Build VS Code", "label": "Build VS Code",
"group": { "group": {
"kind": "build", "kind": "build",
@@ -45,6 +45,16 @@
"applyTo": "allDocuments" "applyTo": "allDocuments"
} }
}, },
{
"type": "npm",
"script": "kill-watchd",
"label": "Kill Build VS Code",
"group": "build",
"presentation": {
"reveal": "never"
},
"problemMatcher": "$tsc"
},
{ {
"label": "Run tests", "label": "Run tests",
"type": "shell", "type": "shell",

View File

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

View File

@@ -107,13 +107,13 @@ kerberos/build/**
# END SQL Modules # END SQL Modules
nsfw/binding.gyp vscode-nsfw/binding.gyp
nsfw/build/** vscode-nsfw/build/**
nsfw/src/** vscode-nsfw/src/**
nsfw/openpa/** vscode-nsfw/openpa/**
nsfw/includes/** vscode-nsfw/includes/**
!nsfw/build/Release/*.node !vscode-nsfw/build/Release/*.node
!nsfw/**/*.a !vscode-nsfw/**/*.a
vsda/build/** vsda/build/**
vsda/ci/** vsda/ci/**

View File

@@ -44,10 +44,10 @@ steps:
- script: | - script: |
./scripts/test.sh --tfs "Unit Tests" ./scripts/test.sh --tfs "Unit Tests"
displayName: Run Unit Tests (Electron) displayName: Run Unit Tests (Electron)
# - script: | {{SQL CARBON EDIT}} disable for now @TODO @anthonydresser # - script: | {{SQL CARBON EDIT}} disable
# yarn test-browser --browser chromium --browser webkit # yarn test-browser --browser chromium --browser webkit --browser firefox
# displayName: Run Unit Tests (Browser) # displayName: Run Unit Tests (Browser)
# - script: | {{SQL CARBON EDIT}} remove step # - script: | {{SQL CARBON EDIT}} disable
# ./scripts/test-integration.sh --tfs "Integration Tests" # ./scripts/test-integration.sh --tfs "Integration Tests"
# displayName: Run Integration Tests (Electron) # displayName: Run Integration Tests (Electron)
- task: PublishTestResults@2 - task: PublishTestResults@2

View File

@@ -77,23 +77,6 @@ steps:
yarn postinstall yarn postinstall
displayName: Run postinstall scripts displayName: Run postinstall scripts
condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) condition: and(succeeded(), eq(variables['CacheRestored'], 'true'))
env:
OSS_GITHUB_ID: "a5d3c261b032765a78de"
OSS_GITHUB_SECRET: $(oss-github-client-secret)
INSIDERS_GITHUB_ID: "31f02627809389d9f111"
INSIDERS_GITHUB_SECRET: $(insiders-github-client-secret)
STABLE_GITHUB_ID: "baa8a44b5e861d918709"
STABLE_GITHUB_SECRET: $(stable-github-client-secret)
EXPLORATION_GITHUB_ID: "94e8376d3a90429aeaea"
EXPLORATION_GITHUB_SECRET: $(exploration-github-client-secret)
VSO_GITHUB_ID: "3d4be8f37a0325b5817d"
VSO_GITHUB_SECRET: $(vso-github-client-secret)
VSO_PPE_GITHUB_ID: "eabf35024dc2e891a492"
VSO_PPE_GITHUB_SECRET: $(vso-ppe-github-client-secret)
VSO_DEV_GITHUB_ID: "84383ebd8a7c5f5efc5c"
VSO_DEV_GITHUB_SECRET: $(vso-dev-github-client-secret)
GITHUB_APP_ID: "Iv1.ae51e546bef24ff1"
GITHUB_APP_SECRET: $(github-app-client-secret)
- script: | - script: |
set -e set -e
@@ -118,7 +101,7 @@ steps:
- script: | - script: |
set -e set -e
yarn test-browser --build --browser chromium --browser webkit yarn test-browser --build --browser chromium --browser webkit --browser firefox
displayName: Run unit tests (Browser) displayName: Run unit tests (Browser)
condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false'))

View File

@@ -1,8 +1,12 @@
pool: pool:
vmImage: 'Ubuntu-16.04' vmImage: 'Ubuntu-16.04'
trigger: none trigger:
pr: none branches:
include: ['master']
pr:
branches:
include: ['master']
steps: steps:
- task: NodeTool@0 - task: NodeTool@0
@@ -27,10 +31,10 @@ steps:
git config user.email "vscode@microsoft.com" git config user.email "vscode@microsoft.com"
git config user.name "VSCode" git config user.name "VSCode"
git checkout origin/electron-6.0.x git checkout origin/electron-8.0.x
git merge origin/master git merge origin/master
# Push master branch into exploration branch # Push master branch into exploration branch
git push origin HEAD:electron-6.0.x git push origin HEAD:electron-8.0.x
displayName: Sync & Merge Exploration displayName: Sync & Merge Exploration

View File

@@ -52,10 +52,10 @@ steps:
- script: | - script: |
DISPLAY=:10 ./scripts/test.sh --tfs "Unit Tests" DISPLAY=:10 ./scripts/test.sh --tfs "Unit Tests"
displayName: Run Unit Tests (Electron) displayName: Run Unit Tests (Electron)
# - script: | {{SQL CARBON EDIT}} disable for now @TODO @anthonydresser # - script: | {{SQL CARBON EDIT}} disable
# DISPLAY=:10 yarn test-browser --browser chromium # DISPLAY=:10 yarn test-browser --browser chromium
# displayName: Run Unit Tests (Browser) # displayName: Run Unit Tests (Browser)
# - script: | {{SQL CARBON EDIT}} remove step # - script: | {{SQL CARBON EDIT}} disable
# DISPLAY=:10 ./scripts/test-integration.sh --tfs "Integration Tests" # DISPLAY=:10 ./scripts/test-integration.sh --tfs "Integration Tests"
# displayName: Run Integration Tests (Electron) # displayName: Run Integration Tests (Electron)
- task: PublishTestResults@2 - task: PublishTestResults@2

View File

@@ -86,23 +86,6 @@ steps:
yarn postinstall yarn postinstall
displayName: Run postinstall scripts displayName: Run postinstall scripts
condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) condition: and(succeeded(), eq(variables['CacheRestored'], 'true'))
env:
OSS_GITHUB_ID: "a5d3c261b032765a78de"
OSS_GITHUB_SECRET: $(oss-github-client-secret)
INSIDERS_GITHUB_ID: "31f02627809389d9f111"
INSIDERS_GITHUB_SECRET: $(insiders-github-client-secret)
STABLE_GITHUB_ID: "baa8a44b5e861d918709"
STABLE_GITHUB_SECRET: $(stable-github-client-secret)
EXPLORATION_GITHUB_ID: "94e8376d3a90429aeaea"
EXPLORATION_GITHUB_SECRET: $(exploration-github-client-secret)
VSO_GITHUB_ID: "3d4be8f37a0325b5817d"
VSO_GITHUB_SECRET: $(vso-github-client-secret)
VSO_PPE_GITHUB_ID: "eabf35024dc2e891a492"
VSO_PPE_GITHUB_SECRET: $(vso-ppe-github-client-secret)
VSO_DEV_GITHUB_ID: "84383ebd8a7c5f5efc5c"
VSO_DEV_GITHUB_SECRET: $(vso-dev-github-client-secret)
GITHUB_APP_ID: "Iv1.ae51e546bef24ff1"
GITHUB_APP_SECRET: $(github-app-client-secret)
- script: | - script: |
set -e set -e

View File

@@ -76,23 +76,6 @@ steps:
yarn postinstall yarn postinstall
displayName: Run postinstall scripts displayName: Run postinstall scripts
condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) condition: and(succeeded(), eq(variables['CacheRestored'], 'true'))
env:
OSS_GITHUB_ID: "a5d3c261b032765a78de"
OSS_GITHUB_SECRET: $(oss-github-client-secret)
INSIDERS_GITHUB_ID: "31f02627809389d9f111"
INSIDERS_GITHUB_SECRET: $(insiders-github-client-secret)
STABLE_GITHUB_ID: "baa8a44b5e861d918709"
STABLE_GITHUB_SECRET: $(stable-github-client-secret)
EXPLORATION_GITHUB_ID: "94e8376d3a90429aeaea"
EXPLORATION_GITHUB_SECRET: $(exploration-github-client-secret)
VSO_GITHUB_ID: "3d4be8f37a0325b5817d"
VSO_GITHUB_SECRET: $(vso-github-client-secret)
VSO_PPE_GITHUB_ID: "eabf35024dc2e891a492"
VSO_PPE_GITHUB_SECRET: $(vso-ppe-github-client-secret)
VSO_DEV_GITHUB_ID: "84383ebd8a7c5f5efc5c"
VSO_DEV_GITHUB_SECRET: $(vso-dev-github-client-secret)
GITHUB_APP_ID: "Iv1.ae51e546bef24ff1"
GITHUB_APP_SECRET: $(github-app-client-secret)
- script: | - script: |
set -e set -e

View File

@@ -74,9 +74,9 @@ steps:
- script: | - script: |
set -e set -e
yarn postinstall yarn generate-github-config
displayName: Run postinstall scripts displayName: Generate GitHub config
condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), eq(variables['CacheRestored'], 'true')) condition: succeeded()
env: env:
OSS_GITHUB_ID: "a5d3c261b032765a78de" OSS_GITHUB_ID: "a5d3c261b032765a78de"
OSS_GITHUB_SECRET: $(oss-github-client-secret) OSS_GITHUB_SECRET: $(oss-github-client-secret)
@@ -95,6 +95,12 @@ steps:
GITHUB_APP_ID: "Iv1.ae51e546bef24ff1" GITHUB_APP_ID: "Iv1.ae51e546bef24ff1"
GITHUB_APP_SECRET: $(github-app-client-secret) GITHUB_APP_SECRET: $(github-app-client-secret)
- script: |
set -e
yarn postinstall
displayName: Run postinstall scripts
condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), eq(variables['CacheRestored'], 'true'))
# Mixin must run before optimize, because the CSS loader will # Mixin must run before optimize, because the CSS loader will
# inline small SVGs # inline small SVGs
- script: | - script: |

View File

@@ -63,7 +63,7 @@ steps:
MESSAGE="DefinitelyTyped/DefinitelyTyped#vscode-types-$TAG_VERSION created. Endgame master, please open this link, examine changes and create a PR:" MESSAGE="DefinitelyTyped/DefinitelyTyped#vscode-types-$TAG_VERSION created. Endgame master, please open this link, examine changes and create a PR:"
LINK="https://github.com/DefinitelyTyped/DefinitelyTyped/compare/vscode-types-$TAG_VERSION?quick_pull=1&body=Updating%20VS%20Code%20Extension%20API.%20See%20https%3A%2F%2Fgithub.com%2Fmicrosoft%2Fvscode%2Fissues%2F70175%20for%20details." LINK="https://github.com/DefinitelyTyped/DefinitelyTyped/compare/vscode-types-$TAG_VERSION?quick_pull=1&body=Updating%20VS%20Code%20Extension%20API.%20See%20https%3A%2F%2Fgithub.com%2Fmicrosoft%2Fvscode%2Fissues%2F70175%20for%20details."
MESSAGE2="[@octref, @jrieken, @kmaetzel, @egamma]. Please review and merge PR to publish @types/vscode." MESSAGE2="[@eamodio, @jrieken, @kmaetzel, @egamma]. Please review and merge PR to publish @types/vscode."
curl -X POST -H "Authorization: Bearer $(SLACK_TOKEN)" \ curl -X POST -H "Authorization: Bearer $(SLACK_TOKEN)" \
-H 'Content-type: application/json; charset=utf-8' \ -H 'Content-type: application/json; charset=utf-8' \

View File

@@ -49,10 +49,10 @@ steps:
- powershell: | - powershell: |
.\scripts\test.bat --tfs "Unit Tests" .\scripts\test.bat --tfs "Unit Tests"
displayName: Run Unit Tests (Electron) displayName: Run Unit Tests (Electron)
# - powershell: | {{SQL CARBON EDIT}} disable for now @TODO @anthonydresser # - powershell: | {{SQL CARBON EDIT}} disable
# yarn test-browser --browser chromium # yarn test-browser --browser chromium --browser firefox
# displayName: Run Unit Tests (Browser) # displayName: Run Unit Tests (Browser)
# - powershell: | {{SQL CARBON EDIT}} remove step # - powershell: | {{SQL CARBON EDIT}} disable
# .\scripts\test-integration.bat --tfs "Integration Tests" # .\scripts\test-integration.bat --tfs "Integration Tests"
# displayName: Run Integration Tests (Electron) # displayName: Run Integration Tests (Electron)
- task: PublishTestResults@2 - task: PublishTestResults@2

View File

@@ -86,23 +86,6 @@ steps:
exec { yarn postinstall } exec { yarn postinstall }
displayName: Run postinstall scripts displayName: Run postinstall scripts
condition: and(succeeded(), eq(variables['CacheRestored'], 'true')) condition: and(succeeded(), eq(variables['CacheRestored'], 'true'))
env:
OSS_GITHUB_ID: "a5d3c261b032765a78de"
OSS_GITHUB_SECRET: $(oss-github-client-secret)
INSIDERS_GITHUB_ID: "31f02627809389d9f111"
INSIDERS_GITHUB_SECRET: $(insiders-github-client-secret)
STABLE_GITHUB_ID: "baa8a44b5e861d918709"
STABLE_GITHUB_SECRET: $(stable-github-client-secret)
EXPLORATION_GITHUB_ID: "94e8376d3a90429aeaea"
EXPLORATION_GITHUB_SECRET: $(exploration-github-client-secret)
VSO_GITHUB_ID: "3d4be8f37a0325b5817d"
VSO_GITHUB_SECRET: $(vso-github-client-secret)
VSO_PPE_GITHUB_ID: "eabf35024dc2e891a492"
VSO_PPE_GITHUB_SECRET: $(vso-ppe-github-client-secret)
VSO_DEV_GITHUB_ID: "84383ebd8a7c5f5efc5c"
VSO_DEV_GITHUB_SECRET: $(vso-dev-github-client-secret)
GITHUB_APP_ID: "Iv1.ae51e546bef24ff1"
GITHUB_APP_SECRET: $(github-app-client-secret)
- powershell: | - powershell: |
. build/azure-pipelines/win32/exec.ps1 . build/azure-pipelines/win32/exec.ps1
@@ -132,7 +115,7 @@ steps:
- powershell: | - powershell: |
. build/azure-pipelines/win32/exec.ps1 . build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop" $ErrorActionPreference = "Stop"
exec { yarn test-browser --build --browser chromium } exec { yarn test-browser --build --browser chromium --browser firefox }
displayName: Run unit tests (Browser) displayName: Run unit tests (Browser)
condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false')) condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false'))

View File

@@ -43,7 +43,7 @@ let editorEntryPoints = [
]; ];
let editorResources = [ let editorResources = [
'out-editor-build/vs/base/browser/ui/codiconLabel/**/*.ttf' 'out-editor-build/vs/base/browser/ui/codicons/**/*.ttf'
]; ];
let BUNDLED_FILE_HEADER = [ let BUNDLED_FILE_HEADER = [

View File

@@ -76,7 +76,7 @@ const vscodeResources = [
'out-build/vs/base/common/performance.js', 'out-build/vs/base/common/performance.js',
'out-build/vs/base/node/languagePacks.js', 'out-build/vs/base/node/languagePacks.js',
'out-build/vs/base/node/{stdForkStart.js,terminateProcess.sh,cpuUsage.sh,ps.sh}', 'out-build/vs/base/node/{stdForkStart.js,terminateProcess.sh,cpuUsage.sh,ps.sh}',
'out-build/vs/base/browser/ui/codiconLabel/codicon/**', 'out-build/vs/base/browser/ui/codicons/codicon/**',
'out-build/vs/workbench/browser/media/*-theme.css', 'out-build/vs/workbench/browser/media/*-theme.css',
'out-build/vs/workbench/contrib/debug/**/*.json', 'out-build/vs/workbench/contrib/debug/**/*.json',
'out-build/vs/workbench/contrib/externalTerminal/**/*.scpt', 'out-build/vs/workbench/contrib/externalTerminal/**/*.scpt',
@@ -186,6 +186,7 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op
const checksums = computeChecksums(out, [ const checksums = computeChecksums(out, [
'vs/workbench/workbench.desktop.main.js', 'vs/workbench/workbench.desktop.main.js',
'vs/workbench/workbench.desktop.main.css', 'vs/workbench/workbench.desktop.main.css',
'vs/workbench/services/extensions/node/extensionHostProcess.js',
'vs/code/electron-browser/workbench/workbench.html', 'vs/code/electron-browser/workbench/workbench.html',
'vs/code/electron-browser/workbench/workbench.js' 'vs/code/electron-browser/workbench/workbench.js'
]); ]);
@@ -357,6 +358,7 @@ const buildRoot = path.dirname(root);
const BUILD_TARGETS = [ const BUILD_TARGETS = [
{ platform: 'win32', arch: 'ia32' }, { platform: 'win32', arch: 'ia32' },
{ platform: 'win32', arch: 'x64' }, { platform: 'win32', arch: 'x64' },
{ platform: 'win32', arch: 'arm64' },
{ platform: 'darwin', arch: null, opts: { stats: true } }, { platform: 'darwin', arch: null, opts: { stats: true } },
{ platform: 'linux', arch: 'ia32' }, { platform: 'linux', arch: 'ia32' },
{ platform: 'linux', arch: 'x64' }, { platform: 'linux', arch: 'x64' },
@@ -488,20 +490,30 @@ const generateVSCodeConfigurationTask = task.define('generate-vscode-configurati
const extensionsDir = path.join(os.tmpdir(), 'tmpextdir'); const extensionsDir = path.join(os.tmpdir(), 'tmpextdir');
const appName = process.env.VSCODE_QUALITY === 'insider' ? 'Visual\\ Studio\\ Code\\ -\\ Insiders.app' : 'Visual\\ Studio\\ Code.app'; const appName = process.env.VSCODE_QUALITY === 'insider' ? 'Visual\\ Studio\\ Code\\ -\\ Insiders.app' : 'Visual\\ Studio\\ Code.app';
const appPath = path.join(buildDir, `VSCode-darwin/${appName}/Contents/Resources/app/bin/code`); const appPath = path.join(buildDir, `VSCode-darwin/${appName}/Contents/Resources/app/bin/code`);
const codeProc = cp.exec(`${appPath} --export-default-configuration='${allConfigDetailsPath}' --wait --user-data-dir='${userDataDir}' --extensions-dir='${extensionsDir}'`); const codeProc = cp.exec(
`${appPath} --export-default-configuration='${allConfigDetailsPath}' --wait --user-data-dir='${userDataDir}' --extensions-dir='${extensionsDir}'`,
(err, stdout, stderr) => {
clearTimeout(timer);
if (err) {
console.log(`err: ${err} ${err.message} ${err.toString()}`);
reject(err);
}
if (stdout) {
console.log(`stdout: ${stdout}`);
}
if (stderr) {
console.log(`stderr: ${stderr}`);
}
resolve();
}
);
const timer = setTimeout(() => { const timer = setTimeout(() => {
codeProc.kill(); codeProc.kill();
reject(new Error('export-default-configuration process timed out')); reject(new Error('export-default-configuration process timed out'));
}, 10 * 1000); }, 12 * 1000);
codeProc.stdout.on('data', d => console.log(d.toString()));
codeProc.stderr.on('data', d => console.log(d.toString()));
codeProc.on('exit', () => {
clearTimeout(timer);
resolve();
});
codeProc.on('error', err => { codeProc.on('error', err => {
clearTimeout(timer); clearTimeout(timer);

View File

@@ -128,6 +128,7 @@ function archiveWin32Setup(arch) {
gulp.task(task.define('vscode-win32-ia32-archive', task.series(util.rimraf(zipDir('ia32')), archiveWin32Setup('ia32')))); gulp.task(task.define('vscode-win32-ia32-archive', task.series(util.rimraf(zipDir('ia32')), archiveWin32Setup('ia32'))));
gulp.task(task.define('vscode-win32-x64-archive', task.series(util.rimraf(zipDir('x64')), archiveWin32Setup('x64')))); gulp.task(task.define('vscode-win32-x64-archive', task.series(util.rimraf(zipDir('x64')), archiveWin32Setup('x64'))));
gulp.task(task.define('vscode-win32-arm64-archive', task.series(util.rimraf(zipDir('arm64')), archiveWin32Setup('arm64'))));
function copyInnoUpdater(arch) { function copyInnoUpdater(arch) {
return () => { return () => {
@@ -150,3 +151,4 @@ gulp.task(task.define('vscode-win32-x64-inno-updater', task.series(copyInnoUpdat
gulp.task(task.define('vscode-win32-ia32-code-helper', task.series(updateIcon(path.join(buildPath('ia32'), 'resources', 'app', 'out', 'vs', 'platform', 'files', 'node', 'watcher', 'win32', 'CodeHelper.exe'))))); gulp.task(task.define('vscode-win32-ia32-code-helper', task.series(updateIcon(path.join(buildPath('ia32'), 'resources', 'app', 'out', 'vs', 'platform', 'files', 'node', 'watcher', 'win32', 'CodeHelper.exe')))));
gulp.task(task.define('vscode-win32-x64-code-helper', task.series(updateIcon(path.join(buildPath('x64'), 'resources', 'app', 'out', 'vs', 'platform', 'files', 'node', 'watcher', 'win32', 'CodeHelper.exe'))))); gulp.task(task.define('vscode-win32-x64-code-helper', task.series(updateIcon(path.join(buildPath('x64'), 'resources', 'app', 'out', 'vs', 'platform', 'files', 'node', 'watcher', 'win32', 'CodeHelper.exe')))));
gulp.task(task.define('vscode-win32-arm64-code-helper', task.series(updateIcon(path.join(buildPath('arm64'), 'resources', 'app', 'out', 'vs', 'platform', 'files', 'node', 'watcher', 'win32', 'CodeHelper.exe')))));

View File

@@ -27,13 +27,7 @@ module.exports = new (_a = class ApiEventNaming {
['TSTypeAnnotation TSTypeReference Identifier[name="Event"]']: (node) => { ['TSTypeAnnotation TSTypeReference Identifier[name="Event"]']: (node) => {
var _a, _b; var _a, _b;
const def = (_b = (_a = node.parent) === null || _a === void 0 ? void 0 : _a.parent) === null || _b === void 0 ? void 0 : _b.parent; const def = (_b = (_a = node.parent) === null || _a === void 0 ? void 0 : _a.parent) === null || _b === void 0 ? void 0 : _b.parent;
let ident; const ident = this.getIdent(def);
if ((def === null || def === void 0 ? void 0 : def.type) === experimental_utils_1.AST_NODE_TYPES.Identifier) {
ident = def;
}
else if (((def === null || def === void 0 ? void 0 : def.type) === experimental_utils_1.AST_NODE_TYPES.TSPropertySignature || (def === null || def === void 0 ? void 0 : def.type) === experimental_utils_1.AST_NODE_TYPES.ClassProperty) && def.key.type === experimental_utils_1.AST_NODE_TYPES.Identifier) {
ident = def.key;
}
if (!ident) { if (!ident) {
// event on unknown structure... // event on unknown structure...
return context.report({ return context.report({
@@ -76,6 +70,18 @@ module.exports = new (_a = class ApiEventNaming {
} }
}; };
} }
getIdent(def) {
if (!def) {
return;
}
if (def.type === experimental_utils_1.AST_NODE_TYPES.Identifier) {
return def;
}
else if ((def.type === experimental_utils_1.AST_NODE_TYPES.TSPropertySignature || def.type === experimental_utils_1.AST_NODE_TYPES.ClassProperty) && def.key.type === experimental_utils_1.AST_NODE_TYPES.Identifier) {
return def.key;
}
return this.getIdent(def.parent);
}
}, },
_a._nameRegExp = /on(Did|Will)([A-Z][a-z]+)([A-Z][a-z]+)?/, _a._nameRegExp = /on(Did|Will)([A-Z][a-z]+)([A-Z][a-z]+)?/,
_a); _a);

View File

@@ -32,14 +32,7 @@ export = new class ApiEventNaming implements eslint.Rule.RuleModule {
['TSTypeAnnotation TSTypeReference Identifier[name="Event"]']: (node: any) => { ['TSTypeAnnotation TSTypeReference Identifier[name="Event"]']: (node: any) => {
const def = (<TSESTree.Identifier>node).parent?.parent?.parent; const def = (<TSESTree.Identifier>node).parent?.parent?.parent;
let ident: TSESTree.Identifier | undefined; const ident = this.getIdent(def);
if (def?.type === AST_NODE_TYPES.Identifier) {
ident = def;
} else if ((def?.type === AST_NODE_TYPES.TSPropertySignature || def?.type === AST_NODE_TYPES.ClassProperty) && def.key.type === AST_NODE_TYPES.Identifier) {
ident = def.key;
}
if (!ident) { if (!ident) {
// event on unknown structure... // event on unknown structure...
@@ -87,5 +80,19 @@ export = new class ApiEventNaming implements eslint.Rule.RuleModule {
} }
}; };
} }
private getIdent(def: TSESTree.Node | undefined): TSESTree.Identifier | undefined {
if (!def) {
return;
}
if (def.type === AST_NODE_TYPES.Identifier) {
return def;
} else if ((def.type === AST_NODE_TYPES.TSPropertySignature || def.type === AST_NODE_TYPES.ClassProperty) && def.key.type === AST_NODE_TYPES.Identifier) {
return def.key;
}
return this.getIdent(def.parent);
}
}; };

View File

@@ -48,7 +48,7 @@
"rollup-plugin-commonjs": "^10.1.0", "rollup-plugin-commonjs": "^10.1.0",
"rollup-plugin-node-resolve": "^5.2.0", "rollup-plugin-node-resolve": "^5.2.0",
"terser": "4.3.8", "terser": "4.3.8",
"typescript": "^3.9.0-dev.20200327", "typescript": "^3.9.0-dev.20200420",
"vsce": "1.48.0", "vsce": "1.48.0",
"vscode-telemetry-extractor": "^1.5.4", "vscode-telemetry-extractor": "^1.5.4",
"xml2js": "^0.4.17" "xml2js": "^0.4.17"

View File

@@ -3462,10 +3462,10 @@ typescript@^3.0.1:
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.3.tgz#c830f657f93f1ea846819e929092f5fe5983e977" resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.3.tgz#c830f657f93f1ea846819e929092f5fe5983e977"
integrity sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g== integrity sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g==
typescript@^3.9.0-dev.20200327: typescript@^3.9.0-dev.20200420:
version "3.9.0-dev.20200327" version "3.9.0-dev.20200420"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.0-dev.20200327.tgz#52179aae816587f772a0526e91143760f2bee42f" resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.0-dev.20200420.tgz#99c2bc0936dbf4479b0b5260d80475ed494b1532"
integrity sha512-/TWD/zPvhAcN2Toqx2NBQ+oDVGVj4iqupjWcUAwL45TfcODeHpzszneABR1b/EjHbtUObtLH40vy5Z6rdVvKzg== integrity sha512-36MW6V+oXNnsSgliSjUWvtOkO21g9+iFGHPFv+O06HsCl3dcuqzBac17m8xuOuWo1LUlEgS6yAnD9fiVgvmCfg==
typical@^4.0.0: typical@^4.0.0:
version "4.0.0" version "4.0.0"

View File

@@ -60,12 +60,12 @@
"git": { "git": {
"name": "electron", "name": "electron",
"repositoryUrl": "https://github.com/electron/electron", "repositoryUrl": "https://github.com/electron/electron",
"commitHash": "d17dfabfcba7bd0bc994b8dac5f5d2000bef572c" "commitHash": "959e80cc53cbebf8eb1d62eb2d14fa8fd86b0394"
} }
}, },
"isOnlyProductionDependency": true, "isOnlyProductionDependency": true,
"license": "MIT", "license": "MIT",
"version": "7.1.11" "version": "7.2.2"
}, },
{ {
"component": { "component": {

View File

@@ -23,7 +23,7 @@
}], }],
"snippets": [{ "snippets": [{
"language": "bat", "language": "bat",
"path": "./snippets/batchfile.snippets.json" "path": "./snippets/batchfile.code-snippets"
}] }]
} }
} }

View File

@@ -411,6 +411,26 @@
"category": "Git" "category": "Git"
} }
], ],
"keybindings": [
{
"command": "git.stageSelectedRanges",
"key": "ctrl+k ctrl+alt+s",
"mac": "cmd+k cmd+alt+s",
"when": "isInDiffEditor"
},
{
"command": "git.unstageSelectedRanges",
"key": "ctrl+k ctrl+u",
"mac": "cmd+k cmd+u",
"when": "isInDiffEditor"
},
{
"command": "git.revertSelectedRanges",
"key": "ctrl+k ctrl+r",
"mac": "cmd+k cmd+r",
"when": "isInDiffEditor"
}
],
"menus": { "menus": {
"commandPalette": [ "commandPalette": [
{ {
@@ -1643,6 +1663,12 @@
"default": "mixed", "default": "mixed",
"description": "%config.untrackedChanges%", "description": "%config.untrackedChanges%",
"scope": "resource" "scope": "resource"
},
"git.showCommitInput": {
"type": "boolean",
"scope": "resource",
"default": true,
"description": "%config.showCommitInput%"
} }
} }
}, },

View File

@@ -102,7 +102,7 @@
"config.enableSmartCommit": "Commit all changes when there are no staged changes.", "config.enableSmartCommit": "Commit all changes when there are no staged changes.",
"config.smartCommitChanges": "Control which changes are automatically staged by Smart Commit.", "config.smartCommitChanges": "Control which changes are automatically staged by Smart Commit.",
"config.smartCommitChanges.all": "Automatically stage all changes.", "config.smartCommitChanges.all": "Automatically stage all changes.",
"config.smartCommitChanges.tracked": "Automatically staged tracked changes only.", "config.smartCommitChanges.tracked": "Automatically stage tracked changes only.",
"config.suggestSmartCommit": "Suggests to enable smart commit (commit all changes when there are no staged changes).", "config.suggestSmartCommit": "Suggests to enable smart commit (commit all changes when there are no staged changes).",
"config.enableCommitSigning": "Enables commit signing with GPG.", "config.enableCommitSigning": "Enables commit signing with GPG.",
"config.discardAllScope": "Controls what changes are discarded by the `Discard all changes` command. `all` discards all changes. `tracked` discards only tracked files. `prompt` shows a prompt dialog every time the action is run.", "config.discardAllScope": "Controls what changes are discarded by the `Discard all changes` command. `all` discards all changes. `tracked` discards only tracked files. `prompt` shows a prompt dialog every time the action is run.",
@@ -143,6 +143,7 @@
"config.untrackedChanges.mixed": "All changes, tracked and untracked, appear together and behave equally.", "config.untrackedChanges.mixed": "All changes, tracked and untracked, appear together and behave equally.",
"config.untrackedChanges.separate": "Untracked changes appear separately in the Source Control view. They are also excluded from several actions.", "config.untrackedChanges.separate": "Untracked changes appear separately in the Source Control view. They are also excluded from several actions.",
"config.untrackedChanges.hidden": "Untracked changes are hidden and excluded from several actions.", "config.untrackedChanges.hidden": "Untracked changes are hidden and excluded from several actions.",
"config.showCommitInput": "Controls whether to show the commit input in the Git source control panel.",
"colors.added": "Color for added resources.", "colors.added": "Color for added resources.",
"colors.modified": "Color for modified resources.", "colors.modified": "Color for modified resources.",
"colors.deleted": "Color for deleted resources.", "colors.deleted": "Color for deleted resources.",

View File

@@ -5,8 +5,8 @@
import { Model } from '../model'; import { Model } from '../model';
import { Repository as BaseRepository, Resource } from '../repository'; import { Repository as BaseRepository, Resource } from '../repository';
import { InputBox, Git, API, Repository, Remote, RepositoryState, Branch, Ref, Submodule, Commit, Change, RepositoryUIState, Status, LogOptions, APIState, CommitOptions } from './git'; import { InputBox, Git, API, Repository, Remote, RepositoryState, Branch, Ref, Submodule, Commit, Change, RepositoryUIState, Status, LogOptions, APIState, CommitOptions, GitExtension, RefType, RemoteSourceProvider } from './git';
import { Event, SourceControlInputBox, Uri, SourceControl } from 'vscode'; import { Event, SourceControlInputBox, Uri, SourceControl, Disposable, commands } from 'vscode';
import { mapEvent } from '../util'; import { mapEvent } from '../util';
import { toGitUri } from '../uri'; import { toGitUri } from '../uri';
@@ -248,5 +248,82 @@ export class ApiImpl implements API {
return result ? new ApiRepository(result) : null; return result ? new ApiRepository(result) : null;
} }
registerRemoteSourceProvider(provider: RemoteSourceProvider): Disposable {
return this._model.registerRemoteSourceProvider(provider);
}
constructor(private _model: Model) { } constructor(private _model: Model) { }
} }
function getRefType(type: RefType): string {
switch (type) {
case RefType.Head: return 'Head';
case RefType.RemoteHead: return 'RemoteHead';
case RefType.Tag: return 'Tag';
}
return 'unknown';
}
function getStatus(status: Status): string {
switch (status) {
case Status.INDEX_MODIFIED: return 'INDEX_MODIFIED';
case Status.INDEX_ADDED: return 'INDEX_ADDED';
case Status.INDEX_DELETED: return 'INDEX_DELETED';
case Status.INDEX_RENAMED: return 'INDEX_RENAMED';
case Status.INDEX_COPIED: return 'INDEX_COPIED';
case Status.MODIFIED: return 'MODIFIED';
case Status.DELETED: return 'DELETED';
case Status.UNTRACKED: return 'UNTRACKED';
case Status.IGNORED: return 'IGNORED';
case Status.INTENT_TO_ADD: return 'INTENT_TO_ADD';
case Status.ADDED_BY_US: return 'ADDED_BY_US';
case Status.ADDED_BY_THEM: return 'ADDED_BY_THEM';
case Status.DELETED_BY_US: return 'DELETED_BY_US';
case Status.DELETED_BY_THEM: return 'DELETED_BY_THEM';
case Status.BOTH_ADDED: return 'BOTH_ADDED';
case Status.BOTH_DELETED: return 'BOTH_DELETED';
case Status.BOTH_MODIFIED: return 'BOTH_MODIFIED';
}
return 'UNKNOWN';
}
export function registerAPICommands(extension: GitExtension): Disposable {
return Disposable.from(
commands.registerCommand('git.api.getRepositories', () => {
const api = extension.getAPI(1);
return api.repositories.map(r => r.rootUri.toString());
}),
commands.registerCommand('git.api.getRepositoryState', (uri: string) => {
const api = extension.getAPI(1);
const repository = api.getRepository(Uri.parse(uri));
if (!repository) {
return null;
}
const state = repository.state;
const ref = (ref: Ref | undefined) => (ref && { ...ref, type: getRefType(ref.type) });
const change = (change: Change) => ({
uri: change.uri.toString(),
originalUri: change.originalUri.toString(),
renameUri: change.renameUri?.toString(),
status: getStatus(change.status)
});
return {
HEAD: ref(state.HEAD),
refs: state.refs.map(ref),
remotes: state.remotes,
submodules: state.submodules,
rebaseCommit: state.rebaseCommit,
mergeChanges: state.mergeChanges.map(change),
indexChanges: state.indexChanges.map(change),
workingTreeChanges: state.workingTreeChanges.map(change)
};
})
);
}

View File

@@ -3,7 +3,8 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { Uri, SourceControlInputBox, Event, CancellationToken } from 'vscode'; import { Uri, Event, Disposable, ProviderResult } from 'vscode';
export { ProviderResult } from 'vscode';
export interface Git { export interface Git {
readonly path: string; readonly path: string;
@@ -189,6 +190,19 @@ export interface Repository {
commit(message: string, opts?: CommitOptions): Promise<void>; commit(message: string, opts?: CommitOptions): Promise<void>;
} }
export interface RemoteSource {
readonly name: string;
readonly description?: string;
readonly url: string | string[];
}
export interface RemoteSourceProvider {
readonly name: string;
readonly icon?: string; // codicon name
readonly supportsQuery?: boolean;
getRemoteSources(query?: string): ProviderResult<RemoteSource[]>;
}
export type APIState = 'uninitialized' | 'initialized'; export type APIState = 'uninitialized' | 'initialized';
export interface API { export interface API {
@@ -201,6 +215,7 @@ export interface API {
toGitUri(uri: Uri, ref: string): Uri; toGitUri(uri: Uri, ref: string): Uri;
getRepository(uri: Uri): Repository | null; getRepository(uri: Uri): Repository | null;
registerRemoteSourceProvider(provider: RemoteSourceProvider): Disposable;
} }
export interface GitExtension { export interface GitExtension {

View File

@@ -6,10 +6,10 @@
import { lstat, Stats } from 'fs'; import { lstat, Stats } from 'fs';
import * as os from 'os'; import * as os from 'os';
import * as path from 'path'; import * as path from 'path';
import { commands, Disposable, LineChange, MessageOptions, OutputChannel, Position, ProgressLocation, QuickPickItem, Range, SourceControlResourceState, TextDocumentShowOptions, TextEditor, Uri, ViewColumn, window, workspace, WorkspaceEdit, WorkspaceFolder, TimelineItem, env } from 'vscode'; import { commands, Disposable, LineChange, MessageOptions, OutputChannel, Position, ProgressLocation, QuickPickItem, Range, SourceControlResourceState, TextDocumentShowOptions, TextEditor, Uri, ViewColumn, window, workspace, WorkspaceEdit, WorkspaceFolder, TimelineItem, env, QuickPick } from 'vscode';
import TelemetryReporter from 'vscode-extension-telemetry'; import TelemetryReporter from 'vscode-extension-telemetry';
import * as nls from 'vscode-nls'; import * as nls from 'vscode-nls';
import { Branch, GitErrorCodes, Ref, RefType, Status, CommitOptions } from './api/git'; import { Branch, GitErrorCodes, Ref, RefType, Status, CommitOptions, RemoteSourceProvider, RemoteSource } from './api/git';
import { ForcePushMode, Git, Stash } from './git'; import { ForcePushMode, Git, Stash } from './git';
import { Model } from './model'; import { Model } from './model';
import { Repository, Resource, ResourceGroupType } from './repository'; import { Repository, Resource, ResourceGroupType } from './repository';
@@ -18,6 +18,7 @@ import { fromGitUri, toGitUri, isGitUri } from './uri';
import { grep, isDescendant, pathEquals } from './util'; import { grep, isDescendant, pathEquals } from './util';
import { Log, LogLevel } from './log'; import { Log, LogLevel } from './log';
import { GitTimelineItem } from './timelineProvider'; import { GitTimelineItem } from './timelineProvider';
import { throttle, debounce } from './decorators';
const localize = nls.loadMessageBundle(); const localize = nls.loadMessageBundle();
@@ -233,6 +234,71 @@ interface PushOptions {
silent?: boolean; silent?: boolean;
} }
async function getQuickPickResult<T extends QuickPickItem>(quickpick: QuickPick<T>): Promise<T | undefined> {
const result = await new Promise<T | undefined>(c => {
quickpick.onDidAccept(() => c(quickpick.selectedItems[0]));
quickpick.onDidHide(() => c(undefined));
quickpick.show();
});
quickpick.hide();
return result;
}
class RemoteSourceProviderQuickPick {
private quickpick: QuickPick<QuickPickItem & { remoteSource?: RemoteSource }>;
constructor(private provider: RemoteSourceProvider) {
this.quickpick = window.createQuickPick();
this.quickpick.ignoreFocusOut = true;
if (provider.supportsQuery) {
this.quickpick.placeholder = localize('type to search', "Repository name (type to search)");
this.quickpick.onDidChangeValue(this.onDidChangeValue, this);
} else {
this.quickpick.placeholder = localize('type to filter', "Repository name");
}
}
@debounce(300)
onDidChangeValue(): void {
this.query();
}
@throttle
async query(): Promise<void> {
this.quickpick.busy = true;
try {
const remoteSources = await this.provider.getRemoteSources(this.quickpick.value) || [];
if (remoteSources.length === 0) {
this.quickpick.items = [{
label: localize('none found', "No remote repositories found."),
alwaysShow: true
}];
} else {
this.quickpick.items = remoteSources.map(remoteSource => ({
label: remoteSource.name,
description: remoteSource.description || (typeof remoteSource.url === 'string' ? remoteSource.url : remoteSource.url[0]),
remoteSource
}));
}
} catch (err) {
this.quickpick.items = [{ label: localize('error', "$(error) Error: {0}", err.message), alwaysShow: true }];
} finally {
this.quickpick.busy = false;
}
}
async pick(): Promise<RemoteSource | undefined> {
this.query();
const result = await getQuickPickResult(this.quickpick);
return result?.remoteSource;
}
}
export class CommandCenter { export class CommandCenter {
private disposables: Disposable[]; private disposables: Disposable[];
@@ -290,7 +356,7 @@ export class CommandCenter {
} }
@command('git.openResource') @command('git.openResource')
async openResource(resource: Resource): Promise<void> { async openResource(resource: Resource, preserveFocus: boolean): Promise<void> {
const repository = this.model.getRepository(resource.resourceUri); const repository = this.model.getRepository(resource.resourceUri);
if (!repository) { if (!repository) {
@@ -301,7 +367,7 @@ export class CommandCenter {
const openDiffOnClick = config.get<boolean>('openDiffOnClick'); const openDiffOnClick = config.get<boolean>('openDiffOnClick');
if (openDiffOnClick) { if (openDiffOnClick) {
await this._openResource(resource, undefined, true, false); await this._openResource(resource, undefined, preserveFocus, false);
} else { } else {
await this.openFile(resource); await this.openFile(resource);
} }
@@ -454,10 +520,51 @@ export class CommandCenter {
@command('git.clone') @command('git.clone')
async clone(url?: string, parentPath?: string): Promise<void> { async clone(url?: string, parentPath?: string): Promise<void> {
if (!url) { if (!url) {
url = await window.showInputBox({ const quickpick = window.createQuickPick<(QuickPickItem & { provider?: RemoteSourceProvider, url?: string })>();
prompt: localize('repourl', "Repository URL"), quickpick.ignoreFocusOut = true;
ignoreFocusOut: true
}); const providers = this.model.getRemoteProviders()
.map(provider => ({ label: (provider.icon ? `$(${provider.icon}) ` : '') + localize('clonefrom', "Clone from {1}", provider.name), alwaysShow: true, provider }));
quickpick.placeholder = providers.length === 0
? localize('provide url', "Provide repository URL.")
: localize('provide url or pick', "Provide repository URL or pick a repository source.");
const updatePicks = (value?: string) => {
if (value) {
quickpick.items = [{
label: localize('repourl', "Clone from URL"),
description: value,
alwaysShow: true,
url: value
},
...providers];
} else {
quickpick.items = providers;
}
};
quickpick.onDidChangeValue(updatePicks);
updatePicks();
const result = await getQuickPickResult(quickpick);
if (result) {
if (result.url) {
url = result.url;
} else if (result.provider) {
const quickpick = new RemoteSourceProviderQuickPick(result.provider);
const remote = await quickpick.pick();
if (remote) {
if (typeof remote.url === 'string') {
url = remote.url;
} else if (remote.url.length > 0) {
url = await window.showQuickPick(remote.url, { ignoreFocusOut: true, placeHolder: localize('pick url', "Choose a URL to clone from.") });
}
}
}
}
} }
if (!url) { if (!url) {

View File

@@ -1,150 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { workspace, Uri, Disposable, Event, EventEmitter, window } from 'vscode';
import { debounce, throttle } from './decorators';
import { fromGitUri, toGitUri } from './uri';
import { Model, ModelChangeEvent, OriginalResourceChangeEvent } from './model';
import { filterEvent, eventToPromise, isDescendant, pathEquals } from './util';
interface CacheRow {
uri: Uri;
timestamp: number;
}
interface Cache {
[uri: string]: CacheRow;
}
const THREE_MINUTES = 1000 * 60 * 3;
const FIVE_MINUTES = 1000 * 60 * 5;
export class GitContentProvider {
private _onDidChange = new EventEmitter<Uri>();
get onDidChange(): Event<Uri> { return this._onDidChange.event; }
private changedRepositoryRoots = new Set<string>();
private cache: Cache = Object.create(null);
private disposables: Disposable[] = [];
constructor(private model: Model) {
this.disposables.push(
model.onDidChangeRepository(this.onDidChangeRepository, this),
model.onDidChangeOriginalResource(this.onDidChangeOriginalResource, this),
workspace.registerTextDocumentContentProvider('git', this)
);
setInterval(() => this.cleanup(), FIVE_MINUTES);
}
private onDidChangeRepository({ repository }: ModelChangeEvent): void {
this.changedRepositoryRoots.add(repository.root);
this.eventuallyFireChangeEvents();
}
private onDidChangeOriginalResource({ uri }: OriginalResourceChangeEvent): void {
if (uri.scheme !== 'file') {
return;
}
this._onDidChange.fire(toGitUri(uri, '', { replaceFileExtension: true }));
}
@debounce(1100)
private eventuallyFireChangeEvents(): void {
this.fireChangeEvents();
}
@throttle
private async fireChangeEvents(): Promise<void> {
if (!window.state.focused) {
const onDidFocusWindow = filterEvent(window.onDidChangeWindowState, e => e.focused);
await eventToPromise(onDidFocusWindow);
}
Object.keys(this.cache).forEach(key => {
const uri = this.cache[key].uri;
const fsPath = uri.fsPath;
for (const root of this.changedRepositoryRoots) {
if (isDescendant(root, fsPath)) {
this._onDidChange.fire(uri);
return;
}
}
});
this.changedRepositoryRoots.clear();
}
async provideTextDocumentContent(uri: Uri): Promise<string> {
let { path, ref, submoduleOf } = fromGitUri(uri);
if (submoduleOf) {
const repository = this.model.getRepository(submoduleOf);
if (!repository) {
return '';
}
if (ref === 'index') {
return await repository.diffIndexWithHEAD(path);
} else {
return await repository.diffWithHEAD(path);
}
}
const repository = this.model.getRepository(uri);
if (!repository) {
return '';
}
const cacheKey = uri.toString();
const timestamp = new Date().getTime();
const cacheValue: CacheRow = { uri, timestamp };
this.cache[cacheKey] = cacheValue;
if (ref === '~') {
const fileUri = Uri.file(path);
const uriString = fileUri.toString();
const [indexStatus] = repository.indexGroup.resourceStates.filter(r => r.resourceUri.toString() === uriString);
ref = indexStatus ? '' : 'HEAD';
} else if (/^~\d$/.test(ref)) {
ref = `:${ref[1]}`;
}
try {
return await repository.show(ref, path);
} catch (err) {
return '';
}
}
private cleanup(): void {
const now = new Date().getTime();
const cache = Object.create(null);
Object.keys(this.cache).forEach(key => {
const row = this.cache[key];
const { path } = fromGitUri(row.uri);
const isOpen = workspace.textDocuments
.filter(d => d.uri.scheme === 'file')
.some(d => pathEquals(d.uri.fsPath, path));
if (isOpen || now - row.timestamp < THREE_MINUTES) {
cache[row.uri.toString()] = row;
}
});
this.cache = cache;
}
dispose(): void {
this.disposables.forEach(d => d.dispose());
}
}

View File

@@ -443,7 +443,10 @@ export class Git {
); );
if (networkPath !== undefined) { if (networkPath !== undefined) {
return path.normalize( return path.normalize(
repoUri.fsPath.replace(networkPath, `${letter.toLowerCase()}:`), repoUri.fsPath.replace(
networkPath,
`${letter.toLowerCase()}:${networkPath.endsWith('\\') ? '\\' : ''}`
),
); );
} }
} catch { } } catch { }
@@ -537,7 +540,8 @@ export class Git {
options.env = assign({}, process.env, this.env, options.env || {}, { options.env = assign({}, process.env, this.env, options.env || {}, {
VSCODE_GIT_COMMAND: args[0], VSCODE_GIT_COMMAND: args[0],
LC_ALL: 'en_US.UTF-8', LC_ALL: 'en_US.UTF-8',
LANG: 'en_US.UTF-8' LANG: 'en_US.UTF-8',
GIT_PAGER: 'cat'
}); });
if (options.cwd) { if (options.cwd) {

View File

@@ -10,7 +10,6 @@ import { ExtensionContext, workspace, window, Disposable, commands, OutputChanne
import { findGit, Git, IGit } from './git'; import { findGit, Git, IGit } from './git';
import { Model } from './model'; import { Model } from './model';
import { CommandCenter } from './commands'; import { CommandCenter } from './commands';
import { GitContentProvider } from './contentProvider';
import { GitFileSystemProvider } from './fileSystemProvider'; import { GitFileSystemProvider } from './fileSystemProvider';
import { GitDecorations } from './decorationProvider'; import { GitDecorations } from './decorationProvider';
import { Askpass } from './askpass'; import { Askpass } from './askpass';
@@ -23,6 +22,7 @@ import { GitExtensionImpl } from './api/extension';
// import * as fs from 'fs'; // import * as fs from 'fs';
import { createIPCServer, IIPCServer } from './ipc/ipcServer'; import { createIPCServer, IIPCServer } from './ipc/ipcServer';
import { GitTimelineProvider } from './timelineProvider'; import { GitTimelineProvider } from './timelineProvider';
import { registerAPICommands } from './api/api1';
const deactivateTasks: { (): Promise<any>; }[] = []; const deactivateTasks: { (): Promise<any>; }[] = [];
@@ -80,7 +80,6 @@ async function createModel(context: ExtensionContext, outputChannel: OutputChann
disposables.push( disposables.push(
new CommandCenter(git, model, outputChannel, telemetryReporter), new CommandCenter(git, model, outputChannel, telemetryReporter),
new GitContentProvider(model),
new GitFileSystemProvider(model), new GitFileSystemProvider(model),
new GitDecorations(model), new GitDecorations(model),
new GitProtocolHandler(), new GitProtocolHandler(),
@@ -141,7 +140,7 @@ async function warnAboutMissingGit(): Promise<void> {
} }
}*/ }*/
export async function activate(context: ExtensionContext): Promise<GitExtension> { export async function _activate(context: ExtensionContext): Promise<GitExtension> {
const disposables: Disposable[] = []; const disposables: Disposable[] = [];
context.subscriptions.push(new Disposable(() => Disposable.from(...disposables).dispose())); context.subscriptions.push(new Disposable(() => Disposable.from(...disposables).dispose()));
@@ -183,10 +182,19 @@ export async function activate(context: ExtensionContext): Promise<GitExtension>
} }
} }
// {{SQL CARBON EDIT}} - Rename info to _info to prevent error due to unused variable export async function activate(context: ExtensionContext): Promise<GitExtension> {
async function checkGitVersion(_info: IGit): Promise<void> { const result = await _activate(context);
context.subscriptions.push(registerAPICommands(result));
return result;
}
async function checkGitVersion(_info: IGit): Promise<void> { // {{SQL CARBON EDIT}} - Rename info to _info to prevent error due to unused variable
return; /* {{SQL CARBON EDIT}} return immediately return; /* {{SQL CARBON EDIT}} return immediately
/*const config = workspace.getConfiguration('git');
const shouldIgnore = config.get<boolean>('ignoreLegacyWarning') === true;
const config = workspace.getConfiguration('git'); const config = workspace.getConfiguration('git');
const shouldIgnore = config.get<boolean>('ignoreLegacyWarning') === true; const shouldIgnore = config.get<boolean>('ignoreLegacyWarning') === true;

View File

@@ -6,13 +6,13 @@
import { workspace, WorkspaceFoldersChangeEvent, Uri, window, Event, EventEmitter, QuickPickItem, Disposable, SourceControl, SourceControlResourceGroup, TextEditor, Memento, OutputChannel } from 'vscode'; import { workspace, WorkspaceFoldersChangeEvent, Uri, window, Event, EventEmitter, QuickPickItem, Disposable, SourceControl, SourceControlResourceGroup, TextEditor, Memento, OutputChannel } from 'vscode';
import { Repository, RepositoryState } from './repository'; import { Repository, RepositoryState } from './repository';
import { memoize, sequentialize, debounce } from './decorators'; import { memoize, sequentialize, debounce } from './decorators';
import { dispose, anyEvent, filterEvent, isDescendant, firstIndex, pathEquals } from './util'; import { dispose, anyEvent, filterEvent, isDescendant, firstIndex, pathEquals, toDisposable } from './util';
import { Git } from './git'; import { Git } from './git';
import * as path from 'path'; import * as path from 'path';
import * as fs from 'fs'; import * as fs from 'fs';
import * as nls from 'vscode-nls'; import * as nls from 'vscode-nls';
import { fromGitUri } from './uri'; import { fromGitUri } from './uri';
import { GitErrorCodes, APIState as State } from './api/git'; import { GitErrorCodes, APIState as State, RemoteSourceProvider } from './api/git';
const localize = nls.loadMessageBundle(); const localize = nls.loadMessageBundle();
@@ -74,6 +74,8 @@ export class Model {
this._onDidChangeState.fire(state); this._onDidChangeState.fire(state);
} }
private remoteProviders = new Set<RemoteSourceProvider>();
private disposables: Disposable[] = []; private disposables: Disposable[] = [];
constructor(readonly git: Git, private globalState: Memento, private outputChannel: OutputChannel) { constructor(readonly git: Git, private globalState: Memento, private outputChannel: OutputChannel) {
@@ -447,6 +449,15 @@ export class Model {
return undefined; return undefined;
} }
registerRemoteSourceProvider(provider: RemoteSourceProvider): Disposable {
this.remoteProviders.add(provider);
return toDisposable(() => this.remoteProviders.delete(provider));
}
getRemoteProviders(): RemoteSourceProvider[] {
return [...this.remoteProviders.values()];
}
dispose(): void { dispose(): void {
const openRepositories = [...this.openRepositories]; const openRepositories = [...this.openRepositories];
openRepositories.forEach(r => r.dispose()); openRepositories.forEach(r => r.dispose());

View File

@@ -743,6 +743,15 @@ export class Repository implements Disposable {
const onConfigListenerForUntracked = filterEvent(workspace.onDidChangeConfiguration, e => e.affectsConfiguration('git.untrackedChanges', root)); const onConfigListenerForUntracked = filterEvent(workspace.onDidChangeConfiguration, e => e.affectsConfiguration('git.untrackedChanges', root));
onConfigListenerForUntracked(this.updateModelState, this, this.disposables); onConfigListenerForUntracked(this.updateModelState, this, this.disposables);
const updateInputBoxVisibility = () => {
const config = workspace.getConfiguration('git', root);
this._sourceControl.inputBox.visible = config.get<boolean>('showCommitInput', true);
};
const onConfigListenerForInputBoxVisibility = filterEvent(workspace.onDidChangeConfiguration, e => e.affectsConfiguration('git.showCommitInput', root));
onConfigListenerForInputBoxVisibility(updateInputBoxVisibility, this, this.disposables);
updateInputBoxVisibility();
this.mergeGroup.hideWhenEmpty = true; this.mergeGroup.hideWhenEmpty = true;
this.untrackedGroup.hideWhenEmpty = true; this.untrackedGroup.hideWhenEmpty = true;

View File

@@ -0,0 +1,8 @@
src/**
!src/common/config.json
out/**
build/**
extension.webpack.config.js
tsconfig.json
yarn.lock
README.md

View File

@@ -14,15 +14,16 @@
"activationEvents": [ "activationEvents": [
"*" "*"
], ],
"aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217",
"main": "./out/extension.js", "main": "./out/extension.js",
"scripts": { "scripts": {
"vscode:prepublish": "npm run compile", "vscode:prepublish": "npm run compile",
"compile": "gulp compile-extension:github-authentication", "compile": "gulp compile-extension:github-authentication",
"watch": "gulp watch-extension:github-authentication", "watch": "gulp watch-extension:github-authentication"
"postinstall": "node build/postinstall.js"
}, },
"dependencies": { "dependencies": {
"uuid": "^3.3.3", "uuid": "^3.3.3",
"vscode-extension-telemetry": "0.1.1",
"vscode-nls": "^4.1.2" "vscode-nls": "^4.1.2"
}, },
"devDependencies": { "devDependencies": {

View File

@@ -7,8 +7,11 @@ import * as vscode from 'vscode';
import { GitHubAuthenticationProvider, onDidChangeSessions } from './github'; import { GitHubAuthenticationProvider, onDidChangeSessions } from './github';
import { uriHandler } from './githubServer'; import { uriHandler } from './githubServer';
import Logger from './common/logger'; import Logger from './common/logger';
import TelemetryReporter from 'vscode-extension-telemetry';
export async function activate(context: vscode.ExtensionContext) { export async function activate(context: vscode.ExtensionContext) {
const { name, version, aiKey } = require('../package.json') as { name: string, version: string, aiKey: string };
const telemetryReporter = new TelemetryReporter(name, version, aiKey);
context.subscriptions.push(vscode.window.registerUriHandler(uriHandler)); context.subscriptions.push(vscode.window.registerUriHandler(uriHandler));
const loginService = new GitHubAuthenticationProvider(); const loginService = new GitHubAuthenticationProvider();
@@ -22,19 +25,29 @@ export async function activate(context: vscode.ExtensionContext) {
getSessions: () => Promise.resolve(loginService.sessions), getSessions: () => Promise.resolve(loginService.sessions),
login: async (scopeList: string[]) => { login: async (scopeList: string[]) => {
try { try {
const session = await loginService.login(scopeList.join(' ')); telemetryReporter.sendTelemetryEvent('login');
const session = await loginService.login(scopeList.sort().join(' '));
Logger.info('Login success!'); Logger.info('Login success!');
onDidChangeSessions.fire({ added: [session.id], removed: [], changed: [] }); onDidChangeSessions.fire({ added: [session.id], removed: [], changed: [] });
return session; return session;
} catch (e) { } catch (e) {
telemetryReporter.sendTelemetryEvent('loginFailed');
vscode.window.showErrorMessage(`Sign in failed: ${e}`); vscode.window.showErrorMessage(`Sign in failed: ${e}`);
Logger.error(e); Logger.error(e);
throw e; throw e;
} }
}, },
logout: async (id: string) => { logout: async (id: string) => {
await loginService.logout(id); try {
onDidChangeSessions.fire({ added: [], removed: [id], changed: [] }); telemetryReporter.sendTelemetryEvent('logout');
await loginService.logout(id);
onDidChangeSessions.fire({ added: [], removed: [id], changed: [] });
} catch (e) {
telemetryReporter.sendTelemetryEvent('logoutFailed');
vscode.window.showErrorMessage(`Sign out failed: ${e}`);
Logger.error(e);
throw e;
}
} }
}); });

View File

@@ -12,12 +12,27 @@ import Logger from './common/logger';
export const onDidChangeSessions = new vscode.EventEmitter<vscode.AuthenticationSessionsChangeEvent>(); export const onDidChangeSessions = new vscode.EventEmitter<vscode.AuthenticationSessionsChangeEvent>();
interface SessionData { interface SessionData {
id: string;
account?: {
displayName: string;
id: string;
}
scopes: string[];
accessToken: string;
}
// TODO remove
interface OldSessionData {
id: string; id: string;
accountName: string; accountName: string;
scopes: string[]; scopes: string[];
accessToken: string; accessToken: string;
} }
function isOldSessionData(x: any): x is OldSessionData {
return !!x.accountName;
}
export class GitHubAuthenticationProvider { export class GitHubAuthenticationProvider {
private _sessions: vscode.AuthenticationSession[] = []; private _sessions: vscode.AuthenticationSession[] = [];
private _githubServer = new GitHubServer(); private _githubServer = new GitHubServer();
@@ -68,15 +83,34 @@ export class GitHubAuthenticationProvider {
const storedSessions = await keychain.getToken(); const storedSessions = await keychain.getToken();
if (storedSessions) { if (storedSessions) {
try { try {
const sessionData: SessionData[] = JSON.parse(storedSessions); const sessionData: (SessionData | OldSessionData)[] = JSON.parse(storedSessions);
return sessionData.map(session => { const sessionPromises = sessionData.map(async (session: SessionData | OldSessionData): Promise<vscode.AuthenticationSession | undefined> => {
return { try {
id: session.id, const needsUserInfo = isOldSessionData(session) || !session.account;
accountName: session.accountName, let userInfo: { id: string, accountName: string };
scopes: session.scopes, if (needsUserInfo) {
getAccessToken: () => Promise.resolve(session.accessToken) userInfo = await this._githubServer.getUserInfo(session.accessToken);
}; }
return {
id: session.id,
account: {
displayName: isOldSessionData(session)
? session.accountName
: session.account?.displayName ?? userInfo!.accountName,
id: isOldSessionData(session)
? userInfo!.id
: session.account?.id ?? userInfo!.id
},
scopes: session.scopes,
getAccessToken: () => Promise.resolve(session.accessToken)
};
} catch (e) {
return undefined;
}
}); });
return (await Promise.all(sessionPromises)).filter((x: vscode.AuthenticationSession | undefined): x is vscode.AuthenticationSession => !!x);
} catch (e) { } catch (e) {
Logger.error(`Error reading sessions: ${e}`); Logger.error(`Error reading sessions: ${e}`);
} }
@@ -90,7 +124,7 @@ export class GitHubAuthenticationProvider {
const resolvedAccessToken = await session.getAccessToken(); const resolvedAccessToken = await session.getAccessToken();
return { return {
id: session.id, id: session.id,
accountName: session.accountName, account: session.account,
scopes: session.scopes, scopes: session.scopes,
accessToken: resolvedAccessToken accessToken: resolvedAccessToken
}; };
@@ -125,7 +159,10 @@ export class GitHubAuthenticationProvider {
return { return {
id: uuid(), id: uuid(),
getAccessToken: () => Promise.resolve(token), getAccessToken: () => Promise.resolve(token),
accountName: userInfo.accountName, account: {
displayName: userInfo.accountName,
id: userInfo.id
},
scopes: scopes scopes: scopes
}; };
} }
@@ -137,7 +174,7 @@ export class GitHubAuthenticationProvider {
this._sessions.push(session); this._sessions.push(session);
} }
this.storeSessions(); await this.storeSessions();
} }
public async logout(id: string) { public async logout(id: string) {
@@ -145,9 +182,13 @@ export class GitHubAuthenticationProvider {
if (sessionIndex > -1) { if (sessionIndex > -1) {
const session = this._sessions.splice(sessionIndex, 1)[0]; const session = this._sessions.splice(sessionIndex, 1)[0];
const token = await session.getAccessToken(); const token = await session.getAccessToken();
await this._githubServer.revokeToken(token); try {
await this._githubServer.revokeToken(token);
} catch (_) {
// ignore, should still remove from keychain
}
} }
this.storeSessions(); await this.storeSessions();
} }
} }

View File

@@ -145,6 +145,7 @@ export class GitHubServer {
Logger.info('Got account info!'); Logger.info('Got account info!');
resolve({ id: json.id, accountName: json.login }); resolve({ id: json.id, accountName: json.login });
} else { } else {
Logger.error('Getting account info failed');
reject(new Error(result.statusMessage)); reject(new Error(result.statusMessage));
} }
}); });
@@ -186,6 +187,7 @@ export class GitHubServer {
Logger.info('Revoked token!'); Logger.info('Revoked token!');
resolve(); resolve();
} else { } else {
Logger.info(`Revoking token failed: ${result.statusMessage}`);
reject(new Error(result.statusMessage)); reject(new Error(result.statusMessage));
} }
}); });

View File

@@ -29,6 +29,15 @@ ansi-regex@^3.0.0:
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=
applicationinsights@1.0.8:
version "1.0.8"
resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-1.0.8.tgz#db6e3d983cf9f9405fe1ee5ba30ac6e1914537b5"
integrity sha512-KzOOGdphOS/lXWMFZe5440LUdFbrLpMvh2SaRxn7BmiI550KAoSb2gIhiq6kJZ9Ir3AxRRztjhzif+e5P5IXIg==
dependencies:
diagnostic-channel "0.2.0"
diagnostic-channel-publishers "0.2.1"
zone.js "0.7.6"
aproba@^1.0.3: aproba@^1.0.3:
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
@@ -91,6 +100,18 @@ detect-libc@^1.0.3:
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=
diagnostic-channel-publishers@0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-0.2.1.tgz#8e2d607a8b6d79fe880b548bc58cc6beb288c4f3"
integrity sha1-ji1geottef6IC1SLxYzGvrKIxPM=
diagnostic-channel@0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/diagnostic-channel/-/diagnostic-channel-0.2.0.tgz#cc99af9612c23fb1fff13612c72f2cbfaa8d5a17"
integrity sha1-zJmvlhLCP7H/8TYSxy8sv6qNWhc=
dependencies:
semver "^5.3.0"
end-of-stream@^1.1.0, end-of-stream@^1.4.1: end-of-stream@^1.1.0, end-of-stream@^1.4.1:
version "1.4.4" version "1.4.4"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
@@ -314,7 +335,7 @@ safe-buffer@~5.1.0, safe-buffer@~5.1.1:
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
semver@^5.4.1: semver@^5.3.0, semver@^5.4.1:
version "5.7.1" version "5.7.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
@@ -436,6 +457,13 @@ uuid@^3.3.3:
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
vscode-extension-telemetry@0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.1.1.tgz#91387e06b33400c57abd48979b0e790415ae110b"
integrity sha512-TkKKG/B/J94DP5qf6xWB4YaqlhWDg6zbbqVx7Bz//stLQNnfE9XS1xm3f6fl24c5+bnEK0/wHgMgZYKIKxPeUA==
dependencies:
applicationinsights "1.0.8"
vscode-nls@^4.1.2: vscode-nls@^4.1.2:
version "4.1.2" version "4.1.2"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.1.2.tgz#ca8bf8bb82a0987b32801f9fddfdd2fb9fd3c167" resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.1.2.tgz#ca8bf8bb82a0987b32801f9fddfdd2fb9fd3c167"
@@ -457,3 +485,8 @@ wrappy@1:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
zone.js@0.7.6:
version "0.7.6"
resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.7.6.tgz#fbbc39d3e0261d0986f1ba06306eb3aeb0d22009"
integrity sha1-+7w50+AmHQmG8boGMG6zrrDSIAk=

View File

@@ -23,7 +23,9 @@ export function activate(context: vscode.ExtensionContext) {
const previewManager = new PreviewManager(extensionRoot, sizeStatusBarEntry, binarySizeStatusBarEntry, zoomStatusBarEntry); const previewManager = new PreviewManager(extensionRoot, sizeStatusBarEntry, binarySizeStatusBarEntry, zoomStatusBarEntry);
context.subscriptions.push(vscode.window.registerCustomEditorProvider2(PreviewManager.viewType, previewManager)); context.subscriptions.push(vscode.window.registerCustomEditorProvider2(PreviewManager.viewType, previewManager, {
supportsMultipleEditorsPerResource: true,
}));
context.subscriptions.push(vscode.commands.registerCommand('imagePreview.zoomIn', () => { context.subscriptions.push(vscode.commands.registerCommand('imagePreview.zoomIn', () => {
previewManager.activePreview?.zoomIn(); previewManager.activePreview?.zoomIn();
@@ -33,4 +35,3 @@ export function activate(context: vscode.ExtensionContext) {
previewManager.activePreview?.zoomOut(); previewManager.activePreview?.zoomOut();
})); }));
} }

View File

@@ -28,7 +28,7 @@ export class PreviewManager implements vscode.CustomEditorProvider {
) { } ) { }
public async openCustomDocument(uri: vscode.Uri) { public async openCustomDocument(uri: vscode.Uri) {
return new vscode.CustomDocument(uri); return { uri, dispose: () => { } };
} }
public async resolveCustomEditor( public async resolveCustomEditor(

View File

@@ -13,12 +13,12 @@ const localize = nls.loadMessageBundle();
import { import {
workspace, window, languages, commands, ExtensionContext, extensions, Uri, LanguageConfiguration, workspace, window, languages, commands, ExtensionContext, extensions, Uri, LanguageConfiguration,
Diagnostic, StatusBarAlignment, TextEditor, TextDocument, FormattingOptions, CancellationToken, Diagnostic, StatusBarAlignment, TextEditor, TextDocument, FormattingOptions, CancellationToken,
ProviderResult, TextEdit, Range, Position, Disposable, CompletionItem, CompletionList, CompletionContext ProviderResult, TextEdit, Range, Position, Disposable, CompletionItem, CompletionList, CompletionContext, Hover, MarkdownString,
} from 'vscode'; } from 'vscode';
import { import {
LanguageClient, LanguageClientOptions, RequestType, ServerOptions, TransportKind, NotificationType, LanguageClient, LanguageClientOptions, RequestType, ServerOptions, TransportKind, NotificationType,
DidChangeConfigurationNotification, HandleDiagnosticsSignature, ResponseError, DocumentRangeFormattingParams, DidChangeConfigurationNotification, HandleDiagnosticsSignature, ResponseError, DocumentRangeFormattingParams,
DocumentRangeFormattingRequest, ProvideCompletionItemsSignature DocumentRangeFormattingRequest, ProvideCompletionItemsSignature, ProvideHoverSignature
} from 'vscode-languageclient'; } from 'vscode-languageclient';
import TelemetryReporter from 'vscode-extension-telemetry'; import TelemetryReporter from 'vscode-extension-telemetry';
@@ -153,25 +153,41 @@ export function activate(context: ExtensionContext) {
}, },
// testing the replace / insert mode // testing the replace / insert mode
provideCompletionItem(document: TextDocument, position: Position, context: CompletionContext, token: CancellationToken, next: ProvideCompletionItemsSignature): ProviderResult<CompletionItem[] | CompletionList> { provideCompletionItem(document: TextDocument, position: Position, context: CompletionContext, token: CancellationToken, next: ProvideCompletionItemsSignature): ProviderResult<CompletionItem[] | CompletionList> {
function updateRanges(item: CompletionItem) { function update(item: CompletionItem) {
const range = item.range; const range = item.range;
if (range instanceof Range && range.end.isAfter(position) && range.start.isBeforeOrEqual(position)) { if (range instanceof Range && range.end.isAfter(position) && range.start.isBeforeOrEqual(position)) {
item.range = { inserting: new Range(range.start, position), replacing: range }; item.range = { inserting: new Range(range.start, position), replacing: range };
} }
if (item.documentation instanceof MarkdownString) {
item.documentation = updateMarkdownString(item.documentation);
}
} }
function updateProposals(r: CompletionItem[] | CompletionList | null | undefined): CompletionItem[] | CompletionList | null | undefined { function updateProposals(r: CompletionItem[] | CompletionList | null | undefined): CompletionItem[] | CompletionList | null | undefined {
if (r) { if (r) {
(Array.isArray(r) ? r : r.items).forEach(updateRanges); (Array.isArray(r) ? r : r.items).forEach(update);
} }
return r; return r;
} }
const isThenable = <T>(obj: ProviderResult<T>): obj is Thenable<T> => obj && (<any>obj)['then'];
const r = next(document, position, context, token); const r = next(document, position, context, token);
if (isThenable<CompletionItem[] | CompletionList | null | undefined>(r)) { if (isThenable<CompletionItem[] | CompletionList | null | undefined>(r)) {
return r.then(updateProposals); return r.then(updateProposals);
} }
return updateProposals(r); return updateProposals(r);
},
provideHover(document: TextDocument, position: Position, token: CancellationToken, next: ProvideHoverSignature) {
function updateHover(r: Hover | null | undefined): Hover | null | undefined {
if (r && Array.isArray(r.contents)) {
r.contents = r.contents.map(h => h instanceof MarkdownString ? updateMarkdownString(h) : h);
}
return r;
}
const r = next(document, position, token);
if (isThenable<Hover | null | undefined>(r)) {
return r.then(updateHover);
}
return updateHover(r);
} }
} }
}; };
@@ -492,3 +508,13 @@ function readJSONFile(location: string) {
return {}; return {};
} }
} }
function isThenable<T>(obj: ProviderResult<T>): obj is Thenable<T> {
return obj && (<any>obj)['then'];
}
function updateMarkdownString(h: MarkdownString): MarkdownString {
const n = new MarkdownString(h.value, true);
n.isTrusted = h.isTrusted;
return n;
}

View File

@@ -22,13 +22,13 @@
"extensions": [ "extensions": [
".json", ".json",
".bowerrc", ".bowerrc",
".jshintrc",
".jscsrc", ".jscsrc",
".swcrc",
".webmanifest", ".webmanifest",
".js.map", ".js.map",
".css.map", ".css.map",
".har" ".har",
".jslintrc",
".jsonld"
], ],
"filenames": [ "filenames": [
"composer.lock", "composer.lock",
@@ -51,7 +51,10 @@
".babelrc", ".babelrc",
".jsonc", ".jsonc",
".eslintrc", ".eslintrc",
".eslintrc.json" ".eslintrc.json",
".jsfmtrc",
".jshintrc",
".swcrc"
], ],
"configuration": "./language-configuration.json" "configuration": "./language-configuration.json"
} }

View File

@@ -68,7 +68,8 @@ function createContext(): TestContext {
packageJSON: '', packageJSON: '',
extensionKind: vscode.ExtensionKind.UI, extensionKind: vscode.ExtensionKind.UI,
exports: extensionApi, exports: extensionApi,
activate: () => {return Promise.resolve();} activate: () => {return Promise.resolve();},
extensionUri: vscode.Uri.parse('')
}, },
apiWrapper: TypeMoq.Mock.ofType(ApiWrapper), apiWrapper: TypeMoq.Mock.ofType(ApiWrapper),
queryRunner: TypeMoq.Mock.ofType(QueryRunner), queryRunner: TypeMoq.Mock.ofType(QueryRunner),
@@ -88,7 +89,8 @@ function createContext(): TestContext {
asAbsolutePath: () => {return '';}, asAbsolutePath: () => {return '';},
storagePath: '', storagePath: '',
globalStoragePath: '', globalStoragePath: '',
logPath: '' logPath: '',
extensionUri: vscode.Uri.parse('')
}, },
outputChannel: { outputChannel: {
name: '', name: '',
@@ -106,7 +108,8 @@ function createContext(): TestContext {
packageJSON: {}, packageJSON: {},
extensionKind: vscode.ExtensionKind.UI, extensionKind: vscode.ExtensionKind.UI,
exports: {}, exports: {},
activate: () => { return Promise.resolve(); } activate: () => { return Promise.resolve(); },
extensionUri: vscode.Uri.parse('')
}, },
workspaceConfig: { workspaceConfig: {
get: () => {return 'value';}, get: () => {return 'value';},

View File

@@ -33,7 +33,7 @@ describe('Dashboard widget', () => {
let testContext = createContext(); let testContext = createContext();
const dashboard = new DashboardWidget(testContext.apiWrapper.object, ''); const dashboard = new DashboardWidget(testContext.apiWrapper.object, '');
dashboard.register(); dashboard.register();
testContext.onClick.fire(); testContext.onClick.fire(undefined);
testContext.apiWrapper.verify(x => x.executeCommand(TypeMoq.It.isAny()), TypeMoq.Times.atLeastOnce()); testContext.apiWrapper.verify(x => x.executeCommand(TypeMoq.It.isAny()), TypeMoq.Times.atLeastOnce());
}); });
}); });

View File

@@ -111,7 +111,7 @@ describe('Add Edit External Languages Tab', () => {
}); });
}); });
testContext.onClick.fire(); testContext.onClick.fire(undefined);
parent.onUpdatedLanguage(languageUpdateModel); parent.onUpdatedLanguage(languageUpdateModel);
await promise; await promise;
should.equal(updateCalled, true); should.equal(updateCalled, true);

View File

@@ -183,7 +183,7 @@ describe('Predict Wizard', () => {
view.modelBrowsePage.modelSourceType = ModelSourceType.RegisteredModels; view.modelBrowsePage.modelSourceType = ModelSourceType.RegisteredModels;
} }
await view.refresh(); await view.refresh();
testContext.onClick.fire(); testContext.onClick.fire(undefined);
should.equal(view.modelSourcePage?.data, ModelSourceType.RegisteredModels); should.equal(view.modelSourcePage?.data, ModelSourceType.RegisteredModels);
should.notEqual(view.localModelsComponent?.data, undefined); should.notEqual(view.localModelsComponent?.data, undefined);

View File

@@ -85,11 +85,11 @@
"snippets": [ "snippets": [
{ {
"language": "markdown", "language": "markdown",
"path": "./snippets/markdown.json" "path": "./snippets/markdown.code-snippets"
} }
] ]
}, },
"scripts": { "scripts": {
"update-grammar": "node ../../build/npm/update-grammar.js microsoft/vscode-markdown-tm-grammar syntaxes/markdown.tmLanguage ./syntaxes/markdown.tmLanguage.json" "update-grammar": "node ../../build/npm/update-grammar.js microsoft/vscode-markdown-tm-grammar syntaxes/markdown.tmLanguage ./syntaxes/markdown.tmLanguage.json"
} }
} }

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -18,8 +18,8 @@ const settings = getSettings();
const vscode = acquireVsCodeApi(); const vscode = acquireVsCodeApi();
// Set VS Code state const state = { ...vscode.getState(), ...getData<any>('data-state') };
let state = getData<{ line: number; fragment: string; }>('data-state'); // Make sure to sync VS Code state here
vscode.setState(state); vscode.setState(state);
const messaging = createPosterForVsCode(vscode); const messaging = createPosterForVsCode(vscode);
@@ -32,23 +32,35 @@ window.onload = () => {
}; };
onceDocumentLoaded(() => { onceDocumentLoaded(() => {
const scrollProgress = state.scrollProgress;
if (typeof scrollProgress === 'number' && !settings.fragment) {
setImmediate(() => {
scrollDisabled = true;
window.scrollTo(0, scrollProgress * document.body.clientHeight);
});
return;
}
if (settings.scrollPreviewWithEditor) { if (settings.scrollPreviewWithEditor) {
setTimeout(() => { setImmediate(() => {
// Try to scroll to fragment if available // Try to scroll to fragment if available
if (state.fragment) { if (settings.fragment) {
const element = getLineElementForFragment(state.fragment); state.fragment = undefined;
vscode.setState(state);
const element = getLineElementForFragment(settings.fragment);
if (element) { if (element) {
scrollDisabled = true; scrollDisabled = true;
scrollToRevealSourceLine(element.line); scrollToRevealSourceLine(element.line);
} }
} else { } else {
const initialLine = +settings.line; if (!isNaN(settings.line!)) {
if (!isNaN(initialLine)) {
scrollDisabled = true; scrollDisabled = true;
scrollToRevealSourceLine(initialLine); scrollToRevealSourceLine(settings.line!);
} }
} }
}, 0); });
} }
}); });
@@ -58,9 +70,10 @@ const onUpdateView = (() => {
scrollToRevealSourceLine(line); scrollToRevealSourceLine(line);
}, 50); }, 50);
return (line: number, settings: any) => { return (line: number) => {
if (!isNaN(line)) { if (!isNaN(line)) {
settings.line = line; state.line = line;
doScroll(line); doScroll(line);
} }
}; };
@@ -91,6 +104,7 @@ let updateImageSizes = throttle(() => {
window.addEventListener('resize', () => { window.addEventListener('resize', () => {
scrollDisabled = true; scrollDisabled = true;
updateScrollProgress();
updateImageSizes(); updateImageSizes();
}, true); }, true);
@@ -105,7 +119,7 @@ window.addEventListener('message', event => {
break; break;
case 'updateView': case 'updateView':
onUpdateView(event.data.line, settings); onUpdateView(event.data.line);
break; break;
} }
}, false); }, false);
@@ -165,15 +179,20 @@ document.addEventListener('click', event => {
}, true); }, true);
window.addEventListener('scroll', throttle(() => { window.addEventListener('scroll', throttle(() => {
updateScrollProgress();
if (scrollDisabled) { if (scrollDisabled) {
scrollDisabled = false; scrollDisabled = false;
} else { } else {
const line = getEditorLineNumberForPageOffset(window.scrollY); const line = getEditorLineNumberForPageOffset(window.scrollY);
if (typeof line === 'number' && !isNaN(line)) { if (typeof line === 'number' && !isNaN(line)) {
messaging.postMessage('revealLine', { line }); messaging.postMessage('revealLine', { line });
state.line = line;
vscode.setState(state);
} }
} }
}, 50)); }, 50));
function updateScrollProgress() {
state.scrollProgress = window.scrollY / document.body.clientHeight;
vscode.setState(state);
}

View File

@@ -5,7 +5,8 @@
export interface PreviewSettings { export interface PreviewSettings {
readonly source: string; readonly source: string;
readonly line: number; readonly line?: number;
readonly fragment?: string
readonly lineCount: number; readonly lineCount: number;
readonly scrollPreviewWithEditor?: boolean; readonly scrollPreviewWithEditor?: boolean;
readonly scrollEditorWithPreview: boolean; readonly scrollEditorWithPreview: boolean;

View File

@@ -66,6 +66,11 @@ export class OpenDocumentLinkCommand implements Command {
} }
} }
const stat = await vscode.workspace.fs.stat(resource);
if (stat.type === vscode.FileType.Directory) {
return vscode.commands.executeCommand('revealInExplorer', resource);
}
return vscode.workspace.openTextDocument(resource) return vscode.workspace.openTextDocument(resource)
.then(document => vscode.window.showTextDocument(document, column)) .then(document => vscode.window.showTextDocument(document, column))
.then(editor => this.tryRevealLine(editor, args.fragment)); .then(editor => this.tryRevealLine(editor, args.fragment));

View File

@@ -13,7 +13,7 @@ import { Disposable } from '../util/dispose';
import * as nls from 'vscode-nls'; import * as nls from 'vscode-nls';
import { getVisibleLine, TopmostLineMonitor } from '../util/topmostLineMonitor'; import { getVisibleLine, TopmostLineMonitor } from '../util/topmostLineMonitor';
import { MarkdownPreviewConfigurationManager } from './previewConfig'; import { MarkdownPreviewConfigurationManager } from './previewConfig';
import { MarkdownContributionProvider, MarkdownContributions } from '../markdownExtensions'; import { MarkdownContributionProvider } from '../markdownExtensions';
import { isMarkdownFile } from '../util/file'; import { isMarkdownFile } from '../util/file';
import { resolveLinkToMarkdownFile } from '../commands/openDocumentLink'; import { resolveLinkToMarkdownFile } from '../commands/openDocumentLink';
import { WebviewResourceProvider, normalizeResource } from '../util/resources'; import { WebviewResourceProvider, normalizeResource } from '../util/resources';
@@ -61,10 +61,14 @@ interface PreviewStyleLoadErrorMessage extends WebviewMessage {
} }
export class PreviewDocumentVersion { export class PreviewDocumentVersion {
public constructor(
public readonly resource: vscode.Uri, private readonly resource: vscode.Uri;
public readonly version: number, private readonly version: number;
) { }
public constructor(document: vscode.TextDocument) {
this.resource = document.uri;
this.version = document.version;
}
public equals(other: PreviewDocumentVersion): boolean { public equals(other: PreviewDocumentVersion): boolean {
return this.resource.fsPath === other.resource.fsPath return this.resource.fsPath === other.resource.fsPath
@@ -72,102 +76,86 @@ export class PreviewDocumentVersion {
} }
} }
interface DynamicPreviewInput { interface MarkdownPreviewDelegate {
readonly resource: vscode.Uri; getTitle?(resource: vscode.Uri): string;
readonly resourceColumn: vscode.ViewColumn; getAdditionalState(): {},
readonly locked: boolean; openPreviewLinkToMarkdownFile(markdownLink: vscode.Uri, fragment: string): void;
readonly line?: number;
} }
export class DynamicMarkdownPreview extends Disposable { class StartingScrollLine {
public readonly type = 'line';
public static readonly viewType = 'markdown.preview'; constructor(
public readonly line: number,
) { }
}
class StartingScrollFragment {
public readonly type = 'fragment';
constructor(
public readonly fragment: string,
) { }
}
type StartingScrollLocation = StartingScrollLine | StartingScrollFragment;
class MarkdownPreview extends Disposable implements WebviewResourceProvider {
private readonly delay = 300; private readonly delay = 300;
private _resource: vscode.Uri; private readonly _resource: vscode.Uri;
private readonly _resourceColumn: vscode.ViewColumn; private readonly _webviewPanel: vscode.WebviewPanel;
private _locked: boolean;
private readonly editor: vscode.WebviewPanel;
private throttleTimer: any; private throttleTimer: any;
private line: number | undefined = undefined;
private line: number | undefined;
private scrollToFragment: string | undefined;
private firstUpdate = true; private firstUpdate = true;
private currentVersion?: PreviewDocumentVersion; private currentVersion?: PreviewDocumentVersion;
private isScrolling = false; private isScrolling = false;
private _disposed: boolean = false; private _disposed: boolean = false;
private imageInfo: { id: string, width: number, height: number; }[] = []; private imageInfo: { readonly id: string, readonly width: number, readonly height: number; }[] = [];
private scrollToFragment: string | undefined;
public static revive( constructor(
input: DynamicPreviewInput,
webview: vscode.WebviewPanel, webview: vscode.WebviewPanel,
contentProvider: MarkdownContentProvider, resource: vscode.Uri,
previewConfigurations: MarkdownPreviewConfigurationManager, startingScroll: StartingScrollLocation | undefined,
logger: Logger, private readonly delegate: MarkdownPreviewDelegate,
topmostLineMonitor: TopmostLineMonitor,
contributionProvider: MarkdownContributionProvider,
): DynamicMarkdownPreview {
webview.webview.options = DynamicMarkdownPreview.getWebviewOptions(input.resource, contributionProvider.contributions);
webview.title = DynamicMarkdownPreview.getPreviewTitle(input.resource, input.locked);
return new DynamicMarkdownPreview(webview, input,
contentProvider, previewConfigurations, logger, topmostLineMonitor, contributionProvider);
}
public static create(
input: DynamicPreviewInput,
previewColumn: vscode.ViewColumn,
contentProvider: MarkdownContentProvider,
previewConfigurations: MarkdownPreviewConfigurationManager,
logger: Logger,
topmostLineMonitor: TopmostLineMonitor,
contributionProvider: MarkdownContributionProvider
): DynamicMarkdownPreview {
const webview = vscode.window.createWebviewPanel(
DynamicMarkdownPreview.viewType,
DynamicMarkdownPreview.getPreviewTitle(input.resource, input.locked),
previewColumn, {
enableFindWidget: true,
...DynamicMarkdownPreview.getWebviewOptions(input.resource, contributionProvider.contributions)
});
return new DynamicMarkdownPreview(webview, input,
contentProvider, previewConfigurations, logger, topmostLineMonitor, contributionProvider);
}
private constructor(
webview: vscode.WebviewPanel,
input: DynamicPreviewInput,
private readonly _contentProvider: MarkdownContentProvider, private readonly _contentProvider: MarkdownContentProvider,
private readonly _previewConfigurations: MarkdownPreviewConfigurationManager, private readonly _previewConfigurations: MarkdownPreviewConfigurationManager,
private readonly _logger: Logger, private readonly _logger: Logger,
topmostLineMonitor: TopmostLineMonitor,
private readonly _contributionProvider: MarkdownContributionProvider, private readonly _contributionProvider: MarkdownContributionProvider,
) { ) {
super(); super();
this._resource = input.resource;
this._resourceColumn = input.resourceColumn; this._webviewPanel = webview;
this._locked = input.locked; this._resource = resource;
this.editor = webview;
if (!isNaN(input.line!)) { switch (startingScroll?.type) {
this.line = input.line; case 'line':
if (!isNaN(startingScroll.line!)) {
this.line = startingScroll.line;
}
break;
case 'fragment':
this.scrollToFragment = startingScroll.fragment;
break;
} }
this._register(this.editor.onDidDispose(() => {
this.dispose();
}));
this._register(this.editor.onDidChangeViewState(e => {
this._onDidChangeViewStateEmitter.fire(e);
}));
this._register(_contributionProvider.onContributionsChanged(() => { this._register(_contributionProvider.onContributionsChanged(() => {
setImmediate(() => this.refresh()); setImmediate(() => this.refresh());
})); }));
this._register(this.editor.webview.onDidReceiveMessage((e: CacheImageSizesMessage | RevealLineMessage | DidClickMessage | ClickLinkMessage | ShowPreviewSecuritySelectorMessage | PreviewStyleLoadErrorMessage) => { this._register(vscode.workspace.onDidChangeTextDocument(event => {
if (this.isPreviewOf(event.document.uri)) {
this.refresh();
}
}));
this._register(this._webviewPanel.webview.onDidReceiveMessage((e: CacheImageSizesMessage | RevealLineMessage | DidClickMessage | ClickLinkMessage | ShowPreviewSecuritySelectorMessage | PreviewStyleLoadErrorMessage) => {
if (e.source !== this._resource.toString()) { if (e.source !== this._resource.toString()) {
return; return;
} }
@@ -194,158 +182,50 @@ export class DynamicMarkdownPreview extends Disposable {
break; break;
case 'previewStyleLoadError': case 'previewStyleLoadError':
vscode.window.showWarningMessage(localize('onPreviewStyleLoadError', "Could not load 'markdown.styles': {0}", e.body.unloadedStyles.join(', '))); vscode.window.showWarningMessage(
localize('onPreviewStyleLoadError',
"Could not load 'markdown.styles': {0}",
e.body.unloadedStyles.join(', ')));
break; break;
} }
})); }));
this._register(vscode.workspace.onDidChangeTextDocument(event => { this.updatePreview();
if (this.isPreviewOf(event.document.uri)) {
this.refresh();
}
}));
this._register(topmostLineMonitor.onDidChanged(event => {
if (this.isPreviewOf(event.resource)) {
this.updateForView(event.resource, event.line);
}
}));
this._register(vscode.window.onDidChangeTextEditorSelection(event => {
if (this.isPreviewOf(event.textEditor.document.uri)) {
this.postMessage({
type: 'onDidChangeTextEditorSelection',
line: event.selections[0].active.line,
source: this.resource.toString()
});
}
}));
this._register(vscode.window.onDidChangeActiveTextEditor(editor => {
if (editor && isMarkdownFile(editor.document) && !this._locked) {
this.update(editor.document.uri, false);
}
}));
this.doUpdate();
} }
private readonly _onDisposeEmitter = this._register(new vscode.EventEmitter<void>()); dispose() {
public readonly onDispose = this._onDisposeEmitter.event; super.dispose();
this._disposed = true;
private readonly _onDidChangeViewStateEmitter = this._register(new vscode.EventEmitter<vscode.WebviewPanelOnDidChangeViewStateEvent>()); clearTimeout(this.throttleTimer);
public readonly onDidChangeViewState = this._onDidChangeViewStateEmitter.event; }
public get resource(): vscode.Uri { public get resource(): vscode.Uri {
return this._resource; return this._resource;
} }
public get resourceColumn(): vscode.ViewColumn {
return this._resourceColumn;
}
public get state() { public get state() {
return { return {
resource: this.resource.toString(), resource: this._resource.toString(),
locked: this._locked,
line: this.line, line: this.line,
resourceColumn: this.resourceColumn,
imageInfo: this.imageInfo, imageInfo: this.imageInfo,
fragment: this.scrollToFragment fragment: this.scrollToFragment,
...this.delegate.getAdditionalState(),
}; };
} }
public dispose() { public refresh() {
if (this._disposed) {
return;
}
this._disposed = true;
this._onDisposeEmitter.fire();
this._onDisposeEmitter.dispose();
this.editor.dispose();
super.dispose();
}
public update(resource: vscode.Uri, isRefresh = true) {
// Reposition scroll preview, position scroll to the top if active text editor
// doesn't corresponds with preview
const editor = vscode.window.activeTextEditor;
if (editor) {
if (!isRefresh || this._previewConfigurations.loadAndCacheConfiguration(this._resource).scrollEditorWithPreview) {
if (editor.document.uri.fsPath === resource.fsPath) {
this.line = getVisibleLine(editor);
} else {
this.line = 0;
}
}
}
// If we have changed resources, cancel any pending updates
const isResourceChange = resource.fsPath !== this._resource.fsPath;
if (isResourceChange) {
clearTimeout(this.throttleTimer);
this.throttleTimer = undefined;
}
this._resource = resource;
// Schedule update if none is pending // Schedule update if none is pending
if (!this.throttleTimer) { if (!this.throttleTimer) {
if (isResourceChange || this.firstUpdate) { if (this.firstUpdate) {
this.doUpdate(isRefresh); this.updatePreview(true);
} else { } else {
this.throttleTimer = setTimeout(() => this.doUpdate(isRefresh), this.delay); this.throttleTimer = setTimeout(() => this.updatePreview(true), this.delay);
} }
} }
this.firstUpdate = false; this.firstUpdate = false;
} }
public refresh() {
this.update(this._resource, true);
}
public updateConfiguration() {
if (this._previewConfigurations.hasConfigurationChanged(this._resource)) {
this.refresh();
}
}
public get position(): vscode.ViewColumn | undefined {
return this.editor.viewColumn;
}
public matchesResource(
otherResource: vscode.Uri,
otherPosition: vscode.ViewColumn | undefined,
otherLocked: boolean
): boolean {
if (this.position !== otherPosition) {
return false;
}
if (this._locked) {
return otherLocked && this.isPreviewOf(otherResource);
} else {
return !otherLocked;
}
}
public matches(otherPreview: DynamicMarkdownPreview): boolean {
return this.matchesResource(otherPreview._resource, otherPreview.position, otherPreview._locked);
}
public reveal(viewColumn: vscode.ViewColumn) {
this.editor.reveal(viewColumn);
}
public toggleLock() {
this._locked = !this._locked;
this.editor.title = DynamicMarkdownPreview.getPreviewTitle(this._resource, this._locked);
}
private get iconPath() { private get iconPath() {
const root = path.join(this._contributionProvider.extensionPath, 'media'); const root = path.join(this._contributionProvider.extensionPath, 'media');
return { return {
@@ -354,18 +234,18 @@ export class DynamicMarkdownPreview extends Disposable {
}; };
} }
private isPreviewOf(resource: vscode.Uri): boolean { public isPreviewOf(resource: vscode.Uri): boolean {
return this._resource.fsPath === resource.fsPath; return this._resource.fsPath === resource.fsPath;
} }
private static getPreviewTitle(resource: vscode.Uri, locked: boolean): string { public postMessage(msg: any) {
return locked if (!this._disposed) {
? localize('lockedPreviewTitle', '[Preview] {0}', path.basename(resource.fsPath)) this._webviewPanel.webview.postMessage(msg);
: localize('previewTitle', 'Preview {0}', path.basename(resource.fsPath)); }
} }
private updateForView(resource: vscode.Uri, topLine: number | undefined) { public scrollTo(topLine: number) {
if (!this.isPreviewOf(resource)) { if (this._disposed) {
return; return;
} }
@@ -374,36 +254,26 @@ export class DynamicMarkdownPreview extends Disposable {
return; return;
} }
if (typeof topLine === 'number') { this._logger.log('updateForView', { markdownFile: this._resource });
this._logger.log('updateForView', { markdownFile: resource }); this.line = topLine;
this.line = topLine; this.postMessage({
this.postMessage({ type: 'updateView',
type: 'updateView', line: topLine,
line: topLine, source: this._resource.toString()
source: resource.toString() });
});
}
} }
private postMessage(msg: any) { private async updatePreview(forceUpdate?: boolean): Promise<void> {
if (!this._disposed) { clearTimeout(this.throttleTimer);
this.editor.webview.postMessage(msg); this.throttleTimer = undefined;
}
}
private async doUpdate(forceUpdate?: boolean): Promise<void> {
if (this._disposed) { if (this._disposed) {
return; return;
} }
const markdownResource = this._resource;
clearTimeout(this.throttleTimer);
this.throttleTimer = undefined;
let document: vscode.TextDocument; let document: vscode.TextDocument;
try { try {
document = await vscode.workspace.openTextDocument(markdownResource); document = await vscode.workspace.openTextDocument(this._resource);
} catch { } catch {
await this.showFileNotFoundError(); await this.showFileNotFoundError();
return; return;
@@ -413,61 +283,24 @@ export class DynamicMarkdownPreview extends Disposable {
return; return;
} }
const pendingVersion = new PreviewDocumentVersion(markdownResource, document.version); const pendingVersion = new PreviewDocumentVersion(document);
if (!forceUpdate && this.currentVersion?.equals(pendingVersion)) { if (!forceUpdate && this.currentVersion?.equals(pendingVersion)) {
if (this.line) { if (this.line) {
this.updateForView(markdownResource, this.line); this.scrollTo(this.line);
} }
return; return;
} }
this.currentVersion = pendingVersion; this.currentVersion = pendingVersion;
if (this._resource === markdownResource) { const content = await this._contentProvider.provideTextDocumentContent(document, this, this._previewConfigurations, this.line, this.state);
const self = this;
const resourceProvider: WebviewResourceProvider = { // Another call to `doUpdate` may have happened.
asWebviewUri: (resource) => { // Make sure we are still updating for the correct document
return this.editor.webview.asWebviewUri(normalizeResource(markdownResource, resource)); if (this.currentVersion?.equals(pendingVersion)) {
}, this.setContent(content);
get cspSource() { return self.editor.webview.cspSource; }
};
const content = await this._contentProvider.provideTextDocumentContent(document, resourceProvider, this._previewConfigurations, this.line, this.state);
// Another call to `doUpdate` may have happened.
// Make sure we are still updating for the correct document
if (this.currentVersion && this.currentVersion.equals(pendingVersion)) {
this.setContent(content);
}
} }
} }
private static getWebviewOptions(
resource: vscode.Uri,
contributions: MarkdownContributions
): vscode.WebviewOptions {
return {
enableScripts: true,
localResourceRoots: DynamicMarkdownPreview.getLocalResourceRoots(resource, contributions)
};
}
private static getLocalResourceRoots(
base: vscode.Uri,
contributions: MarkdownContributions
): ReadonlyArray<vscode.Uri> {
const baseRoots = Array.from(contributions.previewResourceRoots);
const folder = vscode.workspace.getWorkspaceFolder(base);
if (folder) {
const workspaceRoots = vscode.workspace.workspaceFolders?.map(folder => folder.uri);
if (workspaceRoots) {
baseRoots.push(...workspaceRoots);
}
} else if (!base.scheme || base.scheme === 'file') {
baseRoots.push(vscode.Uri.file(path.dirname(base.fsPath)));
}
return baseRoots.map(root => normalizeResource(base, root));
}
private onDidScrollPreview(line: number) { private onDidScrollPreview(line: number) {
this.line = line; this.line = line;
@@ -513,23 +346,55 @@ export class DynamicMarkdownPreview extends Disposable {
} }
private async showFileNotFoundError() { private async showFileNotFoundError() {
this.setContent(this._contentProvider.provideFileNotFoundContent(this._resource)); this._webviewPanel.webview.html = this._contentProvider.provideFileNotFoundContent(this._resource);
} }
private setContent(html: string): void { private setContent(html: string): void {
this.editor.title = DynamicMarkdownPreview.getPreviewTitle(this._resource, this._locked); if (this._disposed) {
this.editor.iconPath = this.iconPath; return;
this.editor.webview.options = DynamicMarkdownPreview.getWebviewOptions(this._resource, this._contributionProvider.contributions); }
this.editor.webview.html = html;
if (this.delegate.getTitle) {
this._webviewPanel.title = this.delegate.getTitle(this._resource);
}
this._webviewPanel.iconPath = this.iconPath;
this._webviewPanel.webview.options = this.getWebviewOptions();
this._webviewPanel.webview.html = html;
} }
private getWebviewOptions(): vscode.WebviewOptions {
return {
enableScripts: true,
localResourceRoots: this.getLocalResourceRoots()
};
}
private getLocalResourceRoots(): ReadonlyArray<vscode.Uri> {
const baseRoots = Array.from(this._contributionProvider.contributions.previewResourceRoots);
const folder = vscode.workspace.getWorkspaceFolder(this._resource);
if (folder) {
const workspaceRoots = vscode.workspace.workspaceFolders?.map(folder => folder.uri);
if (workspaceRoots) {
baseRoots.push(...workspaceRoots);
}
} else if (!this._resource.scheme || this._resource.scheme === 'file') {
baseRoots.push(vscode.Uri.file(path.dirname(this._resource.fsPath)));
}
return baseRoots.map(root => normalizeResource(this._resource, root));
}
private async onDidClickPreviewLink(href: string) { private async onDidClickPreviewLink(href: string) {
let [hrefPath, fragment] = decodeURIComponent(href).split('#'); let [hrefPath, fragment] = decodeURIComponent(href).split('#');
// We perviously already resolve absolute paths. // We perviously already resolve absolute paths.
// Now make sure we handle relative file paths // Now make sure we handle relative file paths
if (hrefPath[0] !== '/') { if (hrefPath[0] !== '/') {
hrefPath = path.join(path.dirname(this.resource.path), hrefPath); // Fix #93691, use this.resource.fsPath instead of this.resource.path
hrefPath = path.join(path.dirname(this.resource.fsPath), hrefPath);
} }
const config = vscode.workspace.getConfiguration('markdown', this.resource); const config = vscode.workspace.getConfiguration('markdown', this.resource);
@@ -537,14 +402,332 @@ export class DynamicMarkdownPreview extends Disposable {
if (openLinks === 'inPreview') { if (openLinks === 'inPreview') {
const markdownLink = await resolveLinkToMarkdownFile(hrefPath); const markdownLink = await resolveLinkToMarkdownFile(hrefPath);
if (markdownLink) { if (markdownLink) {
if (fragment) { this.delegate.openPreviewLinkToMarkdownFile(markdownLink, fragment);
this.scrollToFragment = fragment;
}
this.update(markdownLink);
return; return;
} }
} }
vscode.commands.executeCommand('_markdown.openDocumentLink', { path: hrefPath, fragment, fromResource: this.resource }); vscode.commands.executeCommand('_markdown.openDocumentLink', { path: hrefPath, fragment, fromResource: this.resource });
} }
//#region WebviewResourceProvider
asWebviewUri(resource: vscode.Uri) {
return this._webviewPanel.webview.asWebviewUri(normalizeResource(this._resource, resource));
}
get cspSource() {
return this._webviewPanel.webview.cspSource;
}
//#endregion
} }
export interface ManagedMarkdownPreview {
readonly resource: vscode.Uri;
readonly resourceColumn: vscode.ViewColumn;
readonly onDispose: vscode.Event<void>;
readonly onDidChangeViewState: vscode.Event<vscode.WebviewPanelOnDidChangeViewStateEvent>;
dispose(): void;
refresh(): void;
updateConfiguration(): void;
matchesResource(
otherResource: vscode.Uri,
otherPosition: vscode.ViewColumn | undefined,
otherLocked: boolean
): boolean;
}
export class StaticMarkdownPreview extends Disposable implements ManagedMarkdownPreview {
public static revive(
resource: vscode.Uri,
webview: vscode.WebviewPanel,
contentProvider: MarkdownContentProvider,
previewConfigurations: MarkdownPreviewConfigurationManager,
logger: Logger,
contributionProvider: MarkdownContributionProvider,
): StaticMarkdownPreview {
return new StaticMarkdownPreview(webview, resource, contentProvider, previewConfigurations, logger, contributionProvider);
}
private readonly preview: MarkdownPreview;
private constructor(
private readonly _webviewPanel: vscode.WebviewPanel,
resource: vscode.Uri,
contentProvider: MarkdownContentProvider,
private readonly _previewConfigurations: MarkdownPreviewConfigurationManager,
logger: Logger,
contributionProvider: MarkdownContributionProvider,
) {
super();
this.preview = this._register(new MarkdownPreview(this._webviewPanel, resource, undefined, {
getAdditionalState: () => { return {}; },
openPreviewLinkToMarkdownFile: () => { /* todo */ }
}, contentProvider, _previewConfigurations, logger, contributionProvider));
this._register(this._webviewPanel.onDidDispose(() => {
this.dispose();
}));
this._register(this._webviewPanel.onDidChangeViewState(e => {
this._onDidChangeViewState.fire(e);
}));
}
private readonly _onDispose = this._register(new vscode.EventEmitter<void>());
public readonly onDispose = this._onDispose.event;
private readonly _onDidChangeViewState = this._register(new vscode.EventEmitter<vscode.WebviewPanelOnDidChangeViewStateEvent>());
public readonly onDidChangeViewState = this._onDidChangeViewState.event;
dispose() {
this._onDispose.fire();
super.dispose();
}
public matchesResource(
_otherResource: vscode.Uri,
_otherPosition: vscode.ViewColumn | undefined,
_otherLocked: boolean
): boolean {
return false;
}
public refresh() {
this.preview.refresh();
}
public updateConfiguration() {
if (this._previewConfigurations.hasConfigurationChanged(this.preview.resource)) {
this.refresh();
}
}
public get resource() {
return this.preview.resource;
}
public get resourceColumn() {
return this._webviewPanel.viewColumn || vscode.ViewColumn.One;
}
}
interface DynamicPreviewInput {
readonly resource: vscode.Uri;
readonly resourceColumn: vscode.ViewColumn;
readonly locked: boolean;
readonly line?: number;
}
/**
* A
*/
export class DynamicMarkdownPreview extends Disposable implements ManagedMarkdownPreview {
public static readonly viewType = 'markdown.preview';
private readonly _resourceColumn: vscode.ViewColumn;
private _locked: boolean;
private readonly _webviewPanel: vscode.WebviewPanel;
private _preview: MarkdownPreview;
public static revive(
input: DynamicPreviewInput,
webview: vscode.WebviewPanel,
contentProvider: MarkdownContentProvider,
previewConfigurations: MarkdownPreviewConfigurationManager,
logger: Logger,
topmostLineMonitor: TopmostLineMonitor,
contributionProvider: MarkdownContributionProvider,
): DynamicMarkdownPreview {
return new DynamicMarkdownPreview(webview, input,
contentProvider, previewConfigurations, logger, topmostLineMonitor, contributionProvider);
}
public static create(
input: DynamicPreviewInput,
previewColumn: vscode.ViewColumn,
contentProvider: MarkdownContentProvider,
previewConfigurations: MarkdownPreviewConfigurationManager,
logger: Logger,
topmostLineMonitor: TopmostLineMonitor,
contributionProvider: MarkdownContributionProvider
): DynamicMarkdownPreview {
const webview = vscode.window.createWebviewPanel(
DynamicMarkdownPreview.viewType,
DynamicMarkdownPreview.getPreviewTitle(input.resource, input.locked),
previewColumn, { enableFindWidget: true, });
return new DynamicMarkdownPreview(webview, input,
contentProvider, previewConfigurations, logger, topmostLineMonitor, contributionProvider);
}
private constructor(
webview: vscode.WebviewPanel,
input: DynamicPreviewInput,
private readonly _contentProvider: MarkdownContentProvider,
private readonly _previewConfigurations: MarkdownPreviewConfigurationManager,
private readonly _logger: Logger,
private readonly _topmostLineMonitor: TopmostLineMonitor,
private readonly _contributionProvider: MarkdownContributionProvider,
) {
super();
this._webviewPanel = webview;
this._resourceColumn = input.resourceColumn;
this._locked = input.locked;
this._preview = this.createPreview(input.resource, typeof input.line === 'number' ? new StartingScrollLine(input.line) : undefined);
this._register(webview.onDidDispose(() => { this.dispose(); }));
this._register(this._webviewPanel.onDidChangeViewState(e => {
this._onDidChangeViewStateEmitter.fire(e);
}));
this._register(this._topmostLineMonitor.onDidChanged(event => {
if (this._preview.isPreviewOf(event.resource)) {
this._preview.scrollTo(event.line);
}
}));
this._register(vscode.window.onDidChangeTextEditorSelection(event => {
if (this._preview.isPreviewOf(event.textEditor.document.uri)) {
this._preview.postMessage({
type: 'onDidChangeTextEditorSelection',
line: event.selections[0].active.line,
source: this._preview.resource.toString()
});
}
}));
this._register(vscode.window.onDidChangeActiveTextEditor(editor => {
if (editor && isMarkdownFile(editor.document) && !this._locked && !this._preview.isPreviewOf(editor.document.uri)) {
const line = getVisibleLine(editor);
this.update(editor.document.uri, line ? new StartingScrollLine(line) : undefined);
}
}));
}
private readonly _onDisposeEmitter = this._register(new vscode.EventEmitter<void>());
public readonly onDispose = this._onDisposeEmitter.event;
private readonly _onDidChangeViewStateEmitter = this._register(new vscode.EventEmitter<vscode.WebviewPanelOnDidChangeViewStateEvent>());
public readonly onDidChangeViewState = this._onDidChangeViewStateEmitter.event;
dispose() {
this._preview.dispose();
this._webviewPanel.dispose();
this._onDisposeEmitter.fire();
this._onDisposeEmitter.dispose();
super.dispose();
}
public get resource() {
return this._preview.resource;
}
public get resourceColumn() {
return this._resourceColumn;
}
public reveal(viewColumn: vscode.ViewColumn) {
this._webviewPanel.reveal(viewColumn);
}
public refresh() {
this._preview.refresh();
}
public updateConfiguration() {
if (this._previewConfigurations.hasConfigurationChanged(this._preview.resource)) {
this.refresh();
}
}
public update(newResource: vscode.Uri, scrollLocation?: StartingScrollLocation) {
if (this._preview.isPreviewOf(newResource)) {
switch (scrollLocation?.type) {
case 'line':
this._preview.scrollTo(scrollLocation.line);
return;
case 'fragment':
// Workaround. For fragments, just reload the entire preview
break;
default:
return;
}
}
this._preview.dispose();
this._preview = this.createPreview(newResource, scrollLocation);
}
public toggleLock() {
this._locked = !this._locked;
this._webviewPanel.title = DynamicMarkdownPreview.getPreviewTitle(this._preview.resource, this._locked);
}
private static getPreviewTitle(resource: vscode.Uri, locked: boolean): string {
return locked
? localize('lockedPreviewTitle', '[Preview] {0}', path.basename(resource.fsPath))
: localize('previewTitle', 'Preview {0}', path.basename(resource.fsPath));
}
public get position(): vscode.ViewColumn | undefined {
return this._webviewPanel.viewColumn;
}
public matchesResource(
otherResource: vscode.Uri,
otherPosition: vscode.ViewColumn | undefined,
otherLocked: boolean
): boolean {
if (this.position !== otherPosition) {
return false;
}
if (this._locked) {
return otherLocked && this._preview.isPreviewOf(otherResource);
} else {
return !otherLocked;
}
}
public matches(otherPreview: DynamicMarkdownPreview): boolean {
return this.matchesResource(otherPreview._preview.resource, otherPreview.position, otherPreview._locked);
}
private createPreview(resource: vscode.Uri, startingScroll?: StartingScrollLocation): MarkdownPreview {
return new MarkdownPreview(this._webviewPanel, resource, startingScroll, {
getTitle: (resource) => DynamicMarkdownPreview.getPreviewTitle(resource, this._locked),
getAdditionalState: () => {
return {
resourceColumn: this.resourceColumn,
locked: this._locked,
};
},
openPreviewLinkToMarkdownFile: (link: vscode.Uri, fragment?: string) => {
this.update(link, fragment ? new StartingScrollFragment(fragment) : undefined);
}
},
this._contentProvider,
this._previewConfigurations,
this._logger,
this._contributionProvider);
}
}

View File

@@ -8,7 +8,7 @@ import { Logger } from '../logger';
import { MarkdownContributionProvider } from '../markdownExtensions'; import { MarkdownContributionProvider } from '../markdownExtensions';
import { disposeAll, Disposable } from '../util/dispose'; import { disposeAll, Disposable } from '../util/dispose';
import { TopmostLineMonitor } from '../util/topmostLineMonitor'; import { TopmostLineMonitor } from '../util/topmostLineMonitor';
import { DynamicMarkdownPreview } from './preview'; import { DynamicMarkdownPreview, StaticMarkdownPreview, ManagedMarkdownPreview } from './preview';
import { MarkdownPreviewConfigurationManager } from './previewConfig'; import { MarkdownPreviewConfigurationManager } from './previewConfig';
import { MarkdownContentProvider } from './previewContentProvider'; import { MarkdownContentProvider } from './previewContentProvider';
@@ -18,9 +18,9 @@ export interface DynamicPreviewSettings {
readonly locked: boolean; readonly locked: boolean;
} }
class PreviewStore extends Disposable { class PreviewStore<T extends ManagedMarkdownPreview> extends Disposable {
private readonly _previews = new Set<DynamicMarkdownPreview>(); private readonly _previews = new Set<T>();
public dispose(): void { public dispose(): void {
super.dispose(); super.dispose();
@@ -30,11 +30,11 @@ class PreviewStore extends Disposable {
this._previews.clear(); this._previews.clear();
} }
[Symbol.iterator](): Iterator<DynamicMarkdownPreview> { [Symbol.iterator](): Iterator<T> {
return this._previews[Symbol.iterator](); return this._previews[Symbol.iterator]();
} }
public get(resource: vscode.Uri, previewSettings: DynamicPreviewSettings): DynamicMarkdownPreview | undefined { public get(resource: vscode.Uri, previewSettings: DynamicPreviewSettings): T | undefined {
for (const preview of this._previews) { for (const preview of this._previews) {
if (preview.matchesResource(resource, previewSettings.previewColumn, previewSettings.locked)) { if (preview.matchesResource(resource, previewSettings.previewColumn, previewSettings.locked)) {
return preview; return preview;
@@ -43,11 +43,11 @@ class PreviewStore extends Disposable {
return undefined; return undefined;
} }
public add(preview: DynamicMarkdownPreview) { public add(preview: T) {
this._previews.add(preview); this._previews.add(preview);
} }
public delete(preview: DynamicMarkdownPreview) { public delete(preview: T) {
this._previews.delete(preview); this._previews.delete(preview);
} }
} }
@@ -58,10 +58,10 @@ export class MarkdownPreviewManager extends Disposable implements vscode.Webview
private readonly _topmostLineMonitor = new TopmostLineMonitor(); private readonly _topmostLineMonitor = new TopmostLineMonitor();
private readonly _previewConfigurations = new MarkdownPreviewConfigurationManager(); private readonly _previewConfigurations = new MarkdownPreviewConfigurationManager();
private readonly _dynamicPreviews = this._register(new PreviewStore()); private readonly _dynamicPreviews = this._register(new PreviewStore<DynamicMarkdownPreview>());
private readonly _staticPreviews = this._register(new PreviewStore()); private readonly _staticPreviews = this._register(new PreviewStore<StaticMarkdownPreview>());
private _activePreview: DynamicMarkdownPreview | undefined = undefined; private _activePreview: ManagedMarkdownPreview | undefined = undefined;
private readonly customEditorViewType = 'vscode.markdown.preview.editor'; private readonly customEditorViewType = 'vscode.markdown.preview.editor';
@@ -117,7 +117,7 @@ export class MarkdownPreviewManager extends Disposable implements vscode.Webview
public toggleLock() { public toggleLock() {
const preview = this._activePreview; const preview = this._activePreview;
if (preview) { if (preview instanceof DynamicMarkdownPreview) {
preview.toggleLock(); preview.toggleLock();
// Close any previews that are now redundant, such as having two dynamic previews in the same editor group // Close any previews that are now redundant, such as having two dynamic previews in the same editor group
@@ -133,6 +133,7 @@ export class MarkdownPreviewManager extends Disposable implements vscode.Webview
webview: vscode.WebviewPanel, webview: vscode.WebviewPanel,
state: any state: any
): Promise<void> { ): Promise<void> {
console.log(state);
const resource = vscode.Uri.parse(state.resource); const resource = vscode.Uri.parse(state.resource);
const locked = state.locked; const locked = state.locked;
const line = state.line; const line = state.line;
@@ -150,21 +151,16 @@ export class MarkdownPreviewManager extends Disposable implements vscode.Webview
this.registerDynamicPreview(preview); this.registerDynamicPreview(preview);
} }
public async openCustomDocument(uri: vscode.Uri) {
return new vscode.CustomDocument(uri);
}
public async resolveCustomTextEditor( public async resolveCustomTextEditor(
document: vscode.TextDocument, document: vscode.TextDocument,
webview: vscode.WebviewPanel webview: vscode.WebviewPanel
): Promise<void> { ): Promise<void> {
const preview = DynamicMarkdownPreview.revive( const preview = StaticMarkdownPreview.revive(
{ resource: document.uri, locked: false, resourceColumn: vscode.ViewColumn.One }, document.uri,
webview, webview,
this._contentProvider, this._contentProvider,
this._previewConfigurations, this._previewConfigurations,
this._logger, this._logger,
this._topmostLineMonitor,
this._contributions); this._contributions);
this.registerStaticPreview(preview); this.registerStaticPreview(preview);
} }
@@ -207,7 +203,7 @@ export class MarkdownPreviewManager extends Disposable implements vscode.Webview
return preview; return preview;
} }
private registerStaticPreview(preview: DynamicMarkdownPreview): DynamicMarkdownPreview { private registerStaticPreview(preview: StaticMarkdownPreview): StaticMarkdownPreview {
this._staticPreviews.add(preview); this._staticPreviews.add(preview);
preview.onDispose(() => { preview.onDispose(() => {
@@ -218,7 +214,7 @@ export class MarkdownPreviewManager extends Disposable implements vscode.Webview
return preview; return preview;
} }
private trackActive(preview: DynamicMarkdownPreview): void { private trackActive(preview: ManagedMarkdownPreview): void {
preview.onDidChangeViewState(({ webviewPanel }) => { preview.onDidChangeViewState(({ webviewPanel }) => {
this.setPreviewActiveContext(webviewPanel.active); this.setPreviewActiveContext(webviewPanel.active);
this._activePreview = webviewPanel.active ? preview : undefined; this._activePreview = webviewPanel.active ? preview : undefined;

View File

@@ -10,7 +10,7 @@ import * as vscode from 'vscode';
import { MarkdownContributionProvider as MarkdownContributionProvider } from './markdownExtensions'; import { MarkdownContributionProvider as MarkdownContributionProvider } from './markdownExtensions';
import { Slugifier } from './slugify'; import { Slugifier } from './slugify';
import { SkinnyTextDocument } from './tableOfContentsProvider'; import { SkinnyTextDocument } from './tableOfContentsProvider';
import { Schemes, isOfScheme } from './util/links'; import { MarkdownFileExtensions, Schemes, isOfScheme } from './util/links';
const UNICODE_NEWLINE_REGEX = /\u2028|\u2029/g; const UNICODE_NEWLINE_REGEX = /\u2028|\u2029/g;
@@ -258,7 +258,9 @@ export class MarkdownEngine {
} }
} }
if (uri.fragment) { const extname = path.extname(uri.fsPath);
if (uri.fragment && (extname === '' || MarkdownFileExtensions.includes(extname))) {
uri = uri.with({ uri = uri.with({
fragment: this.slugifier.fromHeading(uri.fragment).value fragment: this.slugifier.fromHeading(uri.fragment).value
}); });

View File

@@ -32,3 +32,15 @@ export function getUriForLinkWithKnownExternalScheme(link: string): vscode.Uri |
export function isOfScheme(scheme: string, link: string): boolean { export function isOfScheme(scheme: string, link: string): boolean {
return link.toLowerCase().startsWith(scheme); return link.toLowerCase().startsWith(scheme);
} }
export const MarkdownFileExtensions: readonly string[] = [
'.md',
'.mkd',
'.mdwn',
'.mdown',
'.markdown',
'.markdn',
'.mdtxt',
'.mdtext',
'.workbook',
];

View File

@@ -138,7 +138,7 @@ export class BookTreeViewProvider implements vscode.TreeDataProvider<BookTreeIte
@debounce(1500) @debounce(1500)
async fireBookRefresh(book: BookModel): Promise<void> { async fireBookRefresh(book: BookModel): Promise<void> {
await book.initializeContents().then(() => { await book.initializeContents().then(() => {
this._onDidChangeTreeData.fire(); this._onDidChangeTreeData.fire(undefined);
}); });
} }
@@ -154,7 +154,7 @@ export class BookTreeViewProvider implements vscode.TreeDataProvider<BookTreeIte
if (this.currentBook === deletedBook) { if (this.currentBook === deletedBook) {
this.currentBook = this.books.length > 0 ? this.books[this.books.length - 1] : undefined; this.currentBook = this.books.length > 0 ? this.books[this.books.length - 1] : undefined;
} }
this._onDidChangeTreeData.fire(); this._onDidChangeTreeData.fire(undefined);
} }
} catch (e) { } catch (e) {
vscode.window.showErrorMessage(loc.closeBookError(book.root, e instanceof Error ? e.message : e)); vscode.window.showErrorMessage(loc.closeBookError(book.root, e instanceof Error ? e.message : e));
@@ -313,7 +313,7 @@ export class BookTreeViewProvider implements vscode.TreeDataProvider<BookTreeIte
if (untitledBookIndex > -1) { if (untitledBookIndex > -1) {
this.books.splice(untitledBookIndex, 1); this.books.splice(untitledBookIndex, 1);
this.currentBook = undefined; this.currentBook = undefined;
this._onDidChangeTreeData.fire(); this._onDidChangeTreeData.fire(undefined);
vscode.commands.executeCommand('bookTreeView.openBook', destinationUri.fsPath, false, undefined); vscode.commands.executeCommand('bookTreeView.openBook', destinationUri.fsPath, false, undefined);
} }
} }

View File

@@ -12,6 +12,7 @@ export class MockExtensionContext implements vscode.ExtensionContext {
workspaceState: vscode.Memento; workspaceState: vscode.Memento;
globalState: vscode.Memento; globalState: vscode.Memento;
extensionPath: string; extensionPath: string;
extensionUri: vscode.Uri;
asAbsolutePath(relativePath: string): string { asAbsolutePath(relativePath: string): string {
return relativePath; return relativePath;
} }

View File

@@ -70,7 +70,7 @@ describe('Manage Package Dialog', () => {
displayName: 'dl2', displayName: 'dl2',
name: 'nl2' name: 'nl2'
}; };
testContext.onClick.fire(); testContext.onClick.fire(undefined);
testContext.dialog.verify(x => x.changeLocation('nl2'), TypeMoq.Times.once()); testContext.dialog.verify(x => x.changeLocation('nl2'), TypeMoq.Times.once());
testContext.dialog.verify(x => x.resetPages(), TypeMoq.Times.once()); testContext.dialog.verify(x => x.resetPages(), TypeMoq.Times.once());
@@ -100,7 +100,7 @@ describe('Manage Package Dialog', () => {
displayName: 'dl2', displayName: 'dl2',
name: 'nl2' name: 'nl2'
}; };
testContext.onClick.fire(); testContext.onClick.fire(undefined);
testContext.dialog.verify(x => x.changeLocation('nl2'), TypeMoq.Times.once()); testContext.dialog.verify(x => x.changeLocation('nl2'), TypeMoq.Times.once());
testContext.dialog.verify(x => x.showErrorMessage(TypeMoq.It.isAny()), TypeMoq.Times.once()); testContext.dialog.verify(x => x.showErrorMessage(TypeMoq.It.isAny()), TypeMoq.Times.once());

View File

@@ -12,6 +12,8 @@
["{", "}"], ["{", "}"],
["[", "]"], ["[", "]"],
["(", ")"], ["(", ")"],
{ "open": "@'", "close": "\n'@", "notIn": ["string", "comment"]},
{ "open": "@\"", "close": "\n\"@", "notIn": ["string", "comment"]},
{ "open": "\"", "close": "\"", "notIn": ["string"]}, { "open": "\"", "close": "\"", "notIn": ["string"]},
{ "open": "'", "close": "'", "notIn": ["string", "comment"]}, { "open": "'", "close": "'", "notIn": ["string", "comment"]},
["<#", "#>"] ["<#", "#>"]
@@ -29,4 +31,4 @@
"end": "^\\s*#[eE]nd[rR]egion\\b" "end": "^\\s*#[eE]nd[rR]egion\\b"
} }
} }
} }

View File

@@ -21,7 +21,7 @@
}], }],
"snippets": [{ "snippets": [{
"language": "powershell", "language": "powershell",
"path": "./snippets/powershell.json" "path": "./snippets/powershell.code-snippets"
}] }]
}, },
"scripts": { "scripts": {

View File

@@ -56,6 +56,6 @@ export class SqlDatabaseProjectTreeViewProvider implements vscode.TreeDataProvid
} }
this.roots = newRoots; this.roots = newRoots;
this._onDidChangeTreeData.fire(); this._onDidChangeTreeData.fire(undefined);
} }
} }

View File

@@ -17,7 +17,9 @@
"menu.background": "#252526", "menu.background": "#252526",
"menu.foreground": "#CCCCCC", "menu.foreground": "#CCCCCC",
"statusBarItem.remoteForeground": "#FFF", "statusBarItem.remoteForeground": "#FFF",
"statusBarItem.remoteBackground": "#16825D" "statusBarItem.remoteBackground": "#16825D",
"sideBarSectionHeader.background": "#0000",
"sideBarSectionHeader.border": "#ccc3"
}, },
"semanticHighlighting": true "semanticHighlighting": true
} }

View File

@@ -97,6 +97,16 @@
"foreground": "#9CDCFE" "foreground": "#9CDCFE"
} }
}, },
{
"name": "Constants and enums",
"scope": [
"variable.other.constant",
"variable.other.enummember"
],
"settings": {
"foreground": "#D4D4D4",
}
},
{ {
"name": "Object keys, TS grammar specific", "name": "Object keys, TS grammar specific",
"scope": [ "scope": [

View File

@@ -17,7 +17,9 @@
"settings.textInputBorder": "#CECECE", "settings.textInputBorder": "#CECECE",
"settings.numberInputBorder": "#CECECE", "settings.numberInputBorder": "#CECECE",
"statusBarItem.remoteForeground": "#FFF", "statusBarItem.remoteForeground": "#FFF",
"statusBarItem.remoteBackground": "#16825D" "statusBarItem.remoteBackground": "#16825D",
"sideBarSectionHeader.background": "#0000",
"sideBarSectionHeader.border": "#61616130"
}, },
"semanticHighlighting": true "semanticHighlighting": true
} }

View File

@@ -97,6 +97,16 @@
"foreground": "#001080" "foreground": "#001080"
} }
}, },
{
"name": "Constants and enums",
"scope": [
"variable.other.constant",
"variable.other.enummember"
],
"settings": {
"foreground": "#000000",
}
},
{ {
"name": "Object keys, TS grammar specific", "name": "Object keys, TS grammar specific",
"scope": [ "scope": [

View File

@@ -14,6 +14,7 @@
"activationEvents": [ "activationEvents": [
"*" "*"
], ],
"aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217",
"main": "./out/extension.js", "main": "./out/extension.js",
"contributes": { "contributes": {
"commands": [ "commands": [
@@ -56,6 +57,7 @@
}, },
"dependencies": { "dependencies": {
"uuid": "^3.3.3", "uuid": "^3.3.3",
"vscode-extension-telemetry": "0.1.1",
"vscode-nls": "^4.1.1" "vscode-nls": "^4.1.1"
} }
} }

View File

@@ -25,7 +25,10 @@ interface IToken {
expiresAt?: number; // UNIX epoch time at which token will expire expiresAt?: number; // UNIX epoch time at which token will expire
refreshToken: string; refreshToken: string;
accountName: string; account: {
displayName: string;
id: string;
};
scope: string; scope: string;
sessionId: string; // The account id + the scope sessionId: string; // The account id + the scope
} }
@@ -44,7 +47,10 @@ interface IStoredSession {
id: string; id: string;
refreshToken: string; refreshToken: string;
scope: string; // Scopes are alphabetized and joined with a space scope: string; // Scopes are alphabetized and joined with a space
accountName: string; account: {
displayName: string,
id: string
}
} }
function parseQuery(uri: vscode.Uri) { function parseQuery(uri: vscode.Uri) {
@@ -76,6 +82,9 @@ export class AzureActiveDirectoryService {
} }
public async initialize(): Promise<void> { public async initialize(): Promise<void> {
// TODO remove, temporary migration
await keychain.migrateToken();
const storedData = await keychain.getToken(); const storedData = await keychain.getToken();
if (storedData) { if (storedData) {
try { try {
@@ -90,7 +99,10 @@ export class AzureActiveDirectoryService {
this._tokens.push({ this._tokens.push({
accessToken: undefined, accessToken: undefined,
refreshToken: session.refreshToken, refreshToken: session.refreshToken,
accountName: session.accountName, account: {
displayName: session.account.displayName,
id: session.account.id
},
scope: session.scope, scope: session.scope,
sessionId: session.id sessionId: session.id
}); });
@@ -122,7 +134,7 @@ export class AzureActiveDirectoryService {
id: token.sessionId, id: token.sessionId,
refreshToken: token.refreshToken, refreshToken: token.refreshToken,
scope: token.scope, scope: token.scope,
accountName: token.accountName account: token.account
}; };
}); });
@@ -196,7 +208,7 @@ export class AzureActiveDirectoryService {
return { return {
id: token.sessionId, id: token.sessionId,
getAccessToken: () => this.resolveAccessToken(token), getAccessToken: () => this.resolveAccessToken(token),
accountName: token.accountName, account: token.account,
scopes: token.scope.split(' ') scopes: token.scope.split(' ')
}; };
} }
@@ -220,8 +232,6 @@ export class AzureActiveDirectoryService {
} catch (e) { } catch (e) {
throw new Error('Unavailable due to network problems'); throw new Error('Unavailable due to network problems');
} }
throw new Error('Unavailable due to network problems');
} }
private getTokenClaims(accessToken: string): ITokenClaims { private getTokenClaims(accessToken: string): ITokenClaims {
@@ -416,7 +426,10 @@ export class AzureActiveDirectoryService {
refreshToken: json.refresh_token, refreshToken: json.refresh_token,
scope, scope,
sessionId: existingId || `${claims.tid}/${(claims.oid || (claims.altsecid || '' + claims.ipd || ''))}/${uuid()}`, sessionId: existingId || `${claims.tid}/${(claims.oid || (claims.altsecid || '' + claims.ipd || ''))}/${uuid()}`,
accountName: claims.email || claims.unique_name || 'user@example.com' account: {
displayName: claims.email || claims.unique_name || 'user@example.com',
id: `${claims.tid}/${(claims.oid || (claims.altsecid || '' + claims.ipd || ''))}`
}
}; };
} }

View File

@@ -6,12 +6,15 @@
import * as vscode from 'vscode'; import * as vscode from 'vscode';
import { AzureActiveDirectoryService, onDidChangeSessions } from './AADHelper'; import { AzureActiveDirectoryService, onDidChangeSessions } from './AADHelper';
import * as nls from 'vscode-nls'; import * as nls from 'vscode-nls';
import TelemetryReporter from 'vscode-extension-telemetry';
const localize = nls.loadMessageBundle(); const localize = nls.loadMessageBundle();
export const DEFAULT_SCOPES = 'https://management.core.windows.net/.default offline_access'; export const DEFAULT_SCOPES = 'https://management.core.windows.net/.default offline_access';
export async function activate(context: vscode.ExtensionContext) { export async function activate(context: vscode.ExtensionContext) {
const { name, version, aiKey } = require('../package.json') as { name: string, version: string, aiKey: string };
const telemetryReporter = new TelemetryReporter(name, version, aiKey);
const loginService = new AzureActiveDirectoryService(); const loginService = new AzureActiveDirectoryService();
@@ -24,18 +27,24 @@ export async function activate(context: vscode.ExtensionContext) {
getSessions: () => Promise.resolve(loginService.sessions), getSessions: () => Promise.resolve(loginService.sessions),
login: async (scopes: string[]) => { login: async (scopes: string[]) => {
try { try {
telemetryReporter.sendTelemetryEvent('login');
await loginService.login(scopes.sort().join(' ')); await loginService.login(scopes.sort().join(' '));
const session = loginService.sessions[loginService.sessions.length - 1]; const session = loginService.sessions[loginService.sessions.length - 1];
onDidChangeSessions.fire({ added: [session.id], removed: [], changed: [] }); onDidChangeSessions.fire({ added: [session.id], removed: [], changed: [] });
return loginService.sessions[0]!; return loginService.sessions[0]!;
} catch (e) { } catch (e) {
telemetryReporter.sendTelemetryEvent('loginFailed');
throw e; throw e;
} }
}, },
logout: async (id: string) => { logout: async (id: string) => {
await loginService.logout(id); try {
onDidChangeSessions.fire({ added: [], removed: [id], changed: [] }); telemetryReporter.sendTelemetryEvent('logout');
vscode.window.showInformationMessage(localize('signedOut', "Successfully signed out.")); await loginService.logout(id);
onDidChangeSessions.fire({ added: [], removed: [id], changed: [] });
} catch (e) {
telemetryReporter.sendTelemetryEvent('logoutFailed');
}
} }
})); }));
@@ -60,7 +69,7 @@ export async function activate(context: vscode.ExtensionContext) {
const selectedSession = await vscode.window.showQuickPick(sessions.map(session => { const selectedSession = await vscode.window.showQuickPick(sessions.map(session => {
return { return {
id: session.id, id: session.id,
label: session.accountName label: session.account.displayName
}; };
})); }));

View File

@@ -28,7 +28,7 @@ export type Keytar = {
deletePassword: typeof keytarType['deletePassword']; deletePassword: typeof keytarType['deletePassword'];
}; };
const SERVICE_ID = `${vscode.env.uriScheme}-vscode.login`; const SERVICE_ID = `${vscode.env.uriScheme}-microsoft.login`;
const ACCOUNT_ID = 'account'; const ACCOUNT_ID = 'account';
export class Keychain { export class Keychain {
@@ -43,13 +43,38 @@ export class Keychain {
this.keytar = keytar; this.keytar = keytar;
} }
// TODO remove, temporary migration
async migrateToken(): Promise<void> {
const oldServiceId = `${vscode.env.uriScheme}-vscode.login`;
try {
const data = await this.keytar.getPassword(oldServiceId, ACCOUNT_ID);
if (data) {
Logger.info('Migrating token...');
this.setToken(data);
await this.keytar.deletePassword(oldServiceId, ACCOUNT_ID);
Logger.info('Migration successful');
}
} catch (e) {
Logger.error(`Migrating token failed: ${e}`);
}
}
async setToken(token: string): Promise<void> { async setToken(token: string): Promise<void> {
try { try {
Logger.trace('Writing to keychain', token); Logger.trace('Writing to keychain', token);
return await this.keytar.setPassword(SERVICE_ID, ACCOUNT_ID, token); return await this.keytar.setPassword(SERVICE_ID, ACCOUNT_ID, token);
} catch (e) { } catch (e) {
// Ignore
Logger.error(`Setting token failed: ${e}`); Logger.error(`Setting token failed: ${e}`);
// Temporary fix for #94005
// This happens when processes write simulatenously to the keychain, most
// likely when trying to refresh the token. Ignore the error since additional
// writes after the first one do not matter. Should actually be fixed upstream.
if (e.message === 'The specified item already exists in the keychain.') {
return;
}
const troubleshooting = localize('troubleshooting', "Troubleshooting Guide"); const troubleshooting = localize('troubleshooting', "Troubleshooting Guide");
const result = await vscode.window.showErrorMessage(localize('keychainWriteError', "Writing login information to the keychain failed with error '{0}'.", e.message), troubleshooting); const result = await vscode.window.showErrorMessage(localize('keychainWriteError', "Writing login information to the keychain failed with error '{0}'.", e.message), troubleshooting);
if (result === troubleshooting) { if (result === troubleshooting) {

View File

@@ -17,7 +17,7 @@ class Log {
private level: Level; private level: Level;
constructor() { constructor() {
this.output = vscode.window.createOutputChannel('Account'); this.output = vscode.window.createOutputChannel('Microsoft Authentication');
this.level = vscode.workspace.getConfiguration('microsoftAccount').get('logLevel') || Level.Info; this.level = vscode.workspace.getConfiguration('microsoftAccount').get('logLevel') || Level.Info;
vscode.workspace.onDidChangeConfiguration(e => { vscode.workspace.onDidChangeConfiguration(e => {
if (e.affectsConfiguration('microsoftAccount.logLevel')) { if (e.affectsConfiguration('microsoftAccount.logLevel')) {

View File

@@ -52,6 +52,15 @@ ansi-styles@^3.2.1:
dependencies: dependencies:
color-convert "^1.9.0" color-convert "^1.9.0"
applicationinsights@1.0.8:
version "1.0.8"
resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-1.0.8.tgz#db6e3d983cf9f9405fe1ee5ba30ac6e1914537b5"
integrity sha512-KzOOGdphOS/lXWMFZe5440LUdFbrLpMvh2SaRxn7BmiI550KAoSb2gIhiq6kJZ9Ir3AxRRztjhzif+e5P5IXIg==
dependencies:
diagnostic-channel "0.2.0"
diagnostic-channel-publishers "0.2.1"
zone.js "0.7.6"
aproba@^1.0.3: aproba@^1.0.3:
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
@@ -170,6 +179,18 @@ detect-libc@^1.0.3:
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=
diagnostic-channel-publishers@0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-0.2.1.tgz#8e2d607a8b6d79fe880b548bc58cc6beb288c4f3"
integrity sha1-ji1geottef6IC1SLxYzGvrKIxPM=
diagnostic-channel@0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/diagnostic-channel/-/diagnostic-channel-0.2.0.tgz#cc99af9612c23fb1fff13612c72f2cbfaa8d5a17"
integrity sha1-zJmvlhLCP7H/8TYSxy8sv6qNWhc=
dependencies:
semver "^5.3.0"
diff@^4.0.1: diff@^4.0.1:
version "4.0.2" version "4.0.2"
resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
@@ -645,6 +666,13 @@ uuid@^3.3.3:
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
vscode-extension-telemetry@0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.1.1.tgz#91387e06b33400c57abd48979b0e790415ae110b"
integrity sha512-TkKKG/B/J94DP5qf6xWB4YaqlhWDg6zbbqVx7Bz//stLQNnfE9XS1xm3f6fl24c5+bnEK0/wHgMgZYKIKxPeUA==
dependencies:
applicationinsights "1.0.8"
vscode-nls@^4.1.1: vscode-nls@^4.1.1:
version "4.1.1" version "4.1.1"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.1.1.tgz#f9916b64e4947b20322defb1e676a495861f133c" resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.1.1.tgz#f9916b64e4947b20322defb1e676a495861f133c"
@@ -666,3 +694,8 @@ wrappy@1:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
zone.js@0.7.6:
version "0.7.6"
resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.7.6.tgz#fbbc39d3e0261d0986f1ba06306eb3aeb0d22009"
integrity sha1-+7w50+AmHQmG8boGMG6zrrDSIAk=

View File

@@ -15,6 +15,9 @@
"postinstall": "node build/npm/postinstall.js", "postinstall": "node build/npm/postinstall.js",
"compile": "gulp compile --max_old_space_size=4095", "compile": "gulp compile --max_old_space_size=4095",
"watch": "gulp watch --max_old_space_size=4095", "watch": "gulp watch --max_old_space_size=4095",
"watchd": "deemon yarn watch",
"kill-watchd": "deemon --kill yarn watch",
"restart-watchd": "deemon --restart yarn watch",
"watch-client": "gulp watch-client --max_old_space_size=4095", "watch-client": "gulp watch-client --max_old_space_size=4095",
"mocha": "mocha test/unit/node/all.js --delay", "mocha": "mocha test/unit/node/all.js --delay",
"precommit": "node build/gulpfile.hygiene.js", "precommit": "node build/gulpfile.hygiene.js",
@@ -56,19 +59,19 @@
"iconv-lite": "0.5.0", "iconv-lite": "0.5.0",
"jquery": "3.4.0", "jquery": "3.4.0",
"jschardet": "2.1.1", "jschardet": "2.1.1",
"keytar": "github:rmacfarlane/node-keytar#334424bd26414923782f144110f4beda19168d24", "keytar": "^5.5.0",
"minimist": "^1.2.5", "minimist": "^1.2.5",
"native-is-elevated": "0.4.1", "native-is-elevated": "0.4.1",
"native-keymap": "2.1.1", "native-keymap": "2.1.1",
"native-watchdog": "1.3.0", "native-watchdog": "1.3.0",
"ng2-charts": "^1.6.0", "ng2-charts": "^1.6.0",
"node-pty": "0.10.0-beta7", "node-pty": "0.10.0-beta8",
"onigasm-umd": "2.2.5", "onigasm-umd": "2.2.5",
"plotly.js-dist-min": "^1.53.0", "plotly.js-dist-min": "^1.53.0",
"reflect-metadata": "^0.1.8", "reflect-metadata": "^0.1.8",
"rxjs": "5.4.0", "rxjs": "5.4.0",
"sanitize-html": "^1.19.1", "sanitize-html": "^1.19.1",
"semver-umd": "^5.5.5", "semver-umd": "^5.5.6",
"slickgrid": "github:anthonydresser/SlickGrid#2.3.33", "slickgrid": "github:anthonydresser/SlickGrid#2.3.33",
"spdlog": "^0.11.1", "spdlog": "^0.11.1",
"sudo-prompt": "9.1.1", "sudo-prompt": "9.1.1",
@@ -76,13 +79,13 @@
"vscode-nsfw": "1.2.8", "vscode-nsfw": "1.2.8",
"vscode-proxy-agent": "^0.5.2", "vscode-proxy-agent": "^0.5.2",
"vscode-ripgrep": "^1.5.8", "vscode-ripgrep": "^1.5.8",
"vscode-sqlite3": "4.0.9", "vscode-sqlite3": "4.0.10",
"vscode-textmate": "4.4.0", "vscode-textmate": "4.4.0",
"xterm": "4.5.0-beta.4", "xterm": "4.6.0-beta.15",
"xterm-addon-search": "0.5.0", "xterm-addon-search": "0.6.0",
"xterm-addon-unicode11": "0.1.1", "xterm-addon-unicode11": "0.2.0-beta.2",
"xterm-addon-web-links": "0.2.1", "xterm-addon-web-links": "0.3.0",
"xterm-addon-webgl": "0.5.0", "xterm-addon-webgl": "0.7.0-beta.6",
"yauzl": "^2.9.2", "yauzl": "^2.9.2",
"yazl": "^2.4.3", "yazl": "^2.4.3",
"zone.js": "^0.8.4" "zone.js": "^0.8.4"
@@ -122,7 +125,8 @@
"cson-parser": "^1.3.3", "cson-parser": "^1.3.3",
"css-loader": "^3.2.0", "css-loader": "^3.2.0",
"debounce": "^1.0.0", "debounce": "^1.0.0",
"electron": "7.1.11", "deemon": "^1.4.0",
"electron": "7.2.2",
"eslint": "6.8.0", "eslint": "6.8.0",
"eslint-plugin-jsdoc": "^19.1.0", "eslint-plugin-jsdoc": "^19.1.0",
"event-stream": "3.3.4", "event-stream": "3.3.4",
@@ -179,7 +183,7 @@
"temp-write": "^3.4.0", "temp-write": "^3.4.0",
"ts-loader": "^4.4.2", "ts-loader": "^4.4.2",
"typemoq": "^0.3.2", "typemoq": "^0.3.2",
"typescript": "^3.9.0-dev.20200327", "typescript": "^3.9.0-dev.20200420",
"typescript-formatter": "7.1.0", "typescript-formatter": "7.1.0",
"underscore": "^1.8.2", "underscore": "^1.8.2",
"vinyl": "^2.0.0", "vinyl": "^2.0.0",

View File

@@ -26,23 +26,23 @@
"minimist": "^1.2.5", "minimist": "^1.2.5",
"native-watchdog": "1.3.0", "native-watchdog": "1.3.0",
"ng2-charts": "^1.6.0", "ng2-charts": "^1.6.0",
"node-pty": "0.10.0-beta7", "node-pty": "0.10.0-beta8",
"onigasm-umd": "2.2.5", "onigasm-umd": "2.2.5",
"reflect-metadata": "^0.1.8", "reflect-metadata": "^0.1.8",
"rxjs": "5.4.0", "rxjs": "5.4.0",
"sanitize-html": "^1.19.1", "sanitize-html": "^1.19.1",
"semver-umd": "^5.5.5", "semver-umd": "^5.5.6",
"slickgrid": "github:anthonydresser/SlickGrid#2.3.33", "slickgrid": "github:anthonydresser/SlickGrid#2.3.33",
"spdlog": "^0.11.1", "spdlog": "^0.11.1",
"vscode-nsfw": "1.2.8", "vscode-nsfw": "1.2.8",
"vscode-proxy-agent": "^0.5.2", "vscode-proxy-agent": "^0.5.2",
"vscode-ripgrep": "^1.5.8", "vscode-ripgrep": "^1.5.8",
"vscode-textmate": "4.4.0", "vscode-textmate": "4.4.0",
"xterm": "4.5.0-beta.4", "xterm": "4.6.0-beta.15",
"xterm-addon-search": "0.5.0", "xterm-addon-search": "0.6.0",
"xterm-addon-unicode11": "0.1.1", "xterm-addon-unicode11": "0.2.0-beta.2",
"xterm-addon-web-links": "0.2.1", "xterm-addon-web-links": "0.3.0",
"xterm-addon-webgl": "0.5.0", "xterm-addon-webgl": "0.7.0-beta.6",
"yauzl": "^2.9.2", "yauzl": "^2.9.2",
"yazl": "^2.4.3", "yazl": "^2.4.3",
"zone.js": "^0.8.4" "zone.js": "^0.8.4"

View File

@@ -20,14 +20,14 @@
"reflect-metadata": "^0.1.8", "reflect-metadata": "^0.1.8",
"rxjs": "5.4.0", "rxjs": "5.4.0",
"sanitize-html": "^1.19.1", "sanitize-html": "^1.19.1",
"semver-umd": "^5.5.5", "semver-umd": "^5.5.6",
"slickgrid": "github:anthonydresser/SlickGrid#2.3.33", "slickgrid": "github:anthonydresser/SlickGrid#2.3.33",
"vscode-textmate": "4.4.0", "vscode-textmate": "4.4.0",
"xterm": "4.5.0-beta.4", "xterm": "4.6.0-beta.15",
"xterm-addon-search": "0.5.0", "xterm-addon-search": "0.6.0",
"xterm-addon-unicode11": "0.1.1", "xterm-addon-unicode11": "0.2.0-beta.2",
"xterm-addon-web-links": "0.2.1", "xterm-addon-web-links": "0.3.0",
"xterm-addon-webgl": "0.5.0", "xterm-addon-webgl": "0.7.0-beta.6",
"zone.js": "^0.8.4" "zone.js": "^0.8.4"
} }
} }

View File

@@ -302,10 +302,10 @@ sanitize-html@^1.19.1:
srcset "^1.0.0" srcset "^1.0.0"
xtend "^4.0.1" xtend "^4.0.1"
semver-umd@^5.5.5: semver-umd@^5.5.6:
version "5.5.5" version "5.5.6"
resolved "https://registry.yarnpkg.com/semver-umd/-/semver-umd-5.5.5.tgz#a2e4280d0e92a2b27695c18811f0e939e144d86f" resolved "https://registry.yarnpkg.com/semver-umd/-/semver-umd-5.5.6.tgz#1d185bbd2caec825c564b54907cd09e14083f228"
integrity sha512-8rUq0nnTzlexpAdYmm8UDYsLkBn0MnBkfrGWPmyDBDDzv71dPOH07szOOaLj/5hO3BYmumYwS+wp3C60zLzh5g== integrity sha512-6ARYXVi4Y4VO5HfyCjT/6xyykBtJwEXSGQ8ON4UPQSFOjZUDsbAE0J614QcBBsLTTyQMEqvsXN804vAqpydjzw==
"slickgrid@github:anthonydresser/SlickGrid#2.3.33": "slickgrid@github:anthonydresser/SlickGrid#2.3.33":
version "2.3.33" version "2.3.33"
@@ -367,30 +367,30 @@ xtend@^4.0.1:
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
xterm-addon-search@0.5.0: xterm-addon-search@0.6.0:
version "0.5.0" version "0.6.0"
resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.5.0.tgz#cd3a2f8056084c28e236d4e732da37682010bcc2" resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.6.0.tgz#542cc2c35e83e7332ce1982b65ad218ee769836c"
integrity sha512-zLVqVTrg5w2nk9fRj3UuVKCPo/dmFe/cLf3EM9Is5Dm6cgOoXmeo9eq2KgD8A0gquAflTFTf0ya2NaFmShHwyg== integrity sha512-k3EsZzUptCXygHFP5rQuCBdWWkI/ZNuX3pDSOVdxPV9jB7U5Aha9guTIZoMP7FIjL8jce+ClQs6q7VINcRV1+w==
xterm-addon-unicode11@0.1.1: xterm-addon-unicode11@0.2.0-beta.2:
version "0.1.1" version "0.2.0-beta.2"
resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.1.1.tgz#b209ef137db38096f68636af4ef4d0c0acba85ad" resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.2.0-beta.2.tgz#2a13ba5b08fdb1005be241816c4e3302674db4af"
integrity sha512-z6vJTL+dpNljwAYzYoyDjJP8A2XjZuEosl0sRa+FGRf3jEyEVWquDM53MfUd1ztVdAPQ839qR6eYK1BXV04Bhw== integrity sha512-Y047mnIWrAj65TpStdyPYoPeDTX4en+XX4Y90KuQB3cW2xIyZj25NSVV9BZdqzSb7gk9M6KBvIcm8chj7S2N8Q==
xterm-addon-web-links@0.2.1: xterm-addon-web-links@0.3.0:
version "0.2.1" version "0.3.0"
resolved "https://registry.yarnpkg.com/xterm-addon-web-links/-/xterm-addon-web-links-0.2.1.tgz#6d1f2ce613e09870badf17615e7a1170a31542b2" resolved "https://registry.yarnpkg.com/xterm-addon-web-links/-/xterm-addon-web-links-0.3.0.tgz#88affe9235c928b41bab660a65330f46d91c940e"
integrity sha512-2KnHtiq0IG7hfwv3jw2/jQeH1RBk2d5CH4zvgwQe00rLofSJqSfgnJ7gwowxxpGHrpbPr6Lv4AmH/joaNw2+HQ== integrity sha512-vGXiIDqNMyxK5S1IzOjDqcgeQrrv7TDcSHiOeCNAoWCI2f+Rap9d18gjgnMKPyR+AbG0KoKnaKA6Dc1du1vs5A==
xterm-addon-webgl@0.5.0: xterm-addon-webgl@0.7.0-beta.6:
version "0.5.0" version "0.7.0-beta.6"
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.5.0.tgz#c1031dc7599cce3509824643ab5f15361c928e3e" resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.7.0-beta.6.tgz#340d728bae7456a1d67a7cb8996dfd51d96721b0"
integrity sha512-hQrvabKCnwXFaEZ+YtoJM9Pm0CIBXL5KSwoU+RiGStU3KYTAcqYP2GsH3dWdvKX6kTWhWLS81dtDsGkfbOciuA== integrity sha512-IoR0hPtG5qBrcLG1B7GSzo4W2hYocP8UgG5LlyXkEkT/0BqVcGnICgR8Ck7EfMmU8ci4jNFiHYjK/Bgc4m2S4g==
xterm@4.5.0-beta.4: xterm@4.6.0-beta.15:
version "4.5.0-beta.4" version "4.6.0-beta.15"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.5.0-beta.4.tgz#701f05553b643236d3fcd8bb7f14045bd4537c92" resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.6.0-beta.15.tgz#93a0cb1ff047a452b03070499e2ccd0ba53e0678"
integrity sha512-Yv1Bf60LTLBMaig1rv033hPz8hQGXZN6VYW2oe/409t2NbJXPg5xZgf47qyaWFV7a5k1BFiwjayJCWaL2nYBew== integrity sha512-5G+3QSM/GKN/Tdq/IIU7FDivzh0eXsv3sNmZFDdtvNggnu2K56l4N5P0KZo0HdFztDfTyW/FLfqsPAwhrK4Khg==
zone.js@^0.8.4: zone.js@^0.8.4:
version "0.8.29" version "0.8.29"

View File

@@ -498,10 +498,10 @@ node-addon-api@1.6.2:
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-1.6.2.tgz#d8aad9781a5cfc4132cc2fecdbdd982534265217" resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-1.6.2.tgz#d8aad9781a5cfc4132cc2fecdbdd982534265217"
integrity sha512-479Bjw9nTE5DdBSZZWprFryHGjUaQC31y1wHo19We/k0BZlrmhqQitWoUL0cD8+scljCbIUL+E58oRDEakdGGA== integrity sha512-479Bjw9nTE5DdBSZZWprFryHGjUaQC31y1wHo19We/k0BZlrmhqQitWoUL0cD8+scljCbIUL+E58oRDEakdGGA==
node-pty@0.10.0-beta7: node-pty@0.10.0-beta8:
version "0.10.0-beta7" version "0.10.0-beta8"
resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-0.10.0-beta7.tgz#7e383b2d1fe2f34509b57187f5a9a6ff90c46111" resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-0.10.0-beta8.tgz#f4aa56c71a794f4580373a3030dfebd25240c6db"
integrity sha512-oC2VyIz9YaIvv6lWjAPZbUzmhLW1ouFmxOogNRNQrKeUzUi2yM/QRmybs+dW/Mhd3V89Yh61Ml0J5yuWiMIBbw== integrity sha512-Ul/hLsadC0SvvShxpne+kq2ebSMcitewlNhrwoXXBvFdCqxJt7Ai1AgMhH7AKBUp06uBeYXThJ2ihTszrkdnYw==
dependencies: dependencies:
nan "^2.14.0" nan "^2.14.0"
@@ -600,10 +600,10 @@ sanitize-html@^1.19.1:
srcset "^1.0.0" srcset "^1.0.0"
xtend "^4.0.1" xtend "^4.0.1"
semver-umd@^5.5.5: semver-umd@^5.5.6:
version "5.5.5" version "5.5.6"
resolved "https://registry.yarnpkg.com/semver-umd/-/semver-umd-5.5.5.tgz#a2e4280d0e92a2b27695c18811f0e939e144d86f" resolved "https://registry.yarnpkg.com/semver-umd/-/semver-umd-5.5.6.tgz#1d185bbd2caec825c564b54907cd09e14083f228"
integrity sha512-8rUq0nnTzlexpAdYmm8UDYsLkBn0MnBkfrGWPmyDBDDzv71dPOH07szOOaLj/5hO3BYmumYwS+wp3C60zLzh5g== integrity sha512-6ARYXVi4Y4VO5HfyCjT/6xyykBtJwEXSGQ8ON4UPQSFOjZUDsbAE0J614QcBBsLTTyQMEqvsXN804vAqpydjzw==
semver@^5.3.0: semver@^5.3.0:
version "5.6.0" version "5.6.0"
@@ -749,30 +749,30 @@ xtend@^4.0.1:
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
xterm-addon-search@0.5.0: xterm-addon-search@0.6.0:
version "0.5.0" version "0.6.0"
resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.5.0.tgz#cd3a2f8056084c28e236d4e732da37682010bcc2" resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.6.0.tgz#542cc2c35e83e7332ce1982b65ad218ee769836c"
integrity sha512-zLVqVTrg5w2nk9fRj3UuVKCPo/dmFe/cLf3EM9Is5Dm6cgOoXmeo9eq2KgD8A0gquAflTFTf0ya2NaFmShHwyg== integrity sha512-k3EsZzUptCXygHFP5rQuCBdWWkI/ZNuX3pDSOVdxPV9jB7U5Aha9guTIZoMP7FIjL8jce+ClQs6q7VINcRV1+w==
xterm-addon-unicode11@0.1.1: xterm-addon-unicode11@0.2.0-beta.2:
version "0.1.1" version "0.2.0-beta.2"
resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.1.1.tgz#b209ef137db38096f68636af4ef4d0c0acba85ad" resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.2.0-beta.2.tgz#2a13ba5b08fdb1005be241816c4e3302674db4af"
integrity sha512-z6vJTL+dpNljwAYzYoyDjJP8A2XjZuEosl0sRa+FGRf3jEyEVWquDM53MfUd1ztVdAPQ839qR6eYK1BXV04Bhw== integrity sha512-Y047mnIWrAj65TpStdyPYoPeDTX4en+XX4Y90KuQB3cW2xIyZj25NSVV9BZdqzSb7gk9M6KBvIcm8chj7S2N8Q==
xterm-addon-web-links@0.2.1: xterm-addon-web-links@0.3.0:
version "0.2.1" version "0.3.0"
resolved "https://registry.yarnpkg.com/xterm-addon-web-links/-/xterm-addon-web-links-0.2.1.tgz#6d1f2ce613e09870badf17615e7a1170a31542b2" resolved "https://registry.yarnpkg.com/xterm-addon-web-links/-/xterm-addon-web-links-0.3.0.tgz#88affe9235c928b41bab660a65330f46d91c940e"
integrity sha512-2KnHtiq0IG7hfwv3jw2/jQeH1RBk2d5CH4zvgwQe00rLofSJqSfgnJ7gwowxxpGHrpbPr6Lv4AmH/joaNw2+HQ== integrity sha512-vGXiIDqNMyxK5S1IzOjDqcgeQrrv7TDcSHiOeCNAoWCI2f+Rap9d18gjgnMKPyR+AbG0KoKnaKA6Dc1du1vs5A==
xterm-addon-webgl@0.5.0: xterm-addon-webgl@0.7.0-beta.6:
version "0.5.0" version "0.7.0-beta.6"
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.5.0.tgz#c1031dc7599cce3509824643ab5f15361c928e3e" resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.7.0-beta.6.tgz#340d728bae7456a1d67a7cb8996dfd51d96721b0"
integrity sha512-hQrvabKCnwXFaEZ+YtoJM9Pm0CIBXL5KSwoU+RiGStU3KYTAcqYP2GsH3dWdvKX6kTWhWLS81dtDsGkfbOciuA== integrity sha512-IoR0hPtG5qBrcLG1B7GSzo4W2hYocP8UgG5LlyXkEkT/0BqVcGnICgR8Ck7EfMmU8ci4jNFiHYjK/Bgc4m2S4g==
xterm@4.5.0-beta.4: xterm@4.6.0-beta.15:
version "4.5.0-beta.4" version "4.6.0-beta.15"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.5.0-beta.4.tgz#701f05553b643236d3fcd8bb7f14045bd4537c92" resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.6.0-beta.15.tgz#93a0cb1ff047a452b03070499e2ccd0ba53e0678"
integrity sha512-Yv1Bf60LTLBMaig1rv033hPz8hQGXZN6VYW2oe/409t2NbJXPg5xZgf47qyaWFV7a5k1BFiwjayJCWaL2nYBew== integrity sha512-5G+3QSM/GKN/Tdq/IIU7FDivzh0eXsv3sNmZFDdtvNggnu2K56l4N5P0KZo0HdFztDfTyW/FLfqsPAwhrK4Khg==
yauzl@^2.9.2: yauzl@^2.9.2:
version "2.10.0" version "2.10.0"

View File

@@ -30,7 +30,8 @@ if not exist out yarn compile
set ELECTRON_RUN_AS_NODE=1 set ELECTRON_RUN_AS_NODE=1
set NODE_ENV=development set NODE_ENV=development
set VSCODE_DEV=1 set VSCODE_DEV=1
set ELECTRON_DEFAULT_ERROR_MODE=1 set ELECTRON_ENABLE_SECURITY_WARNINGS=1
REM set ELECTRON_DEFAULT_ERROR_MODE=1 TODO@ben to investigate if this helps with builds reporting stacks if renderer crashes
set ELECTRON_ENABLE_LOGGING=1 set ELECTRON_ENABLE_LOGGING=1
set ELECTRON_ENABLE_STACK_DUMPING=1 set ELECTRON_ENABLE_STACK_DUMPING=1

View File

@@ -39,6 +39,7 @@ function code() {
ELECTRON_RUN_AS_NODE=1 \ ELECTRON_RUN_AS_NODE=1 \
NODE_ENV=development \ NODE_ENV=development \
VSCODE_DEV=1 \ VSCODE_DEV=1 \
ELECTRON_ENABLE_SECURITY_WARNINGS=1 \
ELECTRON_ENABLE_LOGGING=1 \ ELECTRON_ENABLE_LOGGING=1 \
ELECTRON_ENABLE_STACK_DUMPING=1 \ ELECTRON_ENABLE_STACK_DUMPING=1 \
"$CODE" --inspect=5874 "$ROOT/out/cli.js" . "$@" "$CODE" --inspect=5874 "$ROOT/out/cli.js" . "$@"

View File

@@ -28,8 +28,9 @@ if not exist out yarn compile
:: Configuration :: Configuration
set NODE_ENV=development set NODE_ENV=development
set VSCODE_DEV=1 set VSCODE_DEV=1
set ELECTRON_ENABLE_SECURITY_WARNINGS=1
set VSCODE_CLI=1 set VSCODE_CLI=1
set ELECTRON_DEFAULT_ERROR_MODE=1 REM set ELECTRON_DEFAULT_ERROR_MODE=1 TODO@ben to investigate if this helps with builds reporting stacks if renderer crashes
set ELECTRON_ENABLE_LOGGING=1 set ELECTRON_ENABLE_LOGGING=1
set ELECTRON_ENABLE_STACK_DUMPING=1 set ELECTRON_ENABLE_STACK_DUMPING=1
set VSCODE_LOGS= set VSCODE_LOGS=

View File

@@ -44,6 +44,7 @@ function code() {
# Configuration # Configuration
export NODE_ENV=development export NODE_ENV=development
export VSCODE_DEV=1 export VSCODE_DEV=1
export ELECTRON_ENABLE_SECURITY_WARNINGS=1
export VSCODE_CLI=1 export VSCODE_CLI=1
export ELECTRON_ENABLE_STACK_DUMPING=1 export ELECTRON_ENABLE_STACK_DUMPING=1
export ELECTRON_ENABLE_LOGGING=1 export ELECTRON_ENABLE_LOGGING=1

View File

@@ -27,7 +27,7 @@ import { URI } from 'vs/base/common/uri';
import { dirname, basename } from 'vs/base/common/resources'; import { dirname, basename } from 'vs/base/common/resources';
import { LIGHT, FileThemeIcon, FolderThemeIcon, registerThemingParticipant, IThemeService } from 'vs/platform/theme/common/themeService'; import { LIGHT, FileThemeIcon, FolderThemeIcon, registerThemingParticipant, IThemeService } from 'vs/platform/theme/common/themeService';
import { FileKind } from 'vs/platform/files/common/files'; import { FileKind } from 'vs/platform/files/common/files';
import { WorkbenchAsyncDataTree, ResourceNavigator } from 'vs/platform/list/browser/listService'; import { WorkbenchAsyncDataTree, TreeResourceNavigator } from 'vs/platform/list/browser/listService';
import { localize } from 'vs/nls'; import { localize } from 'vs/nls';
import { timeout } from 'vs/base/common/async'; import { timeout } from 'vs/base/common/async';
import { editorFindMatchHighlight, editorFindMatchHighlightBorder, textLinkForeground, textCodeBlockBackground, focusBorder } from 'vs/platform/theme/common/colorRegistry'; import { editorFindMatchHighlight, editorFindMatchHighlightBorder, textLinkForeground, textCodeBlockBackground, focusBorder } from 'vs/platform/theme/common/colorRegistry';
@@ -416,9 +416,9 @@ export class CustomTreeView extends Disposable implements ITreeView {
accessibilityProvider: { accessibilityProvider: {
getAriaLabel(element: ITreeItem): string { getAriaLabel(element: ITreeItem): string {
return element.label ? element.label.label : ''; return element.label ? element.label.label : '';
} },
getWidgetAriaLabel: () => this.title
}, },
ariaLabel: this.title,
keyboardNavigationLabelProvider: { keyboardNavigationLabelProvider: {
getKeyboardNavigationLabel: (item: ITreeItem) => { getKeyboardNavigationLabel: (item: ITreeItem) => {
return item.label ? item.label.label : (item.resourceUri ? basename(URI.revive(item.resourceUri)) : undefined); return item.label ? item.label.label : (item.resourceUri ? basename(URI.revive(item.resourceUri)) : undefined);
@@ -451,7 +451,7 @@ export class CustomTreeView extends Disposable implements ITreeView {
})); }));
this.tree.setInput(this.root).then(() => this.updateContentAreas()); this.tree.setInput(this.root).then(() => this.updateContentAreas());
const customTreeNavigator = ResourceNavigator.createTreeResourceNavigator(this.tree, { openOnFocus: false, openOnSelection: false }); const customTreeNavigator = new TreeResourceNavigator(this.tree, { openOnFocus: false, openOnSelection: false });
this._register(customTreeNavigator); this._register(customTreeNavigator);
this._register(customTreeNavigator.onDidOpenResource(e => { this._register(customTreeNavigator.onDidOpenResource(e => {
if (!e.browserEvent) { if (!e.browserEvent) {

View File

@@ -28,7 +28,8 @@ class AccountsStatusBarContributions extends Disposable implements IWorkbenchCon
this._register( this._register(
this.statusbarService.addEntry({ this.statusbarService.addEntry({
command: 'workbench.actions.modal.linkedAccount', command: 'workbench.actions.modal.linkedAccount',
text: '$(person-filled)' text: '$(person-filled)',
ariaLabel: 'Accounts'
}, },
'status.accountList', 'status.accountList',
localize('status.problems', "Problems"), localize('status.problems', "Problems"),

View File

@@ -30,6 +30,7 @@ export class ConnectionStatusbarItem extends Disposable implements IWorkbenchCon
this.statusItem = this._register( this.statusItem = this._register(
this.statusbarService.addEntry({ this.statusbarService.addEntry({
text: '', text: '',
ariaLabel: ''
}, },
ConnectionStatusbarItem.ID, ConnectionStatusbarItem.ID,
localize('status.connection.status', "Connection Status"), localize('status.connection.status', "Connection Status"),
@@ -84,7 +85,7 @@ export class ConnectionStatusbarItem extends Disposable implements IWorkbenchCon
} }
this.statusItem.update({ this.statusItem.update({
text, tooltip text, ariaLabel: text, tooltip
}); });
} }
} }

View File

@@ -105,7 +105,7 @@ export class DataExplorerViewPaneContainer extends ViewPaneContainer {
@IContextKeyService private contextKeyService: IContextKeyService, @IContextKeyService private contextKeyService: IContextKeyService,
@IViewDescriptorService viewDescriptorService: IViewDescriptorService @IViewDescriptorService viewDescriptorService: IViewDescriptorService
) { ) {
super(VIEWLET_ID, `${VIEWLET_ID}.state`, { mergeViewWithContainerWhenSingleView: true }, instantiationService, configurationService, layoutService, contextMenuService, telemetryService, extensionService, themeService, storageService, contextService, viewDescriptorService); super(VIEWLET_ID, { mergeViewWithContainerWhenSingleView: true }, instantiationService, configurationService, layoutService, contextMenuService, telemetryService, extensionService, themeService, storageService, contextService, viewDescriptorService);
} }
create(parent: HTMLElement): void { create(parent: HTMLElement): void {

View File

@@ -88,11 +88,13 @@ export class EditDataEditor extends BaseEditor {
} }
if (_editorService) { if (_editorService) {
_editorService.overrideOpenEditor((editor, options, group) => { _editorService.overrideOpenEditor({
if (this.isVisible() && (editor !== this.input || group !== this.group)) { open: (editor, options, group) => {
this.saveEditorViewState(); if (this.isVisible() && (editor !== this.input || group !== this.group)) {
this.saveEditorViewState();
}
return {};
} }
return {};
}); });
} }
} }

View File

@@ -27,7 +27,9 @@ export class EditorReplacementContribution implements IWorkbenchContribution {
@IEditorService private readonly editorService: IEditorService, @IEditorService private readonly editorService: IEditorService,
@IModeService private readonly modeService: IModeService @IModeService private readonly modeService: IModeService
) { ) {
this.editorOpeningListener = this.editorService.overrideOpenEditor((editor, options, group) => this.onEditorOpening(editor, options, group)); this.editorOpeningListener = this.editorService.overrideOpenEditor({
open: (editor, options, group) => this.onEditorOpening(editor, options, group)
});
} }
private onEditorOpening(editor: IEditorInput, options: IEditorOptions | ITextEditorOptions | undefined, group: IEditorGroup): IOpenEditorOverride | undefined { private onEditorOpening(editor: IEditorInput, options: IEditorOptions | ITextEditorOptions | undefined, group: IEditorGroup): IOpenEditorOverride | undefined {

View File

@@ -194,7 +194,7 @@ class MockEditorService extends TestEditorService {
fireOpenEditor(editor: IEditorInput, options: IEditorOptions | ITextEditorOptions | undefined, group: IEditorGroup) { fireOpenEditor(editor: IEditorInput, options: IEditorOptions | ITextEditorOptions | undefined, group: IEditorGroup) {
for (const handler of this.overridenOpens) { for (const handler of this.overridenOpens) {
let response: IOpenEditorOverride | undefined; let response: IOpenEditorOverride | undefined;
if (response = handler(editor, options, group)) { if (response = handler.open(editor, options, group)) {
return response; return response;
} }
} }

View File

@@ -0,0 +1,140 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ExtensionRecommendations, ExtensionRecommendation } from 'vs/workbench/contrib/extensions/browser/extensionRecommendations';
import { IProductService } from 'vs/platform/product/common/productService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { localize } from 'vs/nls';
import { IExtensionRecommendation } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
import { IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionType } from 'vs/platform/extensions/common/extensions';
import { visualizerExtensions } from 'sql/workbench/contrib/extensions/common/constants';
import { IAdsTelemetryService } from 'sql/platform/telemetry/common/telemetry';
import * as TelemetryKeys from 'sql/platform/telemetry/common/telemetryKeys';
import { InstallRecommendedExtensionsByScenarioAction, ShowRecommendedExtensionsByScenarioAction } from 'sql/workbench/contrib/extensions/browser/extensionsActions';
import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys';
const choiceNever = localize('neverShowAgain', "Don't Show Again");
export class ScenarioRecommendations extends ExtensionRecommendations {
readonly _recommendations: ExtensionRecommendation[] = [];
get recommendations(): ReadonlyArray<ExtensionRecommendation> { return this._recommendations; }
constructor(
isExtensionAllowedToBeRecommended: (extensionId: string) => boolean,
@IProductService private readonly productService: IProductService,
@IInstantiationService instantiationService: IInstantiationService,
@IConfigurationService configurationService: IConfigurationService,
@INotificationService notificationService: INotificationService,
@ITelemetryService telemetryService: ITelemetryService,
@IStorageService storageService: IStorageService,
@IExtensionManagementService private readonly extensionManagementService: IExtensionManagementService,
@IAdsTelemetryService private readonly adsTelemetryService: IAdsTelemetryService,
@IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService
) {
super(isExtensionAllowedToBeRecommended, instantiationService, configurationService, notificationService, telemetryService, storageService, storageKeysSyncRegistryService);
// this._recommendations = productService.recommendedExtensionsByScenario.map(r => ({ extensionId: r, reason: { reasonId: ExtensionRecommendationReason.Application, reasonText: localize('defaultRecommendations', "This extension is recommended by Azure Data Studio.") }, source: 'application' }));
}
protected async doActivate(): Promise<void> {
return;
}
// {{SQL CARBON EDIT}}
promptRecommendedExtensionsByScenario(scenarioType: string): void {
const storageKey = 'extensionAssistant/RecommendationsIgnore/' + scenarioType;
if (this.storageService.getBoolean(storageKey, StorageScope.GLOBAL, false)) {
return;
}
const visualizerExtensionNotificationService = 'VisualizerExtensionNotificationService';
let recommendationMessage = localize('ExtensionsRecommended', "Azure Data Studio has extension recommendations.");
if (scenarioType === visualizerExtensions) {
recommendationMessage = localize('VisualizerExtensionsRecommended', "Azure Data Studio has extension recommendations for data visualization.\nOnce installed, you can select the Visualizer icon to visualize your query results.");
}
Promise.all([this.getRecommendedExtensionsByScenario(scenarioType), this.extensionManagementService.getInstalled(ExtensionType.User)]).then(([recommendations, localExtensions]) => {
if (!recommendations.every(rec => { return localExtensions.findIndex(local => local.identifier.id.toLocaleLowerCase() === rec.extensionId.toLocaleLowerCase()) !== -1; })) {
return new Promise<void>(c => {
this.notificationService.prompt(
Severity.Info,
recommendationMessage,
[{
label: localize('installAll', "Install All"),
run: () => {
this.adsTelemetryService.sendActionEvent(
TelemetryKeys.TelemetryView.ExtensionRecommendationDialog,
TelemetryKeys.TelemetryAction.Click,
'InstallButton',
visualizerExtensionNotificationService
);
const installAllAction = this.instantiationService.createInstance(InstallRecommendedExtensionsByScenarioAction, scenarioType, recommendations);
installAllAction.run();
installAllAction.dispose();
}
}, {
label: localize('showRecommendations', "Show Recommendations"),
run: () => {
this.adsTelemetryService.sendActionEvent(
TelemetryKeys.TelemetryView.ExtensionRecommendationDialog,
TelemetryKeys.TelemetryAction.Click,
'ShowRecommendationsButton',
visualizerExtensionNotificationService
);
const showAction = this.instantiationService.createInstance(ShowRecommendedExtensionsByScenarioAction, scenarioType);
showAction.run();
showAction.dispose();
c(undefined);
}
}, {
label: choiceNever,
isSecondary: true,
run: () => {
this.adsTelemetryService.sendActionEvent(
TelemetryKeys.TelemetryView.ExtensionRecommendationDialog,
TelemetryKeys.TelemetryAction.Click,
'NeverShowAgainButton',
visualizerExtensionNotificationService
);
this.storageService.store(storageKey, true, StorageScope.GLOBAL);
c(undefined);
}
}],
{
sticky: true,
onCancel: () => {
this.adsTelemetryService.sendActionEvent(
TelemetryKeys.TelemetryView.ExtensionRecommendationDialog,
TelemetryKeys.TelemetryAction.Click,
'CancelButton',
visualizerExtensionNotificationService
);
c(undefined);
}
}
);
});
} else {
return Promise.resolve();
}
});
}
getRecommendedExtensionsByScenario(scenarioType: string): Promise<IExtensionRecommendation[]> {
if (!scenarioType) {
return Promise.reject(new Error(localize('scenarioTypeUndefined', 'The scenario type for extension recommendations must be provided.')));
}
return Promise.resolve((this.productService.recommendedExtensionsByScenario[scenarioType] || [])
.filter(extensionId => this.isExtensionAllowedToBeRecommended(extensionId))
.map(extensionId => (<IExtensionRecommendation>{ extensionId, sources: ['application'] })));
}
}

View File

@@ -0,0 +1,40 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ExtensionRecommendations, ExtensionRecommendation } from 'vs/workbench/contrib/extensions/browser/extensionRecommendations';
import { IProductService } from 'vs/platform/product/common/productService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { localize } from 'vs/nls';
import { ExtensionRecommendationReason } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys';
export class StaticRecommendations extends ExtensionRecommendations {
readonly _recommendations: ExtensionRecommendation[] = [];
get recommendations(): ReadonlyArray<ExtensionRecommendation> { return this._recommendations; }
constructor(
isExtensionAllowedToBeRecommended: (extensionId: string) => boolean,
@IProductService productService: IProductService,
@IInstantiationService instantiationService: IInstantiationService,
@IConfigurationService configurationService: IConfigurationService,
@INotificationService notificationService: INotificationService,
@ITelemetryService telemetryService: ITelemetryService,
@IStorageService storageService: IStorageService,
@IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService
) {
super(isExtensionAllowedToBeRecommended, instantiationService, configurationService, notificationService, telemetryService, storageService, storageKeysSyncRegistryService);
this._recommendations = productService.recommendedExtensions.map(r => ({ extensionId: r, reason: { reasonId: ExtensionRecommendationReason.Application, reasonText: localize('defaultRecommendations', "This extension is recommended by Azure Data Studio.") }, source: 'application' }));
}
protected async doActivate(): Promise<void> {
return;
}
}

View File

@@ -365,7 +365,8 @@ export class NotebookEditor extends BaseEditor implements IFindNotebookControlle
searchScope: true, searchScope: true,
matchesPosition: false, matchesPosition: false,
matchesCount: false, matchesCount: false,
currentMatch: false currentMatch: false,
loop: true
}; };
this._notebookModel.cells.forEach(cell => { this._notebookModel.cells.forEach(cell => {
this._register(cell.onCellModeChanged((state) => { this._register(cell.onCellModeChanged((state) => {
@@ -450,7 +451,8 @@ export class NotebookEditor extends BaseEditor implements IFindNotebookControlle
searchScope: false, searchScope: false,
matchesPosition: false, matchesPosition: false,
matchesCount: false, matchesCount: false,
currentMatch: false currentMatch: false,
loop: true
}; };
this._onFindStateChange(changeEvent).catch(e => { onUnexpectedError(e); }); this._onFindStateChange(changeEvent).catch(e => { onUnexpectedError(e); });
} }

View File

@@ -172,11 +172,13 @@ export class ProfilerEditor extends BaseEditor {
this._profilerEditorContextKey = CONTEXT_PROFILER_EDITOR.bindTo(this._contextKeyService); this._profilerEditorContextKey = CONTEXT_PROFILER_EDITOR.bindTo(this._contextKeyService);
if (editorService) { if (editorService) {
editorService.overrideOpenEditor((editor, options, group) => { editorService.overrideOpenEditor({
if (this.isVisible() && (editor !== this.input || group !== this.group)) { open: (editor, options, group) => {
this.saveEditorViewState(); if (this.isVisible() && (editor !== this.input || group !== this.group)) {
this.saveEditorViewState();
}
return {};
} }
return {};
}); });
} }
} }
@@ -502,7 +504,8 @@ export class ProfilerEditor extends BaseEditor {
seedSearchStringFromSelection: (controller.getState().searchString.length === 0), seedSearchStringFromSelection: (controller.getState().searchString.length === 0),
shouldFocus: FindStartFocusAction.FocusFindInput, shouldFocus: FindStartFocusAction.FocusFindInput,
shouldAnimate: true, shouldAnimate: true,
updateSearchScope: false updateSearchScope: false,
loop: true
}); });
} }
} else { } else {

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