Archived
Merge from vscode 9bc92b48d945144abb405b9e8df05e18accb9148
This commit is contained in:
+1
-1
@@ -193,7 +193,7 @@
|
|||||||
"typemoq",
|
"typemoq",
|
||||||
"sinon",
|
"sinon",
|
||||||
"vs/nls",
|
"vs/nls",
|
||||||
"azdata",
|
"azdata",
|
||||||
"**/{vs,sql}/base/common/**",
|
"**/{vs,sql}/base/common/**",
|
||||||
"**/{vs,sql}/base/test/common/**",
|
"**/{vs,sql}/base/test/common/**",
|
||||||
"**/{vs,sql}/base/parts/*/common/**",
|
"**/{vs,sql}/base/parts/*/common/**",
|
||||||
|
|||||||
Vendored
-2
@@ -16,8 +16,6 @@
|
|||||||
"request": "attach",
|
"request": "attach",
|
||||||
"name": "Attach to Extension Host",
|
"name": "Attach to Extension Host",
|
||||||
"port": 5870,
|
"port": 5870,
|
||||||
"timeout": 30000,
|
|
||||||
"restart": true,
|
|
||||||
"outFiles": [
|
"outFiles": [
|
||||||
"${workspaceFolder}/out/**/*.js"
|
"${workspaceFolder}/out/**/*.js"
|
||||||
]
|
]
|
||||||
|
|||||||
Vendored
-14
@@ -31,20 +31,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"type": "npm",
|
|
||||||
"script": "strict-function-types-watch",
|
|
||||||
"label": "TS - Strict Function Types",
|
|
||||||
"isBackground": true,
|
|
||||||
"presentation": {
|
|
||||||
"reveal": "never"
|
|
||||||
},
|
|
||||||
"problemMatcher": {
|
|
||||||
"base": "$tsc-watch",
|
|
||||||
"owner": "typescript-function-types",
|
|
||||||
"applyTo": "allDocuments"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "npm",
|
"type": "npm",
|
||||||
"script": "strict-vscode-watch",
|
"script": "strict-vscode-watch",
|
||||||
|
|||||||
@@ -207,7 +207,7 @@ steps:
|
|||||||
"toolVersion": "1.0"
|
"toolVersion": "1.0"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
SessionTimeout: 120
|
SessionTimeout: 60
|
||||||
displayName: Notarization
|
displayName: Notarization
|
||||||
|
|
||||||
- script: |
|
- script: |
|
||||||
|
|||||||
+120
-83
@@ -467,57 +467,61 @@
|
|||||||
],
|
],
|
||||||
"menus": {
|
"menus": {
|
||||||
"commandPalette": [
|
"commandPalette": [
|
||||||
|
{
|
||||||
|
"command": "git.setLogLevel",
|
||||||
|
"when": "config.git.enabled && !git.missing"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"command": "git.clone",
|
"command": "git.clone",
|
||||||
"when": "config.git.enabled"
|
"when": "config.git.enabled && !git.missing"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.init",
|
"command": "git.init",
|
||||||
"when": "config.git.enabled"
|
"when": "config.git.enabled && !git.missing"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.openRepository",
|
"command": "git.openRepository",
|
||||||
"when": "config.git.enabled"
|
"when": "config.git.enabled && !git.missing"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.close",
|
"command": "git.close",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.refresh",
|
"command": "git.refresh",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.openFile",
|
"command": "git.openFile",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.openHEADFile",
|
"command": "git.openHEADFile",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.openChange",
|
"command": "git.openChange",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.stage",
|
"command": "git.stage",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.stageAll",
|
"command": "git.stageAll",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.stageAllTracked",
|
"command": "git.stageAllTracked",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.stageAllUntracked",
|
"command": "git.stageAllUntracked",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.stageSelectedRanges",
|
"command": "git.stageSelectedRanges",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.stageChange",
|
"command": "git.stageChange",
|
||||||
@@ -525,7 +529,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.revertSelectedRanges",
|
"command": "git.revertSelectedRanges",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.revertChange",
|
"command": "git.revertChange",
|
||||||
@@ -537,51 +541,63 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.unstage",
|
"command": "git.unstage",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.unstageAll",
|
"command": "git.unstageAll",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.unstageSelectedRanges",
|
"command": "git.unstageSelectedRanges",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.clean",
|
"command": "git.clean",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.cleanAll",
|
"command": "git.cleanAll",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "git.cleanAllTracked",
|
||||||
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "git.cleanAllUntracked",
|
||||||
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.commit",
|
"command": "git.commit",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.commitStaged",
|
"command": "git.commitStaged",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "git.commitEmpty",
|
||||||
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.commitStagedSigned",
|
"command": "git.commitStagedSigned",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.commitStagedAmend",
|
"command": "git.commitStagedAmend",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.commitAll",
|
"command": "git.commitAll",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.commitAllSigned",
|
"command": "git.commitAllSigned",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.commitAllAmend",
|
"command": "git.commitAllAmend",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.restoreCommitTemplate",
|
"command": "git.restoreCommitTemplate",
|
||||||
@@ -593,111 +609,111 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.undoCommit",
|
"command": "git.undoCommit",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.checkout",
|
"command": "git.checkout",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.branch",
|
"command": "git.branch",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.branchFrom",
|
"command": "git.branchFrom",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.deleteBranch",
|
"command": "git.deleteBranch",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.renameBranch",
|
"command": "git.renameBranch",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.pull",
|
"command": "git.pull",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.pullFrom",
|
"command": "git.pullFrom",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.pullRebase",
|
"command": "git.pullRebase",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.pullFrom",
|
"command": "git.pullFrom",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.merge",
|
"command": "git.merge",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.createTag",
|
"command": "git.createTag",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.deleteTag",
|
"command": "git.deleteTag",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.fetch",
|
"command": "git.fetch",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.fetchPrune",
|
"command": "git.fetchPrune",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.fetchAll",
|
"command": "git.fetchAll",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.push",
|
"command": "git.push",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.pushForce",
|
"command": "git.pushForce",
|
||||||
"when": "config.git.enabled && config.git.allowForcePush && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && config.git.allowForcePush && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.pushTo",
|
"command": "git.pushTo",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.pushToForce",
|
"command": "git.pushToForce",
|
||||||
"when": "config.git.enabled && config.git.allowForcePush && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && config.git.allowForcePush && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.pushWithTags",
|
"command": "git.pushWithTags",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.pushWithTagsForce",
|
"command": "git.pushWithTagsForce",
|
||||||
"when": "config.git.enabled && config.git.allowForcePush && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && config.git.allowForcePush && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.addRemote",
|
"command": "git.addRemote",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.removeRemote",
|
"command": "git.removeRemote",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.sync",
|
"command": "git.sync",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.syncRebase",
|
"command": "git.syncRebase",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.publish",
|
"command": "git.publish",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.showOutput",
|
"command": "git.showOutput",
|
||||||
@@ -705,35 +721,35 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.ignore",
|
"command": "git.ignore",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.stashIncludeUntracked",
|
"command": "git.stashIncludeUntracked",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.stash",
|
"command": "git.stash",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.stashPop",
|
"command": "git.stashPop",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.stashPopLatest",
|
"command": "git.stashPopLatest",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.stashApply",
|
"command": "git.stashApply",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.stashApplyLatest",
|
"command": "git.stashApplyLatest",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.stashDrop",
|
"command": "git.stashDrop",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.timeline.openDiff",
|
"command": "git.timeline.openDiff",
|
||||||
@@ -749,11 +765,6 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"scm/title": [
|
"scm/title": [
|
||||||
{
|
|
||||||
"command": "git.init",
|
|
||||||
"group": "navigation",
|
|
||||||
"when": "config.git.enabled && !scmProvider && gitOpenRepositoryCount == 0 && workspaceFolderCount != 0"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"command": "git.commit",
|
"command": "git.commit",
|
||||||
"group": "navigation",
|
"group": "navigation",
|
||||||
@@ -1227,76 +1238,76 @@
|
|||||||
{
|
{
|
||||||
"command": "git.openFile",
|
"command": "git.openFile",
|
||||||
"group": "navigation",
|
"group": "navigation",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.openChange",
|
"command": "git.openChange",
|
||||||
"group": "navigation",
|
"group": "navigation",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0 && !isInDiffEditor && resourceScheme == file"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0 && !isInDiffEditor && resourceScheme == file"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.stageSelectedRanges",
|
"command": "git.stageSelectedRanges",
|
||||||
"group": "2_git@1",
|
"group": "2_git@1",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.unstageSelectedRanges",
|
"command": "git.unstageSelectedRanges",
|
||||||
"group": "2_git@2",
|
"group": "2_git@2",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.revertSelectedRanges",
|
"command": "git.revertSelectedRanges",
|
||||||
"group": "2_git@3",
|
"group": "2_git@3",
|
||||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
|
"when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"editor/context": [
|
"editor/context": [
|
||||||
{
|
{
|
||||||
"command": "git.stageSelectedRanges",
|
"command": "git.stageSelectedRanges",
|
||||||
"group": "2_git@1",
|
"group": "2_git@1",
|
||||||
"when": "isInDiffRightEditor && config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
|
"when": "isInDiffRightEditor && config.git.enabled && !git.missing && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.unstageSelectedRanges",
|
"command": "git.unstageSelectedRanges",
|
||||||
"group": "2_git@2",
|
"group": "2_git@2",
|
||||||
"when": "isInDiffRightEditor && config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
|
"when": "isInDiffRightEditor && config.git.enabled && !git.missing && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.revertSelectedRanges",
|
"command": "git.revertSelectedRanges",
|
||||||
"group": "2_git@3",
|
"group": "2_git@3",
|
||||||
"when": "isInDiffRightEditor && config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
|
"when": "isInDiffRightEditor && config.git.enabled && !git.missing && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"scm/change/title": [
|
"scm/change/title": [
|
||||||
{
|
{
|
||||||
"command": "git.stageChange",
|
"command": "git.stageChange",
|
||||||
"when": "originalResourceScheme == git"
|
"when": "config.git.enabled && !git.missing && originalResourceScheme == git"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.revertChange",
|
"command": "git.revertChange",
|
||||||
"when": "originalResourceScheme == git"
|
"when": "config.git.enabled && !git.missing && originalResourceScheme == git"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"timeline/item/context": [
|
"timeline/item/context": [
|
||||||
{
|
{
|
||||||
"command": "git.timeline.openDiff",
|
"command": "git.timeline.openDiff",
|
||||||
"group": "inline",
|
"group": "inline",
|
||||||
"when": "timelineItem =~ /git:file\\b/"
|
"when": "config.git.enabled && !git.missing && timelineItem =~ /git:file\\b/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.timeline.openDiff",
|
"command": "git.timeline.openDiff",
|
||||||
"group": "1_timeline",
|
"group": "1_timeline",
|
||||||
"when": "timelineItem =~ /git:file\\b/"
|
"when": "config.git.enabled && !git.missing && timelineItem =~ /git:file\\b/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.timeline.copyCommitId",
|
"command": "git.timeline.copyCommitId",
|
||||||
"group": "2_timeline@1",
|
"group": "2_timeline@1",
|
||||||
"when": "timelineItem =~ /git:file:commit\\b/"
|
"when": "config.git.enabled && !git.missing && timelineItem =~ /git:file:commit\\b/"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.timeline.copyCommitMessage",
|
"command": "git.timeline.copyCommitMessage",
|
||||||
"group": "2_timeline@2",
|
"group": "2_timeline@2",
|
||||||
"when": "timelineItem =~ /git:file:commit\\b/"
|
"when": "config.git.enabled && !git.missing && timelineItem =~ /git:file:commit\\b/"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -1811,7 +1822,34 @@
|
|||||||
72
|
72
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"viewsWelcome": [
|
||||||
|
{
|
||||||
|
"view": "workbench.scm",
|
||||||
|
"contents": "%view.workbench.scm.disabled%",
|
||||||
|
"when": "!config.git.enabled"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"view": "workbench.scm",
|
||||||
|
"contents": "%view.workbench.scm.missing%",
|
||||||
|
"when": "config.git.enabled && git.missing"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"view": "workbench.scm",
|
||||||
|
"contents": "%view.workbench.scm.empty%",
|
||||||
|
"when": "config.git.enabled && !git.missing && workbenchState == empty"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"view": "workbench.scm",
|
||||||
|
"contents": "%view.workbench.scm.folder%",
|
||||||
|
"when": "config.git.enabled && !git.missing && workbenchState == folder"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"view": "workbench.scm",
|
||||||
|
"contents": "%view.workbench.scm.workspace%",
|
||||||
|
"when": "config.git.enabled && !git.missing && workbenchState == workspace"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"byline": "^5.0.0",
|
"byline": "^5.0.0",
|
||||||
@@ -1829,11 +1867,10 @@
|
|||||||
"@types/file-type": "^5.2.1",
|
"@types/file-type": "^5.2.1",
|
||||||
"@types/mocha": "2.2.43",
|
"@types/mocha": "2.2.43",
|
||||||
"@types/node": "^12.11.7",
|
"@types/node": "^12.11.7",
|
||||||
"@types/vscode": "^1.42",
|
|
||||||
"@types/which": "^1.0.28",
|
"@types/which": "^1.0.28",
|
||||||
"mocha": "^3.2.0",
|
"mocha": "^3.2.0",
|
||||||
"mocha-junit-reporter": "^1.23.3",
|
"mocha-junit-reporter": "^1.23.3",
|
||||||
"mocha-multi-reporters": "^1.1.7",
|
"mocha-multi-reporters": "^1.1.7",
|
||||||
"vscode-test": "^1.3.0"
|
"vscode": "^1.1.36"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -149,5 +149,10 @@
|
|||||||
"colors.untracked": "Color for untracked resources.",
|
"colors.untracked": "Color for untracked resources.",
|
||||||
"colors.ignored": "Color for ignored resources.",
|
"colors.ignored": "Color for ignored resources.",
|
||||||
"colors.conflict": "Color for resources with conflicts.",
|
"colors.conflict": "Color for resources with conflicts.",
|
||||||
"colors.submodule": "Color for submodule resources."
|
"colors.submodule": "Color for submodule resources.",
|
||||||
|
"view.workbench.scm.missing": "A valid git installation was not detected, more details can be found in the [git output](command:git.showOutput).\nPlease [install git](https://git-scm.com/), or learn more about how to use Git and source control in VS Code in [our docs](https://aka.ms/vscode-scm).\nIf you're using a different version control system, you can [search the Marketplace](command:workbench.extensions.search?%22%40category%3A%5C%22scm%20providers%5C%22%22) for additional extensions.",
|
||||||
|
"view.workbench.scm.disabled": "If you would like to use git features, please enable git in your [settings](command:workbench.action.openSettings?%5B%22git.enabled%22%5D).\nTo learn more about how to use Git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).",
|
||||||
|
"view.workbench.scm.empty": "In order to use git features, you can open a folder containing a git repository or clone from a URL.\n[Open Folder](command:vscode.openFolder)\n[Clone from URL](command:git.clone)\nTo learn more about how to use Git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).",
|
||||||
|
"view.workbench.scm.folder": "The folder currently open doesn't have a git repository.\n[Initialize Repository](command:git.init)\nTo learn more about how to use Git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).",
|
||||||
|
"view.workbench.scm.workspace": "The workspace currently open doesn't have any folders containing git repositories.\n[Initialize Repository](command:git.init)\nTo learn more about how to use Git and source control in VS Code [read our docs](https://aka.ms/vscode-scm)."
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+1
@@ -44,6 +44,7 @@ export interface Commit {
|
|||||||
readonly authorDate?: Date;
|
readonly authorDate?: Date;
|
||||||
readonly authorName?: string;
|
readonly authorName?: string;
|
||||||
readonly authorEmail?: string;
|
readonly authorEmail?: string;
|
||||||
|
readonly commitDate?: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Submodule {
|
export interface Submodule {
|
||||||
|
|||||||
@@ -333,7 +333,7 @@ function sanitizePath(path: string): string {
|
|||||||
return path.replace(/^([a-z]):\\/i, (_, letter) => `${letter.toUpperCase()}:\\`);
|
return path.replace(/^([a-z]):\\/i, (_, letter) => `${letter.toUpperCase()}:\\`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const COMMIT_FORMAT = '%H%n%aN%n%aE%n%at%n%P%n%B';
|
const COMMIT_FORMAT = '%H%n%aN%n%aE%n%at%n%ct%n%P%n%B';
|
||||||
|
|
||||||
export class Git {
|
export class Git {
|
||||||
|
|
||||||
@@ -525,6 +525,7 @@ export interface Commit {
|
|||||||
authorDate?: Date;
|
authorDate?: Date;
|
||||||
authorName?: string;
|
authorName?: string;
|
||||||
authorEmail?: string;
|
authorEmail?: string;
|
||||||
|
commitDate?: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class GitStatusParser {
|
export class GitStatusParser {
|
||||||
@@ -655,15 +656,16 @@ export function parseGitmodules(raw: string): Submodule[] {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
const commitRegex = /([0-9a-f]{40})\n(.*)\n(.*)\n(.*)\n(.*)(?:\n([^]*?))?(?:\x00)/gm;
|
const commitRegex = /([0-9a-f]{40})\n(.*)\n(.*)\n(.*)\n(.*)\n(.*)(?:\n([^]*?))?(?:\x00)/gm;
|
||||||
|
|
||||||
export function parseGitCommits(data: string): Commit[] {
|
export function parseGitCommits(data: string): Commit[] {
|
||||||
let commits: Commit[] = [];
|
let commits: Commit[] = [];
|
||||||
|
|
||||||
let ref;
|
let ref;
|
||||||
let name;
|
let authorName;
|
||||||
let email;
|
let authorEmail;
|
||||||
let date;
|
let authorDate;
|
||||||
|
let commitDate;
|
||||||
let parents;
|
let parents;
|
||||||
let message;
|
let message;
|
||||||
let match;
|
let match;
|
||||||
@@ -674,7 +676,7 @@ export function parseGitCommits(data: string): Commit[] {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
[, ref, name, email, date, parents, message] = match;
|
[, ref, authorName, authorEmail, authorDate, commitDate, parents, message] = match;
|
||||||
|
|
||||||
if (message[message.length - 1] === '\n') {
|
if (message[message.length - 1] === '\n') {
|
||||||
message = message.substr(0, message.length - 1);
|
message = message.substr(0, message.length - 1);
|
||||||
@@ -685,9 +687,10 @@ export function parseGitCommits(data: string): Commit[] {
|
|||||||
hash: ` ${ref}`.substr(1),
|
hash: ` ${ref}`.substr(1),
|
||||||
message: ` ${message}`.substr(1),
|
message: ` ${message}`.substr(1),
|
||||||
parents: parents ? parents.split(' ') : [],
|
parents: parents ? parents.split(' ') : [],
|
||||||
authorDate: new Date(Number(date) * 1000),
|
authorDate: new Date(Number(authorDate) * 1000),
|
||||||
authorName: ` ${name}`.substr(1),
|
authorName: ` ${authorName}`.substr(1),
|
||||||
authorEmail: ` ${email}`.substr(1)
|
authorEmail: ` ${authorEmail}`.substr(1),
|
||||||
|
commitDate: new Date(Number(commitDate) * 1000),
|
||||||
});
|
});
|
||||||
} while (true);
|
} while (true);
|
||||||
|
|
||||||
|
|||||||
@@ -178,7 +178,8 @@ export async function activate(context: ExtensionContext): Promise<GitExtension>
|
|||||||
// console.warn(err.message);
|
// console.warn(err.message);
|
||||||
// outputChannel.appendLine(err.message);
|
// outputChannel.appendLine(err.message);
|
||||||
|
|
||||||
// warnAboutMissingGit();
|
commands.executeCommand('setContext', 'git.missing', true);
|
||||||
|
// warnAboutMissingGit(); {{SQL CARBON EDIT}} turn-off Git missing prompt
|
||||||
|
|
||||||
return new GitExtensionImpl();
|
return new GitExtensionImpl();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -192,6 +192,7 @@ suite('git', () => {
|
|||||||
John Doe
|
John Doe
|
||||||
john.doe@mail.com
|
john.doe@mail.com
|
||||||
1580811030
|
1580811030
|
||||||
|
1580811031
|
||||||
8e5a374372b8393906c7e380dbb09349c5385554
|
8e5a374372b8393906c7e380dbb09349c5385554
|
||||||
This is a commit message.\x00`;
|
This is a commit message.\x00`;
|
||||||
|
|
||||||
@@ -202,6 +203,7 @@ This is a commit message.\x00`;
|
|||||||
authorDate: new Date(1580811030000),
|
authorDate: new Date(1580811030000),
|
||||||
authorName: 'John Doe',
|
authorName: 'John Doe',
|
||||||
authorEmail: 'john.doe@mail.com',
|
authorEmail: 'john.doe@mail.com',
|
||||||
|
commitDate: new Date(1580811031000),
|
||||||
}]);
|
}]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -210,6 +212,7 @@ This is a commit message.\x00`;
|
|||||||
John Doe
|
John Doe
|
||||||
john.doe@mail.com
|
john.doe@mail.com
|
||||||
1580811030
|
1580811030
|
||||||
|
1580811031
|
||||||
8e5a374372b8393906c7e380dbb09349c5385554 df27d8c75b129ab9b178b386077da2822101b217
|
8e5a374372b8393906c7e380dbb09349c5385554 df27d8c75b129ab9b178b386077da2822101b217
|
||||||
This is a commit message.\x00`;
|
This is a commit message.\x00`;
|
||||||
|
|
||||||
@@ -220,6 +223,7 @@ This is a commit message.\x00`;
|
|||||||
authorDate: new Date(1580811030000),
|
authorDate: new Date(1580811030000),
|
||||||
authorName: 'John Doe',
|
authorName: 'John Doe',
|
||||||
authorEmail: 'john.doe@mail.com',
|
authorEmail: 'john.doe@mail.com',
|
||||||
|
commitDate: new Date(1580811031000),
|
||||||
}]);
|
}]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -228,6 +232,7 @@ This is a commit message.\x00`;
|
|||||||
John Doe
|
John Doe
|
||||||
john.doe@mail.com
|
john.doe@mail.com
|
||||||
1580811030
|
1580811030
|
||||||
|
1580811031
|
||||||
|
|
||||||
This is a commit message.\x00`;
|
This is a commit message.\x00`;
|
||||||
|
|
||||||
@@ -238,6 +243,7 @@ This is a commit message.\x00`;
|
|||||||
authorDate: new Date(1580811030000),
|
authorDate: new Date(1580811030000),
|
||||||
authorName: 'John Doe',
|
authorName: 'John Doe',
|
||||||
authorEmail: 'john.doe@mail.com',
|
authorEmail: 'john.doe@mail.com',
|
||||||
|
commitDate: new Date(1580811031000),
|
||||||
}]);
|
}]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
+436
-21
@@ -31,11 +31,6 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.7.tgz#57682a9771a3f7b09c2497f28129a0462966524a"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.11.7.tgz#57682a9771a3f7b09c2497f28129a0462966524a"
|
||||||
integrity sha512-JNbGaHFCLwgHn/iCckiGSOZ1XYHsKFwREtzPwSGCVld1SGhOlmZw2D4ZI94HQCrBHbADzW9m4LER/8olJTRGHA==
|
integrity sha512-JNbGaHFCLwgHn/iCckiGSOZ1XYHsKFwREtzPwSGCVld1SGhOlmZw2D4ZI94HQCrBHbADzW9m4LER/8olJTRGHA==
|
||||||
|
|
||||||
"@types/vscode@^1.42":
|
|
||||||
version "1.42.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/vscode/-/vscode-1.42.0.tgz#0ad891a9487e91e34be7c56985058a179031eb76"
|
|
||||||
integrity sha512-ds6TceMsh77Fs0Mq0Vap6Y72JbGWB8Bay4DrnJlf5d9ui2RSe1wis13oQm+XhguOeH1HUfLGzaDAoupTUtgabw==
|
|
||||||
|
|
||||||
"@types/which@^1.0.28":
|
"@types/which@^1.0.28":
|
||||||
version "1.0.28"
|
version "1.0.28"
|
||||||
resolved "https://registry.yarnpkg.com/@types/which/-/which-1.0.28.tgz#016e387629b8817bed653fe32eab5d11279c8df6"
|
resolved "https://registry.yarnpkg.com/@types/which/-/which-1.0.28.tgz#016e387629b8817bed653fe32eab5d11279c8df6"
|
||||||
@@ -48,6 +43,16 @@ agent-base@4, agent-base@^4.3.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
es6-promisify "^5.0.0"
|
es6-promisify "^5.0.0"
|
||||||
|
|
||||||
|
ajv@^6.5.5:
|
||||||
|
version "6.11.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.11.0.tgz#c3607cbc8ae392d8a5a536f25b21f8e5f3f87fe9"
|
||||||
|
integrity sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA==
|
||||||
|
dependencies:
|
||||||
|
fast-deep-equal "^3.1.1"
|
||||||
|
fast-json-stable-stringify "^2.0.0"
|
||||||
|
json-schema-traverse "^0.4.1"
|
||||||
|
uri-js "^4.2.2"
|
||||||
|
|
||||||
ansi-regex@^3.0.0:
|
ansi-regex@^3.0.0:
|
||||||
version "3.0.0"
|
version "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"
|
||||||
@@ -62,11 +67,45 @@ applicationinsights@1.0.8:
|
|||||||
diagnostic-channel-publishers "0.2.1"
|
diagnostic-channel-publishers "0.2.1"
|
||||||
zone.js "0.7.6"
|
zone.js "0.7.6"
|
||||||
|
|
||||||
|
asn1@~0.2.3:
|
||||||
|
version "0.2.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136"
|
||||||
|
integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==
|
||||||
|
dependencies:
|
||||||
|
safer-buffer "~2.1.0"
|
||||||
|
|
||||||
|
assert-plus@1.0.0, assert-plus@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
|
||||||
|
integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=
|
||||||
|
|
||||||
|
asynckit@^0.4.0:
|
||||||
|
version "0.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
|
||||||
|
integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
|
||||||
|
|
||||||
|
aws-sign2@~0.7.0:
|
||||||
|
version "0.7.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
|
||||||
|
integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=
|
||||||
|
|
||||||
|
aws4@^1.8.0:
|
||||||
|
version "1.9.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.1.tgz#7e33d8f7d449b3f673cd72deb9abdc552dbe528e"
|
||||||
|
integrity sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==
|
||||||
|
|
||||||
balanced-match@^1.0.0:
|
balanced-match@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
|
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
|
||||||
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
|
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
|
||||||
|
|
||||||
|
bcrypt-pbkdf@^1.0.0:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
|
||||||
|
integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=
|
||||||
|
dependencies:
|
||||||
|
tweetnacl "^0.14.3"
|
||||||
|
|
||||||
brace-expansion@^1.1.7:
|
brace-expansion@^1.1.7:
|
||||||
version "1.1.8"
|
version "1.1.8"
|
||||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292"
|
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292"
|
||||||
@@ -80,16 +119,43 @@ browser-stdout@1.3.0:
|
|||||||
resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f"
|
resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f"
|
||||||
integrity sha1-81HTKWnTL6XXpVZxVCY9korjvR8=
|
integrity sha1-81HTKWnTL6XXpVZxVCY9korjvR8=
|
||||||
|
|
||||||
|
browser-stdout@1.3.1:
|
||||||
|
version "1.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60"
|
||||||
|
integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==
|
||||||
|
|
||||||
|
buffer-from@^1.0.0:
|
||||||
|
version "1.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
|
||||||
|
integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
|
||||||
|
|
||||||
byline@^5.0.0:
|
byline@^5.0.0:
|
||||||
version "5.0.0"
|
version "5.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/byline/-/byline-5.0.0.tgz#741c5216468eadc457b03410118ad77de8c1ddb1"
|
resolved "https://registry.yarnpkg.com/byline/-/byline-5.0.0.tgz#741c5216468eadc457b03410118ad77de8c1ddb1"
|
||||||
integrity sha1-dBxSFkaOrcRXsDQQEYrXfejB3bE=
|
integrity sha1-dBxSFkaOrcRXsDQQEYrXfejB3bE=
|
||||||
|
|
||||||
|
caseless@~0.12.0:
|
||||||
|
version "0.12.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
|
||||||
|
integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
|
||||||
|
|
||||||
charenc@~0.0.1:
|
charenc@~0.0.1:
|
||||||
version "0.0.2"
|
version "0.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
|
resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
|
||||||
integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=
|
integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=
|
||||||
|
|
||||||
|
combined-stream@^1.0.6, combined-stream@~1.0.6:
|
||||||
|
version "1.0.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
|
||||||
|
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
|
||||||
|
dependencies:
|
||||||
|
delayed-stream "~1.0.0"
|
||||||
|
|
||||||
|
commander@2.15.1:
|
||||||
|
version "2.15.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f"
|
||||||
|
integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==
|
||||||
|
|
||||||
commander@2.9.0:
|
commander@2.9.0:
|
||||||
version "2.9.0"
|
version "2.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4"
|
resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4"
|
||||||
@@ -102,11 +168,23 @@ concat-map@0.0.1:
|
|||||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||||
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
|
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
|
||||||
|
|
||||||
|
core-util-is@1.0.2:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||||
|
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
|
||||||
|
|
||||||
crypt@~0.0.1:
|
crypt@~0.0.1:
|
||||||
version "0.0.2"
|
version "0.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b"
|
resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b"
|
||||||
integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=
|
integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=
|
||||||
|
|
||||||
|
dashdash@^1.12.0:
|
||||||
|
version "1.14.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
|
||||||
|
integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=
|
||||||
|
dependencies:
|
||||||
|
assert-plus "^1.0.0"
|
||||||
|
|
||||||
dayjs@1.8.19:
|
dayjs@1.8.19:
|
||||||
version "1.8.19"
|
version "1.8.19"
|
||||||
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.8.19.tgz#5117dc390d8f8e586d53891dbff3fa308f51abfe"
|
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.8.19.tgz#5117dc390d8f8e586d53891dbff3fa308f51abfe"
|
||||||
@@ -140,6 +218,11 @@ debug@^3.1.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
ms "^2.1.1"
|
ms "^2.1.1"
|
||||||
|
|
||||||
|
delayed-stream@~1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
|
||||||
|
integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
|
||||||
|
|
||||||
diagnostic-channel-publishers@0.2.1:
|
diagnostic-channel-publishers@0.2.1:
|
||||||
version "0.2.1"
|
version "0.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-0.2.1.tgz#8e2d607a8b6d79fe880b548bc58cc6beb288c4f3"
|
resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-0.2.1.tgz#8e2d607a8b6d79fe880b548bc58cc6beb288c4f3"
|
||||||
@@ -157,6 +240,19 @@ diff@3.2.0:
|
|||||||
resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9"
|
resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9"
|
||||||
integrity sha1-yc45Okt8vQsFinJck98pkCeGj/k=
|
integrity sha1-yc45Okt8vQsFinJck98pkCeGj/k=
|
||||||
|
|
||||||
|
diff@3.5.0:
|
||||||
|
version "3.5.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
|
||||||
|
integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==
|
||||||
|
|
||||||
|
ecc-jsbn@~0.1.1:
|
||||||
|
version "0.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
|
||||||
|
integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=
|
||||||
|
dependencies:
|
||||||
|
jsbn "~0.1.0"
|
||||||
|
safer-buffer "^2.1.0"
|
||||||
|
|
||||||
es6-promise@^4.0.3:
|
es6-promise@^4.0.3:
|
||||||
version "4.2.8"
|
version "4.2.8"
|
||||||
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
|
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
|
||||||
@@ -174,16 +270,62 @@ escape-string-regexp@1.0.5:
|
|||||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
||||||
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
|
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
|
||||||
|
|
||||||
|
extend@~3.0.2:
|
||||||
|
version "3.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
|
||||||
|
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
|
||||||
|
|
||||||
|
extsprintf@1.3.0:
|
||||||
|
version "1.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
|
||||||
|
integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=
|
||||||
|
|
||||||
|
extsprintf@^1.2.0:
|
||||||
|
version "1.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
|
||||||
|
integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=
|
||||||
|
|
||||||
|
fast-deep-equal@^3.1.1:
|
||||||
|
version "3.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz#545145077c501491e33b15ec408c294376e94ae4"
|
||||||
|
integrity sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==
|
||||||
|
|
||||||
|
fast-json-stable-stringify@^2.0.0:
|
||||||
|
version "2.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
|
||||||
|
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
|
||||||
|
|
||||||
file-type@^7.2.0:
|
file-type@^7.2.0:
|
||||||
version "7.2.0"
|
version "7.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/file-type/-/file-type-7.2.0.tgz#113cfed52e1d6959ab80248906e2f25a8cdccb74"
|
resolved "https://registry.yarnpkg.com/file-type/-/file-type-7.2.0.tgz#113cfed52e1d6959ab80248906e2f25a8cdccb74"
|
||||||
integrity sha1-ETz+1S4daVmrgCSJBuLyWozcy3Q=
|
integrity sha1-ETz+1S4daVmrgCSJBuLyWozcy3Q=
|
||||||
|
|
||||||
|
forever-agent@~0.6.1:
|
||||||
|
version "0.6.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
|
||||||
|
integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
|
||||||
|
|
||||||
|
form-data@~2.3.2:
|
||||||
|
version "2.3.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
|
||||||
|
integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==
|
||||||
|
dependencies:
|
||||||
|
asynckit "^0.4.0"
|
||||||
|
combined-stream "^1.0.6"
|
||||||
|
mime-types "^2.1.12"
|
||||||
|
|
||||||
fs.realpath@^1.0.0:
|
fs.realpath@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||||
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
|
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
|
||||||
|
|
||||||
|
getpass@^0.1.1:
|
||||||
|
version "0.1.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
|
||||||
|
integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=
|
||||||
|
dependencies:
|
||||||
|
assert-plus "^1.0.0"
|
||||||
|
|
||||||
glob@7.1.1:
|
glob@7.1.1:
|
||||||
version "7.1.1"
|
version "7.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8"
|
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8"
|
||||||
@@ -196,7 +338,19 @@ glob@7.1.1:
|
|||||||
once "^1.3.0"
|
once "^1.3.0"
|
||||||
path-is-absolute "^1.0.0"
|
path-is-absolute "^1.0.0"
|
||||||
|
|
||||||
glob@^7.1.3:
|
glob@7.1.2:
|
||||||
|
version "7.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
|
||||||
|
integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==
|
||||||
|
dependencies:
|
||||||
|
fs.realpath "^1.0.0"
|
||||||
|
inflight "^1.0.4"
|
||||||
|
inherits "2"
|
||||||
|
minimatch "^3.0.4"
|
||||||
|
once "^1.3.0"
|
||||||
|
path-is-absolute "^1.0.0"
|
||||||
|
|
||||||
|
glob@^7.1.2:
|
||||||
version "7.1.6"
|
version "7.1.6"
|
||||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
|
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
|
||||||
integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
|
integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
|
||||||
@@ -213,16 +367,39 @@ glob@^7.1.3:
|
|||||||
resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725"
|
resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725"
|
||||||
integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=
|
integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=
|
||||||
|
|
||||||
|
growl@1.10.5:
|
||||||
|
version "1.10.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e"
|
||||||
|
integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==
|
||||||
|
|
||||||
growl@1.9.2:
|
growl@1.9.2:
|
||||||
version "1.9.2"
|
version "1.9.2"
|
||||||
resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f"
|
resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f"
|
||||||
integrity sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=
|
integrity sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=
|
||||||
|
|
||||||
|
har-schema@^2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
|
||||||
|
integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=
|
||||||
|
|
||||||
|
har-validator@~5.1.3:
|
||||||
|
version "5.1.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080"
|
||||||
|
integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==
|
||||||
|
dependencies:
|
||||||
|
ajv "^6.5.5"
|
||||||
|
har-schema "^2.0.0"
|
||||||
|
|
||||||
has-flag@^1.0.0:
|
has-flag@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
|
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
|
||||||
integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=
|
integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=
|
||||||
|
|
||||||
|
has-flag@^3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
|
||||||
|
integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
|
||||||
|
|
||||||
he@1.1.1:
|
he@1.1.1:
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"
|
resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"
|
||||||
@@ -236,7 +413,16 @@ http-proxy-agent@^2.1.0:
|
|||||||
agent-base "4"
|
agent-base "4"
|
||||||
debug "3.1.0"
|
debug "3.1.0"
|
||||||
|
|
||||||
https-proxy-agent@^2.2.4:
|
http-signature@~1.2.0:
|
||||||
|
version "1.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
|
||||||
|
integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=
|
||||||
|
dependencies:
|
||||||
|
assert-plus "^1.0.0"
|
||||||
|
jsprim "^1.2.2"
|
||||||
|
sshpk "^1.7.0"
|
||||||
|
|
||||||
|
https-proxy-agent@^2.2.1:
|
||||||
version "2.2.4"
|
version "2.2.4"
|
||||||
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b"
|
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b"
|
||||||
integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==
|
integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==
|
||||||
@@ -269,21 +455,61 @@ is-buffer@~1.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
|
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
|
||||||
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
|
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
|
||||||
|
|
||||||
|
is-typedarray@~1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
|
||||||
|
integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
|
||||||
|
|
||||||
isexe@^2.0.0:
|
isexe@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
|
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
|
||||||
integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=
|
integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=
|
||||||
|
|
||||||
|
isstream@~0.1.2:
|
||||||
|
version "0.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
|
||||||
|
integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
|
||||||
|
|
||||||
|
jsbn@~0.1.0:
|
||||||
|
version "0.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
|
||||||
|
integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM=
|
||||||
|
|
||||||
jschardet@2.1.1:
|
jschardet@2.1.1:
|
||||||
version "2.1.1"
|
version "2.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-2.1.1.tgz#af6f8fd0b3b0f5d46a8fd9614a4fce490575c184"
|
resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-2.1.1.tgz#af6f8fd0b3b0f5d46a8fd9614a4fce490575c184"
|
||||||
integrity sha512-pA5qG9Zwm8CBpGlK/lo2GE9jPxwqRgMV7Lzc/1iaPccw6v4Rhj8Zg2BTyrdmHmxlJojnbLupLeRnaPLsq03x6Q==
|
integrity sha512-pA5qG9Zwm8CBpGlK/lo2GE9jPxwqRgMV7Lzc/1iaPccw6v4Rhj8Zg2BTyrdmHmxlJojnbLupLeRnaPLsq03x6Q==
|
||||||
|
|
||||||
|
json-schema-traverse@^0.4.1:
|
||||||
|
version "0.4.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
|
||||||
|
integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
|
||||||
|
|
||||||
|
json-schema@0.2.3:
|
||||||
|
version "0.2.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
|
||||||
|
integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=
|
||||||
|
|
||||||
|
json-stringify-safe@~5.0.1:
|
||||||
|
version "5.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
|
||||||
|
integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
|
||||||
|
|
||||||
json3@3.3.2:
|
json3@3.3.2:
|
||||||
version "3.3.2"
|
version "3.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1"
|
resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1"
|
||||||
integrity sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=
|
integrity sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=
|
||||||
|
|
||||||
|
jsprim@^1.2.2:
|
||||||
|
version "1.4.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
|
||||||
|
integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=
|
||||||
|
dependencies:
|
||||||
|
assert-plus "1.0.0"
|
||||||
|
extsprintf "1.3.0"
|
||||||
|
json-schema "0.2.3"
|
||||||
|
verror "1.10.0"
|
||||||
|
|
||||||
lodash._baseassign@^3.0.0:
|
lodash._baseassign@^3.0.0:
|
||||||
version "3.2.0"
|
version "3.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e"
|
resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e"
|
||||||
@@ -354,7 +580,19 @@ md5@^2.1.0:
|
|||||||
crypt "~0.0.1"
|
crypt "~0.0.1"
|
||||||
is-buffer "~1.1.1"
|
is-buffer "~1.1.1"
|
||||||
|
|
||||||
minimatch@^3.0.2, minimatch@^3.0.4:
|
mime-db@1.43.0:
|
||||||
|
version "1.43.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.43.0.tgz#0a12e0502650e473d735535050e7c8f4eb4fae58"
|
||||||
|
integrity sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==
|
||||||
|
|
||||||
|
mime-types@^2.1.12, mime-types@~2.1.19:
|
||||||
|
version "2.1.26"
|
||||||
|
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.26.tgz#9c921fc09b7e149a65dfdc0da4d20997200b0a06"
|
||||||
|
integrity sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==
|
||||||
|
dependencies:
|
||||||
|
mime-db "1.43.0"
|
||||||
|
|
||||||
|
minimatch@3.0.4, minimatch@^3.0.2, minimatch@^3.0.4:
|
||||||
version "3.0.4"
|
version "3.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||||
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
|
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
|
||||||
@@ -410,6 +648,23 @@ mocha@^3.2.0:
|
|||||||
mkdirp "0.5.1"
|
mkdirp "0.5.1"
|
||||||
supports-color "3.1.2"
|
supports-color "3.1.2"
|
||||||
|
|
||||||
|
mocha@^5.2.0:
|
||||||
|
version "5.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6"
|
||||||
|
integrity sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==
|
||||||
|
dependencies:
|
||||||
|
browser-stdout "1.3.1"
|
||||||
|
commander "2.15.1"
|
||||||
|
debug "3.1.0"
|
||||||
|
diff "3.5.0"
|
||||||
|
escape-string-regexp "1.0.5"
|
||||||
|
glob "7.1.2"
|
||||||
|
growl "1.10.5"
|
||||||
|
he "1.1.1"
|
||||||
|
minimatch "3.0.4"
|
||||||
|
mkdirp "0.5.1"
|
||||||
|
supports-color "5.4.0"
|
||||||
|
|
||||||
ms@2.0.0:
|
ms@2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
||||||
@@ -420,6 +675,11 @@ ms@^2.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
||||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||||
|
|
||||||
|
oauth-sign@~0.9.0:
|
||||||
|
version "0.9.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
|
||||||
|
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
|
||||||
|
|
||||||
once@^1.3.0:
|
once@^1.3.0:
|
||||||
version "1.4.0"
|
version "1.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
||||||
@@ -432,14 +692,68 @@ path-is-absolute@^1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
||||||
integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
|
integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
|
||||||
|
|
||||||
rimraf@^2.6.3:
|
performance-now@^2.1.0:
|
||||||
version "2.7.1"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
|
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
|
||||||
integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
|
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
|
||||||
dependencies:
|
|
||||||
glob "^7.1.3"
|
|
||||||
|
|
||||||
"safer-buffer@>= 2.1.2 < 3":
|
psl@^1.1.28:
|
||||||
|
version "1.7.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/psl/-/psl-1.7.0.tgz#f1c4c47a8ef97167dea5d6bbf4816d736e884a3c"
|
||||||
|
integrity sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ==
|
||||||
|
|
||||||
|
punycode@^2.1.0, punycode@^2.1.1:
|
||||||
|
version "2.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
|
||||||
|
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
|
||||||
|
|
||||||
|
qs@~6.5.2:
|
||||||
|
version "6.5.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
|
||||||
|
integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
|
||||||
|
|
||||||
|
querystringify@^2.1.1:
|
||||||
|
version "2.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e"
|
||||||
|
integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==
|
||||||
|
|
||||||
|
request@^2.88.0:
|
||||||
|
version "2.88.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3"
|
||||||
|
integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==
|
||||||
|
dependencies:
|
||||||
|
aws-sign2 "~0.7.0"
|
||||||
|
aws4 "^1.8.0"
|
||||||
|
caseless "~0.12.0"
|
||||||
|
combined-stream "~1.0.6"
|
||||||
|
extend "~3.0.2"
|
||||||
|
forever-agent "~0.6.1"
|
||||||
|
form-data "~2.3.2"
|
||||||
|
har-validator "~5.1.3"
|
||||||
|
http-signature "~1.2.0"
|
||||||
|
is-typedarray "~1.0.0"
|
||||||
|
isstream "~0.1.2"
|
||||||
|
json-stringify-safe "~5.0.1"
|
||||||
|
mime-types "~2.1.19"
|
||||||
|
oauth-sign "~0.9.0"
|
||||||
|
performance-now "^2.1.0"
|
||||||
|
qs "~6.5.2"
|
||||||
|
safe-buffer "^5.1.2"
|
||||||
|
tough-cookie "~2.5.0"
|
||||||
|
tunnel-agent "^0.6.0"
|
||||||
|
uuid "^3.3.2"
|
||||||
|
|
||||||
|
requires-port@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
|
||||||
|
integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
|
||||||
|
|
||||||
|
safe-buffer@^5.0.1, safe-buffer@^5.1.2:
|
||||||
|
version "5.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519"
|
||||||
|
integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==
|
||||||
|
|
||||||
|
"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
|
||||||
version "2.1.2"
|
version "2.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
|
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
|
||||||
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
|
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
|
||||||
@@ -449,6 +763,39 @@ semver@^5.3.0:
|
|||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab"
|
||||||
integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==
|
integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==
|
||||||
|
|
||||||
|
semver@^5.4.1:
|
||||||
|
version "5.7.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
|
||||||
|
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
|
||||||
|
|
||||||
|
source-map-support@^0.5.0:
|
||||||
|
version "0.5.16"
|
||||||
|
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042"
|
||||||
|
integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==
|
||||||
|
dependencies:
|
||||||
|
buffer-from "^1.0.0"
|
||||||
|
source-map "^0.6.0"
|
||||||
|
|
||||||
|
source-map@^0.6.0:
|
||||||
|
version "0.6.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
|
||||||
|
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
|
||||||
|
|
||||||
|
sshpk@^1.7.0:
|
||||||
|
version "1.16.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877"
|
||||||
|
integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==
|
||||||
|
dependencies:
|
||||||
|
asn1 "~0.2.3"
|
||||||
|
assert-plus "^1.0.0"
|
||||||
|
bcrypt-pbkdf "^1.0.0"
|
||||||
|
dashdash "^1.12.0"
|
||||||
|
ecc-jsbn "~0.1.1"
|
||||||
|
getpass "^0.1.1"
|
||||||
|
jsbn "~0.1.0"
|
||||||
|
safer-buffer "^2.0.2"
|
||||||
|
tweetnacl "~0.14.0"
|
||||||
|
|
||||||
strip-ansi@^4.0.0:
|
strip-ansi@^4.0.0:
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f"
|
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f"
|
||||||
@@ -463,6 +810,62 @@ supports-color@3.1.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
has-flag "^1.0.0"
|
has-flag "^1.0.0"
|
||||||
|
|
||||||
|
supports-color@5.4.0:
|
||||||
|
version "5.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54"
|
||||||
|
integrity sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==
|
||||||
|
dependencies:
|
||||||
|
has-flag "^3.0.0"
|
||||||
|
|
||||||
|
tough-cookie@~2.5.0:
|
||||||
|
version "2.5.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
|
||||||
|
integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==
|
||||||
|
dependencies:
|
||||||
|
psl "^1.1.28"
|
||||||
|
punycode "^2.1.1"
|
||||||
|
|
||||||
|
tunnel-agent@^0.6.0:
|
||||||
|
version "0.6.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
|
||||||
|
integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=
|
||||||
|
dependencies:
|
||||||
|
safe-buffer "^5.0.1"
|
||||||
|
|
||||||
|
tweetnacl@^0.14.3, tweetnacl@~0.14.0:
|
||||||
|
version "0.14.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
|
||||||
|
integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
|
||||||
|
|
||||||
|
uri-js@^4.2.2:
|
||||||
|
version "4.2.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0"
|
||||||
|
integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==
|
||||||
|
dependencies:
|
||||||
|
punycode "^2.1.0"
|
||||||
|
|
||||||
|
url-parse@^1.4.4:
|
||||||
|
version "1.4.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278"
|
||||||
|
integrity sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==
|
||||||
|
dependencies:
|
||||||
|
querystringify "^2.1.1"
|
||||||
|
requires-port "^1.0.0"
|
||||||
|
|
||||||
|
uuid@^3.3.2:
|
||||||
|
version "3.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
|
||||||
|
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
|
||||||
|
|
||||||
|
verror@1.10.0:
|
||||||
|
version "1.10.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
|
||||||
|
integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=
|
||||||
|
dependencies:
|
||||||
|
assert-plus "^1.0.0"
|
||||||
|
core-util-is "1.0.2"
|
||||||
|
extsprintf "^1.2.0"
|
||||||
|
|
||||||
vscode-extension-telemetry@0.1.1:
|
vscode-extension-telemetry@0.1.1:
|
||||||
version "0.1.1"
|
version "0.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.1.1.tgz#91387e06b33400c57abd48979b0e790415ae110b"
|
resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.1.1.tgz#91387e06b33400c57abd48979b0e790415ae110b"
|
||||||
@@ -475,20 +878,32 @@ vscode-nls@^4.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.0.0.tgz#4001c8a6caba5cedb23a9c5ce1090395c0e44002"
|
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.0.0.tgz#4001c8a6caba5cedb23a9c5ce1090395c0e44002"
|
||||||
integrity sha512-qCfdzcH+0LgQnBpZA53bA32kzp9rpq/f66Som577ObeuDlFIrtbEJ+A/+CCxjIh4G8dpJYNCKIsxpRAHIfsbNw==
|
integrity sha512-qCfdzcH+0LgQnBpZA53bA32kzp9rpq/f66Som577ObeuDlFIrtbEJ+A/+CCxjIh4G8dpJYNCKIsxpRAHIfsbNw==
|
||||||
|
|
||||||
vscode-test@^1.3.0:
|
vscode-test@^0.4.1:
|
||||||
version "1.3.0"
|
version "0.4.3"
|
||||||
resolved "https://registry.yarnpkg.com/vscode-test/-/vscode-test-1.3.0.tgz#3310ab385d9b887b4c82e8f52be1030e7cf9493d"
|
resolved "https://registry.yarnpkg.com/vscode-test/-/vscode-test-0.4.3.tgz#461ebf25fc4bc93d77d982aed556658a2e2b90b8"
|
||||||
integrity sha512-LddukcBiSU2FVTDr3c1D8lwkiOvwlJdDL2hqVbn6gIz+rpTqUCkMZSKYm94Y1v0WXlHSDQBsXyY+tchWQgGVsw==
|
integrity sha512-EkMGqBSefZH2MgW65nY05rdRSko15uvzq4VAPM5jVmwYuFQKE7eikKXNJDRxL+OITXHB6pI+a3XqqD32Y3KC5w==
|
||||||
dependencies:
|
dependencies:
|
||||||
http-proxy-agent "^2.1.0"
|
http-proxy-agent "^2.1.0"
|
||||||
https-proxy-agent "^2.2.4"
|
https-proxy-agent "^2.2.1"
|
||||||
rimraf "^2.6.3"
|
|
||||||
|
|
||||||
vscode-uri@^2.0.0:
|
vscode-uri@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-2.0.0.tgz#2df704222f72b8a71ff266ba0830ed6c51ac1542"
|
resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-2.0.0.tgz#2df704222f72b8a71ff266ba0830ed6c51ac1542"
|
||||||
integrity sha512-lWXWofDSYD8r/TIyu64MdwB4FaSirQ608PP/TzUyslyOeHGwQ0eTHUZeJrK1ILOmwUHaJtV693m2JoUYroUDpw==
|
integrity sha512-lWXWofDSYD8r/TIyu64MdwB4FaSirQ608PP/TzUyslyOeHGwQ0eTHUZeJrK1ILOmwUHaJtV693m2JoUYroUDpw==
|
||||||
|
|
||||||
|
vscode@^1.1.36:
|
||||||
|
version "1.1.36"
|
||||||
|
resolved "https://registry.yarnpkg.com/vscode/-/vscode-1.1.36.tgz#5e1a0d1bf4977d0c7bc5159a9a13d5b104d4b1b6"
|
||||||
|
integrity sha512-cGFh9jmGLcTapCpPCKvn8aG/j9zVQ+0x5hzYJq5h5YyUXVGa1iamOaB2M2PZXoumQPES4qeAP1FwkI0b6tL4bQ==
|
||||||
|
dependencies:
|
||||||
|
glob "^7.1.2"
|
||||||
|
mocha "^5.2.0"
|
||||||
|
request "^2.88.0"
|
||||||
|
semver "^5.4.1"
|
||||||
|
source-map-support "^0.5.0"
|
||||||
|
url-parse "^1.4.4"
|
||||||
|
vscode-test "^0.4.1"
|
||||||
|
|
||||||
which@^1.3.0:
|
which@^1.3.0:
|
||||||
version "1.3.0"
|
version "1.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a"
|
resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a"
|
||||||
|
|||||||
@@ -76,29 +76,29 @@ let telemetryReporter: TelemetryReporter | undefined;
|
|||||||
|
|
||||||
export function activate(context: ExtensionContext) {
|
export function activate(context: ExtensionContext) {
|
||||||
|
|
||||||
let toDispose = context.subscriptions;
|
const toDispose = context.subscriptions;
|
||||||
|
|
||||||
let rangeFormatting: Disposable | undefined = undefined;
|
let rangeFormatting: Disposable | undefined = undefined;
|
||||||
|
|
||||||
let packageInfo = getPackageInfo(context);
|
const packageInfo = getPackageInfo(context);
|
||||||
telemetryReporter = packageInfo && new TelemetryReporter(packageInfo.name, packageInfo.version, packageInfo.aiKey);
|
telemetryReporter = packageInfo && new TelemetryReporter(packageInfo.name, packageInfo.version, packageInfo.aiKey);
|
||||||
|
|
||||||
let serverMain = readJSONFile(context.asAbsolutePath('./server/package.json')).main;
|
const serverMain = readJSONFile(context.asAbsolutePath('./server/package.json')).main;
|
||||||
let serverModule = context.asAbsolutePath(path.join('server', serverMain));
|
const serverModule = context.asAbsolutePath(path.join('server', serverMain));
|
||||||
|
|
||||||
// The debug options for the server
|
// The debug options for the server
|
||||||
let debugOptions = { execArgv: ['--nolazy', '--inspect=' + (9000 + Math.round(Math.random() * 10000))] };
|
const debugOptions = { execArgv: ['--nolazy', '--inspect=' + (9000 + Math.round(Math.random() * 10000))] };
|
||||||
|
|
||||||
// If the extension is launch in debug mode the debug server options are use
|
// If the extension is launch in debug mode the debug server options are use
|
||||||
// Otherwise the run options are used
|
// Otherwise the run options are used
|
||||||
let serverOptions: ServerOptions = {
|
const serverOptions: ServerOptions = {
|
||||||
run: { module: serverModule, transport: TransportKind.ipc },
|
run: { module: serverModule, transport: TransportKind.ipc },
|
||||||
debug: { module: serverModule, transport: TransportKind.ipc, options: debugOptions }
|
debug: { module: serverModule, transport: TransportKind.ipc, options: debugOptions }
|
||||||
};
|
};
|
||||||
|
|
||||||
let documentSelector = ['json', 'jsonc'];
|
const documentSelector = ['json', 'jsonc'];
|
||||||
|
|
||||||
let schemaResolutionErrorStatusBarItem = window.createStatusBarItem({
|
const schemaResolutionErrorStatusBarItem = window.createStatusBarItem({
|
||||||
id: 'status.json.resolveError',
|
id: 'status.json.resolveError',
|
||||||
name: localize('json.resolveError', "JSON: Schema Resolution Error"),
|
name: localize('json.resolveError', "JSON: Schema Resolution Error"),
|
||||||
alignment: StatusBarAlignment.Right,
|
alignment: StatusBarAlignment.Right,
|
||||||
@@ -109,10 +109,10 @@ export function activate(context: ExtensionContext) {
|
|||||||
schemaResolutionErrorStatusBarItem.text = '$(alert)';
|
schemaResolutionErrorStatusBarItem.text = '$(alert)';
|
||||||
toDispose.push(schemaResolutionErrorStatusBarItem);
|
toDispose.push(schemaResolutionErrorStatusBarItem);
|
||||||
|
|
||||||
let fileSchemaErrors = new Map<string, string>();
|
const fileSchemaErrors = new Map<string, string>();
|
||||||
|
|
||||||
// Options to control the language client
|
// Options to control the language client
|
||||||
let clientOptions: LanguageClientOptions = {
|
const clientOptions: LanguageClientOptions = {
|
||||||
// Register the server for json documents
|
// Register the server for json documents
|
||||||
documentSelector,
|
documentSelector,
|
||||||
initializationOptions: {
|
initializationOptions: {
|
||||||
@@ -172,17 +172,17 @@ export function activate(context: ExtensionContext) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Create the language client and start the client.
|
// Create the language client and start the client.
|
||||||
let client = new LanguageClient('json', localize('jsonserver.name', 'JSON Language Server'), serverOptions, clientOptions);
|
const client = new LanguageClient('json', localize('jsonserver.name', 'JSON Language Server'), serverOptions, clientOptions);
|
||||||
client.registerProposedFeatures();
|
client.registerProposedFeatures();
|
||||||
|
|
||||||
let disposable = client.start();
|
const disposable = client.start();
|
||||||
toDispose.push(disposable);
|
toDispose.push(disposable);
|
||||||
client.onReady().then(() => {
|
client.onReady().then(() => {
|
||||||
const schemaDocuments: { [uri: string]: boolean } = {};
|
const schemaDocuments: { [uri: string]: boolean } = {};
|
||||||
|
|
||||||
// handle content request
|
// handle content request
|
||||||
client.onRequest(VSCodeContentRequest.type, (uriPath: string) => {
|
client.onRequest(VSCodeContentRequest.type, (uriPath: string) => {
|
||||||
let uri = Uri.parse(uriPath);
|
const uri = Uri.parse(uriPath);
|
||||||
if (uri.scheme !== 'http' && uri.scheme !== 'https') {
|
if (uri.scheme !== 'http' && uri.scheme !== 'https') {
|
||||||
return workspace.openTextDocument(uri).then(doc => {
|
return workspace.openTextDocument(uri).then(doc => {
|
||||||
schemaDocuments[uri.toString()] = true;
|
schemaDocuments[uri.toString()] = true;
|
||||||
@@ -212,7 +212,7 @@ export function activate(context: ExtensionContext) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let handleContentChange = (uriString: string) => {
|
const handleContentChange = (uriString: string) => {
|
||||||
if (schemaDocuments[uriString]) {
|
if (schemaDocuments[uriString]) {
|
||||||
client.sendNotification(SchemaContentChangeNotification.type, uriString);
|
client.sendNotification(SchemaContentChangeNotification.type, uriString);
|
||||||
return true;
|
return true;
|
||||||
@@ -220,7 +220,7 @@ export function activate(context: ExtensionContext) {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
let handleActiveEditorChange = (activeEditor?: TextEditor) => {
|
const handleActiveEditorChange = (activeEditor?: TextEditor) => {
|
||||||
if (!activeEditor) {
|
if (!activeEditor) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -244,7 +244,7 @@ export function activate(context: ExtensionContext) {
|
|||||||
}));
|
}));
|
||||||
toDispose.push(window.onDidChangeActiveTextEditor(handleActiveEditorChange));
|
toDispose.push(window.onDidChangeActiveTextEditor(handleActiveEditorChange));
|
||||||
|
|
||||||
let handleRetryResolveSchemaCommand = () => {
|
const handleRetryResolveSchemaCommand = () => {
|
||||||
if (window.activeTextEditor) {
|
if (window.activeTextEditor) {
|
||||||
schemaResolutionErrorStatusBarItem.text = '$(watch)';
|
schemaResolutionErrorStatusBarItem.text = '$(watch)';
|
||||||
const activeDocUri = window.activeTextEditor.document.uri.toString();
|
const activeDocUri = window.activeTextEditor.document.uri.toString();
|
||||||
@@ -282,7 +282,7 @@ export function activate(context: ExtensionContext) {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let languageConfiguration: LanguageConfiguration = {
|
const languageConfiguration: LanguageConfiguration = {
|
||||||
wordPattern: /("(?:[^\\\"]*(?:\\.)?)*"?)|[^\s{}\[\],:]+/,
|
wordPattern: /("(?:[^\\\"]*(?:\\.)?)*"?)|[^\s{}\[\],:]+/,
|
||||||
indentationRules: {
|
indentationRules: {
|
||||||
increaseIndentPattern: /({+(?=([^"]*"[^"]*")*[^"}]*$))|(\[+(?=([^"]*"[^"]*")*[^"\]]*$))/,
|
increaseIndentPattern: /({+(?=([^"]*"[^"]*")*[^"}]*$))|(\[+(?=([^"]*"[^"]*")*[^"\]]*$))/,
|
||||||
@@ -300,7 +300,7 @@ export function activate(context: ExtensionContext) {
|
|||||||
} else if (formatEnabled && !rangeFormatting) {
|
} else if (formatEnabled && !rangeFormatting) {
|
||||||
rangeFormatting = languages.registerDocumentRangeFormattingEditProvider(documentSelector, {
|
rangeFormatting = languages.registerDocumentRangeFormattingEditProvider(documentSelector, {
|
||||||
provideDocumentRangeFormattingEdits(document: TextDocument, range: Range, options: FormattingOptions, token: CancellationToken): ProviderResult<TextEdit[]> {
|
provideDocumentRangeFormattingEdits(document: TextDocument, range: Range, options: FormattingOptions, token: CancellationToken): ProviderResult<TextEdit[]> {
|
||||||
let params: DocumentRangeFormattingParams = {
|
const params: DocumentRangeFormattingParams = {
|
||||||
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document),
|
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document),
|
||||||
range: client.code2ProtocolConverter.asRange(range),
|
range: client.code2ProtocolConverter.asRange(range),
|
||||||
options: client.code2ProtocolConverter.asFormattingOptions(options)
|
options: client.code2ProtocolConverter.asFormattingOptions(options)
|
||||||
@@ -325,11 +325,11 @@ export function deactivate(): Promise<any> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getSchemaAssociation(_context: ExtensionContext): ISchemaAssociations {
|
function getSchemaAssociation(_context: ExtensionContext): ISchemaAssociations {
|
||||||
let associations: ISchemaAssociations = {};
|
const associations: ISchemaAssociations = {};
|
||||||
extensions.all.forEach(extension => {
|
extensions.all.forEach(extension => {
|
||||||
let packageJSON = extension.packageJSON;
|
const packageJSON = extension.packageJSON;
|
||||||
if (packageJSON && packageJSON.contributes && packageJSON.contributes.jsonValidation) {
|
if (packageJSON && packageJSON.contributes && packageJSON.contributes.jsonValidation) {
|
||||||
let jsonValidation = packageJSON.contributes.jsonValidation;
|
const jsonValidation = packageJSON.contributes.jsonValidation;
|
||||||
if (Array.isArray(jsonValidation)) {
|
if (Array.isArray(jsonValidation)) {
|
||||||
jsonValidation.forEach(jv => {
|
jsonValidation.forEach(jv => {
|
||||||
let { fileMatch, url } = jv;
|
let { fileMatch, url } = jv;
|
||||||
@@ -359,11 +359,11 @@ function getSchemaAssociation(_context: ExtensionContext): ISchemaAssociations {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getSettings(): Settings {
|
function getSettings(): Settings {
|
||||||
let httpSettings = workspace.getConfiguration('http');
|
const httpSettings = workspace.getConfiguration('http');
|
||||||
|
|
||||||
let resultLimit: number = Math.trunc(Math.max(0, Number(workspace.getConfiguration().get('json.maxItemsComputed')))) || 5000;
|
const resultLimit: number = Math.trunc(Math.max(0, Number(workspace.getConfiguration().get('json.maxItemsComputed')))) || 5000;
|
||||||
|
|
||||||
let settings: Settings = {
|
const settings: Settings = {
|
||||||
http: {
|
http: {
|
||||||
proxy: httpSettings.get('proxy'),
|
proxy: httpSettings.get('proxy'),
|
||||||
proxyStrictSSL: httpSettings.get('proxyStrictSSL')
|
proxyStrictSSL: httpSettings.get('proxyStrictSSL')
|
||||||
@@ -373,10 +373,18 @@ function getSettings(): Settings {
|
|||||||
resultLimit
|
resultLimit
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let schemaSettingsById: { [schemaId: string]: JSONSchemaSettings } = Object.create(null);
|
const schemaSettingsById: { [schemaId: string]: JSONSchemaSettings } = Object.create(null);
|
||||||
let collectSchemaSettings = (schemaSettings: JSONSchemaSettings[], rootPath?: string, fileMatchPrefix?: string) => {
|
const collectSchemaSettings = (schemaSettings: JSONSchemaSettings[], folderUri?: Uri, isMultiRoot?: boolean) => {
|
||||||
for (let setting of schemaSettings) {
|
|
||||||
let url = getSchemaId(setting, rootPath);
|
let fileMatchPrefix = undefined;
|
||||||
|
if (folderUri && isMultiRoot) {
|
||||||
|
fileMatchPrefix = folderUri.toString();
|
||||||
|
if (fileMatchPrefix[fileMatchPrefix.length - 1] === '/') {
|
||||||
|
fileMatchPrefix = fileMatchPrefix.substr(0, fileMatchPrefix.length - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const setting of schemaSettings) {
|
||||||
|
const url = getSchemaId(setting, folderUri);
|
||||||
if (!url) {
|
if (!url) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -385,69 +393,78 @@ function getSettings(): Settings {
|
|||||||
schemaSetting = schemaSettingsById[url] = { url, fileMatch: [] };
|
schemaSetting = schemaSettingsById[url] = { url, fileMatch: [] };
|
||||||
settings.json!.schemas!.push(schemaSetting);
|
settings.json!.schemas!.push(schemaSetting);
|
||||||
}
|
}
|
||||||
let fileMatches = setting.fileMatch;
|
const fileMatches = setting.fileMatch;
|
||||||
let resultingFileMatches = schemaSetting.fileMatch!;
|
|
||||||
if (Array.isArray(fileMatches)) {
|
if (Array.isArray(fileMatches)) {
|
||||||
if (fileMatchPrefix) {
|
const resultingFileMatches = schemaSetting.fileMatch || [];
|
||||||
for (let fileMatch of fileMatches) {
|
schemaSetting.fileMatch = resultingFileMatches;
|
||||||
if (fileMatch[0] === '/') {
|
const addMatch = (pattern: string) => { // filter duplicates
|
||||||
resultingFileMatches.push(fileMatchPrefix + fileMatch);
|
if (resultingFileMatches.indexOf(pattern) === -1) {
|
||||||
resultingFileMatches.push(fileMatchPrefix + '/*' + fileMatch);
|
resultingFileMatches.push(pattern);
|
||||||
} else {
|
}
|
||||||
resultingFileMatches.push(fileMatchPrefix + '/' + fileMatch);
|
};
|
||||||
resultingFileMatches.push(fileMatchPrefix + '/*/' + fileMatch);
|
for (const fileMatch of fileMatches) {
|
||||||
}
|
if (fileMatchPrefix) {
|
||||||
|
if (fileMatch[0] === '/') {
|
||||||
|
addMatch(fileMatchPrefix + fileMatch);
|
||||||
|
addMatch(fileMatchPrefix + '/*' + fileMatch);
|
||||||
|
} else {
|
||||||
|
addMatch(fileMatchPrefix + '/' + fileMatch);
|
||||||
|
addMatch(fileMatchPrefix + '/*/' + fileMatch);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
addMatch(fileMatch);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
resultingFileMatches.push(...fileMatches);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if (setting.schema) {
|
if (setting.schema && !schemaSetting.schema) {
|
||||||
schemaSetting.schema = setting.schema;
|
schemaSetting.schema = setting.schema;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const folders = workspace.workspaceFolders;
|
||||||
|
|
||||||
// merge global and folder settings. Qualify all file matches with the folder path.
|
// merge global and folder settings. Qualify all file matches with the folder path.
|
||||||
let globalSettings = workspace.getConfiguration('json', null).get<JSONSchemaSettings[]>('schemas');
|
const globalSettings = workspace.getConfiguration('json', null).get<JSONSchemaSettings[]>('schemas');
|
||||||
if (Array.isArray(globalSettings)) {
|
if (Array.isArray(globalSettings)) {
|
||||||
collectSchemaSettings(globalSettings, workspace.rootPath);
|
if (!folders) {
|
||||||
|
collectSchemaSettings(globalSettings);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let folders = workspace.workspaceFolders;
|
|
||||||
if (folders) {
|
if (folders) {
|
||||||
for (let folder of folders) {
|
const isMultiRoot = folders.length > 1;
|
||||||
let folderUri = folder.uri;
|
for (const folder of folders) {
|
||||||
|
const folderUri = folder.uri;
|
||||||
|
|
||||||
let schemaConfigInfo = workspace.getConfiguration('json', folderUri).inspect<JSONSchemaSettings[]>('schemas');
|
const schemaConfigInfo = workspace.getConfiguration('json', folderUri).inspect<JSONSchemaSettings[]>('schemas');
|
||||||
|
|
||||||
let folderSchemas = schemaConfigInfo!.workspaceFolderValue;
|
const folderSchemas = schemaConfigInfo!.workspaceFolderValue;
|
||||||
if (Array.isArray(folderSchemas)) {
|
if (Array.isArray(folderSchemas)) {
|
||||||
let folderPath = folderUri.toString();
|
collectSchemaSettings(folderSchemas, folderUri, isMultiRoot);
|
||||||
if (folderPath[folderPath.length - 1] === '/') {
|
|
||||||
folderPath = folderPath.substr(0, folderPath.length - 1);
|
|
||||||
}
|
|
||||||
collectSchemaSettings(folderSchemas, folderUri.fsPath, folderPath);
|
|
||||||
}
|
}
|
||||||
|
if (Array.isArray(globalSettings)) {
|
||||||
|
collectSchemaSettings(globalSettings, folderUri, isMultiRoot);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSchemaId(schema: JSONSchemaSettings, rootPath?: string) {
|
function getSchemaId(schema: JSONSchemaSettings, folderUri?: Uri) {
|
||||||
let url = schema.url;
|
let url = schema.url;
|
||||||
if (!url) {
|
if (!url) {
|
||||||
if (schema.schema) {
|
if (schema.schema) {
|
||||||
url = schema.schema.id || `vscode://schemas/custom/${encodeURIComponent(hash(schema.schema).toString(16))}`;
|
url = schema.schema.id || `vscode://schemas/custom/${encodeURIComponent(hash(schema.schema).toString(16))}`;
|
||||||
}
|
}
|
||||||
} else if (rootPath && (url[0] === '.' || url[0] === '/')) {
|
} else if (folderUri && (url[0] === '.' || url[0] === '/')) {
|
||||||
url = Uri.file(path.normalize(path.join(rootPath, url))).toString();
|
url = folderUri.with({ path: path.posix.join(folderUri.path, url) }).toString();
|
||||||
}
|
}
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPackageInfo(context: ExtensionContext): IPackageInfo | undefined {
|
function getPackageInfo(context: ExtensionContext): IPackageInfo | undefined {
|
||||||
let extensionPackage = readJSONFile(context.asAbsolutePath('./package.json'));
|
const extensionPackage = readJSONFile(context.asAbsolutePath('./package.json'));
|
||||||
if (extensionPackage) {
|
if (extensionPackage) {
|
||||||
return {
|
return {
|
||||||
name: extensionPackage.name,
|
name: extensionPackage.name,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "vscode-json-languageserver",
|
"name": "vscode-json-languageserver",
|
||||||
"description": "JSON language server",
|
"description": "JSON language server",
|
||||||
"version": "1.2.2",
|
"version": "1.2.3",
|
||||||
"author": "Microsoft Corporation",
|
"author": "Microsoft Corporation",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ interface IToken {
|
|||||||
accessToken?: string; // When unable to refresh due to network problems, the access token becomes undefined
|
accessToken?: string; // When unable to refresh due to network problems, the access token becomes undefined
|
||||||
|
|
||||||
expiresIn?: string; // How long access token is valid, in seconds
|
expiresIn?: string; // How long access token is valid, in seconds
|
||||||
|
expiresAt?: number; // UNIX epoch time at which token will expire
|
||||||
refreshToken: string;
|
refreshToken: string;
|
||||||
|
|
||||||
accountName: string;
|
accountName: string;
|
||||||
@@ -183,12 +184,33 @@ export class AzureActiveDirectoryService {
|
|||||||
private convertToSession(token: IToken): vscode.AuthenticationSession {
|
private convertToSession(token: IToken): vscode.AuthenticationSession {
|
||||||
return {
|
return {
|
||||||
id: token.sessionId,
|
id: token.sessionId,
|
||||||
accessToken: () => !token.accessToken ? Promise.reject('Unavailable due to network problems') : Promise.resolve(token.accessToken),
|
accessToken: () => this.resolveAccessToken(token),
|
||||||
accountName: token.accountName,
|
accountName: token.accountName,
|
||||||
scopes: token.scope.split(' ')
|
scopes: token.scope.split(' ')
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async resolveAccessToken(token: IToken): Promise<string> {
|
||||||
|
if (token.accessToken && (!token.expiresAt || token.expiresAt > Date.now())) {
|
||||||
|
Logger.info('Token available from cache');
|
||||||
|
return Promise.resolve(token.accessToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Logger.info('Token expired or unavailable, trying refresh');
|
||||||
|
const refreshedToken = await this.refreshToken(token.refreshToken, token.scope);
|
||||||
|
if (refreshedToken.accessToken) {
|
||||||
|
Promise.resolve(token.accessToken);
|
||||||
|
} else {
|
||||||
|
throw new Error();
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
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 {
|
||||||
try {
|
try {
|
||||||
return JSON.parse(Buffer.from(accessToken.split('.')[1], 'base64').toString());
|
return JSON.parse(Buffer.from(accessToken.split('.')[1], 'base64').toString());
|
||||||
@@ -252,9 +274,9 @@ export class AzureActiveDirectoryService {
|
|||||||
res.writeHead(302, { Location: '/' });
|
res.writeHead(302, { Location: '/' });
|
||||||
res.end();
|
res.end();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
Logger.error(err.message);
|
|
||||||
res.writeHead(302, { Location: `/?error=${encodeURIComponent(err && err.message || 'Unknown error')}` });
|
res.writeHead(302, { Location: `/?error=${encodeURIComponent(err && err.message || 'Unknown error')}` });
|
||||||
res.end();
|
res.end();
|
||||||
|
throw new Error(err.message);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Logger.error(e.message);
|
Logger.error(e.message);
|
||||||
@@ -263,6 +285,7 @@ export class AzureActiveDirectoryService {
|
|||||||
if (e.message === 'Error listening to server' || e.message === 'Closed' || e.message === 'Timeout waiting for port') {
|
if (e.message === 'Error listening to server' || e.message === 'Closed' || e.message === 'Timeout waiting for port') {
|
||||||
await this.loginWithoutLocalServer(scope);
|
await this.loginWithoutLocalServer(scope);
|
||||||
}
|
}
|
||||||
|
throw new Error(e.message);
|
||||||
} finally {
|
} finally {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
server.close();
|
server.close();
|
||||||
@@ -374,6 +397,7 @@ export class AzureActiveDirectoryService {
|
|||||||
const claims = this.getTokenClaims(json.access_token);
|
const claims = this.getTokenClaims(json.access_token);
|
||||||
return {
|
return {
|
||||||
expiresIn: json.expires_in,
|
expiresIn: json.expires_in,
|
||||||
|
expiresAt: Date.now() + json.expires_in * 1000,
|
||||||
accessToken: json.access_token,
|
accessToken: json.access_token,
|
||||||
refreshToken: json.refresh_token,
|
refreshToken: json.refresh_token,
|
||||||
scope,
|
scope,
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ export async function activate(_: vscode.ExtensionContext) {
|
|||||||
await loginService.login(scopes.sort().join(' '));
|
await loginService.login(scopes.sort().join(' '));
|
||||||
return loginService.sessions[0]!;
|
return loginService.sessions[0]!;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
vscode.window.showErrorMessage(`Logging in failed: ${e}`);
|
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
+1
-1
@@ -50,7 +50,7 @@ function code() {
|
|||||||
export VSCODE_LOGS=
|
export VSCODE_LOGS=
|
||||||
|
|
||||||
# Launch Code
|
# Launch Code
|
||||||
exec "$CODE" . "$@"
|
exec "$CODE" . --no-sandbox "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
function code-wsl()
|
function code-wsl()
|
||||||
|
|||||||
+4
-1
@@ -89,7 +89,7 @@ app.once('ready', function () {
|
|||||||
traceOptions: args['trace-options'] || 'record-until-full,enable-sampling'
|
traceOptions: args['trace-options'] || 'record-until-full,enable-sampling'
|
||||||
};
|
};
|
||||||
|
|
||||||
contentTracing.startRecording(traceOptions, () => onReady());
|
contentTracing.startRecording(traceOptions).finally(() => onReady());
|
||||||
} else {
|
} else {
|
||||||
onReady();
|
onReady();
|
||||||
}
|
}
|
||||||
@@ -169,6 +169,9 @@ function configureCommandlineSwitchesSync(cliArgs) {
|
|||||||
app.commandLine.appendSwitch('js-flags', jsFlags);
|
app.commandLine.appendSwitch('js-flags', jsFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO@Ben TODO@Deepak Electron 7 workaround for https://github.com/microsoft/vscode/issues/88873
|
||||||
|
app.commandLine.appendSwitch('disable-features', 'LayoutNG');
|
||||||
|
|
||||||
return argvConfig;
|
return argvConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export class MainThreadQueryEditor extends Disposable implements MainThreadQuery
|
|||||||
public $connect(fileUri: string, connectionId: string): Thenable<void> {
|
public $connect(fileUri: string, connectionId: string): Thenable<void> {
|
||||||
return new Promise<void>((resolve, reject) => {
|
return new Promise<void>((resolve, reject) => {
|
||||||
let editors = this._editorService.visibleControls.filter(resource => {
|
let editors = this._editorService.visibleControls.filter(resource => {
|
||||||
return !!resource && resource.input.getResource().toString() === fileUri;
|
return !!resource && resource.input.resource.toString() === fileUri;
|
||||||
});
|
});
|
||||||
let editor = editors && editors.length > 0 ? editors[0] : undefined;
|
let editor = editors && editors.length > 0 ? editors[0] : undefined;
|
||||||
let options: IConnectionCompletionOptions = {
|
let options: IConnectionCompletionOptions = {
|
||||||
@@ -76,7 +76,7 @@ export class MainThreadQueryEditor extends Disposable implements MainThreadQuery
|
|||||||
public $connectWithProfile(fileUri: string, connection: azdata.connection.ConnectionProfile): Thenable<void> {
|
public $connectWithProfile(fileUri: string, connection: azdata.connection.ConnectionProfile): Thenable<void> {
|
||||||
return new Promise<void>(async (resolve, reject) => {
|
return new Promise<void>(async (resolve, reject) => {
|
||||||
let editors = this._editorService.visibleControls.filter(resource => {
|
let editors = this._editorService.visibleControls.filter(resource => {
|
||||||
return !!resource && resource.input.getResource().toString() === fileUri;
|
return !!resource && resource.input.resource.toString() === fileUri;
|
||||||
});
|
});
|
||||||
let editor = editors && editors.length > 0 ? editors[0] : undefined;
|
let editor = editors && editors.length > 0 ? editors[0] : undefined;
|
||||||
|
|
||||||
@@ -97,7 +97,7 @@ export class MainThreadQueryEditor extends Disposable implements MainThreadQuery
|
|||||||
}
|
}
|
||||||
|
|
||||||
public $runQuery(fileUri: string, runCurrentQuery: boolean = true): void {
|
public $runQuery(fileUri: string, runCurrentQuery: boolean = true): void {
|
||||||
let filteredEditors = this._editorService.visibleControls.filter(editor => editor.input.getResource().toString() === fileUri);
|
let filteredEditors = this._editorService.visibleControls.filter(editor => editor.input.resource.toString() === fileUri);
|
||||||
if (filteredEditors && filteredEditors.length > 0) {
|
if (filteredEditors && filteredEditors.length > 0) {
|
||||||
let editor = filteredEditors[0];
|
let editor = filteredEditors[0];
|
||||||
if (editor instanceof QueryEditor) {
|
if (editor instanceof QueryEditor) {
|
||||||
@@ -119,7 +119,7 @@ export class MainThreadQueryEditor extends Disposable implements MainThreadQuery
|
|||||||
|
|
||||||
public $createQueryTab(fileUri: string, title: string, componentId: string): void {
|
public $createQueryTab(fileUri: string, title: string, componentId: string): void {
|
||||||
let editors = this._editorService.visibleControls.filter(resource => {
|
let editors = this._editorService.visibleControls.filter(resource => {
|
||||||
return !!resource && resource.input.getResource().toString() === fileUri;
|
return !!resource && resource.input.resource.toString() === fileUri;
|
||||||
});
|
});
|
||||||
|
|
||||||
let editor = editors && editors.length > 0 ? editors[0] : undefined;
|
let editor = editors && editors.length > 0 ? editors[0] : undefined;
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ export class EditDataInput extends EditorInput implements IConnectableInput {
|
|||||||
public save(): Promise<IEditorInput | undefined> { return Promise.resolve(undefined); }
|
public save(): Promise<IEditorInput | undefined> { return Promise.resolve(undefined); }
|
||||||
public getTypeId(): string { return EditDataInput.ID; }
|
public getTypeId(): string { return EditDataInput.ID; }
|
||||||
public setBootstrappedTrue(): void { this._hasBootstrapped = true; }
|
public setBootstrappedTrue(): void { this._hasBootstrapped = true; }
|
||||||
public getResource(): URI { return this._uri; }
|
public get resource(): URI { return this._uri; }
|
||||||
public supportsSplitEditor(): boolean { return false; }
|
public supportsSplitEditor(): boolean { return false; }
|
||||||
public setupComplete() { this._setup = true; }
|
public setupComplete() { this._setup = true; }
|
||||||
public get queryString(): string {
|
public get queryString(): string {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
import { EditorInput } from 'vs/workbench/common/editor';
|
import { EditorInput } from 'vs/workbench/common/editor';
|
||||||
import { Emitter } from 'vs/base/common/event';
|
import { Emitter } from 'vs/base/common/event';
|
||||||
|
import { URI } from 'vs/base/common/uri';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Input for the EditDataResultsEditor. This input helps with logic for the viewing and editing of
|
* Input for the EditDataResultsEditor. This input helps with logic for the viewing and editing of
|
||||||
@@ -102,4 +103,8 @@ export class EditDataResultsInput extends EditorInput {
|
|||||||
get uri(): string {
|
get uri(): string {
|
||||||
return unescape(this._uri);
|
return unescape(this._uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get resource(): URI | undefined {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,8 +46,8 @@ export class DashboardInput extends EditorInput {
|
|||||||
|
|
||||||
// vscode has a comment that Mode's will eventually be removed (not sure the state of this comment)
|
// vscode has a comment that Mode's will eventually be removed (not sure the state of this comment)
|
||||||
// so this might be able to be undone when that happens
|
// so this might be able to be undone when that happens
|
||||||
if (!model.getModel(this.getResource())) {
|
if (!model.getModel(this.resource)) {
|
||||||
model.createModel('', modeService.create('dashboard'), this.getResource());
|
model.createModel('', modeService.create('dashboard'), this.resource);
|
||||||
}
|
}
|
||||||
this._initializedPromise = _connectionService.connectIfNotConnected(_connectionProfile, 'dashboard').then(
|
this._initializedPromise = _connectionService.connectIfNotConnected(_connectionProfile, 'dashboard').then(
|
||||||
u => {
|
u => {
|
||||||
@@ -72,7 +72,7 @@ export class DashboardInput extends EditorInput {
|
|||||||
return DashboardInput.ID;
|
return DashboardInput.ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
public getResource(): URI {
|
public get resource(): URI {
|
||||||
return URI.from({
|
return URI.from({
|
||||||
scheme: 'dashboard',
|
scheme: 'dashboard',
|
||||||
path: 'dashboard'
|
path: 'dashboard'
|
||||||
|
|||||||
@@ -287,4 +287,8 @@ export class ProfilerInput extends EditorInput implements IProfilerSession {
|
|||||||
super.dispose();
|
super.dispose();
|
||||||
this._profilerService.disconnectSession(this.id);
|
this._profilerService.disconnectSession(this.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get resource(): URI | undefined {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,11 +89,11 @@ export class ModelViewInput extends EditorInput {
|
|||||||
return this._title;
|
return this._title;
|
||||||
}
|
}
|
||||||
|
|
||||||
public getResource(): URI {
|
public get resource(): URI | undefined {
|
||||||
if (this._options.resourceName) {
|
if (this._options.resourceName) {
|
||||||
return URI.from({ scheme: ModelViewInput.Scheme, path: this._options.resourceName });
|
return URI.from({ scheme: ModelViewInput.Scheme, path: this._options.resourceName });
|
||||||
}
|
}
|
||||||
return super.getResource();
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get container(): HTMLElement {
|
public get container(): HTMLElement {
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ export class QueryTextEditor extends BaseTextEditor {
|
|||||||
this.refreshEditorConfiguration();
|
this.refreshEditorConfiguration();
|
||||||
}
|
}
|
||||||
|
|
||||||
private refreshEditorConfiguration(configuration = this.textResourceConfigurationService.getValue<IEditorConfiguration>(this.input.getResource())): void {
|
private refreshEditorConfiguration(configuration = this.textResourceConfigurationService.getValue<IEditorConfiguration>(this.input.resource)): void {
|
||||||
if (!this.getControl()) {
|
if (!this.getControl()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ export function getCurrentGlobalConnection(objectExplorerService: IObjectExplore
|
|||||||
|
|
||||||
let activeInput = workbenchEditorService.activeEditor;
|
let activeInput = workbenchEditorService.activeEditor;
|
||||||
if (activeInput) {
|
if (activeInput) {
|
||||||
connection = connectionManagementService.getConnectionProfile(activeInput.getResource().toString());
|
connection = connectionManagementService.getConnectionProfile(activeInput.resource.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
return connection;
|
return connection;
|
||||||
|
|||||||
@@ -166,7 +166,7 @@ export abstract class QueryEditorInput extends EditorInput implements IConnectab
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Getters for private properties
|
// Getters for private properties
|
||||||
public get uri(): string { return this.getResource()!.toString(true); }
|
public get uri(): string { return this.resource!.toString(true); }
|
||||||
public get text(): EditorInput { return this._text; }
|
public get text(): EditorInput { return this._text; }
|
||||||
public get results(): QueryResultsInput { return this._results; }
|
public get results(): QueryResultsInput { return this._results; }
|
||||||
// Description is shown beside the tab name in the combobox of open editors
|
// Description is shown beside the tab name in the combobox of open editors
|
||||||
@@ -191,7 +191,7 @@ export abstract class QueryEditorInput extends EditorInput implements IConnectab
|
|||||||
|
|
||||||
// Forwarding resource functions to the inline sql file editor
|
// Forwarding resource functions to the inline sql file editor
|
||||||
public isDirty(): boolean { return this._text.isDirty(); }
|
public isDirty(): boolean { return this._text.isDirty(); }
|
||||||
public getResource(): URI | undefined { return this._text.getResource(); }
|
public get resource(): URI | undefined { return this._text.resource; }
|
||||||
|
|
||||||
public matchInputInstanceType(inputType: any): boolean {
|
public matchInputInstanceType(inputType: any): boolean {
|
||||||
return (this._text instanceof inputType);
|
return (this._text instanceof inputType);
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { QueryPlanState } from 'sql/workbench/common/editor/query/queryPlanState
|
|||||||
import { MessagePanelState } from 'sql/workbench/common/editor/query/messagePanelState';
|
import { MessagePanelState } from 'sql/workbench/common/editor/query/messagePanelState';
|
||||||
import { GridPanelState } from 'sql/workbench/common/editor/query/gridPanelState';
|
import { GridPanelState } from 'sql/workbench/common/editor/query/gridPanelState';
|
||||||
import { QueryModelViewState } from 'sql/workbench/common/editor/query/modelViewState';
|
import { QueryModelViewState } from 'sql/workbench/common/editor/query/modelViewState';
|
||||||
|
import { URI } from 'vs/base/common/uri';
|
||||||
|
|
||||||
export class ResultsViewState {
|
export class ResultsViewState {
|
||||||
public readonly gridPanelState: GridPanelState = new GridPanelState();
|
public readonly gridPanelState: GridPanelState = new GridPanelState();
|
||||||
@@ -89,4 +90,8 @@ export class QueryResultsInput extends EditorInput {
|
|||||||
get uri(): string {
|
get uri(): string {
|
||||||
return this._uri;
|
return this._uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get resource(): URI | undefined {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -198,7 +198,7 @@ export class CommandLineWorkbenchContribution implements IWorkbenchContribution,
|
|||||||
|
|
||||||
// If an open and connectable query editor exists for the given URI, attach it to the connection profile
|
// If an open and connectable query editor exists for the given URI, attach it to the connection profile
|
||||||
private async processFile(uriString: string, profile: IConnectionProfile, warnOnConnectFailure: boolean): Promise<void> {
|
private async processFile(uriString: string, profile: IConnectionProfile, warnOnConnectFailure: boolean): Promise<void> {
|
||||||
let activeEditor = this._editorService.editors.filter(v => v.getResource().toString() === uriString).pop();
|
let activeEditor = this._editorService.editors.filter(v => v.resource.toString() === uriString).pop();
|
||||||
if (activeEditor instanceof QueryEditorInput && activeEditor.state.connected) {
|
if (activeEditor instanceof QueryEditorInput && activeEditor.state.connected) {
|
||||||
let options: IConnectionCompletionOptions = {
|
let options: IConnectionCompletionOptions = {
|
||||||
params: { connectionType: ConnectionType.editor, runQueryOnCompletion: RunQueryOnConnectionMode.none, input: activeEditor },
|
params: { connectionType: ConnectionType.editor, runQueryOnCompletion: RunQueryOnConnectionMode.none, input: activeEditor },
|
||||||
|
|||||||
@@ -49,12 +49,12 @@ export class EditorReplacementContribution implements IWorkbenchContribution {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!language) { // in the case the input doesn't have a preferred mode set we will attempt to guess the mode from the file path
|
if (!language) { // in the case the input doesn't have a preferred mode set we will attempt to guess the mode from the file path
|
||||||
language = this.modeService.getModeIdByFilepathOrFirstLine(editor.getResource());
|
language = this.modeService.getModeIdByFilepathOrFirstLine(editor.resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!language) {
|
if (!language) {
|
||||||
// just use the extension
|
// just use the extension
|
||||||
language = path.extname(editor.getResource().toString()).slice(1); // remove the .
|
language = path.extname(editor.resource.toString()).slice(1); // remove the .
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!language) {
|
if (!language) {
|
||||||
|
|||||||
@@ -211,7 +211,7 @@ export abstract class NotebookInput extends EditorInput {
|
|||||||
private _notebookFindModel: NotebookFindModel;
|
private _notebookFindModel: NotebookFindModel;
|
||||||
|
|
||||||
constructor(private _title: string,
|
constructor(private _title: string,
|
||||||
private resource: URI,
|
private _resource: URI,
|
||||||
private _textInput: TextInput,
|
private _textInput: TextInput,
|
||||||
@ITextModelService private textModelService: ITextModelService,
|
@ITextModelService private textModelService: ITextModelService,
|
||||||
@IInstantiationService private instantiationService: IInstantiationService,
|
@IInstantiationService private instantiationService: IInstantiationService,
|
||||||
@@ -219,7 +219,6 @@ export abstract class NotebookInput extends EditorInput {
|
|||||||
@IExtensionService private extensionService: IExtensionService
|
@IExtensionService private extensionService: IExtensionService
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
this.resource = resource;
|
|
||||||
this._standardKernels = [];
|
this._standardKernels = [];
|
||||||
this._providersLoaded = this.assignProviders();
|
this._providersLoaded = this.assignProviders();
|
||||||
this._notebookEditorOpenedTimestamp = Date.now();
|
this._notebookEditorOpenedTimestamp = Date.now();
|
||||||
@@ -299,8 +298,8 @@ export abstract class NotebookInput extends EditorInput {
|
|||||||
|
|
||||||
private async setTrustForNewEditor(newInput: IEditorInput | undefined): Promise<void> {
|
private async setTrustForNewEditor(newInput: IEditorInput | undefined): Promise<void> {
|
||||||
let isTrusted = this._model.getNotebookModel().trustedMode;
|
let isTrusted = this._model.getNotebookModel().trustedMode;
|
||||||
if (isTrusted && newInput && newInput.getResource() !== this.getResource()) {
|
if (isTrusted && newInput && newInput.resource !== this.resource) {
|
||||||
await this.notebookService.serializeNotebookStateChange(newInput.getResource(), NotebookChangeType.Saved, undefined, true);
|
await this.notebookService.serializeNotebookStateChange(newInput.resource, NotebookChangeType.Saved, undefined, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,8 +336,8 @@ export abstract class NotebookInput extends EditorInput {
|
|||||||
|
|
||||||
public abstract getTypeId(): string;
|
public abstract getTypeId(): string;
|
||||||
|
|
||||||
getResource(): URI {
|
get resource(): URI {
|
||||||
return this.resource;
|
return this._resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get untitledEditorModel(): IUntitledTextEditorModel {
|
public get untitledEditorModel(): IUntitledTextEditorModel {
|
||||||
|
|||||||
@@ -260,7 +260,7 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe
|
|||||||
|
|
||||||
let editors = this.editorService.visibleControls;
|
let editors = this.editorService.visibleControls;
|
||||||
for (let editor of editors) {
|
for (let editor of editors) {
|
||||||
if (editor && editor.input.getResource() === this._notebookParams.input.notebookUri) {
|
if (editor && editor.input.resource === this._notebookParams.input.notebookUri) {
|
||||||
await editor.group.closeEditor(this._notebookParams.input as NotebookInput, { preserveFocus: true }); // sketchy
|
await editor.group.closeEditor(this._notebookParams.input as NotebookInput, { preserveFocus: true }); // sketchy
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,9 +23,9 @@ export class NotebookEditorInputAssociation implements ILanguageAssociation {
|
|||||||
|
|
||||||
convertInput(activeEditor: IEditorInput): NotebookInput {
|
convertInput(activeEditor: IEditorInput): NotebookInput {
|
||||||
if (activeEditor instanceof FileEditorInput) {
|
if (activeEditor instanceof FileEditorInput) {
|
||||||
return this.instantiationService.createInstance(FileNotebookInput, activeEditor.getName(), activeEditor.getResource(), activeEditor);
|
return this.instantiationService.createInstance(FileNotebookInput, activeEditor.getName(), activeEditor.resource, activeEditor);
|
||||||
} else if (activeEditor instanceof UntitledTextEditorInput) {
|
} else if (activeEditor instanceof UntitledTextEditorInput) {
|
||||||
return this.instantiationService.createInstance(UntitledNotebookInput, activeEditor.getName(), activeEditor.getResource(), activeEditor);
|
return this.instantiationService.createInstance(UntitledNotebookInput, activeEditor.getName(), activeEditor.resource, activeEditor);
|
||||||
} else {
|
} else {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
@@ -48,7 +48,7 @@ export class FileNoteBookEditorInputFactory implements IEditorInputFactory {
|
|||||||
deserialize(instantiationService: IInstantiationService, serializedEditorInput: string): FileNotebookInput | undefined {
|
deserialize(instantiationService: IInstantiationService, serializedEditorInput: string): FileNotebookInput | undefined {
|
||||||
const factory = editorInputFactoryRegistry.getEditorInputFactory(FILE_EDITOR_INPUT_ID);
|
const factory = editorInputFactoryRegistry.getEditorInputFactory(FILE_EDITOR_INPUT_ID);
|
||||||
const fileEditorInput = factory.deserialize(instantiationService, serializedEditorInput) as FileEditorInput;
|
const fileEditorInput = factory.deserialize(instantiationService, serializedEditorInput) as FileEditorInput;
|
||||||
return instantiationService.createInstance(FileNotebookInput, fileEditorInput.getName(), fileEditorInput.getResource(), fileEditorInput);
|
return instantiationService.createInstance(FileNotebookInput, fileEditorInput.getName(), fileEditorInput.resource, fileEditorInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
canSerialize(): boolean { // we can always serialize notebooks
|
canSerialize(): boolean { // we can always serialize notebooks
|
||||||
@@ -68,7 +68,7 @@ export class UntitledNoteBookEditorInputFactory implements IEditorInputFactory {
|
|||||||
deserialize(instantiationService: IInstantiationService, serializedEditorInput: string): UntitledNotebookInput | undefined {
|
deserialize(instantiationService: IInstantiationService, serializedEditorInput: string): UntitledNotebookInput | undefined {
|
||||||
const factory = editorInputFactoryRegistry.getEditorInputFactory(UntitledTextEditorInput.ID);
|
const factory = editorInputFactoryRegistry.getEditorInputFactory(UntitledTextEditorInput.ID);
|
||||||
const untitledEditorInput = factory.deserialize(instantiationService, serializedEditorInput) as UntitledTextEditorInput;
|
const untitledEditorInput = factory.deserialize(instantiationService, serializedEditorInput) as UntitledTextEditorInput;
|
||||||
return instantiationService.createInstance(UntitledNotebookInput, untitledEditorInput.getName(), untitledEditorInput.getResource(), untitledEditorInput);
|
return instantiationService.createInstance(UntitledNotebookInput, untitledEditorInput.getName(), untitledEditorInput.resource, untitledEditorInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
canSerialize(): boolean { // we can always serialize notebooks
|
canSerialize(): boolean { // we can always serialize notebooks
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ suite('Notebook Input', function (): void {
|
|||||||
assert.strictEqual(untitledNotebookInput.untitledEditorModel, testModel);
|
assert.strictEqual(untitledNotebookInput.untitledEditorModel, testModel);
|
||||||
|
|
||||||
// getResource
|
// getResource
|
||||||
assert.strictEqual(untitledNotebookInput.getResource(), untitledUri);
|
assert.strictEqual(untitledNotebookInput.resource, untitledUri);
|
||||||
|
|
||||||
// Standard kernels
|
// Standard kernels
|
||||||
let testKernels = [{
|
let testKernels = [{
|
||||||
|
|||||||
@@ -96,12 +96,12 @@ export class SqlFlavorStatusbarItem extends Disposable implements IWorkbenchCont
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _onEditorClosed(event: IEditorCloseEvent): void {
|
private _onEditorClosed(event: IEditorCloseEvent): void {
|
||||||
let uri = event.editor.getResource().toString();
|
let uri = event.editor.resource.toString();
|
||||||
if (uri && uri in this._sqlStatusEditors) {
|
if (uri && uri in this._sqlStatusEditors) {
|
||||||
// If active editor is being closed, hide the query status.
|
// If active editor is being closed, hide the query status.
|
||||||
let activeEditor = this.editorService.activeControl;
|
let activeEditor = this.editorService.activeControl;
|
||||||
if (activeEditor) {
|
if (activeEditor) {
|
||||||
let currentUri = activeEditor.input.getResource().toString();
|
let currentUri = activeEditor.input.resource.toString();
|
||||||
if (uri === currentUri) {
|
if (uri === currentUri) {
|
||||||
this.hide();
|
this.hide();
|
||||||
}
|
}
|
||||||
@@ -114,7 +114,7 @@ export class SqlFlavorStatusbarItem extends Disposable implements IWorkbenchCont
|
|||||||
private _onEditorsChanged(): void {
|
private _onEditorsChanged(): void {
|
||||||
let activeEditor = this.editorService.activeControl;
|
let activeEditor = this.editorService.activeControl;
|
||||||
if (activeEditor) {
|
if (activeEditor) {
|
||||||
let uri = activeEditor.input.getResource().toString();
|
let uri = activeEditor.input.resource.toString();
|
||||||
|
|
||||||
// Show active editor's language flavor status
|
// Show active editor's language flavor status
|
||||||
if (uri) {
|
if (uri) {
|
||||||
@@ -145,7 +145,7 @@ export class SqlFlavorStatusbarItem extends Disposable implements IWorkbenchCont
|
|||||||
private _showStatus(uri: string): void {
|
private _showStatus(uri: string): void {
|
||||||
let activeEditor = this.editorService.activeControl;
|
let activeEditor = this.editorService.activeControl;
|
||||||
if (activeEditor) {
|
if (activeEditor) {
|
||||||
let currentUri = activeEditor.input.getResource().toString();
|
let currentUri = activeEditor.input.resource.toString();
|
||||||
if (uri === currentUri) {
|
if (uri === currentUri) {
|
||||||
let flavor: SqlProviderEntry = this._sqlStatusEditors[uri];
|
let flavor: SqlProviderEntry = this._sqlStatusEditors[uri];
|
||||||
if (flavor) {
|
if (flavor) {
|
||||||
@@ -186,7 +186,7 @@ export class ChangeFlavorAction extends Action {
|
|||||||
|
|
||||||
public run(): Promise<any> {
|
public run(): Promise<any> {
|
||||||
let activeEditor = this._editorService.activeControl;
|
let activeEditor = this._editorService.activeControl;
|
||||||
let currentUri = activeEditor?.input.getResource().toString();
|
let currentUri = activeEditor?.input.resource.toString();
|
||||||
if (this._connectionManagementService.isConnected(currentUri)) {
|
if (this._connectionManagementService.isConnected(currentUri)) {
|
||||||
let currentProvider = this._connectionManagementService.getProviderIdFromUri(currentUri);
|
let currentProvider = this._connectionManagementService.getProviderIdFromUri(currentUri);
|
||||||
return this._showMessage(Severity.Info, nls.localize('alreadyConnected',
|
return this._showMessage(Severity.Info, nls.localize('alreadyConnected',
|
||||||
@@ -226,4 +226,3 @@ export class ChangeFlavorAction extends Action {
|
|||||||
return Promise.resolve(undefined);
|
return Promise.resolve(undefined);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ export class QueryEditor extends BaseEditor {
|
|||||||
this.queryEditorVisible = queryContext.QueryEditorVisibleContext.bindTo(contextKeyService);
|
this.queryEditorVisible = queryContext.QueryEditorVisibleContext.bindTo(contextKeyService);
|
||||||
|
|
||||||
// Clear view state for deleted files
|
// Clear view state for deleted files
|
||||||
this._register(fileService.onFileChanges(e => this.onFilesChanged(e)));
|
this._register(fileService.onDidFilesChange(e => this.onFilesChanged(e)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private onFilesChanged(e: FileChangesEvent): void {
|
private onFilesChanged(e: FileChangesEvent): void {
|
||||||
@@ -317,7 +317,7 @@ export class QueryEditor extends BaseEditor {
|
|||||||
this.inputDisposables.add(this.input.state.onChange(c => this.updateState(c)));
|
this.inputDisposables.add(this.input.state.onChange(c => this.updateState(c)));
|
||||||
this.updateState({ connectingChange: true, connectedChange: true, executingChange: true, resultsVisibleChange: true, sqlCmdModeChanged: true });
|
this.updateState({ connectingChange: true, connectedChange: true, executingChange: true, resultsVisibleChange: true, sqlCmdModeChanged: true });
|
||||||
|
|
||||||
const editorViewState = this.loadTextEditorViewState(this.input.getResource());
|
const editorViewState = this.loadTextEditorViewState(this.input.resource);
|
||||||
|
|
||||||
if (editorViewState && editorViewState.resultsHeight && this.splitview.length > 1) {
|
if (editorViewState && editorViewState.resultsHeight && this.splitview.length > 1) {
|
||||||
this.splitview.resizeView(1, editorViewState.resultsHeight);
|
this.splitview.resizeView(1, editorViewState.resultsHeight);
|
||||||
@@ -331,7 +331,7 @@ export class QueryEditor extends BaseEditor {
|
|||||||
|
|
||||||
// Otherwise we save the view state to restore it later
|
// Otherwise we save the view state to restore it later
|
||||||
else if (!input.isDisposed()) {
|
else if (!input.isDisposed()) {
|
||||||
this.saveTextEditorViewState(input.getResource());
|
this.saveTextEditorViewState(input.resource);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ export class QueryEditorLanguageAssociation implements ILanguageAssociation {
|
|||||||
@IEditorService private readonly editorService: IEditorService) { }
|
@IEditorService private readonly editorService: IEditorService) { }
|
||||||
|
|
||||||
convertInput(activeEditor: IEditorInput): QueryEditorInput | undefined {
|
convertInput(activeEditor: IEditorInput): QueryEditorInput | undefined {
|
||||||
const queryResultsInput = this.instantiationService.createInstance(QueryResultsInput, activeEditor.getResource().toString(true));
|
const queryResultsInput = this.instantiationService.createInstance(QueryResultsInput, activeEditor.resource.toString(true));
|
||||||
let queryEditorInput: QueryEditorInput;
|
let queryEditorInput: QueryEditorInput;
|
||||||
if (activeEditor instanceof FileEditorInput) {
|
if (activeEditor instanceof FileEditorInput) {
|
||||||
queryEditorInput = this.instantiationService.createInstance(FileQueryEditorInput, '', activeEditor, queryResultsInput);
|
queryEditorInput = this.instantiationService.createInstance(FileQueryEditorInput, '', activeEditor, queryResultsInput);
|
||||||
@@ -81,8 +81,8 @@ export class FileQueryEditorInputFactory implements IEditorInputFactory {
|
|||||||
const factory = editorInputFactoryRegistry.getEditorInputFactory(FILE_EDITOR_INPUT_ID);
|
const factory = editorInputFactoryRegistry.getEditorInputFactory(FILE_EDITOR_INPUT_ID);
|
||||||
const fileEditorInput = factory.deserialize(instantiationService, serializedEditorInput) as FileEditorInput;
|
const fileEditorInput = factory.deserialize(instantiationService, serializedEditorInput) as FileEditorInput;
|
||||||
// only successfully deserilize the file if the resource actually exists
|
// only successfully deserilize the file if the resource actually exists
|
||||||
if (this.fileService.exists(fileEditorInput.getResource())) {
|
if (this.fileService.exists(fileEditorInput.resource)) {
|
||||||
const queryResultsInput = instantiationService.createInstance(QueryResultsInput, fileEditorInput.getResource().toString());
|
const queryResultsInput = instantiationService.createInstance(QueryResultsInput, fileEditorInput.resource.toString());
|
||||||
return instantiationService.createInstance(FileQueryEditorInput, '', fileEditorInput, queryResultsInput);
|
return instantiationService.createInstance(FileQueryEditorInput, '', fileEditorInput, queryResultsInput);
|
||||||
} else {
|
} else {
|
||||||
fileEditorInput.dispose();
|
fileEditorInput.dispose();
|
||||||
@@ -110,7 +110,7 @@ export class UntitledQueryEditorInputFactory implements IEditorInputFactory {
|
|||||||
deserialize(instantiationService: IInstantiationService, serializedEditorInput: string): UntitledQueryEditorInput | undefined {
|
deserialize(instantiationService: IInstantiationService, serializedEditorInput: string): UntitledQueryEditorInput | undefined {
|
||||||
const factory = editorInputFactoryRegistry.getEditorInputFactory(UntitledTextEditorInput.ID);
|
const factory = editorInputFactoryRegistry.getEditorInputFactory(UntitledTextEditorInput.ID);
|
||||||
const untitledEditorInput = factory.deserialize(instantiationService, serializedEditorInput) as UntitledTextEditorInput;
|
const untitledEditorInput = factory.deserialize(instantiationService, serializedEditorInput) as UntitledTextEditorInput;
|
||||||
const queryResultsInput = instantiationService.createInstance(QueryResultsInput, untitledEditorInput.getResource().toString());
|
const queryResultsInput = instantiationService.createInstance(QueryResultsInput, untitledEditorInput.resource.toString());
|
||||||
return instantiationService.createInstance(UntitledQueryEditorInput, '', untitledEditorInput, queryResultsInput);
|
return instantiationService.createInstance(UntitledQueryEditorInput, '', untitledEditorInput, queryResultsInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export class QueryPlanConverter implements ILanguageAssociation {
|
|||||||
constructor(@IInstantiationService private instantiationService: IInstantiationService) { }
|
constructor(@IInstantiationService private instantiationService: IInstantiationService) { }
|
||||||
|
|
||||||
convertInput(activeEditor: IEditorInput): QueryPlanInput {
|
convertInput(activeEditor: IEditorInput): QueryPlanInput {
|
||||||
return this.instantiationService.createInstance(QueryPlanInput, activeEditor.getResource());
|
return this.instantiationService.createInstance(QueryPlanInput, activeEditor.resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
createBase(activeEditor: QueryPlanInput): IEditorInput {
|
createBase(activeEditor: QueryPlanInput): IEditorInput {
|
||||||
@@ -83,4 +83,8 @@ export class QueryPlanInput extends EditorInput {
|
|||||||
public get uniqueSelector(): string {
|
public get uniqueSelector(): string {
|
||||||
return this._uniqueSelector;
|
return this._uniqueSelector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get resource(): URI | undefined {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
"strictBindCallApply": true,
|
"strictBindCallApply": true,
|
||||||
"strictNullChecks": false,
|
"strictNullChecks": false,
|
||||||
"strictPropertyInitialization": false,
|
"strictPropertyInitialization": false,
|
||||||
|
"strict": false,
|
||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"paths": {
|
"paths": {
|
||||||
|
|||||||
@@ -251,14 +251,14 @@ export interface IGlobOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface ParsedStringPattern {
|
interface ParsedStringPattern {
|
||||||
(path: string, basename: string): string | null | Promise<string | null> /* the matching pattern */;
|
(path: string, basename?: string): string | null | Promise<string | null> /* the matching pattern */;
|
||||||
basenames?: string[];
|
basenames?: string[];
|
||||||
patterns?: string[];
|
patterns?: string[];
|
||||||
allBasenames?: string[];
|
allBasenames?: string[];
|
||||||
allPaths?: string[];
|
allPaths?: string[];
|
||||||
}
|
}
|
||||||
interface ParsedExpressionPattern {
|
interface ParsedExpressionPattern {
|
||||||
(path: string, basename: string, name?: string, hasSibling?: (name: string) => boolean | Promise<boolean>): string | null | Promise<string | null> /* the matching pattern */;
|
(path: string, basename?: string, name?: string, hasSibling?: (name: string) => boolean | Promise<boolean>): string | null | Promise<string | null> /* the matching pattern */;
|
||||||
requiresSiblings?: boolean;
|
requiresSiblings?: boolean;
|
||||||
allBasenames?: string[];
|
allBasenames?: string[];
|
||||||
allPaths?: string[];
|
allPaths?: string[];
|
||||||
@@ -374,7 +374,7 @@ function trivia3(pattern: string, options: IGlobOptions): ParsedStringPattern {
|
|||||||
if (n === 1) {
|
if (n === 1) {
|
||||||
return <ParsedStringPattern>parsedPatterns[0];
|
return <ParsedStringPattern>parsedPatterns[0];
|
||||||
}
|
}
|
||||||
const parsedPattern: ParsedStringPattern = function (path: string, basename: string) {
|
const parsedPattern: ParsedStringPattern = function (path: string, basename?: string) {
|
||||||
for (let i = 0, n = parsedPatterns.length; i < n; i++) {
|
for (let i = 0, n = parsedPatterns.length; i < n; i++) {
|
||||||
if ((<ParsedStringPattern>parsedPatterns[i])(path, basename)) {
|
if ((<ParsedStringPattern>parsedPatterns[i])(path, basename)) {
|
||||||
return pattern;
|
return pattern;
|
||||||
@@ -409,7 +409,7 @@ function trivia4and5(path: string, pattern: string, matchPathEnds: boolean): Par
|
|||||||
function toRegExp(pattern: string): ParsedStringPattern {
|
function toRegExp(pattern: string): ParsedStringPattern {
|
||||||
try {
|
try {
|
||||||
const regExp = new RegExp(`^${parseRegExp(pattern)}$`);
|
const regExp = new RegExp(`^${parseRegExp(pattern)}$`);
|
||||||
return function (path: string, basename: string) {
|
return function (path: string) {
|
||||||
regExp.lastIndex = 0; // reset RegExp to its initial state to reuse it!
|
regExp.lastIndex = 0; // reset RegExp to its initial state to reuse it!
|
||||||
return typeof path === 'string' && regExp.test(path) ? pattern : null;
|
return typeof path === 'string' && regExp.test(path) ? pattern : null;
|
||||||
};
|
};
|
||||||
@@ -457,7 +457,7 @@ export function parse(arg1: string | IExpression | IRelativePattern, options: IG
|
|||||||
if (parsedPattern === NULL) {
|
if (parsedPattern === NULL) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
const resultPattern: ParsedPattern & { allBasenames?: string[]; allPaths?: string[]; } = function (path: string, basename: string) {
|
const resultPattern: ParsedPattern & { allBasenames?: string[]; allPaths?: string[]; } = function (path: string, basename?: string) {
|
||||||
return !!parsedPattern(path, basename);
|
return !!parsedPattern(path, basename);
|
||||||
};
|
};
|
||||||
if (parsedPattern.allBasenames) {
|
if (parsedPattern.allBasenames) {
|
||||||
@@ -540,7 +540,7 @@ function parsedExpression(expression: IExpression, options: IGlobOptions): Parse
|
|||||||
return <ParsedStringPattern>parsedPatterns[0];
|
return <ParsedStringPattern>parsedPatterns[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
const resultExpression: ParsedStringPattern = function (path: string, basename: string) {
|
const resultExpression: ParsedStringPattern = function (path: string, basename?: string) {
|
||||||
for (let i = 0, n = parsedPatterns.length; i < n; i++) {
|
for (let i = 0, n = parsedPatterns.length; i < n; i++) {
|
||||||
// Pattern matches path
|
// Pattern matches path
|
||||||
const result = (<ParsedStringPattern>parsedPatterns[i])(path, basename);
|
const result = (<ParsedStringPattern>parsedPatterns[i])(path, basename);
|
||||||
@@ -565,7 +565,7 @@ function parsedExpression(expression: IExpression, options: IGlobOptions): Parse
|
|||||||
return resultExpression;
|
return resultExpression;
|
||||||
}
|
}
|
||||||
|
|
||||||
const resultExpression: ParsedStringPattern = function (path: string, basename: string, hasSibling?: (name: string) => boolean | Promise<boolean>) {
|
const resultExpression: ParsedStringPattern = function (path: string, basename?: string, hasSibling?: (name: string) => boolean | Promise<boolean>) {
|
||||||
let name: string | undefined = undefined;
|
let name: string | undefined = undefined;
|
||||||
|
|
||||||
for (let i = 0, n = parsedPatterns.length; i < n; i++) {
|
for (let i = 0, n = parsedPatterns.length; i < n; i++) {
|
||||||
@@ -620,12 +620,12 @@ function parseExpressionPattern(pattern: string, value: boolean | SiblingClause,
|
|||||||
if (value) {
|
if (value) {
|
||||||
const when = (<SiblingClause>value).when;
|
const when = (<SiblingClause>value).when;
|
||||||
if (typeof when === 'string') {
|
if (typeof when === 'string') {
|
||||||
const result: ParsedExpressionPattern = (path: string, basename: string, name: string, hasSibling: (name: string) => boolean | Promise<boolean>) => {
|
const result: ParsedExpressionPattern = (path: string, basename?: string, name?: string, hasSibling?: (name: string) => boolean | Promise<boolean>) => {
|
||||||
if (!hasSibling || !parsedPattern(path, basename)) {
|
if (!hasSibling || !parsedPattern(path, basename)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const clausePattern = when.replace('$(basename)', name);
|
const clausePattern = when.replace('$(basename)', name!);
|
||||||
const matched = hasSibling(clausePattern);
|
const matched = hasSibling(clausePattern);
|
||||||
return isThenable(matched) ?
|
return isThenable(matched) ?
|
||||||
matched.then(m => m ? pattern : null) :
|
matched.then(m => m ? pattern : null) :
|
||||||
|
|||||||
@@ -3,6 +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 { memoize } from 'vs/base/common/decorators';
|
||||||
|
|
||||||
export interface ILink {
|
export interface ILink {
|
||||||
readonly label: string;
|
readonly label: string;
|
||||||
readonly href: string;
|
readonly href: string;
|
||||||
@@ -10,7 +12,16 @@ export interface ILink {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type LinkedTextNode = string | ILink;
|
export type LinkedTextNode = string | ILink;
|
||||||
export type LinkedText = LinkedTextNode[];
|
|
||||||
|
export class LinkedText {
|
||||||
|
|
||||||
|
constructor(readonly nodes: LinkedTextNode[]) { }
|
||||||
|
|
||||||
|
@memoize
|
||||||
|
toString(): string {
|
||||||
|
return this.nodes.map(node => typeof node === 'string' ? node : node.label).join('');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const LINK_REGEX = /\[([^\]]+)\]\(((?:https?:\/\/|command:)[^\)\s]+)(?: "([^"]+)")?\)/gi;
|
const LINK_REGEX = /\[([^\]]+)\]\(((?:https?:\/\/|command:)[^\)\s]+)(?: "([^"]+)")?\)/gi;
|
||||||
|
|
||||||
@@ -40,5 +51,5 @@ export function parseLinkedText(text: string): LinkedText {
|
|||||||
result.push(text.substring(index));
|
result.push(text.substring(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return new LinkedText(result);
|
||||||
}
|
}
|
||||||
+13
-13
@@ -4,50 +4,50 @@
|
|||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import { parseLinkedText } from 'vs/base/browser/linkedText';
|
import { parseLinkedText } from 'vs/base/common/linkedText';
|
||||||
|
|
||||||
suite('LinkedText', () => {
|
suite('LinkedText', () => {
|
||||||
test('parses correctly', () => {
|
test('parses correctly', () => {
|
||||||
assert.deepEqual(parseLinkedText(''), []);
|
assert.deepEqual(parseLinkedText('').nodes, []);
|
||||||
assert.deepEqual(parseLinkedText('hello'), ['hello']);
|
assert.deepEqual(parseLinkedText('hello').nodes, ['hello']);
|
||||||
assert.deepEqual(parseLinkedText('hello there'), ['hello there']);
|
assert.deepEqual(parseLinkedText('hello there').nodes, ['hello there']);
|
||||||
assert.deepEqual(parseLinkedText('Some message with [link text](http://link.href).'), [
|
assert.deepEqual(parseLinkedText('Some message with [link text](http://link.href).').nodes, [
|
||||||
'Some message with ',
|
'Some message with ',
|
||||||
{ label: 'link text', href: 'http://link.href' },
|
{ label: 'link text', href: 'http://link.href' },
|
||||||
'.'
|
'.'
|
||||||
]);
|
]);
|
||||||
assert.deepEqual(parseLinkedText('Some message with [link text](http://link.href "and a title").'), [
|
assert.deepEqual(parseLinkedText('Some message with [link text](http://link.href "and a title").').nodes, [
|
||||||
'Some message with ',
|
'Some message with ',
|
||||||
{ label: 'link text', href: 'http://link.href', title: 'and a title' },
|
{ label: 'link text', href: 'http://link.href', title: 'and a title' },
|
||||||
'.'
|
'.'
|
||||||
]);
|
]);
|
||||||
assert.deepEqual(parseLinkedText('Some message with [link text](random stuff).'), [
|
assert.deepEqual(parseLinkedText('Some message with [link text](random stuff).').nodes, [
|
||||||
'Some message with [link text](random stuff).'
|
'Some message with [link text](random stuff).'
|
||||||
]);
|
]);
|
||||||
assert.deepEqual(parseLinkedText('Some message with [https link](https://link.href).'), [
|
assert.deepEqual(parseLinkedText('Some message with [https link](https://link.href).').nodes, [
|
||||||
'Some message with ',
|
'Some message with ',
|
||||||
{ label: 'https link', href: 'https://link.href' },
|
{ label: 'https link', href: 'https://link.href' },
|
||||||
'.'
|
'.'
|
||||||
]);
|
]);
|
||||||
assert.deepEqual(parseLinkedText('Some message with [https link](https:).'), [
|
assert.deepEqual(parseLinkedText('Some message with [https link](https:).').nodes, [
|
||||||
'Some message with [https link](https:).'
|
'Some message with [https link](https:).'
|
||||||
]);
|
]);
|
||||||
assert.deepEqual(parseLinkedText('Some message with [a command](command:foobar).'), [
|
assert.deepEqual(parseLinkedText('Some message with [a command](command:foobar).').nodes, [
|
||||||
'Some message with ',
|
'Some message with ',
|
||||||
{ label: 'a command', href: 'command:foobar' },
|
{ label: 'a command', href: 'command:foobar' },
|
||||||
'.'
|
'.'
|
||||||
]);
|
]);
|
||||||
assert.deepEqual(parseLinkedText('Some message with [a command](command:).'), [
|
assert.deepEqual(parseLinkedText('Some message with [a command](command:).').nodes, [
|
||||||
'Some message with [a command](command:).'
|
'Some message with [a command](command:).'
|
||||||
]);
|
]);
|
||||||
assert.deepEqual(parseLinkedText('link [one](command:foo "nice") and link [two](http://foo)...'), [
|
assert.deepEqual(parseLinkedText('link [one](command:foo "nice") and link [two](http://foo)...').nodes, [
|
||||||
'link ',
|
'link ',
|
||||||
{ label: 'one', href: 'command:foo', title: 'nice' },
|
{ label: 'one', href: 'command:foo', title: 'nice' },
|
||||||
' and link ',
|
' and link ',
|
||||||
{ label: 'two', href: 'http://foo' },
|
{ label: 'two', href: 'http://foo' },
|
||||||
'...'
|
'...'
|
||||||
]);
|
]);
|
||||||
assert.deepEqual(parseLinkedText('link\n[one](command:foo "nice")\nand link [two](http://foo)...'), [
|
assert.deepEqual(parseLinkedText('link\n[one](command:foo "nice")\nand link [two](http://foo)...').nodes, [
|
||||||
'link\n',
|
'link\n',
|
||||||
{ label: 'one', href: 'command:foo', title: 'nice' },
|
{ label: 'one', href: 'command:foo', title: 'nice' },
|
||||||
'\nand link ',
|
'\nand link ',
|
||||||
@@ -17,7 +17,7 @@ import { IExtensionManagementService, IExtensionGalleryService, IGlobalExtension
|
|||||||
import { ExtensionManagementService } from 'vs/platform/extensionManagement/node/extensionManagementService';
|
import { ExtensionManagementService } from 'vs/platform/extensionManagement/node/extensionManagementService';
|
||||||
import { ExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionGalleryService';
|
import { ExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionGalleryService';
|
||||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||||
import { ConfigurationService } from 'vs/platform/configuration/node/configurationService';
|
import { ConfigurationService } from 'vs/platform/configuration/common/configurationService';
|
||||||
import { IRequestService } from 'vs/platform/request/common/request';
|
import { IRequestService } from 'vs/platform/request/common/request';
|
||||||
import { RequestService } from 'vs/platform/request/browser/requestService';
|
import { RequestService } from 'vs/platform/request/browser/requestService';
|
||||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import { IStateService } from 'vs/platform/state/node/state';
|
|||||||
import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/environment';
|
import { IEnvironmentService, ParsedArgs } from 'vs/platform/environment/common/environment';
|
||||||
import { EnvironmentService, xdgRuntimeDir } from 'vs/platform/environment/node/environmentService';
|
import { EnvironmentService, xdgRuntimeDir } from 'vs/platform/environment/node/environmentService';
|
||||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||||
import { ConfigurationService } from 'vs/platform/configuration/node/configurationService';
|
import { ConfigurationService } from 'vs/platform/configuration/common/configurationService';
|
||||||
import { IRequestService } from 'vs/platform/request/common/request';
|
import { IRequestService } from 'vs/platform/request/common/request';
|
||||||
import { RequestMainService } from 'vs/platform/request/electron-main/requestMainService';
|
import { RequestMainService } from 'vs/platform/request/electron-main/requestMainService';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import { resolveCommonProperties } from 'vs/platform/telemetry/node/commonProper
|
|||||||
import { IRequestService } from 'vs/platform/request/common/request';
|
import { IRequestService } from 'vs/platform/request/common/request';
|
||||||
import { RequestService } from 'vs/platform/request/node/requestService';
|
import { RequestService } from 'vs/platform/request/node/requestService';
|
||||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||||
import { ConfigurationService } from 'vs/platform/configuration/node/configurationService';
|
import { ConfigurationService } from 'vs/platform/configuration/common/configurationService';
|
||||||
import { AppInsightsAppender } from 'vs/platform/telemetry/node/appInsightsAppender';
|
import { AppInsightsAppender } from 'vs/platform/telemetry/node/appInsightsAppender';
|
||||||
import { mkdirp, writeFile } from 'vs/base/node/pfs';
|
import { mkdirp, writeFile } from 'vs/base/node/pfs';
|
||||||
import { getBaseLabel } from 'vs/base/common/labels';
|
import { getBaseLabel } from 'vs/base/common/labels';
|
||||||
|
|||||||
@@ -1614,7 +1614,7 @@ export namespace CoreEditingCommands {
|
|||||||
constructor() {
|
constructor() {
|
||||||
super({
|
super({
|
||||||
id: 'deleteLeft',
|
id: 'deleteLeft',
|
||||||
precondition: EditorContextKeys.writable,
|
precondition: undefined,
|
||||||
kbOpts: {
|
kbOpts: {
|
||||||
weight: CORE_WEIGHT,
|
weight: CORE_WEIGHT,
|
||||||
kbExpr: EditorContextKeys.textInputFocus,
|
kbExpr: EditorContextKeys.textInputFocus,
|
||||||
@@ -1639,7 +1639,7 @@ export namespace CoreEditingCommands {
|
|||||||
constructor() {
|
constructor() {
|
||||||
super({
|
super({
|
||||||
id: 'deleteRight',
|
id: 'deleteRight',
|
||||||
precondition: EditorContextKeys.writable,
|
precondition: undefined,
|
||||||
kbOpts: {
|
kbOpts: {
|
||||||
weight: CORE_WEIGHT,
|
weight: CORE_WEIGHT,
|
||||||
kbExpr: EditorContextKeys.textInputFocus,
|
kbExpr: EditorContextKeys.textInputFocus,
|
||||||
|
|||||||
@@ -149,6 +149,10 @@ function createLineBreaks(requests: string[], fontInfo: FontInfo, tabSize: numbe
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const enum Constants {
|
||||||
|
SPAN_MODULO_LIMIT = 16384
|
||||||
|
}
|
||||||
|
|
||||||
function renderLine(lineContent: string, initialVisibleColumn: number, tabSize: number, width: number, sb: IStringBuilder): [number[], number[]] {
|
function renderLine(lineContent: string, initialVisibleColumn: number, tabSize: number, width: number, sb: IStringBuilder): [number[], number[]] {
|
||||||
sb.appendASCIIString('<div style="width:');
|
sb.appendASCIIString('<div style="width:');
|
||||||
sb.appendASCIIString(String(width));
|
sb.appendASCIIString(String(width));
|
||||||
@@ -164,7 +168,11 @@ function renderLine(lineContent: string, initialVisibleColumn: number, tabSize:
|
|||||||
let visibleColumns: number[] = [];
|
let visibleColumns: number[] = [];
|
||||||
let nextCharCode = (0 < len ? lineContent.charCodeAt(0) : CharCode.Null);
|
let nextCharCode = (0 < len ? lineContent.charCodeAt(0) : CharCode.Null);
|
||||||
|
|
||||||
|
sb.appendASCIIString('<span>');
|
||||||
for (let charIndex = 0; charIndex < len; charIndex++) {
|
for (let charIndex = 0; charIndex < len; charIndex++) {
|
||||||
|
if (charIndex !== 0 && charIndex % Constants.SPAN_MODULO_LIMIT === 0) {
|
||||||
|
sb.appendASCIIString('</span><span>');
|
||||||
|
}
|
||||||
charOffsets[charIndex] = charOffset;
|
charOffsets[charIndex] = charOffset;
|
||||||
visibleColumns[charIndex] = visibleColumn;
|
visibleColumns[charIndex] = visibleColumn;
|
||||||
const charCode = nextCharCode;
|
const charCode = nextCharCode;
|
||||||
@@ -227,6 +235,7 @@ function renderLine(lineContent: string, initialVisibleColumn: number, tabSize:
|
|||||||
charOffset += producedCharacters;
|
charOffset += producedCharacters;
|
||||||
visibleColumn += charWidth;
|
visibleColumn += charWidth;
|
||||||
}
|
}
|
||||||
|
sb.appendASCIIString('</span>');
|
||||||
|
|
||||||
charOffsets[lineContent.length] = charOffset;
|
charOffsets[lineContent.length] = charOffset;
|
||||||
visibleColumns[lineContent.length] = visibleColumn;
|
visibleColumns[lineContent.length] = visibleColumn;
|
||||||
@@ -240,10 +249,15 @@ function readLineBreaks(range: Range, lineDomNode: HTMLDivElement, lineContent:
|
|||||||
if (lineContent.length <= 1) {
|
if (lineContent.length <= 1) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const textContentNode = lineDomNode.firstChild!;
|
const spans = <HTMLSpanElement[]>Array.prototype.slice.call(lineDomNode.children, 0);
|
||||||
|
|
||||||
const breakOffsets: number[] = [];
|
const breakOffsets: number[] = [];
|
||||||
discoverBreaks(range, textContentNode, charOffsets, 0, null, lineContent.length - 1, null, breakOffsets);
|
try {
|
||||||
|
discoverBreaks(range, spans, charOffsets, 0, null, lineContent.length - 1, null, breakOffsets);
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (breakOffsets.length === 0) {
|
if (breakOffsets.length === 0) {
|
||||||
return null;
|
return null;
|
||||||
@@ -255,13 +269,13 @@ function readLineBreaks(range: Range, lineDomNode: HTMLDivElement, lineContent:
|
|||||||
|
|
||||||
type MaybeRects = ClientRectList | DOMRectList | null;
|
type MaybeRects = ClientRectList | DOMRectList | null;
|
||||||
|
|
||||||
function discoverBreaks(range: Range, textContentNode: Node, charOffsets: number[], low: number, lowRects: MaybeRects, high: number, highRects: MaybeRects, result: number[]): void {
|
function discoverBreaks(range: Range, spans: HTMLSpanElement[], charOffsets: number[], low: number, lowRects: MaybeRects, high: number, highRects: MaybeRects, result: number[]): void {
|
||||||
if (low === high) {
|
if (low === high) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
lowRects = lowRects || readClientRect(range, textContentNode, charOffsets[low], charOffsets[low + 1]);
|
lowRects = lowRects || readClientRect(range, spans, charOffsets[low], charOffsets[low + 1]);
|
||||||
highRects = highRects || readClientRect(range, textContentNode, charOffsets[high], charOffsets[high + 1]);
|
highRects = highRects || readClientRect(range, spans, charOffsets[high], charOffsets[high + 1]);
|
||||||
|
|
||||||
if (Math.abs(lowRects[0].top - highRects[0].top) <= 0.1) {
|
if (Math.abs(lowRects[0].top - highRects[0].top) <= 0.1) {
|
||||||
// same line
|
// same line
|
||||||
@@ -276,13 +290,13 @@ function discoverBreaks(range: Range, textContentNode: Node, charOffsets: number
|
|||||||
}
|
}
|
||||||
|
|
||||||
const mid = low + ((high - low) / 2) | 0;
|
const mid = low + ((high - low) / 2) | 0;
|
||||||
const midRects = readClientRect(range, textContentNode, charOffsets[mid], charOffsets[mid + 1]);
|
const midRects = readClientRect(range, spans, charOffsets[mid], charOffsets[mid + 1]);
|
||||||
discoverBreaks(range, textContentNode, charOffsets, low, lowRects, mid, midRects, result);
|
discoverBreaks(range, spans, charOffsets, low, lowRects, mid, midRects, result);
|
||||||
discoverBreaks(range, textContentNode, charOffsets, mid, midRects, high, highRects, result);
|
discoverBreaks(range, spans, charOffsets, mid, midRects, high, highRects, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
function readClientRect(range: Range, textContentNode: Node, startOffset: number, endOffset: number): ClientRectList | DOMRectList {
|
function readClientRect(range: Range, spans: HTMLSpanElement[], startOffset: number, endOffset: number): ClientRectList | DOMRectList {
|
||||||
range.setStart(textContentNode, startOffset);
|
range.setStart(spans[(startOffset / Constants.SPAN_MODULO_LIMIT) | 0].firstChild!, startOffset % Constants.SPAN_MODULO_LIMIT);
|
||||||
range.setEnd(textContentNode, endOffset);
|
range.setEnd(spans[(endOffset / Constants.SPAN_MODULO_LIMIT) | 0].firstChild!, endOffset % Constants.SPAN_MODULO_LIMIT);
|
||||||
return range.getClientRects();
|
return range.getClientRects();
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -34,11 +34,13 @@ export class MinimapCharRenderer {
|
|||||||
color: RGBA8,
|
color: RGBA8,
|
||||||
backgroundColor: RGBA8,
|
backgroundColor: RGBA8,
|
||||||
fontScale: number,
|
fontScale: number,
|
||||||
useLighterFont: boolean
|
useLighterFont: boolean,
|
||||||
|
force1pxHeight: boolean
|
||||||
): void {
|
): void {
|
||||||
const charWidth = Constants.BASE_CHAR_WIDTH * this.scale;
|
const charWidth = Constants.BASE_CHAR_WIDTH * this.scale;
|
||||||
const charHeight = Constants.BASE_CHAR_HEIGHT * this.scale;
|
const charHeight = Constants.BASE_CHAR_HEIGHT * this.scale;
|
||||||
if (dx + charWidth > target.width || dy + charHeight > target.height) {
|
const renderHeight = (force1pxHeight ? 1 : charHeight);
|
||||||
|
if (dx + charWidth > target.width || dy + renderHeight > target.height) {
|
||||||
console.warn('bad render request outside image data');
|
console.warn('bad render request outside image data');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -60,7 +62,7 @@ export class MinimapCharRenderer {
|
|||||||
let sourceOffset = charIndex * charWidth * charHeight;
|
let sourceOffset = charIndex * charWidth * charHeight;
|
||||||
|
|
||||||
let row = dy * destWidth + dx * Constants.RGBA_CHANNELS_CNT;
|
let row = dy * destWidth + dx * Constants.RGBA_CHANNELS_CNT;
|
||||||
for (let y = 0; y < charHeight; y++) {
|
for (let y = 0; y < renderHeight; y++) {
|
||||||
let column = row;
|
let column = row;
|
||||||
for (let x = 0; x < charWidth; x++) {
|
for (let x = 0; x < charWidth; x++) {
|
||||||
const c = charData[sourceOffset++] / 255;
|
const c = charData[sourceOffset++] / 255;
|
||||||
@@ -80,11 +82,13 @@ export class MinimapCharRenderer {
|
|||||||
dy: number,
|
dy: number,
|
||||||
color: RGBA8,
|
color: RGBA8,
|
||||||
backgroundColor: RGBA8,
|
backgroundColor: RGBA8,
|
||||||
useLighterFont: boolean
|
useLighterFont: boolean,
|
||||||
|
force1pxHeight: boolean
|
||||||
): void {
|
): void {
|
||||||
const charWidth = Constants.BASE_CHAR_WIDTH * this.scale;
|
const charWidth = Constants.BASE_CHAR_WIDTH * this.scale;
|
||||||
const charHeight = Constants.BASE_CHAR_HEIGHT * this.scale;
|
const charHeight = Constants.BASE_CHAR_HEIGHT * this.scale;
|
||||||
if (dx + charWidth > target.width || dy + charHeight > target.height) {
|
const renderHeight = (force1pxHeight ? 1 : charHeight);
|
||||||
|
if (dx + charWidth > target.width || dy + renderHeight > target.height) {
|
||||||
console.warn('bad render request outside image data');
|
console.warn('bad render request outside image data');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -108,7 +112,7 @@ export class MinimapCharRenderer {
|
|||||||
const dest = target.data;
|
const dest = target.data;
|
||||||
|
|
||||||
let row = dy * destWidth + dx * Constants.RGBA_CHANNELS_CNT;
|
let row = dy * destWidth + dx * Constants.RGBA_CHANNELS_CNT;
|
||||||
for (let y = 0; y < charHeight; y++) {
|
for (let y = 0; y < renderHeight; y++) {
|
||||||
let column = row;
|
let column = row;
|
||||||
for (let x = 0; x < charWidth; x++) {
|
for (let x = 0; x < charWidth; x++) {
|
||||||
dest[column++] = colorR;
|
dest[column++] = colorR;
|
||||||
|
|||||||
@@ -276,7 +276,10 @@ export class DecorationsOverviewRuler extends ViewPart {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
public onDecorationsChanged(e: viewEvents.ViewDecorationsChangedEvent): boolean {
|
public onDecorationsChanged(e: viewEvents.ViewDecorationsChangedEvent): boolean {
|
||||||
return true;
|
if (e.affectsOverviewRuler) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
public onFlushed(e: viewEvents.ViewFlushedEvent): boolean {
|
public onFlushed(e: viewEvents.ViewFlushedEvent): boolean {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -287,6 +287,7 @@ export abstract class CommonEditorConfiguration extends Disposable implements IC
|
|||||||
public options!: ComputedEditorOptions;
|
public options!: ComputedEditorOptions;
|
||||||
|
|
||||||
private _isDominatedByLongLines: boolean;
|
private _isDominatedByLongLines: boolean;
|
||||||
|
private _maxLineNumber: number;
|
||||||
private _lineNumbersDigitCount: number;
|
private _lineNumbersDigitCount: number;
|
||||||
|
|
||||||
private _rawOptions: IEditorOptions;
|
private _rawOptions: IEditorOptions;
|
||||||
@@ -298,6 +299,7 @@ export abstract class CommonEditorConfiguration extends Disposable implements IC
|
|||||||
this.isSimpleWidget = isSimpleWidget;
|
this.isSimpleWidget = isSimpleWidget;
|
||||||
|
|
||||||
this._isDominatedByLongLines = false;
|
this._isDominatedByLongLines = false;
|
||||||
|
this._maxLineNumber = 1;
|
||||||
this._lineNumbersDigitCount = 1;
|
this._lineNumbersDigitCount = 1;
|
||||||
|
|
||||||
this._rawOptions = deepCloneAndMigrateOptions(_options);
|
this._rawOptions = deepCloneAndMigrateOptions(_options);
|
||||||
@@ -347,6 +349,7 @@ export abstract class CommonEditorConfiguration extends Disposable implements IC
|
|||||||
fontInfo: this.readConfiguration(bareFontInfo),
|
fontInfo: this.readConfiguration(bareFontInfo),
|
||||||
extraEditorClassName: partialEnv.extraEditorClassName,
|
extraEditorClassName: partialEnv.extraEditorClassName,
|
||||||
isDominatedByLongLines: this._isDominatedByLongLines,
|
isDominatedByLongLines: this._isDominatedByLongLines,
|
||||||
|
maxLineNumber: this._maxLineNumber,
|
||||||
lineNumbersDigitCount: this._lineNumbersDigitCount,
|
lineNumbersDigitCount: this._lineNumbersDigitCount,
|
||||||
emptySelectionClipboard: partialEnv.emptySelectionClipboard,
|
emptySelectionClipboard: partialEnv.emptySelectionClipboard,
|
||||||
pixelRatio: partialEnv.pixelRatio,
|
pixelRatio: partialEnv.pixelRatio,
|
||||||
@@ -405,11 +408,11 @@ export abstract class CommonEditorConfiguration extends Disposable implements IC
|
|||||||
}
|
}
|
||||||
|
|
||||||
public setMaxLineNumber(maxLineNumber: number): void {
|
public setMaxLineNumber(maxLineNumber: number): void {
|
||||||
let digitCount = CommonEditorConfiguration._digitCount(maxLineNumber);
|
if (this._maxLineNumber === maxLineNumber) {
|
||||||
if (this._lineNumbersDigitCount === digitCount) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._lineNumbersDigitCount = digitCount;
|
this._maxLineNumber = maxLineNumber;
|
||||||
|
this._lineNumbersDigitCount = CommonEditorConfiguration._digitCount(maxLineNumber);
|
||||||
this._recomputeOptions();
|
this._recomputeOptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -678,6 +678,7 @@ export interface IEnvironmentalOptions {
|
|||||||
readonly fontInfo: FontInfo;
|
readonly fontInfo: FontInfo;
|
||||||
readonly extraEditorClassName: string;
|
readonly extraEditorClassName: string;
|
||||||
readonly isDominatedByLongLines: boolean;
|
readonly isDominatedByLongLines: boolean;
|
||||||
|
readonly maxLineNumber: number;
|
||||||
readonly lineNumbersDigitCount: number;
|
readonly lineNumbersDigitCount: number;
|
||||||
readonly emptySelectionClipboard: boolean;
|
readonly emptySelectionClipboard: boolean;
|
||||||
readonly pixelRatio: number;
|
readonly pixelRatio: number;
|
||||||
@@ -1691,6 +1692,14 @@ export interface EditorLayoutInfo {
|
|||||||
* The width of the minimap
|
* The width of the minimap
|
||||||
*/
|
*/
|
||||||
readonly minimapWidth: number;
|
readonly minimapWidth: number;
|
||||||
|
readonly minimapHeightIsEditorHeight: boolean;
|
||||||
|
readonly minimapIsSampling: boolean;
|
||||||
|
readonly minimapScale: number;
|
||||||
|
readonly minimapLineHeight: number;
|
||||||
|
readonly minimapCanvasInnerWidth: number;
|
||||||
|
readonly minimapCanvasInnerHeight: number;
|
||||||
|
readonly minimapCanvasOuterWidth: number;
|
||||||
|
readonly minimapCanvasOuterHeight: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Minimap render type
|
* Minimap render type
|
||||||
@@ -1724,6 +1733,7 @@ export interface EditorLayoutInfoComputerEnv {
|
|||||||
outerWidth: number;
|
outerWidth: number;
|
||||||
outerHeight: number;
|
outerHeight: number;
|
||||||
lineHeight: number;
|
lineHeight: number;
|
||||||
|
maxLineNumber: number;
|
||||||
lineNumbersDigitCount: number;
|
lineNumbersDigitCount: number;
|
||||||
typicalHalfwidthCharacterWidth: number;
|
typicalHalfwidthCharacterWidth: number;
|
||||||
maxDigitWidth: number;
|
maxDigitWidth: number;
|
||||||
@@ -1747,6 +1757,7 @@ export class EditorLayoutInfoComputer extends ComputedEditorOption<EditorOption.
|
|||||||
outerWidth: env.outerWidth,
|
outerWidth: env.outerWidth,
|
||||||
outerHeight: env.outerHeight,
|
outerHeight: env.outerHeight,
|
||||||
lineHeight: env.fontInfo.lineHeight,
|
lineHeight: env.fontInfo.lineHeight,
|
||||||
|
maxLineNumber: env.maxLineNumber,
|
||||||
lineNumbersDigitCount: env.lineNumbersDigitCount,
|
lineNumbersDigitCount: env.lineNumbersDigitCount,
|
||||||
typicalHalfwidthCharacterWidth: env.fontInfo.typicalHalfwidthCharacterWidth,
|
typicalHalfwidthCharacterWidth: env.fontInfo.typicalHalfwidthCharacterWidth,
|
||||||
maxDigitWidth: env.fontInfo.maxDigitWidth,
|
maxDigitWidth: env.fontInfo.maxDigitWidth,
|
||||||
@@ -1754,6 +1765,20 @@ export class EditorLayoutInfoComputer extends ComputedEditorOption<EditorOption.
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static computeContainedMinimapLineCount(input: {
|
||||||
|
modelLineCount: number;
|
||||||
|
scrollBeyondLastLine: boolean;
|
||||||
|
height: number;
|
||||||
|
lineHeight: number;
|
||||||
|
pixelRatio: number;
|
||||||
|
}): { typicalViewportLineCount: number; extraLinesBeyondLastLine: number; desiredRatio: number; minimapLineCount: number; } {
|
||||||
|
const typicalViewportLineCount = input.height / input.lineHeight;
|
||||||
|
const extraLinesBeyondLastLine = input.scrollBeyondLastLine ? (typicalViewportLineCount - 1) : 0;
|
||||||
|
const desiredRatio = (input.modelLineCount + extraLinesBeyondLastLine) / (input.pixelRatio * input.height);
|
||||||
|
const minimapLineCount = Math.floor(input.modelLineCount / desiredRatio);
|
||||||
|
return { typicalViewportLineCount, extraLinesBeyondLastLine, desiredRatio, minimapLineCount };
|
||||||
|
}
|
||||||
|
|
||||||
public static computeLayout(options: IComputedEditorOptions, env: EditorLayoutInfoComputerEnv): EditorLayoutInfo {
|
public static computeLayout(options: IComputedEditorOptions, env: EditorLayoutInfoComputerEnv): EditorLayoutInfo {
|
||||||
const outerWidth = env.outerWidth | 0;
|
const outerWidth = env.outerWidth | 0;
|
||||||
const outerHeight = env.outerHeight | 0;
|
const outerHeight = env.outerHeight | 0;
|
||||||
@@ -1766,12 +1791,14 @@ export class EditorLayoutInfoComputer extends ComputedEditorOption<EditorOption.
|
|||||||
const showGlyphMargin = options.get(EditorOption.glyphMargin);
|
const showGlyphMargin = options.get(EditorOption.glyphMargin);
|
||||||
const showLineNumbers = (options.get(EditorOption.lineNumbers).renderType !== RenderLineNumbersType.Off);
|
const showLineNumbers = (options.get(EditorOption.lineNumbers).renderType !== RenderLineNumbersType.Off);
|
||||||
const lineNumbersMinChars = options.get(EditorOption.lineNumbersMinChars) | 0;
|
const lineNumbersMinChars = options.get(EditorOption.lineNumbersMinChars) | 0;
|
||||||
|
const scrollBeyondLastLine = options.get(EditorOption.scrollBeyondLastLine);
|
||||||
const minimap = options.get(EditorOption.minimap);
|
const minimap = options.get(EditorOption.minimap);
|
||||||
const minimapEnabled = minimap.enabled;
|
const minimapEnabled = minimap.enabled;
|
||||||
const minimapSide = minimap.side;
|
const minimapSide = minimap.side;
|
||||||
const minimapRenderCharacters = minimap.renderCharacters;
|
const minimapRenderCharacters = minimap.renderCharacters;
|
||||||
const minimapScale = (pixelRatio >= 2 ? Math.round(minimap.scale * 2) : minimap.scale);
|
let minimapScale = (pixelRatio >= 2 ? Math.round(minimap.scale * 2) : minimap.scale);
|
||||||
const minimapMaxColumn = minimap.maxColumn | 0;
|
const minimapMaxColumn = minimap.maxColumn | 0;
|
||||||
|
const minimapMode = minimap.mode;
|
||||||
|
|
||||||
const scrollbar = options.get(EditorOption.scrollbar);
|
const scrollbar = options.get(EditorOption.scrollbar);
|
||||||
const verticalScrollbarWidth = scrollbar.verticalScrollbarSize | 0;
|
const verticalScrollbarWidth = scrollbar.verticalScrollbarSize | 0;
|
||||||
@@ -1811,19 +1838,65 @@ export class EditorLayoutInfoComputer extends ComputedEditorOption<EditorOption.
|
|||||||
|
|
||||||
const remainingWidth = outerWidth - glyphMarginWidth - lineNumbersWidth - lineDecorationsWidth;
|
const remainingWidth = outerWidth - glyphMarginWidth - lineNumbersWidth - lineDecorationsWidth;
|
||||||
|
|
||||||
|
const baseCharHeight = minimapRenderCharacters ? 2 : 3;
|
||||||
let renderMinimap: RenderMinimap;
|
let renderMinimap: RenderMinimap;
|
||||||
let minimapLeft: number;
|
let minimapLeft: number;
|
||||||
let minimapWidth: number;
|
let minimapWidth: number;
|
||||||
|
let minimapCanvasInnerWidth: number;
|
||||||
|
let minimapCanvasInnerHeight = Math.floor(pixelRatio * outerHeight);
|
||||||
|
let minimapCanvasOuterWidth: number;
|
||||||
|
const minimapCanvasOuterHeight = minimapCanvasInnerHeight / pixelRatio;
|
||||||
|
let minimapHeightIsEditorHeight = false;
|
||||||
|
let minimapIsSampling = false;
|
||||||
|
let minimapLineHeight = baseCharHeight * minimapScale;
|
||||||
let contentWidth: number;
|
let contentWidth: number;
|
||||||
if (!minimapEnabled) {
|
if (!minimapEnabled) {
|
||||||
minimapLeft = 0;
|
minimapLeft = 0;
|
||||||
minimapWidth = 0;
|
minimapWidth = 0;
|
||||||
|
minimapCanvasInnerWidth = 0;
|
||||||
|
minimapCanvasOuterWidth = 0;
|
||||||
|
minimapLineHeight = 1;
|
||||||
renderMinimap = RenderMinimap.None;
|
renderMinimap = RenderMinimap.None;
|
||||||
contentWidth = remainingWidth;
|
contentWidth = remainingWidth;
|
||||||
} else {
|
} else {
|
||||||
// The minimapScale is also the pixel width of each character. Adjust
|
let minimapCharWidth = minimapScale / pixelRatio;
|
||||||
// for the pixel ratio of the screen.
|
let minimapWidthMultiplier: number = 1;
|
||||||
const minimapCharWidth = minimapScale / pixelRatio;
|
|
||||||
|
if (minimapMode === 'cover' || minimapMode === 'contain') {
|
||||||
|
const modelLineCount = env.maxLineNumber;
|
||||||
|
const { typicalViewportLineCount, extraLinesBeyondLastLine, desiredRatio, minimapLineCount } = EditorLayoutInfoComputer.computeContainedMinimapLineCount({
|
||||||
|
modelLineCount: modelLineCount,
|
||||||
|
scrollBeyondLastLine: scrollBeyondLastLine,
|
||||||
|
height: outerHeight,
|
||||||
|
lineHeight: lineHeight,
|
||||||
|
pixelRatio: pixelRatio
|
||||||
|
});
|
||||||
|
// ratio is intentionally not part of the layout to avoid the layout changing all the time
|
||||||
|
// when doing sampling
|
||||||
|
const ratio = modelLineCount / minimapLineCount;
|
||||||
|
|
||||||
|
if (ratio > 1) {
|
||||||
|
minimapHeightIsEditorHeight = true;
|
||||||
|
minimapIsSampling = true;
|
||||||
|
minimapScale = 1;
|
||||||
|
minimapLineHeight = 1;
|
||||||
|
minimapCharWidth = minimapScale / pixelRatio;
|
||||||
|
} else {
|
||||||
|
const effectiveMinimapHeight = Math.ceil((modelLineCount + extraLinesBeyondLastLine) * minimapLineHeight);
|
||||||
|
if (minimapMode === 'cover' || effectiveMinimapHeight > minimapCanvasInnerHeight) {
|
||||||
|
minimapHeightIsEditorHeight = true;
|
||||||
|
const configuredFontScale = minimapScale;
|
||||||
|
minimapLineHeight = Math.min(lineHeight * pixelRatio, Math.max(1, Math.floor(1 / desiredRatio)));
|
||||||
|
minimapScale = Math.min(configuredFontScale + 1, Math.max(1, Math.floor(minimapLineHeight / baseCharHeight)));
|
||||||
|
if (minimapScale > configuredFontScale) {
|
||||||
|
minimapWidthMultiplier = Math.min(2, minimapScale / configuredFontScale);
|
||||||
|
}
|
||||||
|
minimapCharWidth = minimapScale / pixelRatio / minimapWidthMultiplier;
|
||||||
|
minimapCanvasInnerHeight = Math.ceil((Math.max(typicalViewportLineCount, modelLineCount + extraLinesBeyondLastLine)) * minimapLineHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
renderMinimap = minimapRenderCharacters ? RenderMinimap.Text : RenderMinimap.Blocks;
|
renderMinimap = minimapRenderCharacters ? RenderMinimap.Text : RenderMinimap.Blocks;
|
||||||
|
|
||||||
// Given:
|
// Given:
|
||||||
@@ -1855,6 +1928,10 @@ export class EditorLayoutInfoComputer extends ComputedEditorOption<EditorOption.
|
|||||||
} else {
|
} else {
|
||||||
minimapLeft = outerWidth - minimapWidth - verticalScrollbarWidth;
|
minimapLeft = outerWidth - minimapWidth - verticalScrollbarWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
minimapCanvasInnerWidth = Math.floor(pixelRatio * minimapWidth);
|
||||||
|
minimapCanvasOuterWidth = minimapCanvasInnerWidth / pixelRatio;
|
||||||
|
minimapCanvasInnerWidth = Math.floor(minimapCanvasInnerWidth * minimapWidthMultiplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
// (leaving 2px for the cursor to have space after the last character)
|
// (leaving 2px for the cursor to have space after the last character)
|
||||||
@@ -1881,6 +1958,14 @@ export class EditorLayoutInfoComputer extends ComputedEditorOption<EditorOption.
|
|||||||
renderMinimap: renderMinimap,
|
renderMinimap: renderMinimap,
|
||||||
minimapLeft: minimapLeft,
|
minimapLeft: minimapLeft,
|
||||||
minimapWidth: minimapWidth,
|
minimapWidth: minimapWidth,
|
||||||
|
minimapHeightIsEditorHeight: minimapHeightIsEditorHeight,
|
||||||
|
minimapIsSampling: minimapIsSampling,
|
||||||
|
minimapScale: minimapScale,
|
||||||
|
minimapLineHeight: minimapLineHeight,
|
||||||
|
minimapCanvasInnerWidth: minimapCanvasInnerWidth,
|
||||||
|
minimapCanvasInnerHeight: minimapCanvasInnerHeight,
|
||||||
|
minimapCanvasOuterWidth: minimapCanvasOuterWidth,
|
||||||
|
minimapCanvasOuterHeight: minimapCanvasOuterHeight,
|
||||||
|
|
||||||
viewportColumn: viewportColumn,
|
viewportColumn: viewportColumn,
|
||||||
|
|
||||||
@@ -1981,6 +2066,11 @@ export interface IEditorMinimapOptions {
|
|||||||
* Defaults to 'right'.
|
* Defaults to 'right'.
|
||||||
*/
|
*/
|
||||||
side?: 'right' | 'left';
|
side?: 'right' | 'left';
|
||||||
|
/**
|
||||||
|
* Control the minimap rendering mode.
|
||||||
|
* Defaults to 'actual'.
|
||||||
|
*/
|
||||||
|
mode?: 'actual' | 'cover' | 'contain';
|
||||||
/**
|
/**
|
||||||
* Control the rendering of the minimap slider.
|
* Control the rendering of the minimap slider.
|
||||||
* Defaults to 'mouseover'.
|
* Defaults to 'mouseover'.
|
||||||
@@ -1996,7 +2086,6 @@ export interface IEditorMinimapOptions {
|
|||||||
* Defaults to 120.
|
* Defaults to 120.
|
||||||
*/
|
*/
|
||||||
maxColumn?: number;
|
maxColumn?: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Relative size of the font in the minimap. Defaults to 1.
|
* Relative size of the font in the minimap. Defaults to 1.
|
||||||
*/
|
*/
|
||||||
@@ -2010,6 +2099,7 @@ class EditorMinimap extends BaseEditorOption<EditorOption.minimap, EditorMinimap
|
|||||||
constructor() {
|
constructor() {
|
||||||
const defaults: EditorMinimapOptions = {
|
const defaults: EditorMinimapOptions = {
|
||||||
enabled: false, // {{SQL CARBON EDIT}} disable minimap by default
|
enabled: false, // {{SQL CARBON EDIT}} disable minimap by default
|
||||||
|
mode: 'actual',
|
||||||
side: 'right',
|
side: 'right',
|
||||||
showSlider: 'mouseover',
|
showSlider: 'mouseover',
|
||||||
renderCharacters: true,
|
renderCharacters: true,
|
||||||
@@ -2024,6 +2114,17 @@ class EditorMinimap extends BaseEditorOption<EditorOption.minimap, EditorMinimap
|
|||||||
default: defaults.enabled,
|
default: defaults.enabled,
|
||||||
description: nls.localize('minimap.enabled', "Controls whether the minimap is shown.")
|
description: nls.localize('minimap.enabled', "Controls whether the minimap is shown.")
|
||||||
},
|
},
|
||||||
|
'editor.minimap.mode': {
|
||||||
|
type: 'string',
|
||||||
|
enum: ['actual', 'cover', 'contain'],
|
||||||
|
enumDescriptions: [
|
||||||
|
nls.localize('minimap.mode.actual', "The minimap will be displayed in its original size, so it might be higher than the editor."),
|
||||||
|
nls.localize('minimap.mode.cover', "The minimap will always have the height of the editor and will stretch or shrink as necessary."),
|
||||||
|
nls.localize('minimap.mode.contain', "The minimap will shrink as necessary to never be higher than the editor."),
|
||||||
|
],
|
||||||
|
default: defaults.mode,
|
||||||
|
description: nls.localize('minimap.mode', "Controls the rendering mode of the minimap.")
|
||||||
|
},
|
||||||
'editor.minimap.side': {
|
'editor.minimap.side': {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
enum: ['left', 'right'],
|
enum: ['left', 'right'],
|
||||||
@@ -2052,7 +2153,7 @@ class EditorMinimap extends BaseEditorOption<EditorOption.minimap, EditorMinimap
|
|||||||
type: 'number',
|
type: 'number',
|
||||||
default: defaults.maxColumn,
|
default: defaults.maxColumn,
|
||||||
description: nls.localize('minimap.maxColumn', "Limit the width of the minimap to render at most a certain number of columns.")
|
description: nls.localize('minimap.maxColumn', "Limit the width of the minimap to render at most a certain number of columns.")
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -2064,6 +2165,7 @@ class EditorMinimap extends BaseEditorOption<EditorOption.minimap, EditorMinimap
|
|||||||
const input = _input as IEditorMinimapOptions;
|
const input = _input as IEditorMinimapOptions;
|
||||||
return {
|
return {
|
||||||
enabled: EditorBooleanOption.boolean(input.enabled, this.defaultValue.enabled),
|
enabled: EditorBooleanOption.boolean(input.enabled, this.defaultValue.enabled),
|
||||||
|
mode: EditorStringEnumOption.stringSet<'actual' | 'cover' | 'contain'>(input.mode, this.defaultValue.mode, ['actual', 'cover', 'contain']),
|
||||||
side: EditorStringEnumOption.stringSet<'right' | 'left'>(input.side, this.defaultValue.side, ['right', 'left']),
|
side: EditorStringEnumOption.stringSet<'right' | 'left'>(input.side, this.defaultValue.side, ['right', 'left']),
|
||||||
showSlider: EditorStringEnumOption.stringSet<'always' | 'mouseover'>(input.showSlider, this.defaultValue.showSlider, ['always', 'mouseover']),
|
showSlider: EditorStringEnumOption.stringSet<'always' | 'mouseover'>(input.showSlider, this.defaultValue.showSlider, ['always', 'mouseover']),
|
||||||
renderCharacters: EditorBooleanOption.boolean(input.renderCharacters, this.defaultValue.renderCharacters),
|
renderCharacters: EditorBooleanOption.boolean(input.renderCharacters, this.defaultValue.renderCharacters),
|
||||||
|
|||||||
@@ -1423,19 +1423,15 @@ export class TextModel extends Disposable implements model.ITextModel {
|
|||||||
private _changeDecorations<T>(ownerId: number, callback: (changeAccessor: model.IModelDecorationsChangeAccessor) => T): T | null {
|
private _changeDecorations<T>(ownerId: number, callback: (changeAccessor: model.IModelDecorationsChangeAccessor) => T): T | null {
|
||||||
let changeAccessor: model.IModelDecorationsChangeAccessor = {
|
let changeAccessor: model.IModelDecorationsChangeAccessor = {
|
||||||
addDecoration: (range: IRange, options: model.IModelDecorationOptions): string => {
|
addDecoration: (range: IRange, options: model.IModelDecorationOptions): string => {
|
||||||
this._onDidChangeDecorations.fire();
|
|
||||||
return this._deltaDecorationsImpl(ownerId, [], [{ range: range, options: options }])[0];
|
return this._deltaDecorationsImpl(ownerId, [], [{ range: range, options: options }])[0];
|
||||||
},
|
},
|
||||||
changeDecoration: (id: string, newRange: IRange): void => {
|
changeDecoration: (id: string, newRange: IRange): void => {
|
||||||
this._onDidChangeDecorations.fire();
|
|
||||||
this._changeDecorationImpl(id, newRange);
|
this._changeDecorationImpl(id, newRange);
|
||||||
},
|
},
|
||||||
changeDecorationOptions: (id: string, options: model.IModelDecorationOptions) => {
|
changeDecorationOptions: (id: string, options: model.IModelDecorationOptions) => {
|
||||||
this._onDidChangeDecorations.fire();
|
|
||||||
this._changeDecorationOptionsImpl(id, _normalizeOptions(options));
|
this._changeDecorationOptionsImpl(id, _normalizeOptions(options));
|
||||||
},
|
},
|
||||||
removeDecoration: (id: string): void => {
|
removeDecoration: (id: string): void => {
|
||||||
this._onDidChangeDecorations.fire();
|
|
||||||
this._deltaDecorationsImpl(ownerId, [id], []);
|
this._deltaDecorationsImpl(ownerId, [id], []);
|
||||||
},
|
},
|
||||||
deltaDecorations: (oldDecorations: string[], newDecorations: model.IModelDeltaDecoration[]): string[] => {
|
deltaDecorations: (oldDecorations: string[], newDecorations: model.IModelDeltaDecoration[]): string[] => {
|
||||||
@@ -1443,7 +1439,6 @@ export class TextModel extends Disposable implements model.ITextModel {
|
|||||||
// nothing to do
|
// nothing to do
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
this._onDidChangeDecorations.fire();
|
|
||||||
return this._deltaDecorationsImpl(ownerId, oldDecorations, newDecorations);
|
return this._deltaDecorationsImpl(ownerId, oldDecorations, newDecorations);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1474,7 +1469,6 @@ export class TextModel extends Disposable implements model.ITextModel {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
this._onDidChangeDecorations.beginDeferredEmit();
|
this._onDidChangeDecorations.beginDeferredEmit();
|
||||||
this._onDidChangeDecorations.fire();
|
|
||||||
return this._deltaDecorationsImpl(ownerId, oldDecorations, newDecorations);
|
return this._deltaDecorationsImpl(ownerId, oldDecorations, newDecorations);
|
||||||
} finally {
|
} finally {
|
||||||
this._onDidChangeDecorations.endDeferredEmit();
|
this._onDidChangeDecorations.endDeferredEmit();
|
||||||
@@ -1622,6 +1616,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
|||||||
this._decorationsTree.delete(node);
|
this._decorationsTree.delete(node);
|
||||||
node.reset(this.getVersionId(), startOffset, endOffset, range);
|
node.reset(this.getVersionId(), startOffset, endOffset, range);
|
||||||
this._decorationsTree.insert(node);
|
this._decorationsTree.insert(node);
|
||||||
|
this._onDidChangeDecorations.checkAffectedAndFire(node.options);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _changeDecorationOptionsImpl(decorationId: string, options: ModelDecorationOptions): void {
|
private _changeDecorationOptionsImpl(decorationId: string, options: ModelDecorationOptions): void {
|
||||||
@@ -1633,6 +1628,9 @@ export class TextModel extends Disposable implements model.ITextModel {
|
|||||||
const nodeWasInOverviewRuler = (node.options.overviewRuler && node.options.overviewRuler.color ? true : false);
|
const nodeWasInOverviewRuler = (node.options.overviewRuler && node.options.overviewRuler.color ? true : false);
|
||||||
const nodeIsInOverviewRuler = (options.overviewRuler && options.overviewRuler.color ? true : false);
|
const nodeIsInOverviewRuler = (options.overviewRuler && options.overviewRuler.color ? true : false);
|
||||||
|
|
||||||
|
this._onDidChangeDecorations.checkAffectedAndFire(node.options);
|
||||||
|
this._onDidChangeDecorations.checkAffectedAndFire(options);
|
||||||
|
|
||||||
if (nodeWasInOverviewRuler !== nodeIsInOverviewRuler) {
|
if (nodeWasInOverviewRuler !== nodeIsInOverviewRuler) {
|
||||||
// Delete + Insert due to an overview ruler status change
|
// Delete + Insert due to an overview ruler status change
|
||||||
this._decorationsTree.delete(node);
|
this._decorationsTree.delete(node);
|
||||||
@@ -1666,6 +1664,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
|||||||
// (2) remove the node from the tree (if it exists)
|
// (2) remove the node from the tree (if it exists)
|
||||||
if (node) {
|
if (node) {
|
||||||
this._decorationsTree.delete(node);
|
this._decorationsTree.delete(node);
|
||||||
|
this._onDidChangeDecorations.checkAffectedAndFire(node.options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1688,6 +1687,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
|||||||
node.ownerId = ownerId;
|
node.ownerId = ownerId;
|
||||||
node.reset(versionId, startOffset, endOffset, range);
|
node.reset(versionId, startOffset, endOffset, range);
|
||||||
node.setOptions(options);
|
node.setOptions(options);
|
||||||
|
this._onDidChangeDecorations.checkAffectedAndFire(options);
|
||||||
|
|
||||||
this._decorationsTree.insert(node);
|
this._decorationsTree.insert(node);
|
||||||
|
|
||||||
@@ -1713,7 +1713,7 @@ export class TextModel extends Disposable implements model.ITextModel {
|
|||||||
throw new Error('Illegal value for lineNumber');
|
throw new Error('Illegal value for lineNumber');
|
||||||
}
|
}
|
||||||
|
|
||||||
this._tokens.setTokens(this._languageIdentifier.id, lineNumber - 1, this._buffer.getLineLength(lineNumber), tokens);
|
this._tokens.setTokens(this._languageIdentifier.id, lineNumber - 1, this._buffer.getLineLength(lineNumber), tokens, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public setTokens(tokens: MultilineTokens[]): void {
|
public setTokens(tokens: MultilineTokens[]): void {
|
||||||
@@ -1725,16 +1725,34 @@ export class TextModel extends Disposable implements model.ITextModel {
|
|||||||
|
|
||||||
for (let i = 0, len = tokens.length; i < len; i++) {
|
for (let i = 0, len = tokens.length; i < len; i++) {
|
||||||
const element = tokens[i];
|
const element = tokens[i];
|
||||||
ranges.push({ fromLineNumber: element.startLineNumber, toLineNumber: element.startLineNumber + element.tokens.length - 1 });
|
let minChangedLineNumber = 0;
|
||||||
|
let maxChangedLineNumber = 0;
|
||||||
|
let hasChange = false;
|
||||||
for (let j = 0, lenJ = element.tokens.length; j < lenJ; j++) {
|
for (let j = 0, lenJ = element.tokens.length; j < lenJ; j++) {
|
||||||
this.setLineTokens(element.startLineNumber + j, element.tokens[j]);
|
const lineNumber = element.startLineNumber + j;
|
||||||
|
if (hasChange) {
|
||||||
|
this._tokens.setTokens(this._languageIdentifier.id, lineNumber - 1, this._buffer.getLineLength(lineNumber), element.tokens[j], false);
|
||||||
|
maxChangedLineNumber = lineNumber;
|
||||||
|
} else {
|
||||||
|
const lineHasChange = this._tokens.setTokens(this._languageIdentifier.id, lineNumber - 1, this._buffer.getLineLength(lineNumber), element.tokens[j], true);
|
||||||
|
if (lineHasChange) {
|
||||||
|
hasChange = true;
|
||||||
|
minChangedLineNumber = lineNumber;
|
||||||
|
maxChangedLineNumber = lineNumber;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hasChange) {
|
||||||
|
ranges.push({ fromLineNumber: minChangedLineNumber, toLineNumber: maxChangedLineNumber });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this._emitModelTokensChangedEvent({
|
if (ranges.length > 0) {
|
||||||
tokenizationSupportChanged: false,
|
this._emitModelTokensChangedEvent({
|
||||||
ranges: ranges
|
tokenizationSupportChanged: false,
|
||||||
});
|
ranges: ranges
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public setSemanticTokens(tokens: MultilineTokens2[] | null): void {
|
public setSemanticTokens(tokens: MultilineTokens2[] | null): void {
|
||||||
@@ -3083,11 +3101,15 @@ export class DidChangeDecorationsEmitter extends Disposable {
|
|||||||
|
|
||||||
private _deferredCnt: number;
|
private _deferredCnt: number;
|
||||||
private _shouldFire: boolean;
|
private _shouldFire: boolean;
|
||||||
|
private _affectsMinimap: boolean;
|
||||||
|
private _affectsOverviewRuler: boolean;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this._deferredCnt = 0;
|
this._deferredCnt = 0;
|
||||||
this._shouldFire = false;
|
this._shouldFire = false;
|
||||||
|
this._affectsMinimap = false;
|
||||||
|
this._affectsOverviewRuler = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public beginDeferredEmit(): void {
|
public beginDeferredEmit(): void {
|
||||||
@@ -3098,13 +3120,31 @@ export class DidChangeDecorationsEmitter extends Disposable {
|
|||||||
this._deferredCnt--;
|
this._deferredCnt--;
|
||||||
if (this._deferredCnt === 0) {
|
if (this._deferredCnt === 0) {
|
||||||
if (this._shouldFire) {
|
if (this._shouldFire) {
|
||||||
|
const event: IModelDecorationsChangedEvent = {
|
||||||
|
affectsMinimap: this._affectsMinimap,
|
||||||
|
affectsOverviewRuler: this._affectsOverviewRuler,
|
||||||
|
};
|
||||||
this._shouldFire = false;
|
this._shouldFire = false;
|
||||||
this._actual.fire({});
|
this._affectsMinimap = false;
|
||||||
|
this._affectsOverviewRuler = false;
|
||||||
|
this._actual.fire(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public checkAffectedAndFire(options: ModelDecorationOptions): void {
|
||||||
|
if (!this._affectsMinimap) {
|
||||||
|
this._affectsMinimap = options.minimap && options.minimap.position ? true : false;
|
||||||
|
}
|
||||||
|
if (!this._affectsOverviewRuler) {
|
||||||
|
this._affectsOverviewRuler = options.overviewRuler && options.overviewRuler.color ? true : false;
|
||||||
|
}
|
||||||
|
this._shouldFire = true;
|
||||||
|
}
|
||||||
|
|
||||||
public fire(): void {
|
public fire(): void {
|
||||||
|
this._affectsMinimap = true;
|
||||||
|
this._affectsOverviewRuler = true;
|
||||||
this._shouldFire = true;
|
this._shouldFire = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,6 +76,8 @@ export interface IModelContentChangedEvent {
|
|||||||
* An event describing that model decorations have changed.
|
* An event describing that model decorations have changed.
|
||||||
*/
|
*/
|
||||||
export interface IModelDecorationsChangedEvent {
|
export interface IModelDecorationsChangedEvent {
|
||||||
|
readonly affectsMinimap: boolean;
|
||||||
|
readonly affectsOverviewRuler: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -964,10 +964,35 @@ export class TokensStore {
|
|||||||
this._len += insertCount;
|
this._len += insertCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public setTokens(topLevelLanguageId: LanguageId, lineIndex: number, lineTextLength: number, _tokens: Uint32Array | ArrayBuffer | null): void {
|
public setTokens(topLevelLanguageId: LanguageId, lineIndex: number, lineTextLength: number, _tokens: Uint32Array | ArrayBuffer | null, checkEquality: boolean): boolean {
|
||||||
const tokens = TokensStore._massageTokens(topLevelLanguageId, lineTextLength, _tokens);
|
const tokens = TokensStore._massageTokens(topLevelLanguageId, lineTextLength, _tokens);
|
||||||
this._ensureLine(lineIndex);
|
this._ensureLine(lineIndex);
|
||||||
|
const oldTokens = this._lineTokens[lineIndex];
|
||||||
this._lineTokens[lineIndex] = tokens;
|
this._lineTokens[lineIndex] = tokens;
|
||||||
|
|
||||||
|
if (checkEquality) {
|
||||||
|
return !TokensStore._equals(oldTokens, tokens);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static _equals(_a: Uint32Array | ArrayBuffer | null, _b: Uint32Array | ArrayBuffer | null) {
|
||||||
|
if (!_a || !_b) {
|
||||||
|
return !_a && !_b;
|
||||||
|
}
|
||||||
|
|
||||||
|
const a = toUint32Array(_a);
|
||||||
|
const b = toUint32Array(_b);
|
||||||
|
|
||||||
|
if (a.length !== b.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (let i = 0, len = a.length; i < len; i++) {
|
||||||
|
if (a[i] !== b[i]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//#region Editing
|
//#region Editing
|
||||||
|
|||||||
@@ -274,6 +274,16 @@ export class LanguageConfigurationRegistryImpl {
|
|||||||
return ensureValidWordDefinition(value.wordDefinition || null);
|
return ensureValidWordDefinition(value.wordDefinition || null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getWordDefinitions(): [LanguageId, RegExp][] {
|
||||||
|
let result: [LanguageId, RegExp][] = [];
|
||||||
|
this._entries.forEach((value, language) => {
|
||||||
|
if (value) {
|
||||||
|
result.push([language, value.wordDefinition]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public getFoldingRules(languageId: LanguageId): FoldingRules {
|
public getFoldingRules(languageId: LanguageId): FoldingRules {
|
||||||
let value = this._getRichEditSupport(languageId);
|
let value = this._getRichEditSupport(languageId);
|
||||||
if (!value) {
|
if (!value) {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { ConfigurationChangedEvent, EditorOption } from 'vs/editor/common/config
|
|||||||
import { Range } from 'vs/editor/common/core/range';
|
import { Range } from 'vs/editor/common/core/range';
|
||||||
import { Selection } from 'vs/editor/common/core/selection';
|
import { Selection } from 'vs/editor/common/core/selection';
|
||||||
import { ScrollType, IContentSizeChangedEvent } from 'vs/editor/common/editorCommon';
|
import { ScrollType, IContentSizeChangedEvent } from 'vs/editor/common/editorCommon';
|
||||||
|
import { IModelDecorationsChangedEvent } from 'vs/editor/common/model/textModelEvents';
|
||||||
|
|
||||||
export const enum ViewEventType {
|
export const enum ViewEventType {
|
||||||
ViewConfigurationChanged = 1,
|
ViewConfigurationChanged = 1,
|
||||||
@@ -82,8 +83,17 @@ export class ViewDecorationsChangedEvent {
|
|||||||
|
|
||||||
public readonly type = ViewEventType.ViewDecorationsChanged;
|
public readonly type = ViewEventType.ViewDecorationsChanged;
|
||||||
|
|
||||||
constructor() {
|
readonly affectsMinimap: boolean;
|
||||||
// Nothing to do
|
readonly affectsOverviewRuler: boolean;
|
||||||
|
|
||||||
|
constructor(source: IModelDecorationsChangedEvent | null) {
|
||||||
|
if (source) {
|
||||||
|
this.affectsMinimap = source.affectsMinimap;
|
||||||
|
this.affectsOverviewRuler = source.affectsOverviewRuler;
|
||||||
|
} else {
|
||||||
|
this.affectsMinimap = true;
|
||||||
|
this.affectsOverviewRuler = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
|
|||||||
if (this.lines.setWrappingSettings(fontInfo, wrappingStrategy, wrappingInfo.wrappingColumn, wrappingIndent)) {
|
if (this.lines.setWrappingSettings(fontInfo, wrappingStrategy, wrappingInfo.wrappingColumn, wrappingIndent)) {
|
||||||
eventsCollector.emit(new viewEvents.ViewFlushedEvent());
|
eventsCollector.emit(new viewEvents.ViewFlushedEvent());
|
||||||
eventsCollector.emit(new viewEvents.ViewLineMappingChangedEvent());
|
eventsCollector.emit(new viewEvents.ViewLineMappingChangedEvent());
|
||||||
eventsCollector.emit(new viewEvents.ViewDecorationsChangedEvent());
|
eventsCollector.emit(new viewEvents.ViewDecorationsChangedEvent(null));
|
||||||
this.decorations.onLineMappingChanged();
|
this.decorations.onLineMappingChanged();
|
||||||
this.viewLayout.onFlushed(this.getLineCount());
|
this.viewLayout.onFlushed(this.getLineCount());
|
||||||
|
|
||||||
@@ -185,7 +185,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
|
|||||||
if (e.hasChanged(EditorOption.readOnly)) {
|
if (e.hasChanged(EditorOption.readOnly)) {
|
||||||
// Must read again all decorations due to readOnly filtering
|
// Must read again all decorations due to readOnly filtering
|
||||||
this.decorations.reset();
|
this.decorations.reset();
|
||||||
eventsCollector.emit(new viewEvents.ViewDecorationsChangedEvent());
|
eventsCollector.emit(new viewEvents.ViewDecorationsChangedEvent(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
eventsCollector.emit(new viewEvents.ViewConfigurationChangedEvent(e));
|
eventsCollector.emit(new viewEvents.ViewConfigurationChangedEvent(e));
|
||||||
@@ -291,7 +291,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
|
|||||||
|
|
||||||
if (!hadOtherModelChange && hadModelLineChangeThatChangedLineMapping) {
|
if (!hadOtherModelChange && hadModelLineChangeThatChangedLineMapping) {
|
||||||
eventsCollector.emit(new viewEvents.ViewLineMappingChangedEvent());
|
eventsCollector.emit(new viewEvents.ViewLineMappingChangedEvent());
|
||||||
eventsCollector.emit(new viewEvents.ViewDecorationsChangedEvent());
|
eventsCollector.emit(new viewEvents.ViewDecorationsChangedEvent(null));
|
||||||
this.decorations.onLineMappingChanged();
|
this.decorations.onLineMappingChanged();
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
@@ -354,7 +354,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
|
|||||||
const eventsCollector = this._beginEmit();
|
const eventsCollector = this._beginEmit();
|
||||||
eventsCollector.emit(new viewEvents.ViewFlushedEvent());
|
eventsCollector.emit(new viewEvents.ViewFlushedEvent());
|
||||||
eventsCollector.emit(new viewEvents.ViewLineMappingChangedEvent());
|
eventsCollector.emit(new viewEvents.ViewLineMappingChangedEvent());
|
||||||
eventsCollector.emit(new viewEvents.ViewDecorationsChangedEvent());
|
eventsCollector.emit(new viewEvents.ViewDecorationsChangedEvent(null));
|
||||||
} finally {
|
} finally {
|
||||||
this._endEmit();
|
this._endEmit();
|
||||||
}
|
}
|
||||||
@@ -365,7 +365,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
|
|||||||
this.decorations.onModelDecorationsChanged();
|
this.decorations.onModelDecorationsChanged();
|
||||||
try {
|
try {
|
||||||
const eventsCollector = this._beginEmit();
|
const eventsCollector = this._beginEmit();
|
||||||
eventsCollector.emit(new viewEvents.ViewDecorationsChangedEvent());
|
eventsCollector.emit(new viewEvents.ViewDecorationsChangedEvent(e));
|
||||||
} finally {
|
} finally {
|
||||||
this._endEmit();
|
this._endEmit();
|
||||||
}
|
}
|
||||||
@@ -379,7 +379,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
|
|||||||
if (lineMappingChanged) {
|
if (lineMappingChanged) {
|
||||||
eventsCollector.emit(new viewEvents.ViewFlushedEvent());
|
eventsCollector.emit(new viewEvents.ViewFlushedEvent());
|
||||||
eventsCollector.emit(new viewEvents.ViewLineMappingChangedEvent());
|
eventsCollector.emit(new viewEvents.ViewLineMappingChangedEvent());
|
||||||
eventsCollector.emit(new viewEvents.ViewDecorationsChangedEvent());
|
eventsCollector.emit(new viewEvents.ViewDecorationsChangedEvent(null));
|
||||||
this.decorations.onLineMappingChanged();
|
this.decorations.onLineMappingChanged();
|
||||||
this.viewLayout.onFlushed(this.getLineCount());
|
this.viewLayout.onFlushed(this.getLineCount());
|
||||||
this.viewLayout.onHeightMaybeChanged();
|
this.viewLayout.onHeightMaybeChanged();
|
||||||
|
|||||||
@@ -419,8 +419,9 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
|
|||||||
}
|
}
|
||||||
if (currentMatch) {
|
if (currentMatch) {
|
||||||
const ariaLabel = nls.localize('ariaSearchNoResultWithLineNum', "{0} found for '{1}', at {2}", label, searchString, currentMatch.startLineNumber + ':' + currentMatch.startColumn);
|
const ariaLabel = nls.localize('ariaSearchNoResultWithLineNum', "{0} found for '{1}', at {2}", label, searchString, currentMatch.startLineNumber + ':' + currentMatch.startColumn);
|
||||||
const lineContent = this._codeEditor.getModel()?.getLineContent(currentMatch.startLineNumber);
|
const model = this._codeEditor.getModel();
|
||||||
if (lineContent) {
|
if (model && (currentMatch.startLineNumber <= model.getLineCount()) && (currentMatch.startLineNumber >= 1)) {
|
||||||
|
const lineContent = model.getLineContent(currentMatch.startLineNumber);
|
||||||
return `${lineContent}, ${ariaLabel}`;
|
return `${lineContent}, ${ariaLabel}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -180,9 +180,11 @@ suite('SmartSelect', () => {
|
|||||||
// -- bracket selections
|
// -- bracket selections
|
||||||
|
|
||||||
async function assertRanges(provider: SelectionRangeProvider, value: string, ...expected: IRange[]): Promise<void> {
|
async function assertRanges(provider: SelectionRangeProvider, value: string, ...expected: IRange[]): Promise<void> {
|
||||||
|
let index = value.indexOf('|');
|
||||||
|
value = value.replace('|', '');
|
||||||
|
|
||||||
let model = modelService.createModel(value, new StaticLanguageSelector(mode.getLanguageIdentifier()), URI.parse('fake:lang'));
|
let model = modelService.createModel(value, new StaticLanguageSelector(mode.getLanguageIdentifier()), URI.parse('fake:lang'));
|
||||||
let pos = model.getPositionAt(value.indexOf('|'));
|
let pos = model.getPositionAt(index);
|
||||||
let all = await provider.provideSelectionRanges(model, [pos], CancellationToken.None);
|
let all = await provider.provideSelectionRanges(model, [pos], CancellationToken.None);
|
||||||
let ranges = all![0];
|
let ranges = all![0];
|
||||||
|
|
||||||
@@ -197,18 +199,18 @@ suite('SmartSelect', () => {
|
|||||||
|
|
||||||
test('bracket selection', async () => {
|
test('bracket selection', async () => {
|
||||||
await assertRanges(new BracketSelectionRangeProvider(), '(|)',
|
await assertRanges(new BracketSelectionRangeProvider(), '(|)',
|
||||||
new Range(1, 2, 1, 3), new Range(1, 1, 1, 4)
|
new Range(1, 2, 1, 2), new Range(1, 1, 1, 3)
|
||||||
);
|
);
|
||||||
|
|
||||||
await assertRanges(new BracketSelectionRangeProvider(), '[[[](|)]]',
|
await assertRanges(new BracketSelectionRangeProvider(), '[[[](|)]]',
|
||||||
new Range(1, 6, 1, 7), new Range(1, 5, 1, 8), // ()
|
new Range(1, 6, 1, 6), new Range(1, 5, 1, 7), // ()
|
||||||
new Range(1, 3, 1, 8), new Range(1, 2, 1, 9), // [[]()]
|
new Range(1, 3, 1, 7), new Range(1, 2, 1, 8), // [[]()]
|
||||||
new Range(1, 2, 1, 9), new Range(1, 1, 1, 10), // [[[]()]]
|
new Range(1, 2, 1, 8), new Range(1, 1, 1, 9), // [[[]()]]
|
||||||
);
|
);
|
||||||
|
|
||||||
await assertRanges(new BracketSelectionRangeProvider(), '[a[](|)a]',
|
await assertRanges(new BracketSelectionRangeProvider(), '[a[](|)a]',
|
||||||
new Range(1, 6, 1, 7), new Range(1, 5, 1, 8),
|
new Range(1, 6, 1, 6), new Range(1, 5, 1, 7),
|
||||||
new Range(1, 2, 1, 9), new Range(1, 1, 1, 10),
|
new Range(1, 2, 1, 8), new Range(1, 1, 1, 9),
|
||||||
);
|
);
|
||||||
|
|
||||||
// no bracket
|
// no bracket
|
||||||
@@ -219,23 +221,23 @@ suite('SmartSelect', () => {
|
|||||||
await assertRanges(new BracketSelectionRangeProvider(), '|[[[]()]]');
|
await assertRanges(new BracketSelectionRangeProvider(), '|[[[]()]]');
|
||||||
|
|
||||||
// edge
|
// edge
|
||||||
await assertRanges(new BracketSelectionRangeProvider(), '[|[[]()]]', new Range(1, 2, 1, 9), new Range(1, 1, 1, 10));
|
await assertRanges(new BracketSelectionRangeProvider(), '[|[[]()]]', new Range(1, 2, 1, 8), new Range(1, 1, 1, 9));
|
||||||
await assertRanges(new BracketSelectionRangeProvider(), '[[[]()]|]', new Range(1, 2, 1, 9), new Range(1, 1, 1, 10));
|
await assertRanges(new BracketSelectionRangeProvider(), '[[[]()]|]', new Range(1, 2, 1, 8), new Range(1, 1, 1, 9));
|
||||||
|
|
||||||
await assertRanges(new BracketSelectionRangeProvider(), 'aaa(aaa)bbb(b|b)ccc(ccc)', new Range(1, 13, 1, 16), new Range(1, 12, 1, 17));
|
await assertRanges(new BracketSelectionRangeProvider(), 'aaa(aaa)bbb(b|b)ccc(ccc)', new Range(1, 13, 1, 15), new Range(1, 12, 1, 16));
|
||||||
await assertRanges(new BracketSelectionRangeProvider(), '(aaa(aaa)bbb(b|b)ccc(ccc))', new Range(1, 14, 1, 17), new Range(1, 13, 1, 18), new Range(1, 2, 1, 26), new Range(1, 1, 1, 27));
|
await assertRanges(new BracketSelectionRangeProvider(), '(aaa(aaa)bbb(b|b)ccc(ccc))', new Range(1, 14, 1, 16), new Range(1, 13, 1, 17), new Range(1, 2, 1, 25), new Range(1, 1, 1, 26));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('bracket with leading/trailing', async () => {
|
test('bracket with leading/trailing', async () => {
|
||||||
|
|
||||||
await assertRanges(new BracketSelectionRangeProvider(), 'for(a of b){\n foo(|);\n}',
|
await assertRanges(new BracketSelectionRangeProvider(), 'for(a of b){\n foo(|);\n}',
|
||||||
new Range(2, 7, 2, 8), new Range(2, 6, 2, 9),
|
new Range(2, 7, 2, 7), new Range(2, 6, 2, 8),
|
||||||
new Range(1, 13, 3, 1), new Range(1, 12, 3, 2),
|
new Range(1, 13, 3, 1), new Range(1, 12, 3, 2),
|
||||||
new Range(1, 1, 3, 2), new Range(1, 1, 3, 2),
|
new Range(1, 1, 3, 2), new Range(1, 1, 3, 2),
|
||||||
);
|
);
|
||||||
|
|
||||||
await assertRanges(new BracketSelectionRangeProvider(), 'for(a of b)\n{\n foo(|);\n}',
|
await assertRanges(new BracketSelectionRangeProvider(), 'for(a of b)\n{\n foo(|);\n}',
|
||||||
new Range(3, 7, 3, 8), new Range(3, 6, 3, 9),
|
new Range(3, 7, 3, 7), new Range(3, 6, 3, 8),
|
||||||
new Range(2, 2, 4, 1), new Range(2, 1, 4, 2),
|
new Range(2, 2, 4, 1), new Range(2, 1, 4, 2),
|
||||||
new Range(1, 1, 4, 2), new Range(1, 1, 4, 2),
|
new Range(1, 1, 4, 2), new Range(1, 1, 4, 2),
|
||||||
);
|
);
|
||||||
@@ -244,60 +246,60 @@ suite('SmartSelect', () => {
|
|||||||
test('in-word ranges', async () => {
|
test('in-word ranges', async () => {
|
||||||
|
|
||||||
await assertRanges(new WordSelectionRangeProvider(), 'f|ooBar',
|
await assertRanges(new WordSelectionRangeProvider(), 'f|ooBar',
|
||||||
new Range(1, 1, 1, 5), // foo
|
new Range(1, 1, 1, 4), // foo
|
||||||
new Range(1, 1, 1, 8), // fooBar
|
new Range(1, 1, 1, 7), // fooBar
|
||||||
new Range(1, 1, 1, 8), // doc
|
new Range(1, 1, 1, 7), // doc
|
||||||
);
|
);
|
||||||
|
|
||||||
await assertRanges(new WordSelectionRangeProvider(), 'f|oo_Ba',
|
await assertRanges(new WordSelectionRangeProvider(), 'f|oo_Ba',
|
||||||
new Range(1, 1, 1, 5),
|
new Range(1, 1, 1, 4),
|
||||||
new Range(1, 1, 1, 8),
|
new Range(1, 1, 1, 7),
|
||||||
new Range(1, 1, 1, 8),
|
new Range(1, 1, 1, 7),
|
||||||
);
|
);
|
||||||
|
|
||||||
await assertRanges(new WordSelectionRangeProvider(), 'f|oo-Ba',
|
await assertRanges(new WordSelectionRangeProvider(), 'f|oo-Ba',
|
||||||
new Range(1, 1, 1, 5),
|
new Range(1, 1, 1, 4),
|
||||||
new Range(1, 1, 1, 8),
|
new Range(1, 1, 1, 7),
|
||||||
new Range(1, 1, 1, 8),
|
new Range(1, 1, 1, 7),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Default selection should select current word/hump first in camelCase #67493', async function () {
|
test('Default selection should select current word/hump first in camelCase #67493', async function () {
|
||||||
|
|
||||||
await assertRanges(new WordSelectionRangeProvider(), 'Abs|tractSmartSelect',
|
await assertRanges(new WordSelectionRangeProvider(), 'Abs|tractSmartSelect',
|
||||||
new Range(1, 1, 1, 10),
|
new Range(1, 1, 1, 9),
|
||||||
new Range(1, 1, 1, 21),
|
new Range(1, 1, 1, 20),
|
||||||
new Range(1, 1, 1, 21),
|
new Range(1, 1, 1, 20),
|
||||||
);
|
);
|
||||||
|
|
||||||
await assertRanges(new WordSelectionRangeProvider(), 'AbstractSma|rtSelect',
|
await assertRanges(new WordSelectionRangeProvider(), 'AbstractSma|rtSelect',
|
||||||
new Range(1, 9, 1, 15),
|
new Range(1, 9, 1, 14),
|
||||||
new Range(1, 1, 1, 21),
|
new Range(1, 1, 1, 20),
|
||||||
new Range(1, 1, 1, 21),
|
new Range(1, 1, 1, 20),
|
||||||
);
|
);
|
||||||
|
|
||||||
await assertRanges(new WordSelectionRangeProvider(), 'Abstrac-Sma|rt-elect',
|
await assertRanges(new WordSelectionRangeProvider(), 'Abstrac-Sma|rt-elect',
|
||||||
new Range(1, 9, 1, 15),
|
new Range(1, 9, 1, 14),
|
||||||
new Range(1, 1, 1, 21),
|
new Range(1, 1, 1, 20),
|
||||||
new Range(1, 1, 1, 21),
|
new Range(1, 1, 1, 20),
|
||||||
);
|
);
|
||||||
|
|
||||||
await assertRanges(new WordSelectionRangeProvider(), 'Abstrac_Sma|rt_elect',
|
await assertRanges(new WordSelectionRangeProvider(), 'Abstrac_Sma|rt_elect',
|
||||||
new Range(1, 9, 1, 15),
|
new Range(1, 9, 1, 14),
|
||||||
new Range(1, 1, 1, 21),
|
new Range(1, 1, 1, 20),
|
||||||
new Range(1, 1, 1, 21),
|
new Range(1, 1, 1, 20),
|
||||||
);
|
);
|
||||||
|
|
||||||
await assertRanges(new WordSelectionRangeProvider(), 'Abstrac_Sma|rt-elect',
|
await assertRanges(new WordSelectionRangeProvider(), 'Abstrac_Sma|rt-elect',
|
||||||
new Range(1, 9, 1, 15),
|
new Range(1, 9, 1, 14),
|
||||||
new Range(1, 1, 1, 21),
|
new Range(1, 1, 1, 20),
|
||||||
new Range(1, 1, 1, 21),
|
new Range(1, 1, 1, 20),
|
||||||
);
|
);
|
||||||
|
|
||||||
await assertRanges(new WordSelectionRangeProvider(), 'Abstrac_Sma|rtSelect',
|
await assertRanges(new WordSelectionRangeProvider(), 'Abstrac_Sma|rtSelect',
|
||||||
new Range(1, 9, 1, 15),
|
new Range(1, 9, 1, 14),
|
||||||
new Range(1, 1, 1, 21),
|
new Range(1, 1, 1, 20),
|
||||||
new Range(1, 1, 1, 21),
|
new Range(1, 1, 1, 20),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -321,4 +323,49 @@ suite('SmartSelect', () => {
|
|||||||
|
|
||||||
reg.dispose();
|
reg.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Expand selection in words with underscores is inconsistent #90589', async function () {
|
||||||
|
|
||||||
|
await assertRanges(new WordSelectionRangeProvider(), 'Hel|lo_World',
|
||||||
|
new Range(1, 1, 1, 6),
|
||||||
|
new Range(1, 1, 1, 12),
|
||||||
|
new Range(1, 1, 1, 12),
|
||||||
|
);
|
||||||
|
|
||||||
|
await assertRanges(new WordSelectionRangeProvider(), 'Hello_Wo|rld',
|
||||||
|
new Range(1, 7, 1, 12),
|
||||||
|
new Range(1, 1, 1, 12),
|
||||||
|
new Range(1, 1, 1, 12),
|
||||||
|
);
|
||||||
|
|
||||||
|
await assertRanges(new WordSelectionRangeProvider(), 'Hello|_World',
|
||||||
|
new Range(1, 1, 1, 6),
|
||||||
|
new Range(1, 1, 1, 12),
|
||||||
|
new Range(1, 1, 1, 12),
|
||||||
|
);
|
||||||
|
|
||||||
|
await assertRanges(new WordSelectionRangeProvider(), 'Hello_|World',
|
||||||
|
new Range(1, 7, 1, 12),
|
||||||
|
new Range(1, 1, 1, 12),
|
||||||
|
new Range(1, 1, 1, 12),
|
||||||
|
);
|
||||||
|
|
||||||
|
await assertRanges(new WordSelectionRangeProvider(), 'Hello|-World',
|
||||||
|
new Range(1, 1, 1, 6),
|
||||||
|
new Range(1, 1, 1, 12),
|
||||||
|
new Range(1, 1, 1, 12),
|
||||||
|
);
|
||||||
|
|
||||||
|
await assertRanges(new WordSelectionRangeProvider(), 'Hello-|World',
|
||||||
|
new Range(1, 7, 1, 12),
|
||||||
|
new Range(1, 1, 1, 12),
|
||||||
|
new Range(1, 1, 1, 12),
|
||||||
|
);
|
||||||
|
|
||||||
|
await assertRanges(new WordSelectionRangeProvider(), 'Hello|World',
|
||||||
|
new Range(1, 6, 1, 11),
|
||||||
|
new Range(1, 1, 1, 11),
|
||||||
|
new Range(1, 1, 1, 11),
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ export class WordSelectionRangeProvider implements SelectionRangeProvider {
|
|||||||
// LEFT anchor (start)
|
// LEFT anchor (start)
|
||||||
for (; start >= 0; start--) {
|
for (; start >= 0; start--) {
|
||||||
let ch = word.charCodeAt(start);
|
let ch = word.charCodeAt(start);
|
||||||
if (ch === CharCode.Underline || ch === CharCode.Dash) {
|
if ((start !== offset) && (ch === CharCode.Underline || ch === CharCode.Dash)) {
|
||||||
// foo-bar OR foo_bar
|
// foo-bar OR foo_bar
|
||||||
break;
|
break;
|
||||||
} else if (isLowerAsciiLetter(ch) && isUpperAsciiLetter(lastCh)) {
|
} else if (isLowerAsciiLetter(ch) && isUpperAsciiLetter(lastCh)) {
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import { Selection } from 'vs/editor/common/core/selection';
|
|||||||
import { deserializePipePositions, serializePipePositions, testRepeatedActionAndExtractPositions } from 'vs/editor/contrib/wordOperations/test/wordTestUtils';
|
import { deserializePipePositions, serializePipePositions, testRepeatedActionAndExtractPositions } from 'vs/editor/contrib/wordOperations/test/wordTestUtils';
|
||||||
import { CursorWordEndLeft, CursorWordEndLeftSelect, CursorWordEndRight, CursorWordEndRightSelect, CursorWordLeft, CursorWordLeftSelect, CursorWordRight, CursorWordRightSelect, CursorWordStartLeft, CursorWordStartLeftSelect, CursorWordStartRight, CursorWordStartRightSelect, DeleteWordEndLeft, DeleteWordEndRight, DeleteWordLeft, DeleteWordRight, DeleteWordStartLeft, DeleteWordStartRight, CursorWordAccessibilityLeft, CursorWordAccessibilityLeftSelect, CursorWordAccessibilityRight, CursorWordAccessibilityRightSelect } from 'vs/editor/contrib/wordOperations/wordOperations';
|
import { CursorWordEndLeft, CursorWordEndLeftSelect, CursorWordEndRight, CursorWordEndRightSelect, CursorWordLeft, CursorWordLeftSelect, CursorWordRight, CursorWordRightSelect, CursorWordStartLeft, CursorWordStartLeftSelect, CursorWordStartRight, CursorWordStartRightSelect, DeleteWordEndLeft, DeleteWordEndRight, DeleteWordLeft, DeleteWordRight, DeleteWordStartLeft, DeleteWordStartRight, CursorWordAccessibilityLeft, CursorWordAccessibilityLeftSelect, CursorWordAccessibilityRight, CursorWordAccessibilityRightSelect } from 'vs/editor/contrib/wordOperations/wordOperations';
|
||||||
import { withTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor';
|
import { withTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor';
|
||||||
|
import { Handler } from 'vs/editor/common/editorCommon';
|
||||||
|
import { Cursor } from 'vs/editor/common/controller/cursor';
|
||||||
|
|
||||||
suite('WordOperations', () => {
|
suite('WordOperations', () => {
|
||||||
|
|
||||||
@@ -193,6 +195,32 @@ suite('WordOperations', () => {
|
|||||||
assert.deepEqual(actual, EXPECTED);
|
assert.deepEqual(actual, EXPECTED);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('issue #51275 - cursorWordStartLeft does not push undo/redo stack element', () => {
|
||||||
|
function cursorCommand(cursor: Cursor, command: string, extraData?: any, overwriteSource?: string) {
|
||||||
|
cursor.trigger(overwriteSource || 'tests', command, extraData);
|
||||||
|
}
|
||||||
|
|
||||||
|
function type(cursor: Cursor, text: string) {
|
||||||
|
for (let i = 0; i < text.length; i++) {
|
||||||
|
cursorCommand(cursor, Handler.Type, { text: text.charAt(i) }, 'keyboard');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
withTestCodeEditor('', {}, (editor, cursor) => {
|
||||||
|
type(cursor, 'foo bar baz');
|
||||||
|
assert.equal(editor.getValue(), 'foo bar baz');
|
||||||
|
|
||||||
|
cursorWordStartLeft(editor);
|
||||||
|
cursorWordStartLeft(editor);
|
||||||
|
type(cursor, 'q');
|
||||||
|
|
||||||
|
assert.equal(editor.getValue(), 'foo qbar baz');
|
||||||
|
|
||||||
|
cursorCommand(cursor, Handler.Undo, {});
|
||||||
|
assert.equal(editor.getValue(), 'foo bar baz');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
test('cursorWordEndLeft', () => {
|
test('cursorWordEndLeft', () => {
|
||||||
const EXPECTED = ['| /*| Just| some| more| text| a|+=| 3| +|5|-|3| +| 7| */| '].join('\n');
|
const EXPECTED = ['| /*| Just| some| more| text| a|+=| 3| +|5|-|3| +| 7| */| '].join('\n');
|
||||||
const [text,] = deserializePipePositions(EXPECTED);
|
const [text,] = deserializePipePositions(EXPECTED);
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ export abstract class MoveWordCommand extends EditorCommand {
|
|||||||
return this._moveTo(sel, outPosition, this._inSelectionMode);
|
return this._moveTo(sel, outPosition, this._inSelectionMode);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
model.pushStackElement();
|
||||||
editor._getCursors().setStates('moveWordCommand', CursorChangeReason.NotSet, result.map(r => CursorState.fromModelSelection(r)));
|
editor._getCursors().setStates('moveWordCommand', CursorChangeReason.NotSet, result.map(r => CursorState.fromModelSelection(r)));
|
||||||
if (result.length === 1) {
|
if (result.length === 1) {
|
||||||
const pos = new Position(result[0].positionLineNumber, result[0].positionColumn);
|
const pos = new Position(result[0].positionLineNumber, result[0].positionColumn);
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
import 'vs/css!./inspectTokens';
|
import 'vs/css!./inspectTokens';
|
||||||
import { CharCode } from 'vs/base/common/charCode';
|
import { CharCode } from 'vs/base/common/charCode';
|
||||||
import { Color } from 'vs/base/common/color';
|
import { Color } from 'vs/base/common/color';
|
||||||
|
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||||
import { Disposable } from 'vs/base/common/lifecycle';
|
import { Disposable } from 'vs/base/common/lifecycle';
|
||||||
import { escape } from 'vs/base/common/strings';
|
import { escape } from 'vs/base/common/strings';
|
||||||
import { ContentWidgetPositionPreference, IActiveCodeEditor, ICodeEditor, IContentWidget, IContentWidgetPosition } from 'vs/editor/browser/editorBrowser';
|
import { ContentWidgetPositionPreference, IActiveCodeEditor, ICodeEditor, IContentWidget, IContentWidgetPosition } from 'vs/editor/browser/editorBrowser';
|
||||||
@@ -48,6 +49,7 @@ class InspectTokensController extends Disposable implements IEditorContribution
|
|||||||
this._register(this._editor.onDidChangeModel((e) => this.stop()));
|
this._register(this._editor.onDidChangeModel((e) => this.stop()));
|
||||||
this._register(this._editor.onDidChangeModelLanguage((e) => this.stop()));
|
this._register(this._editor.onDidChangeModelLanguage((e) => this.stop()));
|
||||||
this._register(TokenizationRegistry.onDidChange((e) => this.stop()));
|
this._register(TokenizationRegistry.onDidChange((e) => this.stop()));
|
||||||
|
this._register(this._editor.onKeyUp((e) => e.keyCode === KeyCode.Escape && this.stop()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public dispose(): void {
|
public dispose(): void {
|
||||||
@@ -222,13 +224,13 @@ class InspectTokensWidget extends Disposable implements IContentWidget {
|
|||||||
|
|
||||||
result += `<hr class="tokens-inspect-separator" style="clear:both"/>`;
|
result += `<hr class="tokens-inspect-separator" style="clear:both"/>`;
|
||||||
|
|
||||||
let metadata = this._decodeMetadata(data.tokens2[(token2Index << 1) + 1]);
|
let metadata = (token2Index << 1) + 1 < data.tokens2.length ? this._decodeMetadata(data.tokens2[(token2Index << 1) + 1]) : null;
|
||||||
result += `<table class="tm-metadata-table"><tbody>`;
|
result += `<table class="tm-metadata-table"><tbody>`;
|
||||||
result += `<tr><td class="tm-metadata-key">language</td><td class="tm-metadata-value">${escape(metadata.languageIdentifier.language)}</td>`;
|
result += `<tr><td class="tm-metadata-key">language</td><td class="tm-metadata-value">${metadata ? escape(metadata.languageIdentifier.language) : '-?-'}</td>`;
|
||||||
result += `<tr><td class="tm-metadata-key">token type</td><td class="tm-metadata-value">${this._tokenTypeToString(metadata.tokenType)}</td>`;
|
result += `<tr><td class="tm-metadata-key">token type</td><td class="tm-metadata-value">${metadata ? this._tokenTypeToString(metadata.tokenType) : '-?-'}</td>`;
|
||||||
result += `<tr><td class="tm-metadata-key">font style</td><td class="tm-metadata-value">${this._fontStyleToString(metadata.fontStyle)}</td>`;
|
result += `<tr><td class="tm-metadata-key">font style</td><td class="tm-metadata-value">${metadata ? this._fontStyleToString(metadata.fontStyle) : '-?-'}</td>`;
|
||||||
result += `<tr><td class="tm-metadata-key">foreground</td><td class="tm-metadata-value">${Color.Format.CSS.formatHex(metadata.foreground)}</td>`;
|
result += `<tr><td class="tm-metadata-key">foreground</td><td class="tm-metadata-value">${metadata ? Color.Format.CSS.formatHex(metadata.foreground) : '-?-'}</td>`;
|
||||||
result += `<tr><td class="tm-metadata-key">background</td><td class="tm-metadata-value">${Color.Format.CSS.formatHex(metadata.background)}</td>`;
|
result += `<tr><td class="tm-metadata-key">background</td><td class="tm-metadata-value">${metadata ? Color.Format.CSS.formatHex(metadata.background) : '-?-'}</td>`;
|
||||||
result += `</tbody></table>`;
|
result += `</tbody></table>`;
|
||||||
|
|
||||||
result += `<hr class="tokens-inspect-separator"/>`;
|
result += `<hr class="tokens-inspect-separator"/>`;
|
||||||
|
|||||||
@@ -124,6 +124,13 @@ export interface IGlobalEditorOptions {
|
|||||||
* Defaults to 20000.
|
* Defaults to 20000.
|
||||||
*/
|
*/
|
||||||
maxTokenizationLineLength?: number;
|
maxTokenizationLineLength?: number;
|
||||||
|
/**
|
||||||
|
* Theme to be used for rendering.
|
||||||
|
* The current out-of-the-box available themes are: 'vs' (default), 'vs-dark', 'hc-black'.
|
||||||
|
* You can create custom themes via `monaco.editor.defineTheme`.
|
||||||
|
* To switch a theme, use `monaco.editor.setTheme`
|
||||||
|
*/
|
||||||
|
theme?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -334,6 +341,7 @@ export class StandaloneEditor extends StandaloneCodeEditor implements IStandalon
|
|||||||
|
|
||||||
private readonly _contextViewService: ContextViewService;
|
private readonly _contextViewService: ContextViewService;
|
||||||
private readonly _configurationService: IConfigurationService;
|
private readonly _configurationService: IConfigurationService;
|
||||||
|
private readonly _standaloneThemeService: IStandaloneThemeService;
|
||||||
private _ownsModel: boolean;
|
private _ownsModel: boolean;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@@ -363,6 +371,7 @@ export class StandaloneEditor extends StandaloneCodeEditor implements IStandalon
|
|||||||
|
|
||||||
this._contextViewService = <ContextViewService>contextViewService;
|
this._contextViewService = <ContextViewService>contextViewService;
|
||||||
this._configurationService = configurationService;
|
this._configurationService = configurationService;
|
||||||
|
this._standaloneThemeService = themeService;
|
||||||
this._register(toDispose);
|
this._register(toDispose);
|
||||||
this._register(themeDomRegistration);
|
this._register(themeDomRegistration);
|
||||||
|
|
||||||
@@ -391,6 +400,9 @@ export class StandaloneEditor extends StandaloneCodeEditor implements IStandalon
|
|||||||
|
|
||||||
public updateOptions(newOptions: IEditorOptions & IGlobalEditorOptions): void {
|
public updateOptions(newOptions: IEditorOptions & IGlobalEditorOptions): void {
|
||||||
applyConfigurationValues(this._configurationService, newOptions, false);
|
applyConfigurationValues(this._configurationService, newOptions, false);
|
||||||
|
if (typeof newOptions.theme === 'string') {
|
||||||
|
this._standaloneThemeService.setTheme(newOptions.theme);
|
||||||
|
}
|
||||||
super.updateOptions(newOptions);
|
super.updateOptions(newOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -414,6 +426,7 @@ export class StandaloneDiffEditor extends DiffEditorWidget implements IStandalon
|
|||||||
|
|
||||||
private readonly _contextViewService: ContextViewService;
|
private readonly _contextViewService: ContextViewService;
|
||||||
private readonly _configurationService: IConfigurationService;
|
private readonly _configurationService: IConfigurationService;
|
||||||
|
private readonly _standaloneThemeService: IStandaloneThemeService;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
domElement: HTMLElement,
|
domElement: HTMLElement,
|
||||||
@@ -443,6 +456,7 @@ export class StandaloneDiffEditor extends DiffEditorWidget implements IStandalon
|
|||||||
|
|
||||||
this._contextViewService = <ContextViewService>contextViewService;
|
this._contextViewService = <ContextViewService>contextViewService;
|
||||||
this._configurationService = configurationService;
|
this._configurationService = configurationService;
|
||||||
|
this._standaloneThemeService = themeService;
|
||||||
|
|
||||||
this._register(toDispose);
|
this._register(toDispose);
|
||||||
this._register(themeDomRegistration);
|
this._register(themeDomRegistration);
|
||||||
@@ -454,8 +468,11 @@ export class StandaloneDiffEditor extends DiffEditorWidget implements IStandalon
|
|||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
public updateOptions(newOptions: IDiffEditorOptions): void {
|
public updateOptions(newOptions: IDiffEditorOptions & IGlobalEditorOptions): void {
|
||||||
applyConfigurationValues(this._configurationService, newOptions, true);
|
applyConfigurationValues(this._configurationService, newOptions, true);
|
||||||
|
if (typeof newOptions.theme === 'string') {
|
||||||
|
this._standaloneThemeService.setTheme(newOptions.theme);
|
||||||
|
}
|
||||||
super.updateOptions(newOptions);
|
super.updateOptions(newOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ suite('MinimapCharRenderer', () => {
|
|||||||
imageData.data[4 * i + 2] = background.b;
|
imageData.data[4 * i + 2] = background.b;
|
||||||
imageData.data[4 * i + 3] = 255;
|
imageData.data[4 * i + 3] = 255;
|
||||||
}
|
}
|
||||||
renderer.renderChar(imageData, 0, 0, 'd'.charCodeAt(0), color, background, 2, false);
|
renderer.renderChar(imageData, 0, 0, 'd'.charCodeAt(0), color, background, 2, false, false);
|
||||||
|
|
||||||
let actual: number[] = [];
|
let actual: number[] = [];
|
||||||
for (let i = 0; i < imageData.data.length; i++) {
|
for (let i = 0; i < imageData.data.length; i++) {
|
||||||
@@ -108,7 +108,7 @@ suite('MinimapCharRenderer', () => {
|
|||||||
imageData.data[4 * i + 3] = 255;
|
imageData.data[4 * i + 3] = 255;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer.renderChar(imageData, 0, 0, 'd'.charCodeAt(0), color, background, 1, false);
|
renderer.renderChar(imageData, 0, 0, 'd'.charCodeAt(0), color, background, 1, false, false);
|
||||||
|
|
||||||
let actual: number[] = [];
|
let actual: number[] = [];
|
||||||
for (let i = 0; i < imageData.data.length; i++) {
|
for (let i = 0; i < imageData.data.length; i++) {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ interface IEditorLayoutProviderOpts {
|
|||||||
readonly showLineNumbers: boolean;
|
readonly showLineNumbers: boolean;
|
||||||
readonly lineNumbersMinChars: number;
|
readonly lineNumbersMinChars: number;
|
||||||
readonly lineNumbersDigitCount: number;
|
readonly lineNumbersDigitCount: number;
|
||||||
|
maxLineNumber?: number;
|
||||||
|
|
||||||
readonly lineDecorationsWidth: number;
|
readonly lineDecorationsWidth: number;
|
||||||
|
|
||||||
@@ -32,6 +33,7 @@ interface IEditorLayoutProviderOpts {
|
|||||||
readonly minimapSide: 'left' | 'right';
|
readonly minimapSide: 'left' | 'right';
|
||||||
readonly minimapRenderCharacters: boolean;
|
readonly minimapRenderCharacters: boolean;
|
||||||
readonly minimapMaxColumn: number;
|
readonly minimapMaxColumn: number;
|
||||||
|
minimapMode?: 'actual' | 'cover' | 'contain';
|
||||||
readonly pixelRatio: number;
|
readonly pixelRatio: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,6 +47,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
|||||||
options._write(EditorOption.folding, false);
|
options._write(EditorOption.folding, false);
|
||||||
const minimapOptions: EditorMinimapOptions = {
|
const minimapOptions: EditorMinimapOptions = {
|
||||||
enabled: input.minimap,
|
enabled: input.minimap,
|
||||||
|
mode: input.minimapMode || 'actual',
|
||||||
side: input.minimapSide,
|
side: input.minimapSide,
|
||||||
renderCharacters: input.minimapRenderCharacters,
|
renderCharacters: input.minimapRenderCharacters,
|
||||||
maxColumn: input.minimapMaxColumn,
|
maxColumn: input.minimapMaxColumn,
|
||||||
@@ -77,6 +80,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
|||||||
outerWidth: input.outerWidth,
|
outerWidth: input.outerWidth,
|
||||||
outerHeight: input.outerHeight,
|
outerHeight: input.outerHeight,
|
||||||
lineHeight: input.lineHeight,
|
lineHeight: input.lineHeight,
|
||||||
|
maxLineNumber: input.maxLineNumber || Math.pow(10, input.lineNumbersDigitCount) - 1,
|
||||||
lineNumbersDigitCount: input.lineNumbersDigitCount,
|
lineNumbersDigitCount: input.lineNumbersDigitCount,
|
||||||
typicalHalfwidthCharacterWidth: input.typicalHalfwidthCharacterWidth,
|
typicalHalfwidthCharacterWidth: input.typicalHalfwidthCharacterWidth,
|
||||||
maxDigitWidth: input.maxDigitWidth,
|
maxDigitWidth: input.maxDigitWidth,
|
||||||
@@ -125,6 +129,14 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
|||||||
renderMinimap: RenderMinimap.None,
|
renderMinimap: RenderMinimap.None,
|
||||||
minimapLeft: 0,
|
minimapLeft: 0,
|
||||||
minimapWidth: 0,
|
minimapWidth: 0,
|
||||||
|
minimapHeightIsEditorHeight: false,
|
||||||
|
minimapIsSampling: false,
|
||||||
|
minimapScale: 1,
|
||||||
|
minimapLineHeight: 1,
|
||||||
|
minimapCanvasInnerWidth: 0,
|
||||||
|
minimapCanvasInnerHeight: 800,
|
||||||
|
minimapCanvasOuterWidth: 0,
|
||||||
|
minimapCanvasOuterHeight: 800,
|
||||||
viewportColumn: 98,
|
viewportColumn: 98,
|
||||||
|
|
||||||
verticalScrollbarWidth: 0,
|
verticalScrollbarWidth: 0,
|
||||||
@@ -179,6 +191,14 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
|||||||
renderMinimap: RenderMinimap.None,
|
renderMinimap: RenderMinimap.None,
|
||||||
minimapLeft: 0,
|
minimapLeft: 0,
|
||||||
minimapWidth: 0,
|
minimapWidth: 0,
|
||||||
|
minimapHeightIsEditorHeight: false,
|
||||||
|
minimapIsSampling: false,
|
||||||
|
minimapScale: 1,
|
||||||
|
minimapLineHeight: 1,
|
||||||
|
minimapCanvasInnerWidth: 0,
|
||||||
|
minimapCanvasInnerHeight: 800,
|
||||||
|
minimapCanvasOuterWidth: 0,
|
||||||
|
minimapCanvasOuterHeight: 800,
|
||||||
viewportColumn: 97,
|
viewportColumn: 97,
|
||||||
|
|
||||||
verticalScrollbarWidth: 11,
|
verticalScrollbarWidth: 11,
|
||||||
@@ -233,6 +253,14 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
|||||||
renderMinimap: RenderMinimap.None,
|
renderMinimap: RenderMinimap.None,
|
||||||
minimapLeft: 0,
|
minimapLeft: 0,
|
||||||
minimapWidth: 0,
|
minimapWidth: 0,
|
||||||
|
minimapHeightIsEditorHeight: false,
|
||||||
|
minimapIsSampling: false,
|
||||||
|
minimapScale: 1,
|
||||||
|
minimapLineHeight: 1,
|
||||||
|
minimapCanvasInnerWidth: 0,
|
||||||
|
minimapCanvasInnerHeight: 800,
|
||||||
|
minimapCanvasOuterWidth: 0,
|
||||||
|
minimapCanvasOuterHeight: 800,
|
||||||
viewportColumn: 88,
|
viewportColumn: 88,
|
||||||
|
|
||||||
verticalScrollbarWidth: 0,
|
verticalScrollbarWidth: 0,
|
||||||
@@ -287,6 +315,14 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
|||||||
renderMinimap: RenderMinimap.None,
|
renderMinimap: RenderMinimap.None,
|
||||||
minimapLeft: 0,
|
minimapLeft: 0,
|
||||||
minimapWidth: 0,
|
minimapWidth: 0,
|
||||||
|
minimapHeightIsEditorHeight: false,
|
||||||
|
minimapIsSampling: false,
|
||||||
|
minimapScale: 1,
|
||||||
|
minimapLineHeight: 1,
|
||||||
|
minimapCanvasInnerWidth: 0,
|
||||||
|
minimapCanvasInnerHeight: 900,
|
||||||
|
minimapCanvasOuterWidth: 0,
|
||||||
|
minimapCanvasOuterHeight: 900,
|
||||||
viewportColumn: 88,
|
viewportColumn: 88,
|
||||||
|
|
||||||
verticalScrollbarWidth: 0,
|
verticalScrollbarWidth: 0,
|
||||||
@@ -341,6 +377,14 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
|||||||
renderMinimap: RenderMinimap.None,
|
renderMinimap: RenderMinimap.None,
|
||||||
minimapLeft: 0,
|
minimapLeft: 0,
|
||||||
minimapWidth: 0,
|
minimapWidth: 0,
|
||||||
|
minimapHeightIsEditorHeight: false,
|
||||||
|
minimapIsSampling: false,
|
||||||
|
minimapScale: 1,
|
||||||
|
minimapLineHeight: 1,
|
||||||
|
minimapCanvasInnerWidth: 0,
|
||||||
|
minimapCanvasInnerHeight: 900,
|
||||||
|
minimapCanvasOuterWidth: 0,
|
||||||
|
minimapCanvasOuterHeight: 900,
|
||||||
viewportColumn: 88,
|
viewportColumn: 88,
|
||||||
|
|
||||||
verticalScrollbarWidth: 0,
|
verticalScrollbarWidth: 0,
|
||||||
@@ -395,6 +439,14 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
|||||||
renderMinimap: RenderMinimap.None,
|
renderMinimap: RenderMinimap.None,
|
||||||
minimapLeft: 0,
|
minimapLeft: 0,
|
||||||
minimapWidth: 0,
|
minimapWidth: 0,
|
||||||
|
minimapHeightIsEditorHeight: false,
|
||||||
|
minimapIsSampling: false,
|
||||||
|
minimapScale: 1,
|
||||||
|
minimapLineHeight: 1,
|
||||||
|
minimapCanvasInnerWidth: 0,
|
||||||
|
minimapCanvasInnerHeight: 900,
|
||||||
|
minimapCanvasOuterWidth: 0,
|
||||||
|
minimapCanvasOuterHeight: 900,
|
||||||
viewportColumn: 83,
|
viewportColumn: 83,
|
||||||
|
|
||||||
verticalScrollbarWidth: 0,
|
verticalScrollbarWidth: 0,
|
||||||
@@ -449,6 +501,14 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
|||||||
renderMinimap: RenderMinimap.None,
|
renderMinimap: RenderMinimap.None,
|
||||||
minimapLeft: 0,
|
minimapLeft: 0,
|
||||||
minimapWidth: 0,
|
minimapWidth: 0,
|
||||||
|
minimapHeightIsEditorHeight: false,
|
||||||
|
minimapIsSampling: false,
|
||||||
|
minimapScale: 1,
|
||||||
|
minimapLineHeight: 1,
|
||||||
|
minimapCanvasInnerWidth: 0,
|
||||||
|
minimapCanvasInnerHeight: 900,
|
||||||
|
minimapCanvasOuterWidth: 0,
|
||||||
|
minimapCanvasOuterHeight: 900,
|
||||||
viewportColumn: 83,
|
viewportColumn: 83,
|
||||||
|
|
||||||
verticalScrollbarWidth: 0,
|
verticalScrollbarWidth: 0,
|
||||||
@@ -503,6 +563,14 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
|||||||
renderMinimap: RenderMinimap.None,
|
renderMinimap: RenderMinimap.None,
|
||||||
minimapLeft: 0,
|
minimapLeft: 0,
|
||||||
minimapWidth: 0,
|
minimapWidth: 0,
|
||||||
|
minimapHeightIsEditorHeight: false,
|
||||||
|
minimapIsSampling: false,
|
||||||
|
minimapScale: 1,
|
||||||
|
minimapLineHeight: 1,
|
||||||
|
minimapCanvasInnerWidth: 0,
|
||||||
|
minimapCanvasInnerHeight: 900,
|
||||||
|
minimapCanvasOuterWidth: 0,
|
||||||
|
minimapCanvasOuterHeight: 900,
|
||||||
viewportColumn: 82,
|
viewportColumn: 82,
|
||||||
|
|
||||||
verticalScrollbarWidth: 0,
|
verticalScrollbarWidth: 0,
|
||||||
@@ -557,6 +625,14 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
|||||||
renderMinimap: RenderMinimap.None,
|
renderMinimap: RenderMinimap.None,
|
||||||
minimapLeft: 0,
|
minimapLeft: 0,
|
||||||
minimapWidth: 0,
|
minimapWidth: 0,
|
||||||
|
minimapHeightIsEditorHeight: false,
|
||||||
|
minimapIsSampling: false,
|
||||||
|
minimapScale: 1,
|
||||||
|
minimapLineHeight: 1,
|
||||||
|
minimapCanvasInnerWidth: 0,
|
||||||
|
minimapCanvasInnerHeight: 900,
|
||||||
|
minimapCanvasOuterWidth: 0,
|
||||||
|
minimapCanvasOuterHeight: 900,
|
||||||
viewportColumn: 171,
|
viewportColumn: 171,
|
||||||
|
|
||||||
verticalScrollbarWidth: 0,
|
verticalScrollbarWidth: 0,
|
||||||
@@ -611,6 +687,14 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
|||||||
renderMinimap: RenderMinimap.None,
|
renderMinimap: RenderMinimap.None,
|
||||||
minimapLeft: 0,
|
minimapLeft: 0,
|
||||||
minimapWidth: 0,
|
minimapWidth: 0,
|
||||||
|
minimapHeightIsEditorHeight: false,
|
||||||
|
minimapIsSampling: false,
|
||||||
|
minimapScale: 1,
|
||||||
|
minimapLineHeight: 1,
|
||||||
|
minimapCanvasInnerWidth: 0,
|
||||||
|
minimapCanvasInnerHeight: 900,
|
||||||
|
minimapCanvasOuterWidth: 0,
|
||||||
|
minimapCanvasOuterHeight: 900,
|
||||||
viewportColumn: 169,
|
viewportColumn: 169,
|
||||||
|
|
||||||
verticalScrollbarWidth: 0,
|
verticalScrollbarWidth: 0,
|
||||||
@@ -665,6 +749,14 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
|||||||
renderMinimap: RenderMinimap.Text,
|
renderMinimap: RenderMinimap.Text,
|
||||||
minimapLeft: 903,
|
minimapLeft: 903,
|
||||||
minimapWidth: 97,
|
minimapWidth: 97,
|
||||||
|
minimapHeightIsEditorHeight: false,
|
||||||
|
minimapIsSampling: false,
|
||||||
|
minimapScale: 1,
|
||||||
|
minimapLineHeight: 2,
|
||||||
|
minimapCanvasInnerWidth: 97,
|
||||||
|
minimapCanvasInnerHeight: 800,
|
||||||
|
minimapCanvasOuterWidth: 97,
|
||||||
|
minimapCanvasOuterHeight: 800,
|
||||||
viewportColumn: 89,
|
viewportColumn: 89,
|
||||||
|
|
||||||
verticalScrollbarWidth: 0,
|
verticalScrollbarWidth: 0,
|
||||||
@@ -719,6 +811,14 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
|||||||
renderMinimap: RenderMinimap.Text,
|
renderMinimap: RenderMinimap.Text,
|
||||||
minimapLeft: 903,
|
minimapLeft: 903,
|
||||||
minimapWidth: 97,
|
minimapWidth: 97,
|
||||||
|
minimapHeightIsEditorHeight: false,
|
||||||
|
minimapIsSampling: false,
|
||||||
|
minimapScale: 2,
|
||||||
|
minimapLineHeight: 4,
|
||||||
|
minimapCanvasInnerWidth: 194,
|
||||||
|
minimapCanvasInnerHeight: 1600,
|
||||||
|
minimapCanvasOuterWidth: 97,
|
||||||
|
minimapCanvasOuterHeight: 800,
|
||||||
viewportColumn: 89,
|
viewportColumn: 89,
|
||||||
|
|
||||||
verticalScrollbarWidth: 0,
|
verticalScrollbarWidth: 0,
|
||||||
@@ -773,6 +873,14 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
|||||||
renderMinimap: RenderMinimap.Text,
|
renderMinimap: RenderMinimap.Text,
|
||||||
minimapLeft: 945,
|
minimapLeft: 945,
|
||||||
minimapWidth: 55,
|
minimapWidth: 55,
|
||||||
|
minimapHeightIsEditorHeight: false,
|
||||||
|
minimapIsSampling: false,
|
||||||
|
minimapScale: 2,
|
||||||
|
minimapLineHeight: 4,
|
||||||
|
minimapCanvasInnerWidth: 220,
|
||||||
|
minimapCanvasInnerHeight: 3200,
|
||||||
|
minimapCanvasOuterWidth: 55,
|
||||||
|
minimapCanvasOuterHeight: 800,
|
||||||
viewportColumn: 93,
|
viewportColumn: 93,
|
||||||
|
|
||||||
verticalScrollbarWidth: 0,
|
verticalScrollbarWidth: 0,
|
||||||
@@ -827,6 +935,270 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
|||||||
renderMinimap: RenderMinimap.Text,
|
renderMinimap: RenderMinimap.Text,
|
||||||
minimapLeft: 0,
|
minimapLeft: 0,
|
||||||
minimapWidth: 55,
|
minimapWidth: 55,
|
||||||
|
minimapHeightIsEditorHeight: false,
|
||||||
|
minimapIsSampling: false,
|
||||||
|
minimapScale: 2,
|
||||||
|
minimapLineHeight: 4,
|
||||||
|
minimapCanvasInnerWidth: 220,
|
||||||
|
minimapCanvasInnerHeight: 3200,
|
||||||
|
minimapCanvasOuterWidth: 55,
|
||||||
|
minimapCanvasOuterHeight: 800,
|
||||||
|
viewportColumn: 93,
|
||||||
|
|
||||||
|
verticalScrollbarWidth: 0,
|
||||||
|
horizontalScrollbarHeight: 0,
|
||||||
|
|
||||||
|
overviewRuler: {
|
||||||
|
top: 0,
|
||||||
|
width: 0,
|
||||||
|
height: 800,
|
||||||
|
right: 0
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('EditorLayoutProvider 11 - minimap mode cover without sampling', () => {
|
||||||
|
doTest({
|
||||||
|
outerWidth: 1000,
|
||||||
|
outerHeight: 800,
|
||||||
|
showGlyphMargin: false,
|
||||||
|
lineHeight: 16,
|
||||||
|
showLineNumbers: false,
|
||||||
|
lineNumbersMinChars: 0,
|
||||||
|
lineNumbersDigitCount: 3,
|
||||||
|
maxLineNumber: 120,
|
||||||
|
lineDecorationsWidth: 10,
|
||||||
|
typicalHalfwidthCharacterWidth: 10,
|
||||||
|
maxDigitWidth: 10,
|
||||||
|
verticalScrollbarWidth: 0,
|
||||||
|
horizontalScrollbarHeight: 0,
|
||||||
|
scrollbarArrowSize: 0,
|
||||||
|
verticalScrollbarHasArrows: false,
|
||||||
|
minimap: true,
|
||||||
|
minimapSide: 'right',
|
||||||
|
minimapRenderCharacters: true,
|
||||||
|
minimapMaxColumn: 150,
|
||||||
|
minimapMode: 'cover',
|
||||||
|
pixelRatio: 2,
|
||||||
|
}, {
|
||||||
|
width: 1000,
|
||||||
|
height: 800,
|
||||||
|
|
||||||
|
glyphMarginLeft: 0,
|
||||||
|
glyphMarginWidth: 0,
|
||||||
|
|
||||||
|
lineNumbersLeft: 0,
|
||||||
|
lineNumbersWidth: 0,
|
||||||
|
|
||||||
|
decorationsLeft: 0,
|
||||||
|
decorationsWidth: 10,
|
||||||
|
|
||||||
|
contentLeft: 10,
|
||||||
|
contentWidth: 893,
|
||||||
|
|
||||||
|
renderMinimap: RenderMinimap.Text,
|
||||||
|
minimapLeft: 903,
|
||||||
|
minimapWidth: 97,
|
||||||
|
minimapHeightIsEditorHeight: true,
|
||||||
|
minimapIsSampling: false,
|
||||||
|
minimapScale: 3,
|
||||||
|
minimapLineHeight: 13,
|
||||||
|
minimapCanvasInnerWidth: 291,
|
||||||
|
minimapCanvasInnerHeight: 1560,
|
||||||
|
minimapCanvasOuterWidth: 97,
|
||||||
|
minimapCanvasOuterHeight: 800,
|
||||||
|
viewportColumn: 89,
|
||||||
|
|
||||||
|
verticalScrollbarWidth: 0,
|
||||||
|
horizontalScrollbarHeight: 0,
|
||||||
|
|
||||||
|
overviewRuler: {
|
||||||
|
top: 0,
|
||||||
|
width: 0,
|
||||||
|
height: 800,
|
||||||
|
right: 0
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('EditorLayoutProvider 12 - minimap mode cover with sampling', () => {
|
||||||
|
doTest({
|
||||||
|
outerWidth: 1000,
|
||||||
|
outerHeight: 800,
|
||||||
|
showGlyphMargin: false,
|
||||||
|
lineHeight: 16,
|
||||||
|
showLineNumbers: false,
|
||||||
|
lineNumbersMinChars: 0,
|
||||||
|
lineNumbersDigitCount: 4,
|
||||||
|
maxLineNumber: 2500,
|
||||||
|
lineDecorationsWidth: 10,
|
||||||
|
typicalHalfwidthCharacterWidth: 10,
|
||||||
|
maxDigitWidth: 10,
|
||||||
|
verticalScrollbarWidth: 0,
|
||||||
|
horizontalScrollbarHeight: 0,
|
||||||
|
scrollbarArrowSize: 0,
|
||||||
|
verticalScrollbarHasArrows: false,
|
||||||
|
minimap: true,
|
||||||
|
minimapSide: 'right',
|
||||||
|
minimapRenderCharacters: true,
|
||||||
|
minimapMaxColumn: 150,
|
||||||
|
minimapMode: 'cover',
|
||||||
|
pixelRatio: 2,
|
||||||
|
}, {
|
||||||
|
width: 1000,
|
||||||
|
height: 800,
|
||||||
|
|
||||||
|
glyphMarginLeft: 0,
|
||||||
|
glyphMarginWidth: 0,
|
||||||
|
|
||||||
|
lineNumbersLeft: 0,
|
||||||
|
lineNumbersWidth: 0,
|
||||||
|
|
||||||
|
decorationsLeft: 0,
|
||||||
|
decorationsWidth: 10,
|
||||||
|
|
||||||
|
contentLeft: 10,
|
||||||
|
contentWidth: 935,
|
||||||
|
|
||||||
|
renderMinimap: RenderMinimap.Text,
|
||||||
|
minimapLeft: 945,
|
||||||
|
minimapWidth: 55,
|
||||||
|
minimapHeightIsEditorHeight: true,
|
||||||
|
minimapIsSampling: true,
|
||||||
|
minimapScale: 1,
|
||||||
|
minimapLineHeight: 1,
|
||||||
|
minimapCanvasInnerWidth: 110,
|
||||||
|
minimapCanvasInnerHeight: 1600,
|
||||||
|
minimapCanvasOuterWidth: 55,
|
||||||
|
minimapCanvasOuterHeight: 800,
|
||||||
|
viewportColumn: 93,
|
||||||
|
|
||||||
|
verticalScrollbarWidth: 0,
|
||||||
|
horizontalScrollbarHeight: 0,
|
||||||
|
|
||||||
|
overviewRuler: {
|
||||||
|
top: 0,
|
||||||
|
width: 0,
|
||||||
|
height: 800,
|
||||||
|
right: 0
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('EditorLayoutProvider 13 - minimap mode contain without sampling', () => {
|
||||||
|
doTest({
|
||||||
|
outerWidth: 1000,
|
||||||
|
outerHeight: 800,
|
||||||
|
showGlyphMargin: false,
|
||||||
|
lineHeight: 16,
|
||||||
|
showLineNumbers: false,
|
||||||
|
lineNumbersMinChars: 0,
|
||||||
|
lineNumbersDigitCount: 3,
|
||||||
|
maxLineNumber: 120,
|
||||||
|
lineDecorationsWidth: 10,
|
||||||
|
typicalHalfwidthCharacterWidth: 10,
|
||||||
|
maxDigitWidth: 10,
|
||||||
|
verticalScrollbarWidth: 0,
|
||||||
|
horizontalScrollbarHeight: 0,
|
||||||
|
scrollbarArrowSize: 0,
|
||||||
|
verticalScrollbarHasArrows: false,
|
||||||
|
minimap: true,
|
||||||
|
minimapSide: 'right',
|
||||||
|
minimapRenderCharacters: true,
|
||||||
|
minimapMaxColumn: 150,
|
||||||
|
minimapMode: 'contain',
|
||||||
|
pixelRatio: 2,
|
||||||
|
}, {
|
||||||
|
width: 1000,
|
||||||
|
height: 800,
|
||||||
|
|
||||||
|
glyphMarginLeft: 0,
|
||||||
|
glyphMarginWidth: 0,
|
||||||
|
|
||||||
|
lineNumbersLeft: 0,
|
||||||
|
lineNumbersWidth: 0,
|
||||||
|
|
||||||
|
decorationsLeft: 0,
|
||||||
|
decorationsWidth: 10,
|
||||||
|
|
||||||
|
contentLeft: 10,
|
||||||
|
contentWidth: 893,
|
||||||
|
|
||||||
|
renderMinimap: RenderMinimap.Text,
|
||||||
|
minimapLeft: 903,
|
||||||
|
minimapWidth: 97,
|
||||||
|
minimapHeightIsEditorHeight: false,
|
||||||
|
minimapIsSampling: false,
|
||||||
|
minimapScale: 2,
|
||||||
|
minimapLineHeight: 4,
|
||||||
|
minimapCanvasInnerWidth: 194,
|
||||||
|
minimapCanvasInnerHeight: 1600,
|
||||||
|
minimapCanvasOuterWidth: 97,
|
||||||
|
minimapCanvasOuterHeight: 800,
|
||||||
|
viewportColumn: 89,
|
||||||
|
|
||||||
|
verticalScrollbarWidth: 0,
|
||||||
|
horizontalScrollbarHeight: 0,
|
||||||
|
|
||||||
|
overviewRuler: {
|
||||||
|
top: 0,
|
||||||
|
width: 0,
|
||||||
|
height: 800,
|
||||||
|
right: 0
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('EditorLayoutProvider 14 - minimap mode contain with sampling', () => {
|
||||||
|
doTest({
|
||||||
|
outerWidth: 1000,
|
||||||
|
outerHeight: 800,
|
||||||
|
showGlyphMargin: false,
|
||||||
|
lineHeight: 16,
|
||||||
|
showLineNumbers: false,
|
||||||
|
lineNumbersMinChars: 0,
|
||||||
|
lineNumbersDigitCount: 4,
|
||||||
|
maxLineNumber: 2500,
|
||||||
|
lineDecorationsWidth: 10,
|
||||||
|
typicalHalfwidthCharacterWidth: 10,
|
||||||
|
maxDigitWidth: 10,
|
||||||
|
verticalScrollbarWidth: 0,
|
||||||
|
horizontalScrollbarHeight: 0,
|
||||||
|
scrollbarArrowSize: 0,
|
||||||
|
verticalScrollbarHasArrows: false,
|
||||||
|
minimap: true,
|
||||||
|
minimapSide: 'right',
|
||||||
|
minimapRenderCharacters: true,
|
||||||
|
minimapMaxColumn: 150,
|
||||||
|
minimapMode: 'contain',
|
||||||
|
pixelRatio: 2,
|
||||||
|
}, {
|
||||||
|
width: 1000,
|
||||||
|
height: 800,
|
||||||
|
|
||||||
|
glyphMarginLeft: 0,
|
||||||
|
glyphMarginWidth: 0,
|
||||||
|
|
||||||
|
lineNumbersLeft: 0,
|
||||||
|
lineNumbersWidth: 0,
|
||||||
|
|
||||||
|
decorationsLeft: 0,
|
||||||
|
decorationsWidth: 10,
|
||||||
|
|
||||||
|
contentLeft: 10,
|
||||||
|
contentWidth: 935,
|
||||||
|
|
||||||
|
renderMinimap: RenderMinimap.Text,
|
||||||
|
minimapLeft: 945,
|
||||||
|
minimapWidth: 55,
|
||||||
|
minimapHeightIsEditorHeight: true,
|
||||||
|
minimapIsSampling: true,
|
||||||
|
minimapScale: 1,
|
||||||
|
minimapLineHeight: 1,
|
||||||
|
minimapCanvasInnerWidth: 110,
|
||||||
|
minimapCanvasInnerHeight: 1600,
|
||||||
|
minimapCanvasOuterWidth: 55,
|
||||||
|
minimapCanvasOuterHeight: 800,
|
||||||
viewportColumn: 93,
|
viewportColumn: 93,
|
||||||
|
|
||||||
verticalScrollbarWidth: 0,
|
verticalScrollbarWidth: 0,
|
||||||
@@ -881,6 +1253,14 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
|||||||
renderMinimap: RenderMinimap.Text,
|
renderMinimap: RenderMinimap.Text,
|
||||||
minimapLeft: 1096,
|
minimapLeft: 1096,
|
||||||
minimapWidth: 91,
|
minimapWidth: 91,
|
||||||
|
minimapHeightIsEditorHeight: false,
|
||||||
|
minimapIsSampling: false,
|
||||||
|
minimapScale: 2,
|
||||||
|
minimapLineHeight: 4,
|
||||||
|
minimapCanvasInnerWidth: 182,
|
||||||
|
minimapCanvasInnerHeight: 844,
|
||||||
|
minimapCanvasOuterWidth: 91,
|
||||||
|
minimapCanvasOuterHeight: 422,
|
||||||
viewportColumn: 83,
|
viewportColumn: 83,
|
||||||
|
|
||||||
verticalScrollbarWidth: 14,
|
verticalScrollbarWidth: 14,
|
||||||
|
|||||||
Vendored
+22
@@ -1108,6 +1108,13 @@ declare namespace monaco.editor {
|
|||||||
* Defaults to 20000.
|
* Defaults to 20000.
|
||||||
*/
|
*/
|
||||||
maxTokenizationLineLength?: number;
|
maxTokenizationLineLength?: number;
|
||||||
|
/**
|
||||||
|
* Theme to be used for rendering.
|
||||||
|
* The current out-of-the-box available themes are: 'vs' (default), 'vs-dark', 'hc-black'.
|
||||||
|
* You can create custom themes via `monaco.editor.defineTheme`.
|
||||||
|
* To switch a theme, use `monaco.editor.setTheme`
|
||||||
|
*/
|
||||||
|
theme?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2390,6 +2397,8 @@ declare namespace monaco.editor {
|
|||||||
* An event describing that model decorations have changed.
|
* An event describing that model decorations have changed.
|
||||||
*/
|
*/
|
||||||
export interface IModelDecorationsChangedEvent {
|
export interface IModelDecorationsChangedEvent {
|
||||||
|
readonly affectsMinimap: boolean;
|
||||||
|
readonly affectsOverviewRuler: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IModelOptionsChangedEvent {
|
export interface IModelOptionsChangedEvent {
|
||||||
@@ -3334,6 +3343,14 @@ declare namespace monaco.editor {
|
|||||||
* The width of the minimap
|
* The width of the minimap
|
||||||
*/
|
*/
|
||||||
readonly minimapWidth: number;
|
readonly minimapWidth: number;
|
||||||
|
readonly minimapHeightIsEditorHeight: boolean;
|
||||||
|
readonly minimapIsSampling: boolean;
|
||||||
|
readonly minimapScale: number;
|
||||||
|
readonly minimapLineHeight: number;
|
||||||
|
readonly minimapCanvasInnerWidth: number;
|
||||||
|
readonly minimapCanvasInnerHeight: number;
|
||||||
|
readonly minimapCanvasOuterWidth: number;
|
||||||
|
readonly minimapCanvasOuterHeight: number;
|
||||||
/**
|
/**
|
||||||
* Minimap render type
|
* Minimap render type
|
||||||
*/
|
*/
|
||||||
@@ -3383,6 +3400,11 @@ declare namespace monaco.editor {
|
|||||||
* Defaults to 'right'.
|
* Defaults to 'right'.
|
||||||
*/
|
*/
|
||||||
side?: 'right' | 'left';
|
side?: 'right' | 'left';
|
||||||
|
/**
|
||||||
|
* Control the minimap rendering mode.
|
||||||
|
* Defaults to 'actual'.
|
||||||
|
*/
|
||||||
|
mode?: 'actual' | 'cover' | 'contain';
|
||||||
/**
|
/**
|
||||||
* Control the rendering of the minimap slider.
|
* Control the rendering of the minimap slider.
|
||||||
* Defaults to 'mouseover'.
|
* Defaults to 'mouseover'.
|
||||||
|
|||||||
@@ -353,7 +353,7 @@ export class UserSettings extends Disposable {
|
|||||||
super();
|
super();
|
||||||
this.parser = new ConfigurationModelParser(this.userSettingsResource.toString(), this.scopes);
|
this.parser = new ConfigurationModelParser(this.userSettingsResource.toString(), this.scopes);
|
||||||
this._register(this.fileService.watch(dirname(this.userSettingsResource)));
|
this._register(this.fileService.watch(dirname(this.userSettingsResource)));
|
||||||
this._register(Event.filter(this.fileService.onFileChanges, e => e.contains(this.userSettingsResource))(() => this._onDidChange.fire()));
|
this._register(Event.filter(this.fileService.onDidFilesChange, e => e.contains(this.userSettingsResource))(() => this._onDidChange.fire()));
|
||||||
}
|
}
|
||||||
|
|
||||||
async loadConfiguration(): Promise<ConfigurationModel> {
|
async loadConfiguration(): Promise<ConfigurationModel> {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import * as path from 'vs/base/common/path';
|
|||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
|
|
||||||
import { Registry } from 'vs/platform/registry/common/platform';
|
import { Registry } from 'vs/platform/registry/common/platform';
|
||||||
import { ConfigurationService } from 'vs/platform/configuration/node/configurationService';
|
import { ConfigurationService } from 'vs/platform/configuration/common/configurationService';
|
||||||
import * as uuid from 'vs/base/common/uuid';
|
import * as uuid from 'vs/base/common/uuid';
|
||||||
import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry';
|
import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry';
|
||||||
import { testFile } from 'vs/base/test/node/utils';
|
import { testFile } from 'vs/base/test/node/utils';
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export class FileService extends Disposable implements IFileService {
|
|||||||
|
|
||||||
// Forward events from provider
|
// Forward events from provider
|
||||||
const providerDisposables = new DisposableStore();
|
const providerDisposables = new DisposableStore();
|
||||||
providerDisposables.add(provider.onDidChangeFile(changes => this._onFileChanges.fire(new FileChangesEvent(changes))));
|
providerDisposables.add(provider.onDidChangeFile(changes => this._onDidFilesChange.fire(new FileChangesEvent(changes))));
|
||||||
providerDisposables.add(provider.onDidChangeCapabilities(() => this._onDidChangeFileSystemProviderCapabilities.fire({ provider, scheme })));
|
providerDisposables.add(provider.onDidChangeCapabilities(() => this._onDidChangeFileSystemProviderCapabilities.fire({ provider, scheme })));
|
||||||
if (typeof provider.onDidErrorOccur === 'function') {
|
if (typeof provider.onDidErrorOccur === 'function') {
|
||||||
providerDisposables.add(provider.onDidErrorOccur(error => this._onError.fire(new Error(error))));
|
providerDisposables.add(provider.onDidErrorOccur(error => this._onError.fire(new Error(error))));
|
||||||
@@ -147,11 +147,11 @@ export class FileService extends Disposable implements IFileService {
|
|||||||
|
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
private _onAfterOperation: Emitter<FileOperationEvent> = this._register(new Emitter<FileOperationEvent>());
|
private _onDidRunOperation = this._register(new Emitter<FileOperationEvent>());
|
||||||
readonly onAfterOperation: Event<FileOperationEvent> = this._onAfterOperation.event;
|
readonly onDidRunOperation = this._onDidRunOperation.event;
|
||||||
|
|
||||||
private _onError: Emitter<Error> = this._register(new Emitter<Error>());
|
private _onError = this._register(new Emitter<Error>());
|
||||||
readonly onError: Event<Error> = this._onError.event;
|
readonly onError = this._onError.event;
|
||||||
|
|
||||||
//#region File Metadata Resolving
|
//#region File Metadata Resolving
|
||||||
|
|
||||||
@@ -299,7 +299,7 @@ export class FileService extends Disposable implements IFileService {
|
|||||||
const fileStat = await this.writeFile(resource, bufferOrReadableOrStream);
|
const fileStat = await this.writeFile(resource, bufferOrReadableOrStream);
|
||||||
|
|
||||||
// events
|
// events
|
||||||
this._onAfterOperation.fire(new FileOperationEvent(resource, FileOperation.CREATE, fileStat));
|
this._onDidRunOperation.fire(new FileOperationEvent(resource, FileOperation.CREATE, fileStat));
|
||||||
|
|
||||||
return fileStat;
|
return fileStat;
|
||||||
}
|
}
|
||||||
@@ -549,7 +549,7 @@ export class FileService extends Disposable implements IFileService {
|
|||||||
|
|
||||||
// resolve and send events
|
// resolve and send events
|
||||||
const fileStat = await this.resolve(target, { resolveMetadata: true });
|
const fileStat = await this.resolve(target, { resolveMetadata: true });
|
||||||
this._onAfterOperation.fire(new FileOperationEvent(source, mode === 'move' ? FileOperation.MOVE : FileOperation.COPY, fileStat));
|
this._onDidRunOperation.fire(new FileOperationEvent(source, mode === 'move' ? FileOperation.MOVE : FileOperation.COPY, fileStat));
|
||||||
|
|
||||||
return fileStat;
|
return fileStat;
|
||||||
}
|
}
|
||||||
@@ -563,7 +563,7 @@ export class FileService extends Disposable implements IFileService {
|
|||||||
|
|
||||||
// resolve and send events
|
// resolve and send events
|
||||||
const fileStat = await this.resolve(target, { resolveMetadata: true });
|
const fileStat = await this.resolve(target, { resolveMetadata: true });
|
||||||
this._onAfterOperation.fire(new FileOperationEvent(source, mode === 'copy' ? FileOperation.COPY : FileOperation.MOVE, fileStat));
|
this._onDidRunOperation.fire(new FileOperationEvent(source, mode === 'copy' ? FileOperation.COPY : FileOperation.MOVE, fileStat));
|
||||||
|
|
||||||
return fileStat;
|
return fileStat;
|
||||||
}
|
}
|
||||||
@@ -717,7 +717,7 @@ export class FileService extends Disposable implements IFileService {
|
|||||||
|
|
||||||
// events
|
// events
|
||||||
const fileStat = await this.resolve(resource, { resolveMetadata: true });
|
const fileStat = await this.resolve(resource, { resolveMetadata: true });
|
||||||
this._onAfterOperation.fire(new FileOperationEvent(resource, FileOperation.CREATE, fileStat));
|
this._onDidRunOperation.fire(new FileOperationEvent(resource, FileOperation.CREATE, fileStat));
|
||||||
|
|
||||||
return fileStat;
|
return fileStat;
|
||||||
}
|
}
|
||||||
@@ -799,15 +799,15 @@ export class FileService extends Disposable implements IFileService {
|
|||||||
await provider.delete(resource, { recursive, useTrash });
|
await provider.delete(resource, { recursive, useTrash });
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
this._onAfterOperation.fire(new FileOperationEvent(resource, FileOperation.DELETE));
|
this._onDidRunOperation.fire(new FileOperationEvent(resource, FileOperation.DELETE));
|
||||||
}
|
}
|
||||||
|
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
//#region File Watching
|
//#region File Watching
|
||||||
|
|
||||||
private _onFileChanges: Emitter<FileChangesEvent> = this._register(new Emitter<FileChangesEvent>());
|
private _onDidFilesChange = this._register(new Emitter<FileChangesEvent>());
|
||||||
readonly onFileChanges: Event<FileChangesEvent> = this._onFileChanges.event;
|
readonly onDidFilesChange = this._onDidFilesChange.event;
|
||||||
|
|
||||||
private activeWatchers = new Map<string, { disposable: IDisposable, count: number }>();
|
private activeWatchers = new Map<string, { disposable: IDisposable, count: number }>();
|
||||||
|
|
||||||
|
|||||||
@@ -63,12 +63,12 @@ export interface IFileService {
|
|||||||
* Allows to listen for file changes. The event will fire for every file within the opened workspace
|
* Allows to listen for file changes. The event will fire for every file within the opened workspace
|
||||||
* (if any) as well as all files that have been watched explicitly using the #watch() API.
|
* (if any) as well as all files that have been watched explicitly using the #watch() API.
|
||||||
*/
|
*/
|
||||||
readonly onFileChanges: Event<FileChangesEvent>;
|
readonly onDidFilesChange: Event<FileChangesEvent>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An event that is fired upon successful completion of a certain file operation.
|
* An event that is fired upon successful completion of a certain file operation.
|
||||||
*/
|
*/
|
||||||
readonly onAfterOperation: Event<FileOperationEvent>;
|
readonly onDidRunOperation: Event<FileOperationEvent>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve the properties of a file/folder identified by the resource.
|
* Resolve the properties of a file/folder identified by the resource.
|
||||||
@@ -471,15 +471,7 @@ export interface IFileChange {
|
|||||||
|
|
||||||
export class FileChangesEvent {
|
export class FileChangesEvent {
|
||||||
|
|
||||||
private readonly _changes: readonly IFileChange[];
|
constructor(public readonly changes: readonly IFileChange[]) { }
|
||||||
|
|
||||||
constructor(changes: readonly IFileChange[]) {
|
|
||||||
this._changes = changes;
|
|
||||||
}
|
|
||||||
|
|
||||||
get changes() {
|
|
||||||
return this._changes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this change event contains the provided file with the given change type (if provided). In case of
|
* Returns true if this change event contains the provided file with the given change type (if provided). In case of
|
||||||
@@ -493,7 +485,7 @@ export class FileChangesEvent {
|
|||||||
|
|
||||||
const checkForChangeType = !isUndefinedOrNull(type);
|
const checkForChangeType = !isUndefinedOrNull(type);
|
||||||
|
|
||||||
return this._changes.some(change => {
|
return this.changes.some(change => {
|
||||||
if (checkForChangeType && change.type !== type) {
|
if (checkForChangeType && change.type !== type) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -550,11 +542,11 @@ export class FileChangesEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private getOfType(type: FileChangeType): IFileChange[] {
|
private getOfType(type: FileChangeType): IFileChange[] {
|
||||||
return this._changes.filter(change => change.type === type);
|
return this.changes.filter(change => change.type === type);
|
||||||
}
|
}
|
||||||
|
|
||||||
private hasType(type: FileChangeType): boolean {
|
private hasType(type: FileChangeType): boolean {
|
||||||
return this._changes.some(change => {
|
return this.changes.some(change => {
|
||||||
return change.type === type;
|
return change.type === type;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-3
@@ -66,9 +66,7 @@ export class InMemoryFileSystemProvider extends Disposable implements IFileSyste
|
|||||||
async readdir(resource: URI): Promise<[string, FileType][]> {
|
async readdir(resource: URI): Promise<[string, FileType][]> {
|
||||||
const entry = this._lookupAsDirectory(resource, false);
|
const entry = this._lookupAsDirectory(resource, false);
|
||||||
let result: [string, FileType][] = [];
|
let result: [string, FileType][] = [];
|
||||||
for (const [name, child] of entry.entries) {
|
entry.entries.forEach((child, name) => result.push([name, child.type]));
|
||||||
result.push([name, child.type]);
|
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ export class FileWatcher extends Disposable {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private path: string,
|
private path: string,
|
||||||
private onFileChanges: (changes: IDiskFileChange[]) => void,
|
private onDidFilesChange: (changes: IDiskFileChange[]) => void,
|
||||||
private onLogMessage: (msg: ILogMessage) => void,
|
private onLogMessage: (msg: ILogMessage) => void,
|
||||||
private verboseLogging: boolean
|
private verboseLogging: boolean
|
||||||
) {
|
) {
|
||||||
@@ -101,7 +101,7 @@ export class FileWatcher extends Disposable {
|
|||||||
|
|
||||||
// Fire
|
// Fire
|
||||||
if (normalizedFileChanges.length > 0) {
|
if (normalizedFileChanges.length > 0) {
|
||||||
this.onFileChanges(normalizedFileChanges);
|
this.onDidFilesChange(normalizedFileChanges);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export class FileWatcher extends Disposable {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private folders: IWatcherRequest[],
|
private folders: IWatcherRequest[],
|
||||||
private onFileChanges: (changes: IDiskFileChange[]) => void,
|
private onDidFilesChange: (changes: IDiskFileChange[]) => void,
|
||||||
private onLogMessage: (msg: ILogMessage) => void,
|
private onLogMessage: (msg: ILogMessage) => void,
|
||||||
private verboseLogging: boolean,
|
private verboseLogging: boolean,
|
||||||
) {
|
) {
|
||||||
@@ -68,7 +68,7 @@ export class FileWatcher extends Disposable {
|
|||||||
this.service.setVerboseLogging(this.verboseLogging);
|
this.service.setVerboseLogging(this.verboseLogging);
|
||||||
|
|
||||||
const options = {};
|
const options = {};
|
||||||
this._register(this.service.watch(options)(e => !this.isDisposed && this.onFileChanges(e)));
|
this._register(this.service.watch(options)(e => !this.isDisposed && this.onDidFilesChange(e)));
|
||||||
|
|
||||||
this._register(this.service.onLogMessage(m => this.onLogMessage(m)));
|
this._register(this.service.onLogMessage(m => this.onLogMessage(m)));
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export class FileWatcher extends Disposable {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private folders: IWatcherRequest[],
|
private folders: IWatcherRequest[],
|
||||||
private onFileChanges: (changes: IDiskFileChange[]) => void,
|
private onDidFilesChange: (changes: IDiskFileChange[]) => void,
|
||||||
private onLogMessage: (msg: ILogMessage) => void,
|
private onLogMessage: (msg: ILogMessage) => void,
|
||||||
private verboseLogging: boolean,
|
private verboseLogging: boolean,
|
||||||
private watcherOptions: IWatcherOptions = {}
|
private watcherOptions: IWatcherOptions = {}
|
||||||
@@ -67,7 +67,7 @@ export class FileWatcher extends Disposable {
|
|||||||
|
|
||||||
this.service.setVerboseLogging(this.verboseLogging);
|
this.service.setVerboseLogging(this.verboseLogging);
|
||||||
|
|
||||||
this._register(this.service.watch(this.watcherOptions)(e => !this.isDisposed && this.onFileChanges(e)));
|
this._register(this.service.watch(this.watcherOptions)(e => !this.isDisposed && this.onDidFilesChange(e)));
|
||||||
|
|
||||||
this._register(this.service.onLogMessage(m => this.onLogMessage(m)));
|
this._register(this.service.onLogMessage(m => this.onLogMessage(m)));
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export class FileWatcher implements IDisposable {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
folders: { path: string, excludes: string[] }[],
|
folders: { path: string, excludes: string[] }[],
|
||||||
private onFileChanges: (changes: IDiskFileChange[]) => void,
|
private onDidFilesChange: (changes: IDiskFileChange[]) => void,
|
||||||
private onLogMessage: (msg: ILogMessage) => void,
|
private onLogMessage: (msg: ILogMessage) => void,
|
||||||
private verboseLogging: boolean
|
private verboseLogging: boolean
|
||||||
) {
|
) {
|
||||||
@@ -62,7 +62,7 @@ export class FileWatcher implements IDisposable {
|
|||||||
|
|
||||||
// Emit through event emitter
|
// Emit through event emitter
|
||||||
if (events.length > 0) {
|
if (events.length > 0) {
|
||||||
this.onFileChanges(events);
|
this.onDidFilesChange(events);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ suite('Disk File Service', function () {
|
|||||||
|
|
||||||
test('createFolder', async () => {
|
test('createFolder', async () => {
|
||||||
let event: FileOperationEvent | undefined;
|
let event: FileOperationEvent | undefined;
|
||||||
disposables.add(service.onAfterOperation(e => event = e));
|
disposables.add(service.onDidRunOperation(e => event = e));
|
||||||
|
|
||||||
const parent = await service.resolve(URI.file(testDir));
|
const parent = await service.resolve(URI.file(testDir));
|
||||||
|
|
||||||
@@ -185,7 +185,7 @@ suite('Disk File Service', function () {
|
|||||||
|
|
||||||
test('createFolder: creating multiple folders at once', async () => {
|
test('createFolder: creating multiple folders at once', async () => {
|
||||||
let event: FileOperationEvent;
|
let event: FileOperationEvent;
|
||||||
disposables.add(service.onAfterOperation(e => event = e));
|
disposables.add(service.onDidRunOperation(e => event = e));
|
||||||
|
|
||||||
const multiFolderPaths = ['a', 'couple', 'of', 'folders'];
|
const multiFolderPaths = ['a', 'couple', 'of', 'folders'];
|
||||||
const parent = await service.resolve(URI.file(testDir));
|
const parent = await service.resolve(URI.file(testDir));
|
||||||
@@ -460,7 +460,7 @@ suite('Disk File Service', function () {
|
|||||||
|
|
||||||
test('deleteFile', async () => {
|
test('deleteFile', async () => {
|
||||||
let event: FileOperationEvent;
|
let event: FileOperationEvent;
|
||||||
disposables.add(service.onAfterOperation(e => event = e));
|
disposables.add(service.onDidRunOperation(e => event = e));
|
||||||
|
|
||||||
const resource = URI.file(join(testDir, 'deep', 'conway.js'));
|
const resource = URI.file(join(testDir, 'deep', 'conway.js'));
|
||||||
const source = await service.resolve(resource);
|
const source = await service.resolve(resource);
|
||||||
@@ -496,7 +496,7 @@ suite('Disk File Service', function () {
|
|||||||
const source = await service.resolve(link);
|
const source = await service.resolve(link);
|
||||||
|
|
||||||
let event: FileOperationEvent;
|
let event: FileOperationEvent;
|
||||||
disposables.add(service.onAfterOperation(e => event = e));
|
disposables.add(service.onDidRunOperation(e => event = e));
|
||||||
|
|
||||||
await service.del(source.resource);
|
await service.del(source.resource);
|
||||||
|
|
||||||
@@ -519,7 +519,7 @@ suite('Disk File Service', function () {
|
|||||||
await symlink(target.fsPath, link.fsPath);
|
await symlink(target.fsPath, link.fsPath);
|
||||||
|
|
||||||
let event: FileOperationEvent;
|
let event: FileOperationEvent;
|
||||||
disposables.add(service.onAfterOperation(e => event = e));
|
disposables.add(service.onDidRunOperation(e => event = e));
|
||||||
|
|
||||||
await service.del(link);
|
await service.del(link);
|
||||||
|
|
||||||
@@ -532,7 +532,7 @@ suite('Disk File Service', function () {
|
|||||||
|
|
||||||
test('deleteFolder (recursive)', async () => {
|
test('deleteFolder (recursive)', async () => {
|
||||||
let event: FileOperationEvent;
|
let event: FileOperationEvent;
|
||||||
disposables.add(service.onAfterOperation(e => event = e));
|
disposables.add(service.onDidRunOperation(e => event = e));
|
||||||
|
|
||||||
const resource = URI.file(join(testDir, 'deep'));
|
const resource = URI.file(join(testDir, 'deep'));
|
||||||
const source = await service.resolve(resource);
|
const source = await service.resolve(resource);
|
||||||
@@ -561,7 +561,7 @@ suite('Disk File Service', function () {
|
|||||||
|
|
||||||
test('move', async () => {
|
test('move', async () => {
|
||||||
let event: FileOperationEvent;
|
let event: FileOperationEvent;
|
||||||
disposables.add(service.onAfterOperation(e => event = e));
|
disposables.add(service.onDidRunOperation(e => event = e));
|
||||||
|
|
||||||
const source = URI.file(join(testDir, 'index.html'));
|
const source = URI.file(join(testDir, 'index.html'));
|
||||||
const sourceContents = readFileSync(source.fsPath);
|
const sourceContents = readFileSync(source.fsPath);
|
||||||
@@ -641,7 +641,7 @@ suite('Disk File Service', function () {
|
|||||||
|
|
||||||
async function testMoveAcrossProviders(sourceFile = 'index.html'): Promise<void> {
|
async function testMoveAcrossProviders(sourceFile = 'index.html'): Promise<void> {
|
||||||
let event: FileOperationEvent;
|
let event: FileOperationEvent;
|
||||||
disposables.add(service.onAfterOperation(e => event = e));
|
disposables.add(service.onDidRunOperation(e => event = e));
|
||||||
|
|
||||||
const source = URI.file(join(testDir, sourceFile));
|
const source = URI.file(join(testDir, sourceFile));
|
||||||
const sourceContents = readFileSync(source.fsPath);
|
const sourceContents = readFileSync(source.fsPath);
|
||||||
@@ -665,7 +665,7 @@ suite('Disk File Service', function () {
|
|||||||
|
|
||||||
test('move - multi folder', async () => {
|
test('move - multi folder', async () => {
|
||||||
let event: FileOperationEvent;
|
let event: FileOperationEvent;
|
||||||
disposables.add(service.onAfterOperation(e => event = e));
|
disposables.add(service.onDidRunOperation(e => event = e));
|
||||||
|
|
||||||
const multiFolderPaths = ['a', 'couple', 'of', 'folders'];
|
const multiFolderPaths = ['a', 'couple', 'of', 'folders'];
|
||||||
const renameToPath = join(...multiFolderPaths, 'other.html');
|
const renameToPath = join(...multiFolderPaths, 'other.html');
|
||||||
@@ -684,7 +684,7 @@ suite('Disk File Service', function () {
|
|||||||
|
|
||||||
test('move - directory', async () => {
|
test('move - directory', async () => {
|
||||||
let event: FileOperationEvent;
|
let event: FileOperationEvent;
|
||||||
disposables.add(service.onAfterOperation(e => event = e));
|
disposables.add(service.onDidRunOperation(e => event = e));
|
||||||
|
|
||||||
const source = URI.file(join(testDir, 'deep'));
|
const source = URI.file(join(testDir, 'deep'));
|
||||||
|
|
||||||
@@ -728,7 +728,7 @@ suite('Disk File Service', function () {
|
|||||||
|
|
||||||
async function testMoveFolderAcrossProviders(): Promise<void> {
|
async function testMoveFolderAcrossProviders(): Promise<void> {
|
||||||
let event: FileOperationEvent;
|
let event: FileOperationEvent;
|
||||||
disposables.add(service.onAfterOperation(e => event = e));
|
disposables.add(service.onDidRunOperation(e => event = e));
|
||||||
|
|
||||||
const source = URI.file(join(testDir, 'deep'));
|
const source = URI.file(join(testDir, 'deep'));
|
||||||
const sourceChildren = readdirSync(source.fsPath);
|
const sourceChildren = readdirSync(source.fsPath);
|
||||||
@@ -753,7 +753,7 @@ suite('Disk File Service', function () {
|
|||||||
|
|
||||||
test('move - MIX CASE', async () => {
|
test('move - MIX CASE', async () => {
|
||||||
let event: FileOperationEvent;
|
let event: FileOperationEvent;
|
||||||
disposables.add(service.onAfterOperation(e => event = e));
|
disposables.add(service.onDidRunOperation(e => event = e));
|
||||||
|
|
||||||
const source = await service.resolve(URI.file(join(testDir, 'index.html')), { resolveMetadata: true });
|
const source = await service.resolve(URI.file(join(testDir, 'index.html')), { resolveMetadata: true });
|
||||||
assert.ok(source.size > 0);
|
assert.ok(source.size > 0);
|
||||||
@@ -774,7 +774,7 @@ suite('Disk File Service', function () {
|
|||||||
|
|
||||||
test('move - same file', async () => {
|
test('move - same file', async () => {
|
||||||
let event: FileOperationEvent;
|
let event: FileOperationEvent;
|
||||||
disposables.add(service.onAfterOperation(e => event = e));
|
disposables.add(service.onDidRunOperation(e => event = e));
|
||||||
|
|
||||||
const source = await service.resolve(URI.file(join(testDir, 'index.html')), { resolveMetadata: true });
|
const source = await service.resolve(URI.file(join(testDir, 'index.html')), { resolveMetadata: true });
|
||||||
assert.ok(source.size > 0);
|
assert.ok(source.size > 0);
|
||||||
@@ -794,7 +794,7 @@ suite('Disk File Service', function () {
|
|||||||
|
|
||||||
test('move - same file #2', async () => {
|
test('move - same file #2', async () => {
|
||||||
let event: FileOperationEvent;
|
let event: FileOperationEvent;
|
||||||
disposables.add(service.onAfterOperation(e => event = e));
|
disposables.add(service.onDidRunOperation(e => event = e));
|
||||||
|
|
||||||
const source = await service.resolve(URI.file(join(testDir, 'index.html')), { resolveMetadata: true });
|
const source = await service.resolve(URI.file(join(testDir, 'index.html')), { resolveMetadata: true });
|
||||||
assert.ok(source.size > 0);
|
assert.ok(source.size > 0);
|
||||||
@@ -817,7 +817,7 @@ suite('Disk File Service', function () {
|
|||||||
|
|
||||||
test('move - source parent of target', async () => {
|
test('move - source parent of target', async () => {
|
||||||
let event: FileOperationEvent;
|
let event: FileOperationEvent;
|
||||||
disposables.add(service.onAfterOperation(e => event = e));
|
disposables.add(service.onDidRunOperation(e => event = e));
|
||||||
|
|
||||||
let source = await service.resolve(URI.file(join(testDir, 'index.html')), { resolveMetadata: true });
|
let source = await service.resolve(URI.file(join(testDir, 'index.html')), { resolveMetadata: true });
|
||||||
const originalSize = source.size;
|
const originalSize = source.size;
|
||||||
@@ -839,7 +839,7 @@ suite('Disk File Service', function () {
|
|||||||
|
|
||||||
test('move - FILE_MOVE_CONFLICT', async () => {
|
test('move - FILE_MOVE_CONFLICT', async () => {
|
||||||
let event: FileOperationEvent;
|
let event: FileOperationEvent;
|
||||||
disposables.add(service.onAfterOperation(e => event = e));
|
disposables.add(service.onDidRunOperation(e => event = e));
|
||||||
|
|
||||||
let source = await service.resolve(URI.file(join(testDir, 'index.html')), { resolveMetadata: true });
|
let source = await service.resolve(URI.file(join(testDir, 'index.html')), { resolveMetadata: true });
|
||||||
const originalSize = source.size;
|
const originalSize = source.size;
|
||||||
@@ -863,7 +863,7 @@ suite('Disk File Service', function () {
|
|||||||
let createEvent: FileOperationEvent;
|
let createEvent: FileOperationEvent;
|
||||||
let moveEvent: FileOperationEvent;
|
let moveEvent: FileOperationEvent;
|
||||||
let deleteEvent: FileOperationEvent;
|
let deleteEvent: FileOperationEvent;
|
||||||
disposables.add(service.onAfterOperation(e => {
|
disposables.add(service.onDidRunOperation(e => {
|
||||||
if (e.operation === FileOperation.CREATE) {
|
if (e.operation === FileOperation.CREATE) {
|
||||||
createEvent = e;
|
createEvent = e;
|
||||||
} else if (e.operation === FileOperation.DELETE) {
|
} else if (e.operation === FileOperation.DELETE) {
|
||||||
@@ -927,7 +927,7 @@ suite('Disk File Service', function () {
|
|||||||
|
|
||||||
async function doTestCopy(sourceName: string = 'index.html') {
|
async function doTestCopy(sourceName: string = 'index.html') {
|
||||||
let event: FileOperationEvent;
|
let event: FileOperationEvent;
|
||||||
disposables.add(service.onAfterOperation(e => event = e));
|
disposables.add(service.onDidRunOperation(e => event = e));
|
||||||
|
|
||||||
const source = await service.resolve(URI.file(join(testDir, sourceName)));
|
const source = await service.resolve(URI.file(join(testDir, sourceName)));
|
||||||
const target = URI.file(join(testDir, 'other.html'));
|
const target = URI.file(join(testDir, 'other.html'));
|
||||||
@@ -952,7 +952,7 @@ suite('Disk File Service', function () {
|
|||||||
let createEvent: FileOperationEvent;
|
let createEvent: FileOperationEvent;
|
||||||
let copyEvent: FileOperationEvent;
|
let copyEvent: FileOperationEvent;
|
||||||
let deleteEvent: FileOperationEvent;
|
let deleteEvent: FileOperationEvent;
|
||||||
disposables.add(service.onAfterOperation(e => {
|
disposables.add(service.onDidRunOperation(e => {
|
||||||
if (e.operation === FileOperation.CREATE) {
|
if (e.operation === FileOperation.CREATE) {
|
||||||
createEvent = e;
|
createEvent = e;
|
||||||
} else if (e.operation === FileOperation.DELETE) {
|
} else if (e.operation === FileOperation.DELETE) {
|
||||||
@@ -1057,7 +1057,7 @@ suite('Disk File Service', function () {
|
|||||||
|
|
||||||
test('copy - same file', async () => {
|
test('copy - same file', async () => {
|
||||||
let event: FileOperationEvent;
|
let event: FileOperationEvent;
|
||||||
disposables.add(service.onAfterOperation(e => event = e));
|
disposables.add(service.onDidRunOperation(e => event = e));
|
||||||
|
|
||||||
const source = await service.resolve(URI.file(join(testDir, 'index.html')), { resolveMetadata: true });
|
const source = await service.resolve(URI.file(join(testDir, 'index.html')), { resolveMetadata: true });
|
||||||
assert.ok(source.size > 0);
|
assert.ok(source.size > 0);
|
||||||
@@ -1077,7 +1077,7 @@ suite('Disk File Service', function () {
|
|||||||
|
|
||||||
test('copy - same file #2', async () => {
|
test('copy - same file #2', async () => {
|
||||||
let event: FileOperationEvent;
|
let event: FileOperationEvent;
|
||||||
disposables.add(service.onAfterOperation(e => event = e));
|
disposables.add(service.onDidRunOperation(e => event = e));
|
||||||
|
|
||||||
const source = await service.resolve(URI.file(join(testDir, 'index.html')), { resolveMetadata: true });
|
const source = await service.resolve(URI.file(join(testDir, 'index.html')), { resolveMetadata: true });
|
||||||
assert.ok(source.size > 0);
|
assert.ok(source.size > 0);
|
||||||
@@ -1567,7 +1567,7 @@ suite('Disk File Service', function () {
|
|||||||
|
|
||||||
async function assertCreateFile(converter: (content: string) => VSBuffer | VSBufferReadable | VSBufferReadableStream): Promise<void> {
|
async function assertCreateFile(converter: (content: string) => VSBuffer | VSBufferReadable | VSBufferReadableStream): Promise<void> {
|
||||||
let event: FileOperationEvent;
|
let event: FileOperationEvent;
|
||||||
disposables.add(service.onAfterOperation(e => event = e));
|
disposables.add(service.onDidRunOperation(e => event = e));
|
||||||
|
|
||||||
const contents = 'Hello World';
|
const contents = 'Hello World';
|
||||||
const resource = URI.file(join(testDir, 'test.txt'));
|
const resource = URI.file(join(testDir, 'test.txt'));
|
||||||
@@ -1600,7 +1600,7 @@ suite('Disk File Service', function () {
|
|||||||
|
|
||||||
test('createFile (allows to overwrite existing)', async () => {
|
test('createFile (allows to overwrite existing)', async () => {
|
||||||
let event: FileOperationEvent;
|
let event: FileOperationEvent;
|
||||||
disposables.add(service.onAfterOperation(e => event = e));
|
disposables.add(service.onDidRunOperation(e => event = e));
|
||||||
|
|
||||||
const contents = 'Hello World';
|
const contents = 'Hello World';
|
||||||
const resource = URI.file(join(testDir, 'test.txt'));
|
const resource = URI.file(join(testDir, 'test.txt'));
|
||||||
@@ -2152,7 +2152,7 @@ suite('Disk File Service', function () {
|
|||||||
return event.changes.map(change => `Change: type ${toString(change.type)} path ${change.resource.toString()}`).join('\n');
|
return event.changes.map(change => `Change: type ${toString(change.type)} path ${change.resource.toString()}`).join('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
const listenerDisposable = service.onFileChanges(event => {
|
const listenerDisposable = service.onDidFilesChange(event => {
|
||||||
watcherDisposable.dispose();
|
watcherDisposable.dispose();
|
||||||
listenerDisposable.dispose();
|
listenerDisposable.dispose();
|
||||||
|
|
||||||
|
|||||||
@@ -15,14 +15,14 @@ function toFileChangesEvent(changes: IDiskFileChange[]): FileChangesEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class TestFileWatcher {
|
class TestFileWatcher {
|
||||||
private readonly _onFileChanges: Emitter<FileChangesEvent>;
|
private readonly _onDidFilesChange: Emitter<FileChangesEvent>;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this._onFileChanges = new Emitter<FileChangesEvent>();
|
this._onDidFilesChange = new Emitter<FileChangesEvent>();
|
||||||
}
|
}
|
||||||
|
|
||||||
get onFileChanges(): Event<FileChangesEvent> {
|
get onDidFilesChange(): Event<FileChangesEvent> {
|
||||||
return this._onFileChanges.event;
|
return this._onDidFilesChange.event;
|
||||||
}
|
}
|
||||||
|
|
||||||
report(changes: IDiskFileChange[]): void {
|
report(changes: IDiskFileChange[]): void {
|
||||||
@@ -36,7 +36,7 @@ class TestFileWatcher {
|
|||||||
|
|
||||||
// Emit through event emitter
|
// Emit through event emitter
|
||||||
if (normalizedEvents.length > 0) {
|
if (normalizedEvents.length > 0) {
|
||||||
this._onFileChanges.fire(toFileChangesEvent(normalizedEvents));
|
this._onDidFilesChange.fire(toFileChangesEvent(normalizedEvents));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -62,7 +62,7 @@ suite('Normalizer', () => {
|
|||||||
{ path: deleted.fsPath, type: FileChangeType.DELETED },
|
{ path: deleted.fsPath, type: FileChangeType.DELETED },
|
||||||
];
|
];
|
||||||
|
|
||||||
watch.onFileChanges(e => {
|
watch.onDidFilesChange(e => {
|
||||||
assert.ok(e);
|
assert.ok(e);
|
||||||
assert.equal(e.changes.length, 3);
|
assert.equal(e.changes.length, 3);
|
||||||
assert.ok(e.contains(added, FileChangeType.ADDED));
|
assert.ok(e.contains(added, FileChangeType.ADDED));
|
||||||
@@ -101,7 +101,7 @@ suite('Normalizer', () => {
|
|||||||
{ path: updatedFile.fsPath, type: FileChangeType.UPDATED }
|
{ path: updatedFile.fsPath, type: FileChangeType.UPDATED }
|
||||||
];
|
];
|
||||||
|
|
||||||
watch.onFileChanges(e => {
|
watch.onDidFilesChange(e => {
|
||||||
assert.ok(e);
|
assert.ok(e);
|
||||||
assert.equal(e.changes.length, 5);
|
assert.equal(e.changes.length, 5);
|
||||||
|
|
||||||
@@ -131,7 +131,7 @@ suite('Normalizer', () => {
|
|||||||
{ path: unrelated.fsPath, type: FileChangeType.UPDATED },
|
{ path: unrelated.fsPath, type: FileChangeType.UPDATED },
|
||||||
];
|
];
|
||||||
|
|
||||||
watch.onFileChanges(e => {
|
watch.onDidFilesChange(e => {
|
||||||
assert.ok(e);
|
assert.ok(e);
|
||||||
assert.equal(e.changes.length, 1);
|
assert.equal(e.changes.length, 1);
|
||||||
|
|
||||||
@@ -156,7 +156,7 @@ suite('Normalizer', () => {
|
|||||||
{ path: unrelated.fsPath, type: FileChangeType.UPDATED },
|
{ path: unrelated.fsPath, type: FileChangeType.UPDATED },
|
||||||
];
|
];
|
||||||
|
|
||||||
watch.onFileChanges(e => {
|
watch.onDidFilesChange(e => {
|
||||||
assert.ok(e);
|
assert.ok(e);
|
||||||
assert.equal(e.changes.length, 2);
|
assert.equal(e.changes.length, 2);
|
||||||
|
|
||||||
@@ -182,7 +182,7 @@ suite('Normalizer', () => {
|
|||||||
{ path: unrelated.fsPath, type: FileChangeType.UPDATED },
|
{ path: unrelated.fsPath, type: FileChangeType.UPDATED },
|
||||||
];
|
];
|
||||||
|
|
||||||
watch.onFileChanges(e => {
|
watch.onDidFilesChange(e => {
|
||||||
assert.ok(e);
|
assert.ok(e);
|
||||||
assert.equal(e.changes.length, 2);
|
assert.equal(e.changes.length, 2);
|
||||||
|
|
||||||
@@ -211,7 +211,7 @@ suite('Normalizer', () => {
|
|||||||
{ path: updated.fsPath, type: FileChangeType.DELETED }
|
{ path: updated.fsPath, type: FileChangeType.DELETED }
|
||||||
];
|
];
|
||||||
|
|
||||||
watch.onFileChanges(e => {
|
watch.onDidFilesChange(e => {
|
||||||
assert.ok(e);
|
assert.ok(e);
|
||||||
assert.equal(e.changes.length, 2);
|
assert.equal(e.changes.length, 2);
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ interface IServiceMock<T> {
|
|||||||
service: any;
|
service: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isSinonSpyLike = (fn: Function): fn is sinon.SinonSpy => fn && 'callCount' in fn;
|
||||||
|
|
||||||
export class TestInstantiationService extends InstantiationService {
|
export class TestInstantiationService extends InstantiationService {
|
||||||
|
|
||||||
private _servciesMap: Map<ServiceIdentifier<any>, any>;
|
private _servciesMap: Map<ServiceIdentifier<any>, any>;
|
||||||
@@ -37,10 +39,10 @@ export class TestInstantiationService extends InstantiationService {
|
|||||||
|
|
||||||
public stub<T>(service: ServiceIdentifier<T>, ctor: Function): T;
|
public stub<T>(service: ServiceIdentifier<T>, ctor: Function): T;
|
||||||
public stub<T>(service: ServiceIdentifier<T>, obj: Partial<T>): T;
|
public stub<T>(service: ServiceIdentifier<T>, obj: Partial<T>): T;
|
||||||
public stub<T>(service: ServiceIdentifier<T>, ctor: Function, property: string, value: any): sinon.SinonStub;
|
public stub<T, V>(service: ServiceIdentifier<T>, ctor: Function, property: string, value: V): V extends Function ? sinon.SinonSpy : sinon.SinonStub;
|
||||||
public stub<T>(service: ServiceIdentifier<T>, obj: Partial<T>, property: string, value: any): sinon.SinonStub;
|
public stub<T, V>(service: ServiceIdentifier<T>, obj: Partial<T>, property: string, value: V): V extends Function ? sinon.SinonSpy : sinon.SinonStub;
|
||||||
public stub<T>(service: ServiceIdentifier<T>, property: string, value: any): sinon.SinonStub;
|
public stub<T, V>(service: ServiceIdentifier<T>, property: string, value: V): V extends Function ? sinon.SinonSpy : sinon.SinonStub;
|
||||||
public stub<T>(serviceIdentifier: ServiceIdentifier<T>, arg2: any, arg3?: string, arg4?: any): sinon.SinonStub {
|
public stub<T>(serviceIdentifier: ServiceIdentifier<T>, arg2: any, arg3?: string, arg4?: any): sinon.SinonStub | sinon.SinonSpy {
|
||||||
let service = typeof arg2 !== 'string' ? arg2 : undefined;
|
let service = typeof arg2 !== 'string' ? arg2 : undefined;
|
||||||
let serviceMock: IServiceMock<any> = { id: serviceIdentifier, service: service };
|
let serviceMock: IServiceMock<any> = { id: serviceIdentifier, service: service };
|
||||||
let property = typeof arg2 === 'string' ? arg2 : arg3;
|
let property = typeof arg2 === 'string' ? arg2 : arg3;
|
||||||
@@ -53,9 +55,11 @@ export class TestInstantiationService extends InstantiationService {
|
|||||||
stubObject[property].restore();
|
stubObject[property].restore();
|
||||||
}
|
}
|
||||||
if (typeof value === 'function') {
|
if (typeof value === 'function') {
|
||||||
stubObject[property] = value;
|
const spy = isSinonSpyLike(value) ? value : sinon.spy(value);
|
||||||
|
stubObject[property] = spy;
|
||||||
|
return spy;
|
||||||
} else {
|
} else {
|
||||||
let stub = value ? sinon.stub().returns(value) : sinon.stub();
|
const stub = value ? sinon.stub().returns(value) : sinon.stub();
|
||||||
stubObject[property] = stub;
|
stubObject[property] = stub;
|
||||||
return stub;
|
return stub;
|
||||||
}
|
}
|
||||||
@@ -67,9 +71,9 @@ export class TestInstantiationService extends InstantiationService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public stubPromise<T>(service?: ServiceIdentifier<T>, fnProperty?: string, value?: any): T | sinon.SinonStub;
|
public stubPromise<T>(service?: ServiceIdentifier<T>, fnProperty?: string, value?: any): T | sinon.SinonStub;
|
||||||
public stubPromise<T>(service?: ServiceIdentifier<T>, ctor?: any, fnProperty?: string, value?: any): sinon.SinonStub;
|
public stubPromise<T, V>(service?: ServiceIdentifier<T>, ctor?: any, fnProperty?: string, value?: V): V extends Function ? sinon.SinonSpy : sinon.SinonStub;
|
||||||
public stubPromise<T>(service?: ServiceIdentifier<T>, obj?: any, fnProperty?: string, value?: any): sinon.SinonStub;
|
public stubPromise<T, V>(service?: ServiceIdentifier<T>, obj?: any, fnProperty?: string, value?: V): V extends Function ? sinon.SinonSpy : sinon.SinonStub;
|
||||||
public stubPromise(arg1?: any, arg2?: any, arg3?: any, arg4?: any): sinon.SinonStub {
|
public stubPromise(arg1?: any, arg2?: any, arg3?: any, arg4?: any): sinon.SinonStub | sinon.SinonSpy {
|
||||||
arg3 = typeof arg2 === 'string' ? Promise.resolve(arg3) : arg3;
|
arg3 = typeof arg2 === 'string' ? Promise.resolve(arg3) : arg3;
|
||||||
arg4 = typeof arg2 !== 'string' && typeof arg3 === 'string' ? Promise.resolve(arg4) : arg4;
|
arg4 = typeof arg2 !== 'string' && typeof arg3 === 'string' ? Promise.resolve(arg4) : arg4;
|
||||||
return this.stub(arg1, arg2, arg3, arg4);
|
return this.stub(arg1, arg2, arg3, arg4);
|
||||||
|
|||||||
@@ -135,15 +135,15 @@ export namespace IMarkerData {
|
|||||||
export function makeKeyOptionalMessage(markerData: IMarkerData, useMessage: boolean): string {
|
export function makeKeyOptionalMessage(markerData: IMarkerData, useMessage: boolean): string {
|
||||||
let result: string[] = [emptyString];
|
let result: string[] = [emptyString];
|
||||||
if (markerData.source) {
|
if (markerData.source) {
|
||||||
result.push(markerData.source.replace('¦', '\¦'));
|
result.push(markerData.source.replace('¦', '\\¦'));
|
||||||
} else {
|
} else {
|
||||||
result.push(emptyString);
|
result.push(emptyString);
|
||||||
}
|
}
|
||||||
if (markerData.code) {
|
if (markerData.code) {
|
||||||
if (typeof markerData.code === 'string') {
|
if (typeof markerData.code === 'string') {
|
||||||
result.push(markerData.code.replace('¦', '\¦'));
|
result.push(markerData.code.replace('¦', '\\¦'));
|
||||||
} else {
|
} else {
|
||||||
result.push(markerData.code.value.replace('¦', '\¦'));
|
result.push(markerData.code.value.replace('¦', '\\¦'));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
result.push(emptyString);
|
result.push(emptyString);
|
||||||
@@ -157,7 +157,7 @@ export namespace IMarkerData {
|
|||||||
// Modifed to not include the message as part of the marker key to work around
|
// Modifed to not include the message as part of the marker key to work around
|
||||||
// https://github.com/microsoft/vscode/issues/77475
|
// https://github.com/microsoft/vscode/issues/77475
|
||||||
if (markerData.message && useMessage) {
|
if (markerData.message && useMessage) {
|
||||||
result.push(markerData.message.replace('¦', '\¦'));
|
result.push(markerData.message.replace('¦', '\\¦'));
|
||||||
} else {
|
} else {
|
||||||
result.push(emptyString);
|
result.push(emptyString);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
import BaseSeverity from 'vs/base/common/severity';
|
import BaseSeverity from 'vs/base/common/severity';
|
||||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||||
import { IAction } from 'vs/base/common/actions';
|
import { IAction } from 'vs/base/common/actions';
|
||||||
import { Event, Emitter } from 'vs/base/common/event';
|
import { Event } from 'vs/base/common/event';
|
||||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||||
|
|
||||||
export import Severity = BaseSeverity;
|
export import Severity = BaseSeverity;
|
||||||
@@ -318,16 +318,14 @@ export class NoOpNotification implements INotificationHandle {
|
|||||||
|
|
||||||
readonly progress = new NoOpProgress();
|
readonly progress = new NoOpProgress();
|
||||||
|
|
||||||
private readonly _onDidClose: Emitter<void> = new Emitter();
|
readonly onDidClose = Event.None;
|
||||||
readonly onDidClose: Event<void> = this._onDidClose.event;
|
readonly onDidChangeVisibility = Event.None;
|
||||||
|
|
||||||
updateSeverity(severity: Severity): void { }
|
updateSeverity(severity: Severity): void { }
|
||||||
updateMessage(message: NotificationMessage): void { }
|
updateMessage(message: NotificationMessage): void { }
|
||||||
updateActions(actions?: INotificationActions): void { }
|
updateActions(actions?: INotificationActions): void { }
|
||||||
|
|
||||||
close(): void {
|
close(): void { }
|
||||||
this._onDidClose.dispose();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class NoOpProgress implements INotificationProgress {
|
export class NoOpProgress implements INotificationProgress {
|
||||||
|
|||||||
@@ -17,7 +17,11 @@ export interface IProgressService {
|
|||||||
|
|
||||||
_serviceBrand: undefined;
|
_serviceBrand: undefined;
|
||||||
|
|
||||||
withProgress<R = any>(options: IProgressOptions | IProgressNotificationOptions | IProgressWindowOptions | IProgressCompositeOptions, task: (progress: IProgress<IProgressStep>) => Promise<R>, onDidCancel?: (choice?: number) => void): Promise<R>;
|
withProgress<R = any>(
|
||||||
|
options: IProgressOptions | IProgressNotificationOptions | IProgressWindowOptions | IProgressCompositeOptions,
|
||||||
|
task: (progress: IProgress<IProgressStep>) => Promise<R>,
|
||||||
|
onDidCancel?: (choice?: number) => void
|
||||||
|
): Promise<R>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IProgressIndicator {
|
export interface IProgressIndicator {
|
||||||
@@ -45,19 +49,19 @@ export const enum ProgressLocation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface IProgressOptions {
|
export interface IProgressOptions {
|
||||||
location: ProgressLocation | string;
|
readonly location: ProgressLocation | string;
|
||||||
title?: string;
|
readonly title?: string;
|
||||||
source?: string;
|
readonly source?: string;
|
||||||
total?: number;
|
readonly total?: number;
|
||||||
cancellable?: boolean;
|
readonly cancellable?: boolean;
|
||||||
buttons?: string[];
|
readonly buttons?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IProgressNotificationOptions extends IProgressOptions {
|
export interface IProgressNotificationOptions extends IProgressOptions {
|
||||||
readonly location: ProgressLocation.Notification;
|
readonly location: ProgressLocation.Notification;
|
||||||
readonly primaryActions?: ReadonlyArray<IAction>;
|
readonly primaryActions?: ReadonlyArray<IAction>;
|
||||||
readonly secondaryActions?: ReadonlyArray<IAction>;
|
readonly secondaryActions?: ReadonlyArray<IAction>;
|
||||||
delay?: number;
|
readonly delay?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IProgressWindowOptions extends IProgressOptions {
|
export interface IProgressWindowOptions extends IProgressOptions {
|
||||||
@@ -66,8 +70,8 @@ export interface IProgressWindowOptions extends IProgressOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface IProgressCompositeOptions extends IProgressOptions {
|
export interface IProgressCompositeOptions extends IProgressOptions {
|
||||||
location: ProgressLocation.Explorer | ProgressLocation.Extensions | ProgressLocation.Scm | string;
|
readonly location: ProgressLocation.Explorer | ProgressLocation.Extensions | ProgressLocation.Scm | string;
|
||||||
delay?: number;
|
readonly delay?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IProgressStep {
|
export interface IProgressStep {
|
||||||
@@ -96,20 +100,14 @@ export interface IProgress<T> {
|
|||||||
|
|
||||||
export class Progress<T> implements IProgress<T> {
|
export class Progress<T> implements IProgress<T> {
|
||||||
|
|
||||||
private _callback: (data: T) => void;
|
|
||||||
private _value?: T;
|
private _value?: T;
|
||||||
|
get value(): T | undefined { return this._value; }
|
||||||
|
|
||||||
constructor(callback: (data: T) => void) {
|
constructor(private callback: (data: T) => void) { }
|
||||||
this._callback = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
get value(): T | undefined {
|
|
||||||
return this._value;
|
|
||||||
}
|
|
||||||
|
|
||||||
report(item: T) {
|
report(item: T) {
|
||||||
this._value = item;
|
this._value = item;
|
||||||
this._callback(this._value);
|
this.callback(this._value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -224,7 +224,7 @@ export class FileStorageDatabase extends Disposable implements IStorageDatabase
|
|||||||
this.isWatching = true;
|
this.isWatching = true;
|
||||||
|
|
||||||
this._register(this.fileService.watch(this.file));
|
this._register(this.fileService.watch(this.file));
|
||||||
this._register(this.fileService.onFileChanges(e => {
|
this._register(this.fileService.onDidFilesChange(e => {
|
||||||
if (document.hasFocus()) {
|
if (document.hasFocus()) {
|
||||||
return; // optimization: ignore changes from ourselves by checking for focus
|
return; // optimization: ignore changes from ourselves by checking for focus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -428,6 +428,10 @@ export const minimapError = registerColor('minimap.errorHighlight', { dark: new
|
|||||||
export const minimapWarning = registerColor('minimap.warningHighlight', { dark: editorWarningForeground, light: editorWarningForeground, hc: editorWarningBorder }, nls.localize('overviewRuleWarning', 'Minimap marker color for warnings.'));
|
export const minimapWarning = registerColor('minimap.warningHighlight', { dark: editorWarningForeground, light: editorWarningForeground, hc: editorWarningBorder }, nls.localize('overviewRuleWarning', 'Minimap marker color for warnings.'));
|
||||||
export const minimapBackground = registerColor('minimap.background', { dark: null, light: null, hc: null }, nls.localize('minimapBackground', "Minimap background color."));
|
export const minimapBackground = registerColor('minimap.background', { dark: null, light: null, hc: null }, nls.localize('minimapBackground', "Minimap background color."));
|
||||||
|
|
||||||
|
export const minimapSliderBackground = registerColor('minimapSlider.background', { light: transparent(scrollbarSliderBackground, 0.5), dark: transparent(scrollbarSliderBackground, 0.5), hc: transparent(scrollbarSliderBackground, 0.5) }, nls.localize('minimapSliderBackground', "Minimap slider background color."));
|
||||||
|
export const minimapSliderHoverBackground = registerColor('minimapSlider.hoverBackground', { light: transparent(scrollbarSliderHoverBackground, 0.5), dark: transparent(scrollbarSliderHoverBackground, 0.5), hc: transparent(scrollbarSliderHoverBackground, 0.5) }, nls.localize('minimapSliderHoverBackground', "Minimap slider background color when hovering."));
|
||||||
|
export const minimapSliderActiveBackground = registerColor('minimapSlider.activeBackground', { light: transparent(scrollbarSliderActiveBackground, 0.5), dark: transparent(scrollbarSliderActiveBackground, 0.5), hc: transparent(scrollbarSliderActiveBackground, 0.5) }, nls.localize('minimapSliderActiveBackground', "Minimap slider background color when clicked on."));
|
||||||
|
|
||||||
export const problemsErrorIconForeground = registerColor('problemsErrorIcon.foreground', { dark: editorErrorForeground, light: editorErrorForeground, hc: editorErrorForeground }, nls.localize('problemsErrorIconForeground', "The color used for the problems error icon."));
|
export const problemsErrorIconForeground = registerColor('problemsErrorIcon.foreground', { dark: editorErrorForeground, light: editorErrorForeground, hc: editorErrorForeground }, nls.localize('problemsErrorIconForeground', "The color used for the problems error icon."));
|
||||||
export const problemsWarningIconForeground = registerColor('problemsWarningIcon.foreground', { dark: editorWarningForeground, light: editorWarningForeground, hc: editorWarningForeground }, nls.localize('problemsWarningIconForeground', "The color used for the problems warning icon."));
|
export const problemsWarningIconForeground = registerColor('problemsWarningIcon.foreground', { dark: editorWarningForeground, light: editorWarningForeground, hc: editorWarningForeground }, nls.localize('problemsWarningIconForeground', "The color used for the problems warning icon."));
|
||||||
export const problemsInfoIconForeground = registerColor('problemsInfoIcon.foreground', { dark: editorInfoForeground, light: editorInfoForeground, hc: editorInfoForeground }, nls.localize('problemsInfoIconForeground', "The color used for the problems info icon."));
|
export const problemsInfoIconForeground = registerColor('problemsInfoIcon.foreground', { dark: editorInfoForeground, light: editorInfoForeground, hc: editorInfoForeground }, nls.localize('problemsInfoIconForeground', "The color used for the problems info icon."));
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||||
|
import { URI } from 'vs/base/common/uri';
|
||||||
|
|
||||||
|
export const IUndoRedoService = createDecorator<IUndoRedoService>('undoRedoService');
|
||||||
|
|
||||||
|
export interface IUndoRedoContext {
|
||||||
|
replaceCurrentElement(others: IUndoRedoElement[]): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IUndoRedoElement {
|
||||||
|
/**
|
||||||
|
* None, one or multiple resources that this undo/redo element impacts.
|
||||||
|
*/
|
||||||
|
readonly resources: URI[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The label of the undo/redo element.
|
||||||
|
*/
|
||||||
|
readonly label: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Undo.
|
||||||
|
* Will always be called before `redo`.
|
||||||
|
* Can be called multiple times.
|
||||||
|
* e.g. `undo` -> `redo` -> `undo` -> `redo`
|
||||||
|
*/
|
||||||
|
undo(ctx: IUndoRedoContext): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redo.
|
||||||
|
* Will always be called after `undo`.
|
||||||
|
* Can be called multiple times.
|
||||||
|
* e.g. `undo` -> `redo` -> `undo` -> `redo`
|
||||||
|
*/
|
||||||
|
redo(ctx: IUndoRedoContext): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalidate the edits concerning `resource`.
|
||||||
|
* i.e. the undo/redo stack for that particular resource has been destroyed.
|
||||||
|
*/
|
||||||
|
invalidate(resource: URI): boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IUndoRedoService {
|
||||||
|
_serviceBrand: undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new element to the `undo` stack.
|
||||||
|
* This will destroy the `redo` stack.
|
||||||
|
*/
|
||||||
|
pushElement(element: IUndoRedoElement): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the last pushed element. If the last pushed element has been undone, returns null.
|
||||||
|
*/
|
||||||
|
getLastElement(resource: URI): IUndoRedoElement | null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove elements that target `resource`.
|
||||||
|
*/
|
||||||
|
removeElements(resource: URI): void;
|
||||||
|
|
||||||
|
canUndo(resource: URI): boolean;
|
||||||
|
undo(resource: URI): void;
|
||||||
|
|
||||||
|
redo(resource: URI): void;
|
||||||
|
canRedo(resource: URI): boolean;
|
||||||
|
}
|
||||||
@@ -0,0 +1,241 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import { IUndoRedoService, IUndoRedoElement } from 'vs/platform/undoRedo/common/undoRedo';
|
||||||
|
import { URI } from 'vs/base/common/uri';
|
||||||
|
import { getComparisonKey as uriGetComparisonKey } from 'vs/base/common/resources';
|
||||||
|
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||||
|
|
||||||
|
class StackElement {
|
||||||
|
public readonly actual: IUndoRedoElement;
|
||||||
|
public readonly label: string;
|
||||||
|
public readonly resources: URI[];
|
||||||
|
public readonly strResources: string[];
|
||||||
|
|
||||||
|
constructor(actual: IUndoRedoElement) {
|
||||||
|
this.actual = actual;
|
||||||
|
this.label = actual.label;
|
||||||
|
this.resources = actual.resources;
|
||||||
|
this.strResources = this.resources.map(resource => uriGetComparisonKey(resource));
|
||||||
|
}
|
||||||
|
|
||||||
|
public invalidate(resource: URI): void {
|
||||||
|
if (this.resources.length > 1) {
|
||||||
|
this.actual.invalidate(resource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ResourceEditStack {
|
||||||
|
public resource: URI;
|
||||||
|
public past: StackElement[];
|
||||||
|
public future: StackElement[];
|
||||||
|
|
||||||
|
constructor(resource: URI) {
|
||||||
|
this.resource = resource;
|
||||||
|
this.past = [];
|
||||||
|
this.future = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class UndoRedoService implements IUndoRedoService {
|
||||||
|
_serviceBrand: undefined;
|
||||||
|
|
||||||
|
private readonly _editStacks: Map<string, ResourceEditStack>;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this._editStacks = new Map<string, ResourceEditStack>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public pushElement(_element: IUndoRedoElement): void {
|
||||||
|
const element = new StackElement(_element);
|
||||||
|
for (let i = 0, len = element.resources.length; i < len; i++) {
|
||||||
|
const resource = element.resources[i];
|
||||||
|
const strResource = element.strResources[i];
|
||||||
|
|
||||||
|
let editStack: ResourceEditStack;
|
||||||
|
if (this._editStacks.has(strResource)) {
|
||||||
|
editStack = this._editStacks.get(strResource)!;
|
||||||
|
} else {
|
||||||
|
editStack = new ResourceEditStack(resource);
|
||||||
|
this._editStacks.set(strResource, editStack);
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove the future
|
||||||
|
for (const futureElement of editStack.future) {
|
||||||
|
futureElement.invalidate(resource);
|
||||||
|
}
|
||||||
|
editStack.future = [];
|
||||||
|
editStack.past.push(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public getLastElement(resource: URI): IUndoRedoElement | null {
|
||||||
|
const strResource = uriGetComparisonKey(resource);
|
||||||
|
if (this._editStacks.has(strResource)) {
|
||||||
|
const editStack = this._editStacks.get(strResource)!;
|
||||||
|
if (editStack.future.length > 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (editStack.past.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return editStack.past[editStack.past.length - 1].actual;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public removeElements(resource: URI): void {
|
||||||
|
const strResource = uriGetComparisonKey(resource);
|
||||||
|
if (this._editStacks.has(strResource)) {
|
||||||
|
const editStack = this._editStacks.get(strResource)!;
|
||||||
|
for (const pastElement of editStack.past) {
|
||||||
|
pastElement.invalidate(resource);
|
||||||
|
}
|
||||||
|
for (const futureElement of editStack.future) {
|
||||||
|
futureElement.invalidate(resource);
|
||||||
|
}
|
||||||
|
this._editStacks.delete(strResource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public canUndo(resource: URI): boolean {
|
||||||
|
const strResource = uriGetComparisonKey(resource);
|
||||||
|
if (this._editStacks.has(strResource)) {
|
||||||
|
const editStack = this._editStacks.get(strResource)!;
|
||||||
|
return (editStack.past.length > 0);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public undo(resource: URI): void {
|
||||||
|
const strResource = uriGetComparisonKey(resource);
|
||||||
|
if (!this._editStacks.has(strResource)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const editStack = this._editStacks.get(strResource)!;
|
||||||
|
if (editStack.past.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const element = editStack.past[editStack.past.length - 1];
|
||||||
|
|
||||||
|
let replaceCurrentElement: IUndoRedoElement[] | null = null as IUndoRedoElement[] | null;
|
||||||
|
try {
|
||||||
|
element.actual.undo({
|
||||||
|
replaceCurrentElement: (others: IUndoRedoElement[]): void => {
|
||||||
|
replaceCurrentElement = others;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
onUnexpectedError(e);
|
||||||
|
editStack.past.pop();
|
||||||
|
editStack.future.push(element);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (replaceCurrentElement === null) {
|
||||||
|
// regular case
|
||||||
|
editStack.past.pop();
|
||||||
|
editStack.future.push(element);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const replaceCurrentElementMap = new Map<string, StackElement>();
|
||||||
|
for (const _replace of replaceCurrentElement) {
|
||||||
|
const replace = new StackElement(_replace);
|
||||||
|
for (const strResource of replace.strResources) {
|
||||||
|
replaceCurrentElementMap.set(strResource, replace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0, len = element.strResources.length; i < len; i++) {
|
||||||
|
const strResource = element.strResources[i];
|
||||||
|
if (this._editStacks.has(strResource)) {
|
||||||
|
const editStack = this._editStacks.get(strResource)!;
|
||||||
|
for (let j = editStack.past.length - 1; j >= 0; j--) {
|
||||||
|
if (editStack.past[j] === element) {
|
||||||
|
if (replaceCurrentElementMap.has(strResource)) {
|
||||||
|
editStack.past[j] = replaceCurrentElementMap.get(strResource)!;
|
||||||
|
} else {
|
||||||
|
editStack.past.splice(j, 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public canRedo(resource: URI): boolean {
|
||||||
|
const strResource = uriGetComparisonKey(resource);
|
||||||
|
if (this._editStacks.has(strResource)) {
|
||||||
|
const editStack = this._editStacks.get(strResource)!;
|
||||||
|
return (editStack.future.length > 0);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
redo(resource: URI): void {
|
||||||
|
const strResource = uriGetComparisonKey(resource);
|
||||||
|
if (!this._editStacks.has(strResource)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const editStack = this._editStacks.get(strResource)!;
|
||||||
|
if (editStack.future.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const element = editStack.future[editStack.future.length - 1];
|
||||||
|
|
||||||
|
let replaceCurrentElement: IUndoRedoElement[] | null = null as IUndoRedoElement[] | null;
|
||||||
|
try {
|
||||||
|
element.actual.redo({
|
||||||
|
replaceCurrentElement: (others: IUndoRedoElement[]): void => {
|
||||||
|
replaceCurrentElement = others;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
onUnexpectedError(e);
|
||||||
|
editStack.future.pop();
|
||||||
|
editStack.past.push(element);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (replaceCurrentElement === null) {
|
||||||
|
// regular case
|
||||||
|
editStack.future.pop();
|
||||||
|
editStack.past.push(element);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const replaceCurrentElementMap = new Map<string, StackElement>();
|
||||||
|
for (const _replace of replaceCurrentElement) {
|
||||||
|
const replace = new StackElement(_replace);
|
||||||
|
for (const strResource of replace.strResources) {
|
||||||
|
replaceCurrentElementMap.set(strResource, replace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0, len = element.strResources.length; i < len; i++) {
|
||||||
|
const strResource = element.strResources[i];
|
||||||
|
if (this._editStacks.has(strResource)) {
|
||||||
|
const editStack = this._editStacks.get(strResource)!;
|
||||||
|
for (let j = editStack.future.length - 1; j >= 0; j--) {
|
||||||
|
if (editStack.future[j] === element) {
|
||||||
|
if (replaceCurrentElementMap.has(strResource)) {
|
||||||
|
editStack.future[j] = replaceCurrentElementMap.get(strResource)!;
|
||||||
|
} else {
|
||||||
|
editStack.future.splice(j, 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -174,7 +174,7 @@ export abstract class AbstractFileSynchroniser extends AbstractSynchroniser {
|
|||||||
) {
|
) {
|
||||||
super(source, fileService, environmentService, userDataSyncStoreService, userDataSyncEnablementService, telemetryService, logService);
|
super(source, fileService, environmentService, userDataSyncStoreService, userDataSyncEnablementService, telemetryService, logService);
|
||||||
this._register(this.fileService.watch(dirname(file)));
|
this._register(this.fileService.watch(dirname(file)));
|
||||||
this._register(this.fileService.onFileChanges(e => this.onFileChanges(e)));
|
this._register(this.fileService.onDidFilesChange(e => this.onFileChanges(e)));
|
||||||
}
|
}
|
||||||
|
|
||||||
async stop(): Promise<void> {
|
async stop(): Promise<void> {
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export class GlobalStateSynchroniser extends AbstractSynchroniser implements IUs
|
|||||||
) {
|
) {
|
||||||
super(SyncSource.GlobalState, fileService, environmentService, userDataSyncStoreService, userDataSyncEnablementService, telemetryService, logService);
|
super(SyncSource.GlobalState, fileService, environmentService, userDataSyncStoreService, userDataSyncEnablementService, telemetryService, logService);
|
||||||
this._register(this.fileService.watch(dirname(this.environmentService.argvResource)));
|
this._register(this.fileService.watch(dirname(this.environmentService.argvResource)));
|
||||||
this._register(Event.filter(this.fileService.onFileChanges, e => e.contains(this.environmentService.argvResource))(() => this._onDidChangeLocal.fire()));
|
this._register(Event.filter(this.fileService.onDidFilesChange, e => e.contains(this.environmentService.argvResource))(() => this._onDidChangeLocal.fire()));
|
||||||
}
|
}
|
||||||
|
|
||||||
async pull(): Promise<void> {
|
async pull(): Promise<void> {
|
||||||
|
|||||||
@@ -14,6 +14,9 @@ export class UserDataAuthTokenService extends Disposable implements IUserDataAut
|
|||||||
private _onDidChangeToken: Emitter<string | undefined> = this._register(new Emitter<string | undefined>());
|
private _onDidChangeToken: Emitter<string | undefined> = this._register(new Emitter<string | undefined>());
|
||||||
readonly onDidChangeToken: Event<string | undefined> = this._onDidChangeToken.event;
|
readonly onDidChangeToken: Event<string | undefined> = this._onDidChangeToken.event;
|
||||||
|
|
||||||
|
private _onTokenFailed: Emitter<void> = this._register(new Emitter<void>());
|
||||||
|
readonly onTokenFailed: Event<void> = this._onTokenFailed.event;
|
||||||
|
|
||||||
private _token: string | undefined;
|
private _token: string | undefined;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
@@ -30,4 +33,8 @@ export class UserDataAuthTokenService extends Disposable implements IUserDataAut
|
|||||||
this._onDidChangeToken.fire(token);
|
this._onDidChangeToken.fire(token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sendTokenFailed(): void {
|
||||||
|
this._onTokenFailed.fire();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,6 +72,13 @@ export class UserDataAutoSyncService extends Disposable implements IUserDataAuto
|
|||||||
return this.sync(loop, auto);
|
return this.sync(loop, auto);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (e instanceof UserDataSyncError && e.code === UserDataSyncErrorCode.SessionExpired) {
|
||||||
|
this.logService.info('Auto Sync: Cloud has new session');
|
||||||
|
this.logService.info('Auto Sync: Resetting the local sync state.');
|
||||||
|
await this.userDataSyncService.resetLocal();
|
||||||
|
this.logService.info('Auto Sync: Completed resetting the local sync state.');
|
||||||
|
return this.sync(loop, auto);
|
||||||
|
}
|
||||||
this.logService.error(e);
|
this.logService.error(e);
|
||||||
this.successiveFailures++;
|
this.successiveFailures++;
|
||||||
this._onError.fire(e instanceof UserDataSyncError ? { code: e.code, source: e.source } : { code: UserDataSyncErrorCode.Unknown });
|
this._onError.fire(e instanceof UserDataSyncError ? { code: e.code, source: e.source } : { code: UserDataSyncErrorCode.Unknown });
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
|
|||||||
import { IStringDictionary } from 'vs/base/common/collections';
|
import { IStringDictionary } from 'vs/base/common/collections';
|
||||||
import { FormattingOptions } from 'vs/base/common/jsonFormatter';
|
import { FormattingOptions } from 'vs/base/common/jsonFormatter';
|
||||||
import { URI } from 'vs/base/common/uri';
|
import { URI } from 'vs/base/common/uri';
|
||||||
import { isEqual } from 'vs/base/common/resources';
|
import { isEqual, joinPath } from 'vs/base/common/resources';
|
||||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||||
|
|
||||||
export const CONFIGURATION_SYNC_STORE_KEY = 'configurationSync.store';
|
export const CONFIGURATION_SYNC_STORE_KEY = 'configurationSync.store';
|
||||||
@@ -120,23 +120,27 @@ export interface IUserData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface IUserDataSyncStore {
|
export interface IUserDataSyncStore {
|
||||||
url: string;
|
url: URI;
|
||||||
authenticationProviderId: string;
|
authenticationProviderId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getUserDataSyncStore(configurationService: IConfigurationService): IUserDataSyncStore | undefined {
|
export function getUserDataSyncStore(configurationService: IConfigurationService): IUserDataSyncStore | undefined {
|
||||||
const value = configurationService.getValue<IUserDataSyncStore>(CONFIGURATION_SYNC_STORE_KEY);
|
const value = configurationService.getValue<{ url: string, authenticationProviderId: string }>(CONFIGURATION_SYNC_STORE_KEY);
|
||||||
return value && value.url && value.authenticationProviderId ? value : undefined;
|
if (value && value.url && value.authenticationProviderId) {
|
||||||
|
return {
|
||||||
|
url: joinPath(URI.parse(value.url), 'v1'),
|
||||||
|
authenticationProviderId: value.authenticationProviderId
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ALL_RESOURCE_KEYS: ResourceKey[] = ['settings', 'keybindings', 'extensions', 'globalState'];
|
export const ALL_RESOURCE_KEYS: ResourceKey[] = ['settings', 'keybindings', 'extensions', 'globalState'];
|
||||||
export type ResourceKey = 'settings' | 'keybindings' | 'extensions' | 'globalState';
|
export type ResourceKey = 'settings' | 'keybindings' | 'extensions' | 'globalState';
|
||||||
|
|
||||||
export interface IUserDataManifest {
|
export interface IUserDataManifest {
|
||||||
settings: string;
|
latest?: Record<ResourceKey, string>
|
||||||
keybindings: string;
|
session: string;
|
||||||
extensions: string;
|
|
||||||
globalState: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const IUserDataSyncStoreService = createDecorator<IUserDataSyncStoreService>('IUserDataSyncStoreService');
|
export const IUserDataSyncStoreService = createDecorator<IUserDataSyncStoreService>('IUserDataSyncStoreService');
|
||||||
@@ -162,6 +166,7 @@ export enum UserDataSyncErrorCode {
|
|||||||
TooLarge = 'TooLarge',
|
TooLarge = 'TooLarge',
|
||||||
NoRef = 'NoRef',
|
NoRef = 'NoRef',
|
||||||
TurnedOff = 'TurnedOff',
|
TurnedOff = 'TurnedOff',
|
||||||
|
SessionExpired = 'SessionExpired',
|
||||||
|
|
||||||
// Local Errors
|
// Local Errors
|
||||||
LocalPreconditionFailed = 'LocalPreconditionFailed',
|
LocalPreconditionFailed = 'LocalPreconditionFailed',
|
||||||
@@ -303,9 +308,11 @@ export interface IUserDataAuthTokenService {
|
|||||||
_serviceBrand: undefined;
|
_serviceBrand: undefined;
|
||||||
|
|
||||||
readonly onDidChangeToken: Event<string | undefined>;
|
readonly onDidChangeToken: Event<string | undefined>;
|
||||||
|
readonly onTokenFailed: Event<void>;
|
||||||
|
|
||||||
getToken(): Promise<string | undefined>;
|
getToken(): Promise<string | undefined>;
|
||||||
setToken(accessToken: string | undefined): Promise<void>;
|
setToken(accessToken: string | undefined): Promise<void>;
|
||||||
|
sendTokenFailed(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const IUserDataSyncLogService = createDecorator<IUserDataSyncLogService>('IUserDataSyncLogService');
|
export const IUserDataSyncLogService = createDecorator<IUserDataSyncLogService>('IUserDataSyncLogService');
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ export class UserDataAuthTokenServiceChannel implements IServerChannel {
|
|||||||
listen(_: unknown, event: string): Event<any> {
|
listen(_: unknown, event: string): Event<any> {
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case 'onDidChangeToken': return this.service.onDidChangeToken;
|
case 'onDidChangeToken': return this.service.onDidChangeToken;
|
||||||
|
case 'onTokenFailed': return this.service.onTokenFailed;
|
||||||
}
|
}
|
||||||
throw new Error(`Event not found: ${event}`);
|
throw new Error(`Event not found: ${event}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,11 +14,14 @@ import { toErrorMessage } from 'vs/base/common/errorMessage';
|
|||||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||||
import { equals } from 'vs/base/common/arrays';
|
import { equals } from 'vs/base/common/arrays';
|
||||||
import { localize } from 'vs/nls';
|
import { localize } from 'vs/nls';
|
||||||
|
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
|
||||||
|
|
||||||
type SyncErrorClassification = {
|
type SyncErrorClassification = {
|
||||||
source: { classification: 'SystemMetaData', purpose: 'FeatureInsight', isMeasurement: true };
|
source: { classification: 'SystemMetaData', purpose: 'FeatureInsight', isMeasurement: true };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const SESSION_ID_KEY = 'sync.sessionId';
|
||||||
|
|
||||||
export class UserDataSyncService extends Disposable implements IUserDataSyncService {
|
export class UserDataSyncService extends Disposable implements IUserDataSyncService {
|
||||||
|
|
||||||
_serviceBrand: any;
|
_serviceBrand: any;
|
||||||
@@ -48,6 +51,7 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
|
|||||||
@IUserDataSyncLogService private readonly logService: IUserDataSyncLogService,
|
@IUserDataSyncLogService private readonly logService: IUserDataSyncLogService,
|
||||||
@IUserDataAuthTokenService private readonly userDataAuthTokenService: IUserDataAuthTokenService,
|
@IUserDataAuthTokenService private readonly userDataAuthTokenService: IUserDataAuthTokenService,
|
||||||
@ITelemetryService private readonly telemetryService: ITelemetryService,
|
@ITelemetryService private readonly telemetryService: ITelemetryService,
|
||||||
|
@IStorageService private readonly storageService: IStorageService,
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
this.keybindingsSynchroniser = this._register(this.instantiationService.createInstance(KeybindingsSynchroniser));
|
this.keybindingsSynchroniser = this._register(this.instantiationService.createInstance(KeybindingsSynchroniser));
|
||||||
@@ -96,7 +100,7 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
|
|||||||
this.setStatus(SyncStatus.Syncing);
|
this.setStatus(SyncStatus.Syncing);
|
||||||
}
|
}
|
||||||
|
|
||||||
const manifest = await this.userDataSyncStoreService.manifest();
|
let manifest = await this.userDataSyncStoreService.manifest();
|
||||||
|
|
||||||
// Server has no data but this machine was synced before
|
// Server has no data but this machine was synced before
|
||||||
if (manifest === null && await this.hasPreviouslySynced()) {
|
if (manifest === null && await this.hasPreviouslySynced()) {
|
||||||
@@ -104,14 +108,30 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
|
|||||||
throw new UserDataSyncError(localize('turned off', "Cannot sync because syncing is turned off in the cloud"), UserDataSyncErrorCode.TurnedOff);
|
throw new UserDataSyncError(localize('turned off', "Cannot sync because syncing is turned off in the cloud"), UserDataSyncErrorCode.TurnedOff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const sessionId = this.storageService.get(SESSION_ID_KEY, StorageScope.GLOBAL);
|
||||||
|
// Server session is different from client session
|
||||||
|
if (sessionId && manifest && sessionId !== manifest.session) {
|
||||||
|
throw new UserDataSyncError(localize('session expired', "Cannot sync because current session is expired"), UserDataSyncErrorCode.SessionExpired);
|
||||||
|
}
|
||||||
|
|
||||||
for (const synchroniser of this.synchronisers) {
|
for (const synchroniser of this.synchronisers) {
|
||||||
try {
|
try {
|
||||||
await synchroniser.sync(manifest ? manifest[synchroniser.resourceKey] : undefined);
|
await synchroniser.sync(manifest && manifest.latest ? manifest.latest[synchroniser.resourceKey] : undefined);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.handleSyncError(e, synchroniser.source);
|
this.handleSyncError(e, synchroniser.source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// After syncing, get the manifest if it was not available before
|
||||||
|
if (manifest === null) {
|
||||||
|
manifest = await this.userDataSyncStoreService.manifest();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update local session id
|
||||||
|
if (manifest && manifest.session !== sessionId) {
|
||||||
|
this.storageService.store(SESSION_ID_KEY, manifest.session, StorageScope.GLOBAL);
|
||||||
|
}
|
||||||
|
|
||||||
this.logService.info(`Sync done. Took ${new Date().getTime() - startTime}ms`);
|
this.logService.info(`Sync done. Took ${new Date().getTime() - startTime}ms`);
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
@@ -140,26 +160,6 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
|
|||||||
return synchroniser.accept(content);
|
return synchroniser.accept(content);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async hasPreviouslySynced(): Promise<boolean> {
|
|
||||||
await this.checkEnablement();
|
|
||||||
for (const synchroniser of this.synchronisers) {
|
|
||||||
if (await synchroniser.hasPreviouslySynced()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async hasLocalData(): Promise<boolean> {
|
|
||||||
await this.checkEnablement();
|
|
||||||
for (const synchroniser of this.synchronisers) {
|
|
||||||
if (await synchroniser.hasLocalData()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
async getRemoteContent(source: SyncSource, preview: boolean): Promise<string | null> {
|
async getRemoteContent(source: SyncSource, preview: boolean): Promise<string | null> {
|
||||||
await this.checkEnablement();
|
await this.checkEnablement();
|
||||||
for (const synchroniser of this.synchronisers) {
|
for (const synchroniser of this.synchronisers) {
|
||||||
@@ -189,6 +189,7 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
|
|||||||
|
|
||||||
async resetLocal(): Promise<void> {
|
async resetLocal(): Promise<void> {
|
||||||
await this.checkEnablement();
|
await this.checkEnablement();
|
||||||
|
this.storageService.remove(SESSION_ID_KEY, StorageScope.GLOBAL);
|
||||||
for (const synchroniser of this.synchronisers) {
|
for (const synchroniser of this.synchronisers) {
|
||||||
try {
|
try {
|
||||||
synchroniser.resetLocal();
|
synchroniser.resetLocal();
|
||||||
@@ -199,6 +200,26 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async hasPreviouslySynced(): Promise<boolean> {
|
||||||
|
await this.checkEnablement();
|
||||||
|
for (const synchroniser of this.synchronisers) {
|
||||||
|
if (await synchroniser.hasPreviouslySynced()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async hasLocalData(): Promise<boolean> {
|
||||||
|
await this.checkEnablement();
|
||||||
|
for (const synchroniser of this.synchronisers) {
|
||||||
|
if (await synchroniser.hasLocalData()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private async resetRemote(): Promise<void> {
|
private async resetRemote(): Promise<void> {
|
||||||
await this.checkEnablement();
|
await this.checkEnablement();
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
import { Disposable, } from 'vs/base/common/lifecycle';
|
import { Disposable, } from 'vs/base/common/lifecycle';
|
||||||
import { IUserData, IUserDataSyncStoreService, UserDataSyncErrorCode, IUserDataSyncStore, getUserDataSyncStore, IUserDataAuthTokenService, SyncSource, UserDataSyncStoreError, IUserDataSyncLogService, IUserDataManifest } from 'vs/platform/userDataSync/common/userDataSync';
|
import { IUserData, IUserDataSyncStoreService, UserDataSyncErrorCode, IUserDataSyncStore, getUserDataSyncStore, IUserDataAuthTokenService, SyncSource, UserDataSyncStoreError, IUserDataSyncLogService, IUserDataManifest } from 'vs/platform/userDataSync/common/userDataSync';
|
||||||
import { IRequestService, asText, isSuccess, asJson } from 'vs/platform/request/common/request';
|
import { IRequestService, asText, isSuccess, asJson } from 'vs/platform/request/common/request';
|
||||||
import { URI } from 'vs/base/common/uri';
|
|
||||||
import { joinPath } from 'vs/base/common/resources';
|
import { joinPath } from 'vs/base/common/resources';
|
||||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||||
import { IHeaders, IRequestOptions, IRequestContext } from 'vs/base/parts/request/common/request';
|
import { IHeaders, IRequestOptions, IRequestContext } from 'vs/base/parts/request/common/request';
|
||||||
@@ -33,7 +32,7 @@ export class UserDataSyncStoreService extends Disposable implements IUserDataSyn
|
|||||||
throw new Error('No settings sync store url configured.');
|
throw new Error('No settings sync store url configured.');
|
||||||
}
|
}
|
||||||
|
|
||||||
const url = joinPath(URI.parse(this.userDataSyncStore.url), 'resource', key, 'latest').toString();
|
const url = joinPath(this.userDataSyncStore.url, 'resource', key, 'latest').toString();
|
||||||
const headers: IHeaders = {};
|
const headers: IHeaders = {};
|
||||||
// Disable caching as they are cached by synchronisers
|
// Disable caching as they are cached by synchronisers
|
||||||
headers['Cache-Control'] = 'no-cache';
|
headers['Cache-Control'] = 'no-cache';
|
||||||
@@ -65,7 +64,7 @@ export class UserDataSyncStoreService extends Disposable implements IUserDataSyn
|
|||||||
throw new Error('No settings sync store url configured.');
|
throw new Error('No settings sync store url configured.');
|
||||||
}
|
}
|
||||||
|
|
||||||
const url = joinPath(URI.parse(this.userDataSyncStore.url), 'resource', key).toString();
|
const url = joinPath(this.userDataSyncStore.url, 'resource', key).toString();
|
||||||
const headers: IHeaders = { 'Content-Type': 'text/plain' };
|
const headers: IHeaders = { 'Content-Type': 'text/plain' };
|
||||||
if (ref) {
|
if (ref) {
|
||||||
headers['If-Match'] = ref;
|
headers['If-Match'] = ref;
|
||||||
@@ -89,7 +88,7 @@ export class UserDataSyncStoreService extends Disposable implements IUserDataSyn
|
|||||||
throw new Error('No settings sync store url configured.');
|
throw new Error('No settings sync store url configured.');
|
||||||
}
|
}
|
||||||
|
|
||||||
const url = joinPath(URI.parse(this.userDataSyncStore.url), 'resource', 'latest').toString();
|
const url = joinPath(this.userDataSyncStore.url, 'manifest').toString();
|
||||||
const headers: IHeaders = { 'Content-Type': 'application/json' };
|
const headers: IHeaders = { 'Content-Type': 'application/json' };
|
||||||
|
|
||||||
const context = await this.request({ type: 'GET', url, headers }, undefined, CancellationToken.None);
|
const context = await this.request({ type: 'GET', url, headers }, undefined, CancellationToken.None);
|
||||||
@@ -105,7 +104,7 @@ export class UserDataSyncStoreService extends Disposable implements IUserDataSyn
|
|||||||
throw new Error('No settings sync store url configured.');
|
throw new Error('No settings sync store url configured.');
|
||||||
}
|
}
|
||||||
|
|
||||||
const url = joinPath(URI.parse(this.userDataSyncStore.url), 'resource').toString();
|
const url = joinPath(this.userDataSyncStore.url, 'resource').toString();
|
||||||
const headers: IHeaders = { 'Content-Type': 'text/plain' };
|
const headers: IHeaders = { 'Content-Type': 'text/plain' };
|
||||||
|
|
||||||
const context = await this.request({ type: 'DELETE', url, headers }, undefined, CancellationToken.None);
|
const context = await this.request({ type: 'DELETE', url, headers }, undefined, CancellationToken.None);
|
||||||
@@ -134,6 +133,7 @@ export class UserDataSyncStoreService extends Disposable implements IUserDataSyn
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (context.res.statusCode === 401) {
|
if (context.res.statusCode === 401) {
|
||||||
|
this.authTokenService.sendTokenFailed();
|
||||||
throw new UserDataSyncStoreError(`Request '${options.url?.toString()}' failed because of Unauthorized (401).`, UserDataSyncErrorCode.Unauthorized, source);
|
throw new UserDataSyncStoreError(`Request '${options.url?.toString()}' failed because of Unauthorized (401).`, UserDataSyncErrorCode.Unauthorized, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,11 +5,7 @@
|
|||||||
|
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import { merge } from 'vs/platform/userDataSync/common/keybindingsMerge';
|
import { merge } from 'vs/platform/userDataSync/common/keybindingsMerge';
|
||||||
import { IStringDictionary } from 'vs/base/common/collections';
|
import { TestUserDataSyncUtilService } from 'vs/platform/userDataSync/test/common/userDataSyncClient';
|
||||||
import { IUserDataSyncUtilService } from 'vs/platform/userDataSync/common/userDataSync';
|
|
||||||
import { FormattingOptions } from 'vs/base/common/jsonFormatter';
|
|
||||||
import { URI } from 'vs/base/common/uri';
|
|
||||||
import type { IExtensionIdentifier } from 'vs/platform/extensionManagement/common/extensionManagement';
|
|
||||||
|
|
||||||
suite('KeybindingsMerge - No Conflicts', () => {
|
suite('KeybindingsMerge - No Conflicts', () => {
|
||||||
|
|
||||||
@@ -613,7 +609,7 @@ suite('KeybindingsMerge - No Conflicts', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
async function mergeKeybindings(localContent: string, remoteContent: string, baseContent: string | null) {
|
async function mergeKeybindings(localContent: string, remoteContent: string, baseContent: string | null) {
|
||||||
const userDataSyncUtilService = new MockUserDataSyncUtilService();
|
const userDataSyncUtilService = new TestUserDataSyncUtilService();
|
||||||
const formattingOptions = await userDataSyncUtilService.resolveFormattingOptions();
|
const formattingOptions = await userDataSyncUtilService.resolveFormattingOptions();
|
||||||
return merge(localContent, remoteContent, baseContent, formattingOptions, userDataSyncUtilService);
|
return merge(localContent, remoteContent, baseContent, formattingOptions, userDataSyncUtilService);
|
||||||
}
|
}
|
||||||
@@ -621,22 +617,3 @@ async function mergeKeybindings(localContent: string, remoteContent: string, bas
|
|||||||
function stringify(value: any): string {
|
function stringify(value: any): string {
|
||||||
return JSON.stringify(value, null, '\t');
|
return JSON.stringify(value, null, '\t');
|
||||||
}
|
}
|
||||||
|
|
||||||
class MockUserDataSyncUtilService implements IUserDataSyncUtilService {
|
|
||||||
|
|
||||||
_serviceBrand: any;
|
|
||||||
|
|
||||||
async resolveUserBindings(userbindings: string[]): Promise<IStringDictionary<string>> {
|
|
||||||
const keys: IStringDictionary<string> = {};
|
|
||||||
for (const keybinding of userbindings) {
|
|
||||||
keys[keybinding] = keybinding;
|
|
||||||
}
|
|
||||||
return keys;
|
|
||||||
}
|
|
||||||
|
|
||||||
async resolveFormattingOptions(file?: URI): Promise<FormattingOptions> {
|
|
||||||
return { eol: '\n', insertSpaces: false, tabSize: 4 };
|
|
||||||
}
|
|
||||||
|
|
||||||
async ignoreExtensionsToSync(extensions: IExtensionIdentifier[]): Promise<void> { }
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -0,0 +1,246 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import { IRequestService } from 'vs/platform/request/common/request';
|
||||||
|
import { IRequestOptions, IRequestContext, IHeaders } from 'vs/base/parts/request/common/request';
|
||||||
|
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||||
|
import { IUserData, ResourceKey, IUserDataManifest, ALL_RESOURCE_KEYS, IUserDataAuthTokenService, IUserDataSyncLogService, IUserDataSyncStoreService, IUserDataSyncUtilService, IUserDataSyncEnablementService, ISettingsSyncService, IUserDataSyncService } from 'vs/platform/userDataSync/common/userDataSync';
|
||||||
|
import { bufferToStream, VSBuffer } from 'vs/base/common/buffer';
|
||||||
|
import { generateUuid } from 'vs/base/common/uuid';
|
||||||
|
import { UserDataSyncService } from 'vs/platform/userDataSync/common/userDataSyncService';
|
||||||
|
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
|
||||||
|
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||||
|
import { NullLogService, ILogService } from 'vs/platform/log/common/log';
|
||||||
|
import { UserDataSyncStoreService } from 'vs/platform/userDataSync/common/userDataSyncStoreService';
|
||||||
|
import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||||
|
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||||
|
import { IFileService } from 'vs/platform/files/common/files';
|
||||||
|
import { FileService } from 'vs/platform/files/common/fileService';
|
||||||
|
import { Schemas } from 'vs/base/common/network';
|
||||||
|
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||||
|
import { IStorageService, InMemoryStorageService } from 'vs/platform/storage/common/storage';
|
||||||
|
import { URI } from 'vs/base/common/uri';
|
||||||
|
import { joinPath } from 'vs/base/common/resources';
|
||||||
|
import { IStringDictionary } from 'vs/base/common/collections';
|
||||||
|
import { FormattingOptions } from 'vs/base/common/jsonFormatter';
|
||||||
|
import { UserDataSyncEnablementService } from 'vs/platform/userDataSync/common/userDataSyncEnablementService';
|
||||||
|
import { IGlobalExtensionEnablementService, IExtensionManagementService, IExtensionGalleryService, DidInstallExtensionEvent, DidUninstallExtensionEvent } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||||
|
import { GlobalExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionEnablementService';
|
||||||
|
import { InMemoryFileSystemProvider } from 'vs/platform/files/common/inMemoryFilesystemProvider';
|
||||||
|
import { ConfigurationService } from 'vs/platform/configuration/common/configurationService';
|
||||||
|
import { Disposable } from 'vs/base/common/lifecycle';
|
||||||
|
import { SettingsSynchroniser } from 'vs/platform/userDataSync/common/settingsSync';
|
||||||
|
import { Emitter } from 'vs/base/common/event';
|
||||||
|
|
||||||
|
export class UserDataSyncClient extends Disposable {
|
||||||
|
|
||||||
|
readonly instantiationService: TestInstantiationService;
|
||||||
|
|
||||||
|
constructor(readonly testServer: UserDataSyncTestServer = new UserDataSyncTestServer()) {
|
||||||
|
super();
|
||||||
|
this.instantiationService = new TestInstantiationService();
|
||||||
|
}
|
||||||
|
|
||||||
|
async setUp(empty: boolean = false): Promise<void> {
|
||||||
|
const userDataDirectory = URI.file('userdata').with({ scheme: Schemas.inMemory });
|
||||||
|
const userDataSyncHome = joinPath(userDataDirectory, '.sync');
|
||||||
|
const environmentService = this.instantiationService.stub(IEnvironmentService, <Partial<IEnvironmentService>>{
|
||||||
|
userDataSyncHome,
|
||||||
|
settingsResource: joinPath(userDataDirectory, 'settings.json'),
|
||||||
|
settingsSyncPreviewResource: joinPath(userDataSyncHome, 'settings.json'),
|
||||||
|
keybindingsResource: joinPath(userDataDirectory, 'keybindings.json'),
|
||||||
|
keybindingsSyncPreviewResource: joinPath(userDataSyncHome, 'keybindings.json'),
|
||||||
|
argvResource: joinPath(userDataDirectory, 'argv.json'),
|
||||||
|
});
|
||||||
|
|
||||||
|
const logService = new NullLogService();
|
||||||
|
this.instantiationService.stub(ILogService, logService);
|
||||||
|
|
||||||
|
const fileService = this._register(new FileService(logService));
|
||||||
|
fileService.registerProvider(Schemas.inMemory, new InMemoryFileSystemProvider());
|
||||||
|
this.instantiationService.stub(IFileService, fileService);
|
||||||
|
|
||||||
|
this.instantiationService.stub(IStorageService, new InMemoryStorageService());
|
||||||
|
|
||||||
|
await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString(JSON.stringify({
|
||||||
|
'configurationSync.store': {
|
||||||
|
url: this.testServer.url,
|
||||||
|
authenticationProviderId: 'test'
|
||||||
|
}
|
||||||
|
})));
|
||||||
|
|
||||||
|
const configurationService = new ConfigurationService(environmentService.settingsResource, fileService);
|
||||||
|
await configurationService.initialize();
|
||||||
|
this.instantiationService.stub(IConfigurationService, configurationService);
|
||||||
|
|
||||||
|
this.instantiationService.stub(IRequestService, this.testServer);
|
||||||
|
this.instantiationService.stub(IUserDataAuthTokenService, <Partial<IUserDataAuthTokenService>>{
|
||||||
|
onDidChangeToken: new Emitter<string | undefined>().event,
|
||||||
|
async getToken() { return 'token'; }
|
||||||
|
});
|
||||||
|
|
||||||
|
this.instantiationService.stub(IUserDataSyncLogService, logService);
|
||||||
|
this.instantiationService.stub(ITelemetryService, NullTelemetryService);
|
||||||
|
this.instantiationService.stub(IUserDataSyncStoreService, this.instantiationService.createInstance(UserDataSyncStoreService));
|
||||||
|
this.instantiationService.stub(IUserDataSyncUtilService, new TestUserDataSyncUtilService());
|
||||||
|
this.instantiationService.stub(IUserDataSyncEnablementService, this.instantiationService.createInstance(UserDataSyncEnablementService));
|
||||||
|
|
||||||
|
this.instantiationService.stub(IGlobalExtensionEnablementService, this.instantiationService.createInstance(GlobalExtensionEnablementService));
|
||||||
|
this.instantiationService.stub(IExtensionManagementService, <Partial<IExtensionManagementService>>{
|
||||||
|
async getInstalled() { return []; },
|
||||||
|
onDidInstallExtension: new Emitter<DidInstallExtensionEvent>().event,
|
||||||
|
onDidUninstallExtension: new Emitter<DidUninstallExtensionEvent>().event,
|
||||||
|
});
|
||||||
|
this.instantiationService.stub(IExtensionGalleryService, <Partial<IExtensionGalleryService>>{
|
||||||
|
isEnabled() { return true; },
|
||||||
|
async getCompatibleExtension() { return null; }
|
||||||
|
});
|
||||||
|
|
||||||
|
this.instantiationService.stub(ISettingsSyncService, this.instantiationService.createInstance(SettingsSynchroniser));
|
||||||
|
this.instantiationService.stub(IUserDataSyncService, this.instantiationService.createInstance(UserDataSyncService));
|
||||||
|
|
||||||
|
if (empty) {
|
||||||
|
await fileService.del(environmentService.settingsResource);
|
||||||
|
} else {
|
||||||
|
await fileService.writeFile(environmentService.keybindingsResource, VSBuffer.fromString(JSON.stringify([])));
|
||||||
|
await fileService.writeFile(environmentService.argvResource, VSBuffer.fromString(JSON.stringify({ 'locale': 'en' })));
|
||||||
|
}
|
||||||
|
await configurationService.reloadConfiguration();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export class UserDataSyncTestServer implements IRequestService {
|
||||||
|
|
||||||
|
_serviceBrand: any;
|
||||||
|
|
||||||
|
readonly url: string = 'http://host:3000';
|
||||||
|
private session: string | null = null;
|
||||||
|
private readonly data: Map<ResourceKey, IUserData> = new Map<ResourceKey, IUserData>();
|
||||||
|
|
||||||
|
private _requests: { url: string, type: string, headers?: IHeaders }[] = [];
|
||||||
|
get requests(): { url: string, type: string, headers?: IHeaders }[] { return this._requests; }
|
||||||
|
|
||||||
|
private _responses: { status: number }[] = [];
|
||||||
|
get responses(): { status: number }[] { return this._responses; }
|
||||||
|
reset(): void { this._requests = []; this._responses = []; }
|
||||||
|
|
||||||
|
async resolveProxy(url: string): Promise<string | undefined> { return url; }
|
||||||
|
|
||||||
|
async request(options: IRequestOptions, token: CancellationToken): Promise<IRequestContext> {
|
||||||
|
const headers: IHeaders = {};
|
||||||
|
if (options.headers) {
|
||||||
|
if (options.headers['If-None-Match']) {
|
||||||
|
headers['If-None-Match'] = options.headers['If-None-Match'];
|
||||||
|
}
|
||||||
|
if (options.headers['If-Match']) {
|
||||||
|
headers['If-Match'] = options.headers['If-Match'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this._requests.push({ url: options.url!, type: options.type!, headers });
|
||||||
|
const requestContext = await this.doRequest(options);
|
||||||
|
this._responses.push({ status: requestContext.res.statusCode! });
|
||||||
|
return requestContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async doRequest(options: IRequestOptions): Promise<IRequestContext> {
|
||||||
|
const versionUrl = `${this.url}/v1/`;
|
||||||
|
const relativePath = options.url!.indexOf(versionUrl) === 0 ? options.url!.substring(versionUrl.length) : undefined;
|
||||||
|
const segments = relativePath ? relativePath.split('/') : [];
|
||||||
|
if (options.type === 'GET' && segments.length === 1 && segments[0] === 'manifest') {
|
||||||
|
return this.getManifest(options.headers);
|
||||||
|
}
|
||||||
|
if (options.type === 'GET' && segments.length === 3 && segments[0] === 'resource' && segments[2] === 'latest') {
|
||||||
|
return this.getLatestData(segments[1], options.headers);
|
||||||
|
}
|
||||||
|
if (options.type === 'POST' && segments.length === 2 && segments[0] === 'resource') {
|
||||||
|
return this.writeData(segments[1], options.data, options.headers);
|
||||||
|
}
|
||||||
|
if (options.type === 'DELETE' && segments.length === 1 && segments[0] === 'resource') {
|
||||||
|
return this.clear(options.headers);
|
||||||
|
}
|
||||||
|
return this.toResponse(501);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getManifest(headers?: IHeaders): Promise<IRequestContext> {
|
||||||
|
if (this.session) {
|
||||||
|
const latest: Record<ResourceKey, string> = Object.create({});
|
||||||
|
const manifest: IUserDataManifest = { session: this.session, latest };
|
||||||
|
this.data.forEach((value, key) => latest[key] = value.ref);
|
||||||
|
return this.toResponse(200, { 'Content-Type': 'application/json' }, JSON.stringify(manifest));
|
||||||
|
}
|
||||||
|
return this.toResponse(204);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getLatestData(resource: string, headers: IHeaders = {}): Promise<IRequestContext> {
|
||||||
|
const resourceKey = ALL_RESOURCE_KEYS.find(key => key === resource);
|
||||||
|
if (resourceKey) {
|
||||||
|
const data = this.data.get(resourceKey);
|
||||||
|
if (!data) {
|
||||||
|
return this.toResponse(204, { etag: '0' });
|
||||||
|
}
|
||||||
|
if (headers['If-None-Match'] === data.ref) {
|
||||||
|
return this.toResponse(304);
|
||||||
|
}
|
||||||
|
return this.toResponse(200, { etag: data.ref }, data.content || '');
|
||||||
|
}
|
||||||
|
return this.toResponse(204);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async writeData(resource: string, content: string = '', headers: IHeaders = {}): Promise<IRequestContext> {
|
||||||
|
if (!headers['If-Match']) {
|
||||||
|
return this.toResponse(428);
|
||||||
|
}
|
||||||
|
if (!this.session) {
|
||||||
|
this.session = generateUuid();
|
||||||
|
}
|
||||||
|
const resourceKey = ALL_RESOURCE_KEYS.find(key => key === resource);
|
||||||
|
if (resourceKey) {
|
||||||
|
const data = this.data.get(resourceKey);
|
||||||
|
if (headers['If-Match'] !== (data ? data.ref : '0')) {
|
||||||
|
return this.toResponse(412);
|
||||||
|
}
|
||||||
|
const ref = `${parseInt(data?.ref || '0') + 1}`;
|
||||||
|
this.data.set(resourceKey, { ref, content });
|
||||||
|
return this.toResponse(200, { etag: ref });
|
||||||
|
}
|
||||||
|
return this.toResponse(204);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async clear(headers?: IHeaders): Promise<IRequestContext> {
|
||||||
|
this.data.clear();
|
||||||
|
this.session = null;
|
||||||
|
return this.toResponse(204);
|
||||||
|
}
|
||||||
|
|
||||||
|
private toResponse(statusCode: number, headers?: IHeaders, data?: string): IRequestContext {
|
||||||
|
return {
|
||||||
|
res: {
|
||||||
|
headers: headers || {},
|
||||||
|
statusCode
|
||||||
|
},
|
||||||
|
stream: bufferToStream(VSBuffer.fromString(data || ''))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class TestUserDataSyncUtilService implements IUserDataSyncUtilService {
|
||||||
|
|
||||||
|
_serviceBrand: any;
|
||||||
|
|
||||||
|
async resolveUserBindings(userbindings: string[]): Promise<IStringDictionary<string>> {
|
||||||
|
const keys: IStringDictionary<string> = {};
|
||||||
|
for (const keybinding of userbindings) {
|
||||||
|
keys[keybinding] = keybinding;
|
||||||
|
}
|
||||||
|
return keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
async resolveFormattingOptions(file?: URI): Promise<FormattingOptions> {
|
||||||
|
return { eol: '\n', insertSpaces: false, tabSize: 4 };
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,555 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import * as assert from 'assert';
|
||||||
|
import { IUserDataSyncService, UserDataSyncError, UserDataSyncErrorCode, SyncStatus, SyncSource } from 'vs/platform/userDataSync/common/userDataSync';
|
||||||
|
import { UserDataSyncClient, UserDataSyncTestServer } from 'vs/platform/userDataSync/test/common/userDataSyncClient';
|
||||||
|
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||||
|
import { IFileService } from 'vs/platform/files/common/files';
|
||||||
|
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||||
|
import { VSBuffer } from 'vs/base/common/buffer';
|
||||||
|
|
||||||
|
suite('UserDataSyncService', () => {
|
||||||
|
|
||||||
|
const disposableStore = new DisposableStore();
|
||||||
|
|
||||||
|
teardown(() => disposableStore.clear());
|
||||||
|
|
||||||
|
test('test first time sync ever', async () => {
|
||||||
|
// Setup the client
|
||||||
|
const target = new UserDataSyncTestServer();
|
||||||
|
const client = disposableStore.add(new UserDataSyncClient(target));
|
||||||
|
await client.setUp();
|
||||||
|
const testObject = client.instantiationService.get(IUserDataSyncService);
|
||||||
|
|
||||||
|
// Sync for first time
|
||||||
|
await testObject.sync();
|
||||||
|
|
||||||
|
assert.deepEqual(target.requests, [
|
||||||
|
// Manifest
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/manifest`, headers: {} },
|
||||||
|
// Settings
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/resource/settings/latest`, headers: {} },
|
||||||
|
{ type: 'POST', url: `${target.url}/v1/resource/settings`, headers: { 'If-Match': '0' } },
|
||||||
|
// Keybindings
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/resource/keybindings/latest`, headers: {} },
|
||||||
|
{ type: 'POST', url: `${target.url}/v1/resource/keybindings`, headers: { 'If-Match': '0' } },
|
||||||
|
// Global state
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/resource/globalState/latest`, headers: {} },
|
||||||
|
{ type: 'POST', url: `${target.url}/v1/resource/globalState`, headers: { 'If-Match': '0' } },
|
||||||
|
// Extensions
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/resource/extensions/latest`, headers: {} },
|
||||||
|
{ type: 'POST', url: `${target.url}/v1/resource/extensions`, headers: { 'If-Match': '0' } },
|
||||||
|
// Manifest
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/manifest`, headers: {} },
|
||||||
|
]);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test('test first time sync ever with no data', async () => {
|
||||||
|
// Setup the client
|
||||||
|
const target = new UserDataSyncTestServer();
|
||||||
|
const client = disposableStore.add(new UserDataSyncClient(target));
|
||||||
|
await client.setUp(true);
|
||||||
|
const testObject = client.instantiationService.get(IUserDataSyncService);
|
||||||
|
|
||||||
|
// Sync for first time
|
||||||
|
await testObject.sync();
|
||||||
|
|
||||||
|
assert.deepEqual(target.requests, [
|
||||||
|
// Manifest
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/manifest`, headers: {} },
|
||||||
|
// Settings
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/resource/settings/latest`, headers: {} },
|
||||||
|
// Keybindings
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/resource/keybindings/latest`, headers: {} },
|
||||||
|
// Global state
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/resource/globalState/latest`, headers: {} },
|
||||||
|
{ type: 'POST', url: `${target.url}/v1/resource/globalState`, headers: { 'If-Match': '0' } },
|
||||||
|
// Extensions
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/resource/extensions/latest`, headers: {} },
|
||||||
|
{ type: 'POST', url: `${target.url}/v1/resource/extensions`, headers: { 'If-Match': '0' } },
|
||||||
|
// Manifest
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/manifest`, headers: {} },
|
||||||
|
]);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test('test first time sync from the client with no changes - pull', async () => {
|
||||||
|
const target = new UserDataSyncTestServer();
|
||||||
|
|
||||||
|
// Setup and sync from the first client
|
||||||
|
const client = disposableStore.add(new UserDataSyncClient(target));
|
||||||
|
await client.setUp();
|
||||||
|
await client.instantiationService.get(IUserDataSyncService).sync();
|
||||||
|
|
||||||
|
// Setup the test client
|
||||||
|
const testClient = disposableStore.add(new UserDataSyncClient(target));
|
||||||
|
await testClient.setUp();
|
||||||
|
const testObject = testClient.instantiationService.get(IUserDataSyncService);
|
||||||
|
|
||||||
|
// Sync (pull) from the test client
|
||||||
|
target.reset();
|
||||||
|
await testObject.isFirstTimeSyncWithMerge();
|
||||||
|
await testObject.pull();
|
||||||
|
|
||||||
|
assert.deepEqual(target.requests, [
|
||||||
|
// Manifest
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/manifest`, headers: {} },
|
||||||
|
// Settings
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/resource/settings/latest`, headers: {} },
|
||||||
|
// Keybindings
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/resource/keybindings/latest`, headers: {} },
|
||||||
|
// Global state
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/resource/globalState/latest`, headers: {} },
|
||||||
|
// Extensions
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/resource/extensions/latest`, headers: {} },
|
||||||
|
]);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test('test first time sync from the client with changes - pull', async () => {
|
||||||
|
const target = new UserDataSyncTestServer();
|
||||||
|
|
||||||
|
// Setup and sync from the first client
|
||||||
|
const client = disposableStore.add(new UserDataSyncClient(target));
|
||||||
|
await client.setUp();
|
||||||
|
await client.instantiationService.get(IUserDataSyncService).sync();
|
||||||
|
|
||||||
|
// Setup the test client with changes
|
||||||
|
const testClient = disposableStore.add(new UserDataSyncClient(target));
|
||||||
|
await testClient.setUp();
|
||||||
|
const testObject = testClient.instantiationService.get(IUserDataSyncService);
|
||||||
|
const fileService = testClient.instantiationService.get(IFileService);
|
||||||
|
const environmentService = testClient.instantiationService.get(IEnvironmentService);
|
||||||
|
await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString(JSON.stringify({ 'editor.fontSize': 14 })));
|
||||||
|
await fileService.writeFile(environmentService.keybindingsResource, VSBuffer.fromString(JSON.stringify([{ 'command': 'abcd', 'key': 'cmd+c' }])));
|
||||||
|
await fileService.writeFile(environmentService.argvResource, VSBuffer.fromString(JSON.stringify({ 'locale': 'de' })));
|
||||||
|
|
||||||
|
// Sync (pull) from the test client
|
||||||
|
target.reset();
|
||||||
|
await testObject.isFirstTimeSyncWithMerge();
|
||||||
|
await testObject.pull();
|
||||||
|
|
||||||
|
assert.deepEqual(target.requests, [
|
||||||
|
// Manifest
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/manifest`, headers: {} },
|
||||||
|
// Settings
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/resource/settings/latest`, headers: {} },
|
||||||
|
// Keybindings
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/resource/keybindings/latest`, headers: {} },
|
||||||
|
// Global state
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/resource/globalState/latest`, headers: {} },
|
||||||
|
// Extensions
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/resource/extensions/latest`, headers: {} },
|
||||||
|
]);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test('test first time sync from the client with no changes - merge', async () => {
|
||||||
|
const target = new UserDataSyncTestServer();
|
||||||
|
|
||||||
|
// Setup and sync from the first client
|
||||||
|
const client = disposableStore.add(new UserDataSyncClient(target));
|
||||||
|
await client.setUp();
|
||||||
|
await client.instantiationService.get(IUserDataSyncService).sync();
|
||||||
|
|
||||||
|
// Setup the test client
|
||||||
|
const testClient = disposableStore.add(new UserDataSyncClient(target));
|
||||||
|
await testClient.setUp();
|
||||||
|
const testObject = testClient.instantiationService.get(IUserDataSyncService);
|
||||||
|
|
||||||
|
// Sync (merge) from the test client
|
||||||
|
target.reset();
|
||||||
|
await testObject.isFirstTimeSyncWithMerge();
|
||||||
|
await testObject.sync();
|
||||||
|
|
||||||
|
assert.deepEqual(target.requests, [
|
||||||
|
// Manifest
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/manifest`, headers: {} },
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/manifest`, headers: {} },
|
||||||
|
// Settings
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/resource/settings/latest`, headers: {} },
|
||||||
|
// Keybindings
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/resource/keybindings/latest`, headers: {} },
|
||||||
|
// Global state
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/resource/globalState/latest`, headers: {} },
|
||||||
|
// Extensions
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/resource/extensions/latest`, headers: {} },
|
||||||
|
]);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test('test first time sync from the client with changes - merge', async () => {
|
||||||
|
const target = new UserDataSyncTestServer();
|
||||||
|
|
||||||
|
// Setup and sync from the first client
|
||||||
|
const client = disposableStore.add(new UserDataSyncClient(target));
|
||||||
|
await client.setUp();
|
||||||
|
await client.instantiationService.get(IUserDataSyncService).sync();
|
||||||
|
|
||||||
|
// Setup the test client with changes
|
||||||
|
const testClient = disposableStore.add(new UserDataSyncClient(target));
|
||||||
|
await testClient.setUp();
|
||||||
|
const fileService = testClient.instantiationService.get(IFileService);
|
||||||
|
const environmentService = testClient.instantiationService.get(IEnvironmentService);
|
||||||
|
await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString(JSON.stringify({ 'editor.fontSize': 14 })));
|
||||||
|
await fileService.writeFile(environmentService.keybindingsResource, VSBuffer.fromString(JSON.stringify([{ 'command': 'abcd', 'key': 'cmd+c' }])));
|
||||||
|
await fileService.writeFile(environmentService.argvResource, VSBuffer.fromString(JSON.stringify({ 'locale': 'de' })));
|
||||||
|
const testObject = testClient.instantiationService.get(IUserDataSyncService);
|
||||||
|
|
||||||
|
// Sync (merge) from the test client
|
||||||
|
target.reset();
|
||||||
|
await testObject.isFirstTimeSyncWithMerge();
|
||||||
|
await testObject.sync();
|
||||||
|
|
||||||
|
assert.deepEqual(target.requests, [
|
||||||
|
// Manifest
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/manifest`, headers: {} },
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/manifest`, headers: {} },
|
||||||
|
// Settings
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/resource/settings/latest`, headers: {} },
|
||||||
|
{ type: 'POST', url: `${target.url}/v1/resource/settings`, headers: { 'If-Match': '1' } },
|
||||||
|
// Keybindings
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/resource/keybindings/latest`, headers: {} },
|
||||||
|
{ type: 'POST', url: `${target.url}/v1/resource/keybindings`, headers: { 'If-Match': '1' } },
|
||||||
|
// Global state
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/resource/globalState/latest`, headers: {} },
|
||||||
|
{ type: 'POST', url: `${target.url}/v1/resource/globalState`, headers: { 'If-Match': '1' } },
|
||||||
|
// Extensions
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/resource/extensions/latest`, headers: {} },
|
||||||
|
]);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test('test sync when there are no changes', async () => {
|
||||||
|
const target = new UserDataSyncTestServer();
|
||||||
|
|
||||||
|
// Setup and sync from the client
|
||||||
|
const client = disposableStore.add(new UserDataSyncClient(target));
|
||||||
|
await client.setUp();
|
||||||
|
const testObject = client.instantiationService.get(IUserDataSyncService);
|
||||||
|
await testObject.sync();
|
||||||
|
|
||||||
|
// sync from the client again
|
||||||
|
target.reset();
|
||||||
|
await testObject.sync();
|
||||||
|
|
||||||
|
assert.deepEqual(target.requests, [
|
||||||
|
// Manifest
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/manifest`, headers: {} },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('test sync when there are local changes', async () => {
|
||||||
|
const target = new UserDataSyncTestServer();
|
||||||
|
|
||||||
|
// Setup and sync from the client
|
||||||
|
const client = disposableStore.add(new UserDataSyncClient(target));
|
||||||
|
await client.setUp();
|
||||||
|
const testObject = client.instantiationService.get(IUserDataSyncService);
|
||||||
|
await testObject.sync();
|
||||||
|
target.reset();
|
||||||
|
|
||||||
|
// Do changes in the client
|
||||||
|
const fileService = client.instantiationService.get(IFileService);
|
||||||
|
const environmentService = client.instantiationService.get(IEnvironmentService);
|
||||||
|
await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString(JSON.stringify({ 'editor.fontSize': 14 })));
|
||||||
|
await fileService.writeFile(environmentService.keybindingsResource, VSBuffer.fromString(JSON.stringify([{ 'command': 'abcd', 'key': 'cmd+c' }])));
|
||||||
|
await fileService.writeFile(environmentService.argvResource, VSBuffer.fromString(JSON.stringify({ 'locale': 'de' })));
|
||||||
|
|
||||||
|
// Sync from the client
|
||||||
|
await testObject.sync();
|
||||||
|
|
||||||
|
assert.deepEqual(target.requests, [
|
||||||
|
// Manifest
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/manifest`, headers: {} },
|
||||||
|
// Settings
|
||||||
|
{ type: 'POST', url: `${target.url}/v1/resource/settings`, headers: { 'If-Match': '1' } },
|
||||||
|
// Keybindings
|
||||||
|
{ type: 'POST', url: `${target.url}/v1/resource/keybindings`, headers: { 'If-Match': '1' } },
|
||||||
|
// Global state
|
||||||
|
{ type: 'POST', url: `${target.url}/v1/resource/globalState`, headers: { 'If-Match': '1' } },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('test sync when there are remote changes', async () => {
|
||||||
|
const target = new UserDataSyncTestServer();
|
||||||
|
|
||||||
|
// Sync from first client
|
||||||
|
const client = disposableStore.add(new UserDataSyncClient(target));
|
||||||
|
await client.setUp();
|
||||||
|
await client.instantiationService.get(IUserDataSyncService).sync();
|
||||||
|
|
||||||
|
// Sync from test client
|
||||||
|
const testClient = disposableStore.add(new UserDataSyncClient(target));
|
||||||
|
await testClient.setUp();
|
||||||
|
const testObject = testClient.instantiationService.get(IUserDataSyncService);
|
||||||
|
await testObject.sync();
|
||||||
|
|
||||||
|
// Do changes in first client and sync
|
||||||
|
const fileService = client.instantiationService.get(IFileService);
|
||||||
|
const environmentService = client.instantiationService.get(IEnvironmentService);
|
||||||
|
await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString(JSON.stringify({ 'editor.fontSize': 14 })));
|
||||||
|
await fileService.writeFile(environmentService.keybindingsResource, VSBuffer.fromString(JSON.stringify([{ 'command': 'abcd', 'key': 'cmd+c' }])));
|
||||||
|
await fileService.writeFile(environmentService.argvResource, VSBuffer.fromString(JSON.stringify({ 'locale': 'de' })));
|
||||||
|
await client.instantiationService.get(IUserDataSyncService).sync();
|
||||||
|
|
||||||
|
// Sync from test client
|
||||||
|
target.reset();
|
||||||
|
await testObject.sync();
|
||||||
|
|
||||||
|
assert.deepEqual(target.requests, [
|
||||||
|
// Manifest
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/manifest`, headers: {} },
|
||||||
|
// Settings
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/resource/settings/latest`, headers: { 'If-None-Match': '1' } },
|
||||||
|
// Keybindings
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/resource/keybindings/latest`, headers: { 'If-None-Match': '1' } },
|
||||||
|
// Global state
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/resource/globalState/latest`, headers: { 'If-None-Match': '1' } },
|
||||||
|
]);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test('test delete', async () => {
|
||||||
|
const target = new UserDataSyncTestServer();
|
||||||
|
|
||||||
|
// Sync from the client
|
||||||
|
const testClient = disposableStore.add(new UserDataSyncClient(target));
|
||||||
|
await testClient.setUp();
|
||||||
|
const testObject = testClient.instantiationService.get(IUserDataSyncService);
|
||||||
|
await testObject.sync();
|
||||||
|
|
||||||
|
// Reset from the client
|
||||||
|
target.reset();
|
||||||
|
await testObject.reset();
|
||||||
|
|
||||||
|
assert.deepEqual(target.requests, [
|
||||||
|
// Manifest
|
||||||
|
{ type: 'DELETE', url: `${target.url}/v1/resource`, headers: {} },
|
||||||
|
]);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test('test delete and sync', async () => {
|
||||||
|
const target = new UserDataSyncTestServer();
|
||||||
|
|
||||||
|
// Sync from the client
|
||||||
|
const testClient = disposableStore.add(new UserDataSyncClient(target));
|
||||||
|
await testClient.setUp();
|
||||||
|
const testObject = testClient.instantiationService.get(IUserDataSyncService);
|
||||||
|
await testObject.sync();
|
||||||
|
|
||||||
|
// Reset from the client
|
||||||
|
await testObject.reset();
|
||||||
|
|
||||||
|
// Sync again
|
||||||
|
target.reset();
|
||||||
|
await testObject.sync();
|
||||||
|
|
||||||
|
assert.deepEqual(target.requests, [
|
||||||
|
// Manifest
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/manifest`, headers: {} },
|
||||||
|
// Settings
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/resource/settings/latest`, headers: {} },
|
||||||
|
{ type: 'POST', url: `${target.url}/v1/resource/settings`, headers: { 'If-Match': '0' } },
|
||||||
|
// Keybindings
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/resource/keybindings/latest`, headers: {} },
|
||||||
|
{ type: 'POST', url: `${target.url}/v1/resource/keybindings`, headers: { 'If-Match': '0' } },
|
||||||
|
// Global state
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/resource/globalState/latest`, headers: {} },
|
||||||
|
{ type: 'POST', url: `${target.url}/v1/resource/globalState`, headers: { 'If-Match': '0' } },
|
||||||
|
// Extensions
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/resource/extensions/latest`, headers: {} },
|
||||||
|
{ type: 'POST', url: `${target.url}/v1/resource/extensions`, headers: { 'If-Match': '0' } },
|
||||||
|
// Manifest
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/manifest`, headers: {} },
|
||||||
|
]);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test('test delete on one client throws turned off error on other client while syncing', async () => {
|
||||||
|
const target = new UserDataSyncTestServer();
|
||||||
|
|
||||||
|
// Set up and sync from the client
|
||||||
|
const client = disposableStore.add(new UserDataSyncClient(target));
|
||||||
|
await client.setUp();
|
||||||
|
await client.instantiationService.get(IUserDataSyncService).sync();
|
||||||
|
|
||||||
|
// Set up and sync from the test client
|
||||||
|
const testClient = disposableStore.add(new UserDataSyncClient(target));
|
||||||
|
await testClient.setUp();
|
||||||
|
const testObject = testClient.instantiationService.get(IUserDataSyncService);
|
||||||
|
await testObject.sync();
|
||||||
|
|
||||||
|
// Reset from the first client
|
||||||
|
await client.instantiationService.get(IUserDataSyncService).reset();
|
||||||
|
|
||||||
|
// Sync from the test client
|
||||||
|
target.reset();
|
||||||
|
try {
|
||||||
|
await testObject.sync();
|
||||||
|
} catch (e) {
|
||||||
|
assert.ok(e instanceof UserDataSyncError);
|
||||||
|
assert.deepEqual((<UserDataSyncError>e).code, UserDataSyncErrorCode.TurnedOff);
|
||||||
|
assert.deepEqual(target.requests, [
|
||||||
|
// Manifest
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/manifest`, headers: {} },
|
||||||
|
]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw assert.fail('Should fail with turned off error');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('test creating new session from one client throws session expired error on another client while syncing', async () => {
|
||||||
|
const target = new UserDataSyncTestServer();
|
||||||
|
|
||||||
|
// Set up and sync from the client
|
||||||
|
const client = disposableStore.add(new UserDataSyncClient(target));
|
||||||
|
await client.setUp();
|
||||||
|
await client.instantiationService.get(IUserDataSyncService).sync();
|
||||||
|
|
||||||
|
// Set up and sync from the test client
|
||||||
|
const testClient = disposableStore.add(new UserDataSyncClient(target));
|
||||||
|
await testClient.setUp();
|
||||||
|
const testObject = testClient.instantiationService.get(IUserDataSyncService);
|
||||||
|
await testObject.sync();
|
||||||
|
|
||||||
|
// Reset from the first client
|
||||||
|
await client.instantiationService.get(IUserDataSyncService).reset();
|
||||||
|
|
||||||
|
// Sync again from the first client to create new session
|
||||||
|
await client.instantiationService.get(IUserDataSyncService).sync();
|
||||||
|
|
||||||
|
// Sync from the test client
|
||||||
|
target.reset();
|
||||||
|
try {
|
||||||
|
await testObject.sync();
|
||||||
|
} catch (e) {
|
||||||
|
assert.ok(e instanceof UserDataSyncError);
|
||||||
|
assert.deepEqual((<UserDataSyncError>e).code, UserDataSyncErrorCode.SessionExpired);
|
||||||
|
assert.deepEqual(target.requests, [
|
||||||
|
// Manifest
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/manifest`, headers: {} },
|
||||||
|
]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw assert.fail('Should fail with turned off error');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('test sync status', async () => {
|
||||||
|
const target = new UserDataSyncTestServer();
|
||||||
|
|
||||||
|
// Setup the client
|
||||||
|
const client = disposableStore.add(new UserDataSyncClient(target));
|
||||||
|
await client.setUp();
|
||||||
|
const testObject = client.instantiationService.get(IUserDataSyncService);
|
||||||
|
|
||||||
|
// sync from the client
|
||||||
|
const actualStatuses: SyncStatus[] = [];
|
||||||
|
const disposable = testObject.onDidChangeStatus(status => actualStatuses.push(status));
|
||||||
|
await testObject.sync();
|
||||||
|
|
||||||
|
disposable.dispose();
|
||||||
|
assert.deepEqual(actualStatuses, [SyncStatus.Syncing, SyncStatus.Idle, SyncStatus.Syncing, SyncStatus.Idle, SyncStatus.Syncing, SyncStatus.Idle, SyncStatus.Syncing, SyncStatus.Idle]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('test sync conflicts status', async () => {
|
||||||
|
const target = new UserDataSyncTestServer();
|
||||||
|
|
||||||
|
// Setup and sync from the first client
|
||||||
|
const client = disposableStore.add(new UserDataSyncClient(target));
|
||||||
|
await client.setUp();
|
||||||
|
let fileService = client.instantiationService.get(IFileService);
|
||||||
|
let environmentService = client.instantiationService.get(IEnvironmentService);
|
||||||
|
await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString(JSON.stringify({ 'editor.fontSize': 14 })));
|
||||||
|
await client.instantiationService.get(IUserDataSyncService).sync();
|
||||||
|
|
||||||
|
// Setup the test client
|
||||||
|
const testClient = disposableStore.add(new UserDataSyncClient(target));
|
||||||
|
await testClient.setUp();
|
||||||
|
fileService = testClient.instantiationService.get(IFileService);
|
||||||
|
environmentService = testClient.instantiationService.get(IEnvironmentService);
|
||||||
|
await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString(JSON.stringify({ 'editor.fontSize': 16 })));
|
||||||
|
const testObject = testClient.instantiationService.get(IUserDataSyncService);
|
||||||
|
|
||||||
|
// sync from the client
|
||||||
|
await testObject.sync();
|
||||||
|
|
||||||
|
assert.deepEqual(testObject.status, SyncStatus.HasConflicts);
|
||||||
|
assert.deepEqual(testObject.conflictsSources, [SyncSource.Settings]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('test sync will sync other non conflicted areas', async () => {
|
||||||
|
const target = new UserDataSyncTestServer();
|
||||||
|
|
||||||
|
// Setup and sync from the first client
|
||||||
|
const client = disposableStore.add(new UserDataSyncClient(target));
|
||||||
|
await client.setUp();
|
||||||
|
let fileService = client.instantiationService.get(IFileService);
|
||||||
|
let environmentService = client.instantiationService.get(IEnvironmentService);
|
||||||
|
await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString(JSON.stringify({ 'editor.fontSize': 14 })));
|
||||||
|
await client.instantiationService.get(IUserDataSyncService).sync();
|
||||||
|
|
||||||
|
// Setup the test client and get conflicts in settings
|
||||||
|
const testClient = disposableStore.add(new UserDataSyncClient(target));
|
||||||
|
await testClient.setUp();
|
||||||
|
let testFileService = testClient.instantiationService.get(IFileService);
|
||||||
|
let testEnvironmentService = testClient.instantiationService.get(IEnvironmentService);
|
||||||
|
await testFileService.writeFile(testEnvironmentService.settingsResource, VSBuffer.fromString(JSON.stringify({ 'editor.fontSize': 16 })));
|
||||||
|
const testObject = testClient.instantiationService.get(IUserDataSyncService);
|
||||||
|
await testObject.sync();
|
||||||
|
|
||||||
|
// sync from the first client with changes in keybindings
|
||||||
|
await fileService.writeFile(environmentService.keybindingsResource, VSBuffer.fromString(JSON.stringify([{ 'command': 'abcd', 'key': 'cmd+c' }])));
|
||||||
|
await client.instantiationService.get(IUserDataSyncService).sync();
|
||||||
|
|
||||||
|
// sync from the test client
|
||||||
|
target.reset();
|
||||||
|
const actualStatuses: SyncStatus[] = [];
|
||||||
|
const disposable = testObject.onDidChangeStatus(status => actualStatuses.push(status));
|
||||||
|
await testObject.sync();
|
||||||
|
|
||||||
|
disposable.dispose();
|
||||||
|
assert.deepEqual(actualStatuses, []);
|
||||||
|
assert.deepEqual(testObject.status, SyncStatus.HasConflicts);
|
||||||
|
|
||||||
|
assert.deepEqual(target.requests, [
|
||||||
|
// Manifest
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/manifest`, headers: {} },
|
||||||
|
// Keybindings
|
||||||
|
{ type: 'GET', url: `${target.url}/v1/resource/keybindings/latest`, headers: { 'If-None-Match': '1' } },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('test stop sync reset status', async () => {
|
||||||
|
const target = new UserDataSyncTestServer();
|
||||||
|
|
||||||
|
// Setup and sync from the first client
|
||||||
|
const client = disposableStore.add(new UserDataSyncClient(target));
|
||||||
|
await client.setUp();
|
||||||
|
let fileService = client.instantiationService.get(IFileService);
|
||||||
|
let environmentService = client.instantiationService.get(IEnvironmentService);
|
||||||
|
await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString(JSON.stringify({ 'editor.fontSize': 14 })));
|
||||||
|
await client.instantiationService.get(IUserDataSyncService).sync();
|
||||||
|
|
||||||
|
// Setup the test client
|
||||||
|
const testClient = disposableStore.add(new UserDataSyncClient(target));
|
||||||
|
await testClient.setUp();
|
||||||
|
fileService = testClient.instantiationService.get(IFileService);
|
||||||
|
environmentService = testClient.instantiationService.get(IEnvironmentService);
|
||||||
|
await fileService.writeFile(environmentService.settingsResource, VSBuffer.fromString(JSON.stringify({ 'editor.fontSize': 16 })));
|
||||||
|
const testObject = testClient.instantiationService.get(IUserDataSyncService);
|
||||||
|
await testObject.sync();
|
||||||
|
|
||||||
|
// sync from the client
|
||||||
|
await testObject.stop();
|
||||||
|
|
||||||
|
assert.deepEqual(testObject.status, SyncStatus.Idle);
|
||||||
|
assert.deepEqual(testObject.conflictsSources, []);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
@@ -15,6 +15,9 @@ import { Registry } from 'vs/platform/registry/common/platform';
|
|||||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||||
import { ILogService } from 'vs/platform/log/common/log';
|
import { ILogService } from 'vs/platform/log/common/log';
|
||||||
import { CancellationTokenSource } from 'vs/base/common/cancellation';
|
import { CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||||
|
import { IWorkingCopyFileService } from 'vs/workbench/services/workingCopy/common/workingCopyFileService';
|
||||||
|
import { URI } from 'vs/base/common/uri';
|
||||||
|
import { IWaitUntil } from 'vs/base/common/event';
|
||||||
|
|
||||||
@extHostCustomer
|
@extHostCustomer
|
||||||
export class MainThreadFileSystemEventService {
|
export class MainThreadFileSystemEventService {
|
||||||
@@ -28,6 +31,7 @@ export class MainThreadFileSystemEventService {
|
|||||||
@IProgressService progressService: IProgressService,
|
@IProgressService progressService: IProgressService,
|
||||||
@IConfigurationService configService: IConfigurationService,
|
@IConfigurationService configService: IConfigurationService,
|
||||||
@ILogService logService: ILogService,
|
@ILogService logService: ILogService,
|
||||||
|
@IWorkingCopyFileService workingCopyFileService: IWorkingCopyFileService
|
||||||
) {
|
) {
|
||||||
|
|
||||||
const proxy = extHostContext.getProxy(ExtHostContext.ExtHostFileSystemEventService);
|
const proxy = extHostContext.getProxy(ExtHostContext.ExtHostFileSystemEventService);
|
||||||
@@ -38,7 +42,7 @@ export class MainThreadFileSystemEventService {
|
|||||||
changed: [],
|
changed: [],
|
||||||
deleted: []
|
deleted: []
|
||||||
};
|
};
|
||||||
this._listener.add(fileService.onFileChanges(event => {
|
this._listener.add(fileService.onDidFilesChange(event => {
|
||||||
for (let change of event.changes) {
|
for (let change of event.changes) {
|
||||||
switch (change.type) {
|
switch (change.type) {
|
||||||
case FileChangeType.ADDED:
|
case FileChangeType.ADDED:
|
||||||
@@ -66,9 +70,7 @@ export class MainThreadFileSystemEventService {
|
|||||||
messages.set(FileOperation.DELETE, localize('msg-delete', "Running 'File Delete' participants..."));
|
messages.set(FileOperation.DELETE, localize('msg-delete', "Running 'File Delete' participants..."));
|
||||||
messages.set(FileOperation.MOVE, localize('msg-rename', "Running 'File Rename' participants..."));
|
messages.set(FileOperation.MOVE, localize('msg-rename', "Running 'File Rename' participants..."));
|
||||||
|
|
||||||
|
function participateInFileOperation(e: IWaitUntil, operation: FileOperation, target: URI, source?: URI): void {
|
||||||
this._listener.add(textFileService.onWillRunOperation(e => {
|
|
||||||
|
|
||||||
const timeout = configService.getValue<number>('files.participants.timeout');
|
const timeout = configService.getValue<number>('files.participants.timeout');
|
||||||
if (timeout <= 0) {
|
if (timeout <= 0) {
|
||||||
return; // disabled
|
return; // disabled
|
||||||
@@ -76,19 +78,19 @@ export class MainThreadFileSystemEventService {
|
|||||||
|
|
||||||
const p = progressService.withProgress({ location: ProgressLocation.Window }, progress => {
|
const p = progressService.withProgress({ location: ProgressLocation.Window }, progress => {
|
||||||
|
|
||||||
progress.report({ message: messages.get(e.operation) });
|
progress.report({ message: messages.get(operation) });
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
|
||||||
const cts = new CancellationTokenSource();
|
const cts = new CancellationTokenSource();
|
||||||
|
|
||||||
const timeoutHandle = setTimeout(() => {
|
const timeoutHandle = setTimeout(() => {
|
||||||
logService.trace('CANCELLED file participants because of timeout', timeout, e.target, e.operation);
|
logService.trace('CANCELLED file participants because of timeout', timeout, target, operation);
|
||||||
cts.cancel();
|
cts.cancel();
|
||||||
reject(new Error('timeout'));
|
reject(new Error('timeout'));
|
||||||
}, timeout);
|
}, timeout);
|
||||||
|
|
||||||
proxy.$onWillRunFileOperation(e.operation, e.target, e.source, timeout, cts.token)
|
proxy.$onWillRunFileOperation(operation, target, source, timeout, cts.token)
|
||||||
.then(resolve, reject)
|
.then(resolve, reject)
|
||||||
.finally(() => clearTimeout(timeoutHandle));
|
.finally(() => clearTimeout(timeoutHandle));
|
||||||
});
|
});
|
||||||
@@ -96,10 +98,14 @@ export class MainThreadFileSystemEventService {
|
|||||||
});
|
});
|
||||||
|
|
||||||
e.waitUntil(p);
|
e.waitUntil(p);
|
||||||
}));
|
}
|
||||||
|
|
||||||
|
this._listener.add(textFileService.onWillCreateTextFile(e => participateInFileOperation(e, FileOperation.CREATE, e.resource)));
|
||||||
|
this._listener.add(workingCopyFileService.onBeforeWorkingCopyFileOperation(e => participateInFileOperation(e, e.operation, e.target, e.source)));
|
||||||
|
|
||||||
// AFTER file operation
|
// AFTER file operation
|
||||||
this._listener.add(textFileService.onDidRunOperation(e => proxy.$onDidRunFileOperation(e.operation, e.target, e.source)));
|
this._listener.add(textFileService.onDidCreateTextFile(e => proxy.$onDidRunFileOperation(FileOperation.CREATE, e.resource, undefined)));
|
||||||
|
this._listener.add(workingCopyFileService.onDidRunWorkingCopyFileOperation(e => proxy.$onDidRunFileOperation(e.operation, e.target, e.source)));
|
||||||
}
|
}
|
||||||
|
|
||||||
dispose(): void {
|
dispose(): void {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import * as search from 'vs/workbench/contrib/search/common/search';
|
|||||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||||
import { Position as EditorPosition } from 'vs/editor/common/core/position';
|
import { Position as EditorPosition } from 'vs/editor/common/core/position';
|
||||||
import { Range as EditorRange, IRange } from 'vs/editor/common/core/range';
|
import { Range as EditorRange, IRange } from 'vs/editor/common/core/range';
|
||||||
import { ExtHostContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, MainContext, IExtHostContext, ILanguageConfigurationDto, IRegExpDto, IIndentationRuleDto, IOnEnterRuleDto, ILocationDto, IWorkspaceSymbolDto, reviveWorkspaceEditDto, IDocumentFilterDto, IDefinitionLinkDto, ISignatureHelpProviderMetadataDto, ILinkDto, ICallHierarchyItemDto, ISuggestDataDto, ICodeActionDto, ISuggestDataDtoField, ISuggestResultDtoField, ICodeActionProviderMetadataDto } from '../common/extHost.protocol';
|
import { ExtHostContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, MainContext, IExtHostContext, ILanguageConfigurationDto, IRegExpDto, IIndentationRuleDto, IOnEnterRuleDto, ILocationDto, IWorkspaceSymbolDto, reviveWorkspaceEditDto, IDocumentFilterDto, IDefinitionLinkDto, ISignatureHelpProviderMetadataDto, ILinkDto, ICallHierarchyItemDto, ISuggestDataDto, ICodeActionDto, ISuggestDataDtoField, ISuggestResultDtoField, ICodeActionProviderMetadataDto, ILanguageWordDefinitionDto } from '../common/extHost.protocol';
|
||||||
import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
|
import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
|
||||||
import { LanguageConfiguration, IndentationRule, OnEnterRule } from 'vs/editor/common/modes/languageConfiguration';
|
import { LanguageConfiguration, IndentationRule, OnEnterRule } from 'vs/editor/common/modes/languageConfiguration';
|
||||||
import { IModeService } from 'vs/editor/common/services/modeService';
|
import { IModeService } from 'vs/editor/common/services/modeService';
|
||||||
@@ -36,6 +36,34 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
|||||||
) {
|
) {
|
||||||
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostLanguageFeatures);
|
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostLanguageFeatures);
|
||||||
this._modeService = modeService;
|
this._modeService = modeService;
|
||||||
|
|
||||||
|
if (this._modeService) {
|
||||||
|
const updateAllWordDefinitions = () => {
|
||||||
|
const langWordPairs = LanguageConfigurationRegistry.getWordDefinitions();
|
||||||
|
let wordDefinitionDtos: ILanguageWordDefinitionDto[] = [];
|
||||||
|
for (const [languageId, wordDefinition] of langWordPairs) {
|
||||||
|
const language = this._modeService.getLanguageIdentifier(languageId);
|
||||||
|
if (!language) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
wordDefinitionDtos.push({
|
||||||
|
languageId: language.language,
|
||||||
|
regexSource: wordDefinition.source,
|
||||||
|
regexFlags: wordDefinition.flags
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this._proxy.$setWordDefinitions(wordDefinitionDtos);
|
||||||
|
};
|
||||||
|
LanguageConfigurationRegistry.onDidChange((e) => {
|
||||||
|
const wordDefinition = LanguageConfigurationRegistry.getWordDefinition(e.languageIdentifier.id);
|
||||||
|
this._proxy.$setWordDefinitions([{
|
||||||
|
languageId: e.languageIdentifier.language,
|
||||||
|
regexSource: wordDefinition.source,
|
||||||
|
regexFlags: wordDefinition.flags
|
||||||
|
}]);
|
||||||
|
});
|
||||||
|
updateAllWordDefinitions();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dispose(): void {
|
dispose(): void {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user