mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-08 17:19:48 +01:00
Merge branch 'master' into misolori/icon-font-dialog
This commit is contained in:
Vendored
+1
@@ -131,6 +131,7 @@
|
||||
"linux": {
|
||||
"runtimeExecutable": "${workspaceFolder}/scripts/code.sh"
|
||||
},
|
||||
"port": 9222,
|
||||
"timeout": 20000,
|
||||
"env": {
|
||||
"VSCODE_EXTHOST_WILL_SEND_SOCKET": null
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
disturl "https://atom.io/download/electron"
|
||||
target "6.1.4"
|
||||
target "6.1.5"
|
||||
runtime "electron"
|
||||
|
||||
@@ -22,8 +22,6 @@ This repository ("`Code - OSS`") is where we (Microsoft) develop the [Visual Stu
|
||||
|
||||
Visual Studio Code is updated monthly with new features and bug fixes. You can download it for Windows, macOS, and Linux on [Visual Studio Code's website](https://code.visualstudio.com/Download). To get the latest releases every day, install the [Insiders build](https://code.visualstudio.com/insiders).
|
||||
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
There are many ways in which you can participate in the project, for example:
|
||||
@@ -52,11 +50,11 @@ please see the document [How to Contribute](https://github.com/Microsoft/vscode/
|
||||
|
||||
## Related Projects
|
||||
|
||||
Many of the core components and extensions to Code live in their own repositories on GitHub. For example, the [node debug adapter](https://github.com/microsoft/vscode-node-debug) and the [mono debug adapter](https://github.com/microsoft/vscode-mono-debug) have their own repositories. For a complete list, please visit the [Related Projects](https://github.com/Microsoft/vscode/wiki/Related-Projects) page on our [wiki](https://github.com/Microsoft/vscode/wiki).
|
||||
Many of the core components and extensions to VS Code live in their own repositories on GitHub. For example, the [node debug adapter](https://github.com/microsoft/vscode-node-debug) and the [mono debug adapter](https://github.com/microsoft/vscode-mono-debug) have their own repositories. For a complete list, please visit the [Related Projects](https://github.com/Microsoft/vscode/wiki/Related-Projects) page on our [wiki](https://github.com/Microsoft/vscode/wiki).
|
||||
|
||||
## Bundled Extensions
|
||||
|
||||
Code includes a set of built-in extensions located in the [extensions](extensions) folder, including grammars and snippets for many languages. Extensions that provide rich language support (code completion, Go to Definition) for a language have the suffix `language-features`. For example, the `json` extension provides coloring for `JSON` and the `json-language-features` provides rich language support for `JSON`.
|
||||
VS Code includes a set of built-in extensions located in the [extensions](extensions) folder, including grammars and snippets for many languages. Extensions that provide rich language support (code completion, Go to Definition) for a language have the suffix `language-features`. For example, the `json` extension provides coloring for `JSON` and the `json-language-features` provides rich language support for `JSON`.
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
|
||||
@@ -12,23 +12,24 @@ steps:
|
||||
vstsFeed: 'npm-vscode'
|
||||
platformIndependent: true
|
||||
alias: 'Compilation'
|
||||
dryRun: true
|
||||
|
||||
- task: NodeTool@0
|
||||
inputs:
|
||||
versionSpec: "12.13.0"
|
||||
condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true'))
|
||||
condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'))
|
||||
|
||||
- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2
|
||||
inputs:
|
||||
versionSpec: "1.x"
|
||||
condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true'))
|
||||
condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'))
|
||||
|
||||
- task: AzureKeyVault@1
|
||||
displayName: 'Azure Key Vault: Get Secrets'
|
||||
inputs:
|
||||
azureSubscription: 'vscode-builds-subscription'
|
||||
KeyVaultName: vscode
|
||||
condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true'))
|
||||
condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'))
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
@@ -41,7 +42,7 @@ steps:
|
||||
git config user.email "vscode@microsoft.com"
|
||||
git config user.name "VSCode"
|
||||
displayName: Prepare tooling
|
||||
condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true'))
|
||||
condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'))
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
@@ -49,33 +50,33 @@ steps:
|
||||
git fetch distro
|
||||
git merge $(node -p "require('./package.json').distro")
|
||||
displayName: Merge distro
|
||||
condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true'))
|
||||
condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'))
|
||||
|
||||
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
|
||||
inputs:
|
||||
keyfile: 'build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock'
|
||||
targetfolder: '**/node_modules, !**/node_modules/**/node_modules'
|
||||
vstsFeed: 'npm-vscode'
|
||||
condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true'))
|
||||
condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'))
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
CHILD_CONCURRENCY=1 yarn --frozen-lockfile
|
||||
displayName: Install dependencies
|
||||
condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true'), ne(variables['CacheRestored'], 'true'))
|
||||
condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), ne(variables['CacheRestored'], 'true'))
|
||||
|
||||
- task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1
|
||||
inputs:
|
||||
keyfile: 'build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock'
|
||||
targetfolder: '**/node_modules, !**/node_modules/**/node_modules'
|
||||
vstsFeed: 'npm-vscode'
|
||||
condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true'), ne(variables['CacheRestored'], 'true'))
|
||||
condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), ne(variables['CacheRestored'], 'true'))
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
yarn postinstall
|
||||
displayName: Run postinstall scripts
|
||||
condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true'), eq(variables['CacheRestored'], 'true'))
|
||||
condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), eq(variables['CacheRestored'], 'true'))
|
||||
|
||||
# Mixin must run before optimize, because the CSS loader will
|
||||
# inline small SVGs
|
||||
@@ -83,7 +84,7 @@ steps:
|
||||
set -e
|
||||
node build/azure-pipelines/mixin
|
||||
displayName: Mix in quality
|
||||
condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true'))
|
||||
condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'))
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
@@ -91,20 +92,20 @@ steps:
|
||||
yarn gulp tslint
|
||||
yarn monaco-compile-check
|
||||
displayName: Run hygiene, tslint and monaco compile checks
|
||||
condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true'), eq(variables['VSCODE_STEP_ON_IT'], 'false'))
|
||||
condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'), eq(variables['VSCODE_STEP_ON_IT'], 'false'))
|
||||
|
||||
- script: |
|
||||
set -
|
||||
./build/azure-pipelines/common/extract-telemetry.sh
|
||||
displayName: Extract Telemetry
|
||||
condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true'))
|
||||
condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'))
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
AZURE_WEBVIEW_STORAGE_ACCESS_KEY="$(vscode-webview-storage-key)" \
|
||||
./build/azure-pipelines/common/publish-webview.sh
|
||||
displayName: Publish Webview
|
||||
condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true'))
|
||||
condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'))
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
@@ -114,14 +115,14 @@ steps:
|
||||
yarn gulp minify-vscode-reh
|
||||
yarn gulp minify-vscode-reh-web
|
||||
displayName: Compile
|
||||
condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true'))
|
||||
condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'))
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
AZURE_STORAGE_ACCESS_KEY="$(ticino-storage-key)" \
|
||||
node build/azure-pipelines/upload-sourcemaps
|
||||
displayName: Upload sourcemaps
|
||||
condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true'))
|
||||
condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'))
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
@@ -129,7 +130,7 @@ steps:
|
||||
AZURE_DOCUMENTDB_MASTERKEY="$(builds-docdb-key-readwrite)" \
|
||||
node build/azure-pipelines/common/createBuild.js $VERSION
|
||||
displayName: Create build
|
||||
condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true'))
|
||||
condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'))
|
||||
|
||||
- task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1
|
||||
inputs:
|
||||
@@ -138,4 +139,4 @@ steps:
|
||||
vstsFeed: 'npm-vscode'
|
||||
platformIndependent: true
|
||||
alias: 'Compilation'
|
||||
condition: and(succeeded(), ne(variables['CacheRestored-Compilation'], 'true'))
|
||||
condition: and(succeeded(), ne(variables['CacheExists-Compilation'], 'true'))
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[
|
||||
{
|
||||
"name": "ms-vscode.node-debug",
|
||||
"version": "1.41.0",
|
||||
"version": "1.41.1",
|
||||
"repo": "https://github.com/Microsoft/vscode-node-debug",
|
||||
"metadata": {
|
||||
"id": "b6ded8fb-a0a0-4c1c-acbd-ab2a3bc995a6",
|
||||
|
||||
@@ -109,7 +109,8 @@ const tasks = compilations.map(function (tsconfigFile) {
|
||||
|
||||
const compileTask = task.define(`compile-extension:${name}`, task.series(cleanTask, () => {
|
||||
const pipeline = createPipeline(false, true);
|
||||
const input = pipeline.tsProjectSrc();
|
||||
const nonts = gulp.src(src, srcOpts).pipe(filter(['**', '!**/*.ts']));
|
||||
const input = es.merge(nonts, pipeline.tsProjectSrc());
|
||||
|
||||
return input
|
||||
.pipe(pipeline())
|
||||
@@ -118,7 +119,8 @@ const tasks = compilations.map(function (tsconfigFile) {
|
||||
|
||||
const watchTask = task.define(`watch-extension:${name}`, task.series(cleanTask, () => {
|
||||
const pipeline = createPipeline(false);
|
||||
const input = pipeline.tsProjectSrc();
|
||||
const nonts = gulp.src(src, srcOpts).pipe(filter(['**', '!**/*.ts']));
|
||||
const input = es.merge(nonts, pipeline.tsProjectSrc());
|
||||
const watchInput = watcher(src, { ...srcOpts, ...{ readDelay: 200 } });
|
||||
|
||||
return watchInput
|
||||
@@ -128,7 +130,8 @@ const tasks = compilations.map(function (tsconfigFile) {
|
||||
|
||||
const compileBuildTask = task.define(`compile-build-extension-${name}`, task.series(cleanTask, () => {
|
||||
const pipeline = createPipeline(true, true);
|
||||
const input = pipeline.tsProjectSrc();
|
||||
const nonts = gulp.src(src, srcOpts).pipe(filter(['**', '!**/*.ts']));
|
||||
const input = es.merge(nonts, pipeline.tsProjectSrc());
|
||||
|
||||
return input
|
||||
.pipe(pipeline())
|
||||
|
||||
+2
-2
@@ -60,12 +60,12 @@
|
||||
"git": {
|
||||
"name": "electron",
|
||||
"repositoryUrl": "https://github.com/electron/electron",
|
||||
"commitHash": "a5b474e8248803f54efc2c2c724c3322590c4fda"
|
||||
"commitHash": "6f62f91822a80192cb711c604f1a8f1a176f328d"
|
||||
}
|
||||
},
|
||||
"isOnlyProductionDependency": true,
|
||||
"license": "MIT",
|
||||
"version": "6.1.4"
|
||||
"version": "6.1.5"
|
||||
},
|
||||
{
|
||||
"component": {
|
||||
|
||||
@@ -18,6 +18,16 @@
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"remoteEnv": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"description": "Remote environment variables."
|
||||
},
|
||||
"extensions": {
|
||||
"type": "array",
|
||||
"description": "An array of extensions that should be installed into the container.",
|
||||
|
||||
@@ -22,6 +22,16 @@
|
||||
"$ref": "vscode://schemas/settings/machine",
|
||||
"description": "Machine specific settings that should be copied into the container."
|
||||
},
|
||||
"remoteEnv": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"description": "Remote environment variables."
|
||||
},
|
||||
"postCreateCommand": {
|
||||
"type": [
|
||||
"string",
|
||||
@@ -55,6 +65,13 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"containerEnv": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "Container environment variables."
|
||||
},
|
||||
"runArgs": {
|
||||
"type": "array",
|
||||
"description": "The arguments required when starting in the container.",
|
||||
|
||||
@@ -13,6 +13,6 @@ module.exports = withDefaults({
|
||||
context: __dirname,
|
||||
entry: {
|
||||
main: './src/main.ts',
|
||||
['askpass-main']: './src/askpass-main.ts'
|
||||
['askpass-main']: './src/askpass/askpass-main.ts'
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1194,7 +1194,7 @@
|
||||
{
|
||||
"command": "git.openFile",
|
||||
"group": "navigation",
|
||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
|
||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^gitfs$|^file$/"
|
||||
},
|
||||
{
|
||||
"command": "git.openChange",
|
||||
@@ -1204,44 +1204,44 @@
|
||||
{
|
||||
"command": "git.stageSelectedRanges",
|
||||
"group": "2_git@1",
|
||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
|
||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^gitfs$|^file$/"
|
||||
},
|
||||
{
|
||||
"command": "git.unstageSelectedRanges",
|
||||
"group": "2_git@2",
|
||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
|
||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^gitfs$|^file$/"
|
||||
},
|
||||
{
|
||||
"command": "git.revertSelectedRanges",
|
||||
"group": "2_git@3",
|
||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
|
||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^gitfs$|^file$/"
|
||||
}
|
||||
],
|
||||
"editor/context": [
|
||||
{
|
||||
"command": "git.stageSelectedRanges",
|
||||
"group": "2_git@1",
|
||||
"when": "isInDiffRightEditor && config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
|
||||
"when": "isInDiffRightEditor && config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^gitfs$|^file$/"
|
||||
},
|
||||
{
|
||||
"command": "git.unstageSelectedRanges",
|
||||
"group": "2_git@2",
|
||||
"when": "isInDiffRightEditor && config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
|
||||
"when": "isInDiffRightEditor && config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^gitfs$|^file$/"
|
||||
},
|
||||
{
|
||||
"command": "git.revertSelectedRanges",
|
||||
"group": "2_git@3",
|
||||
"when": "isInDiffRightEditor && config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
|
||||
"when": "isInDiffRightEditor && config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^gitfs$|^file$/"
|
||||
}
|
||||
],
|
||||
"scm/change/title": [
|
||||
{
|
||||
"command": "git.stageChange",
|
||||
"when": "originalResourceScheme == git"
|
||||
"when": "originalResourceScheme == gitfs"
|
||||
},
|
||||
{
|
||||
"command": "git.revertChange",
|
||||
"when": "originalResourceScheme == git"
|
||||
"when": "originalResourceScheme == gitfs"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -1608,12 +1608,6 @@
|
||||
"default": "mixed",
|
||||
"description": "%config.untrackedChanges%",
|
||||
"scope": "resource"
|
||||
},
|
||||
"git.restoreCommitTemplateComments": {
|
||||
"type": "boolean",
|
||||
"scope": "resource",
|
||||
"default": true,
|
||||
"description": "%config.restoreCommitTemplateComments%"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
"command.publish": "Publish Branch...",
|
||||
"command.showOutput": "Show Git Output",
|
||||
"command.ignore": "Add to .gitignore",
|
||||
"command.revealInExplorer": "Reveal in Explorer",
|
||||
"command.revealInExplorer": "Reveal in Side Bar",
|
||||
"command.stashIncludeUntracked": "Stash (Include Untracked)",
|
||||
"command.stash": "Stash",
|
||||
"command.stashPop": "Pop Stash...",
|
||||
@@ -139,7 +139,6 @@
|
||||
"config.untrackedChanges.mixed": "All changes, tracked and untracked, appear together and behave equally.",
|
||||
"config.untrackedChanges.separate": "Untracked changes appear separately in the Source Control view. They are also excluded from several actions.",
|
||||
"config.untrackedChanges.hidden": "Untracked changes are hidden and excluded from several actions.",
|
||||
"config.restoreCommitTemplateComments": "Controls whether to restore commit template comments in the commit input box.",
|
||||
"colors.added": "Color for added resources.",
|
||||
"colors.modified": "Color for modified resources.",
|
||||
"colors.deleted": "Color for deleted resources.",
|
||||
|
||||
@@ -8,6 +8,7 @@ import { Repository as BaseRepository, Resource } from '../repository';
|
||||
import { InputBox, Git, API, Repository, Remote, RepositoryState, Branch, Ref, Submodule, Commit, Change, RepositoryUIState, Status, LogOptions, APIState } from './git';
|
||||
import { Event, SourceControlInputBox, Uri, SourceControl } from 'vscode';
|
||||
import { mapEvent } from '../util';
|
||||
import { toGitUri } from '../uri';
|
||||
|
||||
class ApiInputBox implements InputBox {
|
||||
set value(value: string) { this._inputBox.value = value; }
|
||||
@@ -234,5 +235,9 @@ export class ApiImpl implements API {
|
||||
return this._model.repositories.map(r => new ApiRepository(r));
|
||||
}
|
||||
|
||||
toGitUri(uri: Uri, ref: string): Uri {
|
||||
return toGitUri(uri, ref);
|
||||
}
|
||||
|
||||
constructor(private _model: Model) { }
|
||||
}
|
||||
|
||||
Vendored
+2
@@ -185,6 +185,8 @@ export interface API {
|
||||
readonly repositories: Repository[];
|
||||
readonly onDidOpenRepository: Event<Repository>;
|
||||
readonly onDidCloseRepository: Event<Repository>;
|
||||
|
||||
toGitUri(uri: Uri, ref: string): Uri;
|
||||
}
|
||||
|
||||
export interface GitExtension {
|
||||
|
||||
@@ -1,119 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Disposable, window, InputBoxOptions } from 'vscode';
|
||||
import { denodeify } from './util';
|
||||
import * as path from 'path';
|
||||
import * as http from 'http';
|
||||
import * as os from 'os';
|
||||
import * as fs from 'fs';
|
||||
import * as crypto from 'crypto';
|
||||
|
||||
const randomBytes = denodeify<Buffer>(crypto.randomBytes);
|
||||
|
||||
export interface AskpassEnvironment {
|
||||
GIT_ASKPASS: string;
|
||||
ELECTRON_RUN_AS_NODE?: string;
|
||||
VSCODE_GIT_ASKPASS_NODE?: string;
|
||||
VSCODE_GIT_ASKPASS_MAIN?: string;
|
||||
VSCODE_GIT_ASKPASS_HANDLE?: string;
|
||||
}
|
||||
|
||||
function getIPCHandlePath(nonce: string): string {
|
||||
if (process.platform === 'win32') {
|
||||
return `\\\\.\\pipe\\vscode-git-askpass-${nonce}-sock`;
|
||||
}
|
||||
|
||||
if (process.env['XDG_RUNTIME_DIR']) {
|
||||
return path.join(process.env['XDG_RUNTIME_DIR'] as string, `vscode-git-askpass-${nonce}.sock`);
|
||||
}
|
||||
|
||||
return path.join(os.tmpdir(), `vscode-git-askpass-${nonce}.sock`);
|
||||
}
|
||||
|
||||
export class Askpass implements Disposable {
|
||||
|
||||
private server: http.Server;
|
||||
private ipcHandlePathPromise: Promise<string>;
|
||||
private ipcHandlePath: string | undefined;
|
||||
private enabled = true;
|
||||
|
||||
constructor() {
|
||||
this.server = http.createServer((req, res) => this.onRequest(req, res));
|
||||
this.ipcHandlePathPromise = this.setup().catch(err => {
|
||||
console.error(err);
|
||||
return '';
|
||||
});
|
||||
}
|
||||
|
||||
private async setup(): Promise<string> {
|
||||
const buffer = await randomBytes(20);
|
||||
const nonce = buffer.toString('hex');
|
||||
const ipcHandlePath = getIPCHandlePath(nonce);
|
||||
this.ipcHandlePath = ipcHandlePath;
|
||||
|
||||
try {
|
||||
this.server.listen(ipcHandlePath);
|
||||
this.server.on('error', err => console.error(err));
|
||||
} catch (err) {
|
||||
console.error('Could not launch git askpass helper.');
|
||||
this.enabled = false;
|
||||
}
|
||||
|
||||
return ipcHandlePath;
|
||||
}
|
||||
|
||||
private onRequest(req: http.IncomingMessage, res: http.ServerResponse): void {
|
||||
const chunks: string[] = [];
|
||||
req.setEncoding('utf8');
|
||||
req.on('data', (d: string) => chunks.push(d));
|
||||
req.on('end', () => {
|
||||
const { request, host } = JSON.parse(chunks.join(''));
|
||||
|
||||
this.prompt(host, request).then(result => {
|
||||
res.writeHead(200);
|
||||
res.end(JSON.stringify(result));
|
||||
}, () => {
|
||||
res.writeHead(500);
|
||||
res.end();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private async prompt(host: string, request: string): Promise<string> {
|
||||
const options: InputBoxOptions = {
|
||||
password: /password/i.test(request),
|
||||
placeHolder: request,
|
||||
prompt: `Git: ${host}`,
|
||||
ignoreFocusOut: true
|
||||
};
|
||||
|
||||
return await window.showInputBox(options) || '';
|
||||
}
|
||||
|
||||
async getEnv(): Promise<AskpassEnvironment> {
|
||||
if (!this.enabled) {
|
||||
return {
|
||||
GIT_ASKPASS: path.join(__dirname, 'askpass-empty.sh')
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
ELECTRON_RUN_AS_NODE: '1',
|
||||
GIT_ASKPASS: path.join(__dirname, 'askpass.sh'),
|
||||
VSCODE_GIT_ASKPASS_NODE: process.execPath,
|
||||
VSCODE_GIT_ASKPASS_MAIN: path.join(__dirname, 'askpass-main.js'),
|
||||
VSCODE_GIT_ASKPASS_HANDLE: await this.ipcHandlePathPromise
|
||||
};
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.server.close();
|
||||
|
||||
if (this.ipcHandlePath && process.platform !== 'win32') {
|
||||
fs.unlinkSync(this.ipcHandlePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,9 +3,9 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as http from 'http';
|
||||
import * as fs from 'fs';
|
||||
import * as nls from 'vscode-nls';
|
||||
import { IPCClient } from '../ipc/ipcClient';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
@@ -20,10 +20,6 @@ function main(argv: string[]): void {
|
||||
return fatal('Wrong number of arguments');
|
||||
}
|
||||
|
||||
if (!process.env['VSCODE_GIT_ASKPASS_HANDLE']) {
|
||||
return fatal('Missing handle');
|
||||
}
|
||||
|
||||
if (!process.env['VSCODE_GIT_ASKPASS_PIPE']) {
|
||||
return fatal('Missing pipe');
|
||||
}
|
||||
@@ -33,40 +29,14 @@ function main(argv: string[]): void {
|
||||
}
|
||||
|
||||
const output = process.env['VSCODE_GIT_ASKPASS_PIPE'] as string;
|
||||
const socketPath = process.env['VSCODE_GIT_ASKPASS_HANDLE'] as string;
|
||||
const request = argv[2];
|
||||
const host = argv[4].substring(1, argv[4].length - 2);
|
||||
const opts: http.RequestOptions = {
|
||||
socketPath,
|
||||
path: '/',
|
||||
method: 'POST'
|
||||
};
|
||||
const ipcClient = new IPCClient('askpass');
|
||||
|
||||
const req = http.request(opts, res => {
|
||||
if (res.statusCode !== 200) {
|
||||
return fatal(`Bad status code: ${res.statusCode}`);
|
||||
}
|
||||
|
||||
const chunks: string[] = [];
|
||||
res.setEncoding('utf8');
|
||||
res.on('data', (d: string) => chunks.push(d));
|
||||
res.on('end', () => {
|
||||
const raw = chunks.join('');
|
||||
|
||||
try {
|
||||
const result = JSON.parse(raw);
|
||||
fs.writeFileSync(output, result + '\n');
|
||||
} catch (err) {
|
||||
return fatal(`Error parsing response`);
|
||||
}
|
||||
|
||||
setTimeout(() => process.exit(0), 0);
|
||||
});
|
||||
});
|
||||
|
||||
req.on('error', () => fatal('Error in request'));
|
||||
req.write(JSON.stringify({ request, host }));
|
||||
req.end();
|
||||
ipcClient.call({ request, host }).then(res => {
|
||||
fs.writeFileSync(output, res + '\n');
|
||||
setTimeout(() => process.exit(0), 0);
|
||||
}).catch(err => fatal(err));
|
||||
}
|
||||
|
||||
main(process.argv);
|
||||
@@ -0,0 +1,56 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { window, InputBoxOptions } from 'vscode';
|
||||
import { IDisposable } from '../util';
|
||||
import * as path from 'path';
|
||||
import { IIPCHandler, IIPCServer } from '../ipc/ipcServer';
|
||||
|
||||
export interface AskpassEnvironment {
|
||||
GIT_ASKPASS: string;
|
||||
ELECTRON_RUN_AS_NODE?: string;
|
||||
VSCODE_GIT_ASKPASS_NODE?: string;
|
||||
VSCODE_GIT_ASKPASS_MAIN?: string;
|
||||
VSCODE_GIT_ASKPASS_HANDLE?: string;
|
||||
}
|
||||
|
||||
export class Askpass implements IIPCHandler {
|
||||
|
||||
private disposable: IDisposable;
|
||||
|
||||
static getDisabledEnv(): AskpassEnvironment {
|
||||
return {
|
||||
GIT_ASKPASS: path.join(__dirname, 'askpass-empty.sh')
|
||||
};
|
||||
}
|
||||
|
||||
constructor(ipc: IIPCServer) {
|
||||
this.disposable = ipc.registerHandler('askpass', this);
|
||||
}
|
||||
|
||||
async handle({ request, host }: { request: string, host: string }): Promise<string> {
|
||||
const options: InputBoxOptions = {
|
||||
password: /password/i.test(request),
|
||||
placeHolder: request,
|
||||
prompt: `Git: ${host}`,
|
||||
ignoreFocusOut: true
|
||||
};
|
||||
|
||||
return await window.showInputBox(options) || '';
|
||||
}
|
||||
|
||||
getEnv(): AskpassEnvironment {
|
||||
return {
|
||||
ELECTRON_RUN_AS_NODE: '1',
|
||||
GIT_ASKPASS: path.join(__dirname, 'askpass.sh'),
|
||||
VSCODE_GIT_ASKPASS_NODE: process.execPath,
|
||||
VSCODE_GIT_ASKPASS_MAIN: path.join(__dirname, 'askpass-main.js')
|
||||
};
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.disposable.dispose();
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ import { CommitOptions, ForcePushMode, Git, Stash } from './git';
|
||||
import { Model } from './model';
|
||||
import { Repository, Resource, ResourceGroupType } from './repository';
|
||||
import { applyLineChanges, getModifiedRange, intersectDiffWithRange, invertLineChange, toLineRanges } from './staging';
|
||||
import { fromGitUri, toGitUri } from './uri';
|
||||
import { fromGitUri, toGitUri, isGitUri } from './uri';
|
||||
import { grep, isDescendant, pathEquals } from './util';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
@@ -170,14 +170,14 @@ function command(commandId: string, options: CommandOptions = {}): Function {
|
||||
};
|
||||
}
|
||||
|
||||
const ImageMimetypes = [
|
||||
'image/png',
|
||||
'image/gif',
|
||||
'image/jpeg',
|
||||
'image/webp',
|
||||
'image/tiff',
|
||||
'image/bmp'
|
||||
];
|
||||
// const ImageMimetypes = [
|
||||
// 'image/png',
|
||||
// 'image/gif',
|
||||
// 'image/jpeg',
|
||||
// 'image/webp',
|
||||
// 'image/tiff',
|
||||
// 'image/bmp'
|
||||
// ];
|
||||
|
||||
async function categorizeResourceByResolution(resources: Resource[]): Promise<{ merge: Resource[], resolved: Resource[], unresolved: Resource[], deletionConflicts: Resource[] }> {
|
||||
const selection = resources.filter(s => s instanceof Resource) as Resource[];
|
||||
@@ -295,10 +295,10 @@ export class CommandCenter {
|
||||
}
|
||||
} else {
|
||||
if (resource.type !== Status.DELETED_BY_THEM) {
|
||||
left = await this.getLeftResource(resource);
|
||||
left = this.getLeftResource(resource);
|
||||
}
|
||||
|
||||
right = await this.getRightResource(resource);
|
||||
right = this.getRightResource(resource);
|
||||
}
|
||||
|
||||
const title = this.getTitle(resource);
|
||||
@@ -330,79 +330,40 @@ export class CommandCenter {
|
||||
}
|
||||
}
|
||||
|
||||
private async getURI(uri: Uri, ref: string): Promise<Uri | undefined> {
|
||||
const repository = this.model.getRepository(uri);
|
||||
|
||||
if (!repository) {
|
||||
return toGitUri(uri, ref);
|
||||
}
|
||||
|
||||
try {
|
||||
let gitRef = ref;
|
||||
|
||||
if (gitRef === '~') {
|
||||
const uriString = uri.toString();
|
||||
const [indexStatus] = repository.indexGroup.resourceStates.filter(r => r.resourceUri.toString() === uriString);
|
||||
gitRef = indexStatus ? '' : 'HEAD';
|
||||
}
|
||||
|
||||
const { size, object } = await repository.getObjectDetails(gitRef, uri.fsPath);
|
||||
const { mimetype } = await repository.detectObjectType(object);
|
||||
|
||||
if (mimetype === 'text/plain') {
|
||||
return toGitUri(uri, ref);
|
||||
}
|
||||
|
||||
if (size > 1000000) { // 1 MB
|
||||
return Uri.parse(`data:;label:${path.basename(uri.fsPath)};description:${gitRef},`);
|
||||
}
|
||||
|
||||
if (ImageMimetypes.indexOf(mimetype) > -1) {
|
||||
const contents = await repository.buffer(gitRef, uri.fsPath);
|
||||
return Uri.parse(`data:${mimetype};label:${path.basename(uri.fsPath)};description:${gitRef};size:${size};base64,${contents.toString('base64')}`);
|
||||
}
|
||||
|
||||
return Uri.parse(`data:;label:${path.basename(uri.fsPath)};description:${gitRef},`);
|
||||
|
||||
} catch (err) {
|
||||
return toGitUri(uri, ref);
|
||||
}
|
||||
}
|
||||
|
||||
private async getLeftResource(resource: Resource): Promise<Uri | undefined> {
|
||||
private getLeftResource(resource: Resource): Uri | undefined {
|
||||
switch (resource.type) {
|
||||
case Status.INDEX_MODIFIED:
|
||||
case Status.INDEX_RENAMED:
|
||||
case Status.INDEX_ADDED:
|
||||
return this.getURI(resource.original, 'HEAD');
|
||||
return toGitUri(resource.original, 'HEAD');
|
||||
|
||||
case Status.MODIFIED:
|
||||
case Status.UNTRACKED:
|
||||
return this.getURI(resource.resourceUri, '~');
|
||||
return toGitUri(resource.resourceUri, '~');
|
||||
|
||||
case Status.DELETED_BY_THEM:
|
||||
return this.getURI(resource.resourceUri, '');
|
||||
return toGitUri(resource.resourceUri, '');
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private async getRightResource(resource: Resource): Promise<Uri | undefined> {
|
||||
private getRightResource(resource: Resource): Uri | undefined {
|
||||
switch (resource.type) {
|
||||
case Status.INDEX_MODIFIED:
|
||||
case Status.INDEX_ADDED:
|
||||
case Status.INDEX_COPIED:
|
||||
case Status.INDEX_RENAMED:
|
||||
return this.getURI(resource.resourceUri, '');
|
||||
return toGitUri(resource.resourceUri, '');
|
||||
|
||||
case Status.INDEX_DELETED:
|
||||
case Status.DELETED:
|
||||
return this.getURI(resource.resourceUri, 'HEAD');
|
||||
return toGitUri(resource.resourceUri, 'HEAD');
|
||||
|
||||
case Status.DELETED_BY_US:
|
||||
return this.getURI(resource.resourceUri, '~3');
|
||||
return toGitUri(resource.resourceUri, '~3');
|
||||
|
||||
case Status.DELETED_BY_THEM:
|
||||
return this.getURI(resource.resourceUri, '~2');
|
||||
return toGitUri(resource.resourceUri, '~2');
|
||||
|
||||
case Status.MODIFIED:
|
||||
case Status.UNTRACKED:
|
||||
@@ -692,7 +653,7 @@ export class CommandCenter {
|
||||
let uris: Uri[] | undefined;
|
||||
|
||||
if (arg instanceof Uri) {
|
||||
if (arg.scheme === 'git') {
|
||||
if (isGitUri(arg)) {
|
||||
uris = [Uri.file(fromGitUri(arg).path)];
|
||||
} else if (arg.scheme === 'file') {
|
||||
uris = [arg];
|
||||
@@ -771,7 +732,7 @@ export class CommandCenter {
|
||||
return;
|
||||
}
|
||||
|
||||
const HEAD = await this.getLeftResource(resource);
|
||||
const HEAD = this.getLeftResource(resource);
|
||||
const basename = path.basename(resource.resourceUri.fsPath);
|
||||
const title = `${basename} (HEAD)`;
|
||||
|
||||
@@ -1117,7 +1078,7 @@ export class CommandCenter {
|
||||
const modifiedDocument = textEditor.document;
|
||||
const modifiedUri = modifiedDocument.uri;
|
||||
|
||||
if (modifiedUri.scheme !== 'git') {
|
||||
if (!isGitUri(modifiedUri)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1445,6 +1406,7 @@ export class CommandCenter {
|
||||
const message = repository.inputBox.value;
|
||||
const getCommitMessage = async () => {
|
||||
let _message: string | undefined = message;
|
||||
|
||||
if (!_message) {
|
||||
let value: string | undefined = undefined;
|
||||
|
||||
@@ -1469,7 +1431,7 @@ export class CommandCenter {
|
||||
});
|
||||
}
|
||||
|
||||
return _message ? repository.cleanUpCommitEditMessage(_message) : _message;
|
||||
return _message;
|
||||
};
|
||||
|
||||
const didCommit = await this.smartCommit(repository, getCommitMessage, opts);
|
||||
@@ -2162,9 +2124,14 @@ export class CommandCenter {
|
||||
return;
|
||||
}
|
||||
|
||||
const branchName = repository.HEAD && repository.HEAD.name || '';
|
||||
|
||||
if (remotes.length === 1) {
|
||||
return await repository.pushTo(remotes[0].name, branchName, true);
|
||||
}
|
||||
|
||||
const addRemote = new AddRemoteItem(this);
|
||||
const picks = [...repository.remotes.map(r => ({ label: r.name, description: r.pushUrl })), addRemote];
|
||||
const branchName = repository.HEAD && repository.HEAD.name || '';
|
||||
const placeHolder = localize('pick remote', "Pick a remote to publish the branch '{0}' to:", branchName);
|
||||
const choice = await window.showQuickPick(picks, { placeHolder });
|
||||
|
||||
@@ -2454,7 +2421,7 @@ export class CommandCenter {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (uri.scheme === 'git') {
|
||||
if (isGitUri(uri)) {
|
||||
const { path } = fromGitUri(uri);
|
||||
uri = Uri.file(path);
|
||||
}
|
||||
|
||||
@@ -147,4 +147,4 @@ export class GitContentProvider {
|
||||
dispose(): void {
|
||||
this.disposables.forEach(d => d.dispose());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,199 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { workspace, Uri, Disposable, Event, EventEmitter, window, FileSystemProvider, FileChangeEvent, FileStat, FileType, FileChangeType, FileSystemError } from 'vscode';
|
||||
import { debounce, throttle } from './decorators';
|
||||
import { fromGitUri, toGitUri } from './uri';
|
||||
import { Model, ModelChangeEvent, OriginalResourceChangeEvent } from './model';
|
||||
import { filterEvent, eventToPromise, isDescendant, pathEquals, EmptyDisposable } from './util';
|
||||
|
||||
interface CacheRow {
|
||||
uri: Uri;
|
||||
timestamp: number;
|
||||
}
|
||||
|
||||
const THREE_MINUTES = 1000 * 60 * 3;
|
||||
const FIVE_MINUTES = 1000 * 60 * 5;
|
||||
|
||||
export class GitFileSystemProvider implements FileSystemProvider {
|
||||
|
||||
private _onDidChangeFile = new EventEmitter<FileChangeEvent[]>();
|
||||
readonly onDidChangeFile: Event<FileChangeEvent[]> = this._onDidChangeFile.event;
|
||||
|
||||
private changedRepositoryRoots = new Set<string>();
|
||||
private cache = new Map<string, CacheRow>();
|
||||
private mtime = new Date().getTime();
|
||||
private disposables: Disposable[] = [];
|
||||
|
||||
constructor(private model: Model) {
|
||||
this.disposables.push(
|
||||
model.onDidChangeRepository(this.onDidChangeRepository, this),
|
||||
model.onDidChangeOriginalResource(this.onDidChangeOriginalResource, this),
|
||||
workspace.registerFileSystemProvider('gitfs', this, { isReadonly: true, isCaseSensitive: true }),
|
||||
workspace.registerResourceLabelFormatter({
|
||||
scheme: 'gitfs',
|
||||
formatting: {
|
||||
label: '${path} (git)',
|
||||
separator: '/'
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
setInterval(() => this.cleanup(), FIVE_MINUTES);
|
||||
}
|
||||
|
||||
private onDidChangeRepository({ repository }: ModelChangeEvent): void {
|
||||
this.changedRepositoryRoots.add(repository.root);
|
||||
this.eventuallyFireChangeEvents();
|
||||
}
|
||||
|
||||
private onDidChangeOriginalResource({ uri }: OriginalResourceChangeEvent): void {
|
||||
if (uri.scheme !== 'file') {
|
||||
return;
|
||||
}
|
||||
|
||||
const gitUri = toGitUri(uri, '', { replaceFileExtension: true });
|
||||
this.mtime = new Date().getTime();
|
||||
this._onDidChangeFile.fire([{ type: FileChangeType.Changed, uri: gitUri }]);
|
||||
}
|
||||
|
||||
@debounce(1100)
|
||||
private eventuallyFireChangeEvents(): void {
|
||||
this.fireChangeEvents();
|
||||
}
|
||||
|
||||
@throttle
|
||||
private async fireChangeEvents(): Promise<void> {
|
||||
if (!window.state.focused) {
|
||||
const onDidFocusWindow = filterEvent(window.onDidChangeWindowState, e => e.focused);
|
||||
await eventToPromise(onDidFocusWindow);
|
||||
}
|
||||
|
||||
const events: FileChangeEvent[] = [];
|
||||
|
||||
for (const { uri } of this.cache.values()) {
|
||||
const fsPath = uri.fsPath;
|
||||
|
||||
for (const root of this.changedRepositoryRoots) {
|
||||
if (isDescendant(root, fsPath)) {
|
||||
events.push({ type: FileChangeType.Changed, uri });
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (events.length > 0) {
|
||||
this.mtime = new Date().getTime();
|
||||
this._onDidChangeFile.fire(events);
|
||||
}
|
||||
|
||||
this.changedRepositoryRoots.clear();
|
||||
}
|
||||
|
||||
private cleanup(): void {
|
||||
const now = new Date().getTime();
|
||||
const cache = new Map<string, CacheRow>();
|
||||
|
||||
for (const row of this.cache.values()) {
|
||||
const { path } = fromGitUri(row.uri);
|
||||
const isOpen = workspace.textDocuments
|
||||
.filter(d => d.uri.scheme === 'file')
|
||||
.some(d => pathEquals(d.uri.fsPath, path));
|
||||
|
||||
if (isOpen || now - row.timestamp < THREE_MINUTES) {
|
||||
cache.set(row.uri.toString(), row);
|
||||
} else {
|
||||
// TODO: should fire delete events?
|
||||
}
|
||||
}
|
||||
|
||||
this.cache = cache;
|
||||
}
|
||||
|
||||
watch(): Disposable {
|
||||
return EmptyDisposable;
|
||||
}
|
||||
|
||||
stat(uri: Uri): FileStat {
|
||||
const { submoduleOf } = fromGitUri(uri);
|
||||
const repository = submoduleOf ? this.model.getRepository(submoduleOf) : this.model.getRepository(uri);
|
||||
|
||||
if (!repository) {
|
||||
throw FileSystemError.FileNotFound();
|
||||
}
|
||||
|
||||
return { type: FileType.File, size: 0, mtime: this.mtime, ctime: 0 };
|
||||
}
|
||||
|
||||
readDirectory(): Thenable<[string, FileType][]> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
createDirectory(): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
async readFile(uri: Uri): Promise<Uint8Array> {
|
||||
let { path, ref, submoduleOf } = fromGitUri(uri);
|
||||
|
||||
if (submoduleOf) {
|
||||
const repository = this.model.getRepository(submoduleOf);
|
||||
|
||||
if (!repository) {
|
||||
throw FileSystemError.FileNotFound();
|
||||
}
|
||||
|
||||
const encoder = new TextEncoder();
|
||||
|
||||
if (ref === 'index') {
|
||||
return encoder.encode(await repository.diffIndexWithHEAD(path));
|
||||
} else {
|
||||
return encoder.encode(await repository.diffWithHEAD(path));
|
||||
}
|
||||
}
|
||||
|
||||
const repository = this.model.getRepository(uri);
|
||||
|
||||
if (!repository) {
|
||||
throw FileSystemError.FileNotFound();
|
||||
}
|
||||
|
||||
const timestamp = new Date().getTime();
|
||||
const cacheValue: CacheRow = { uri, timestamp };
|
||||
|
||||
this.cache.set(uri.toString(), cacheValue);
|
||||
|
||||
if (ref === '~') {
|
||||
const fileUri = Uri.file(path);
|
||||
const uriString = fileUri.toString();
|
||||
const [indexStatus] = repository.indexGroup.resourceStates.filter(r => r.resourceUri.toString() === uriString);
|
||||
ref = indexStatus ? '' : 'HEAD';
|
||||
} else if (/^~\d$/.test(ref)) {
|
||||
ref = `:${ref[1]}`;
|
||||
}
|
||||
|
||||
try {
|
||||
return await repository.buffer(ref, path);
|
||||
} catch (err) {
|
||||
return new Uint8Array(0);
|
||||
}
|
||||
}
|
||||
|
||||
writeFile(): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
delete(): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
rename(): void {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.disposables.forEach(d => d.dispose());
|
||||
}
|
||||
}
|
||||
+11
-23
@@ -3,7 +3,7 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as fs from 'fs';
|
||||
import { promises as fs, exists } from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as os from 'os';
|
||||
import * as cp from 'child_process';
|
||||
@@ -11,7 +11,7 @@ import * as which from 'which';
|
||||
import { EventEmitter } from 'events';
|
||||
import iconv = require('iconv-lite');
|
||||
import * as filetype from 'file-type';
|
||||
import { assign, groupBy, denodeify, IDisposable, toDisposable, dispose, mkdirp, readBytes, detectUnicodeEncoding, Encoding, onceEvent, splitInChunks, Limiter } from './util';
|
||||
import { assign, groupBy, IDisposable, toDisposable, dispose, mkdirp, readBytes, detectUnicodeEncoding, Encoding, onceEvent, splitInChunks, Limiter } from './util';
|
||||
import { CancellationToken, Progress } from 'vscode';
|
||||
import { URI } from 'vscode-uri';
|
||||
import { detectEncoding } from './encoding';
|
||||
@@ -22,8 +22,6 @@ import { StringDecoder } from 'string_decoder';
|
||||
// https://github.com/microsoft/vscode/issues/65693
|
||||
const MAX_CLI_LENGTH = 30000;
|
||||
|
||||
const readfile = denodeify<string, string | null, string>(fs.readFile);
|
||||
|
||||
export interface IGit {
|
||||
path: string;
|
||||
version: string;
|
||||
@@ -350,7 +348,7 @@ export class Git {
|
||||
let folderPath = path.join(parentPath, folderName);
|
||||
let count = 1;
|
||||
|
||||
while (count < 20 && await new Promise(c => fs.exists(folderPath, c))) {
|
||||
while (count < 20 && await new Promise(c => exists(folderPath, c))) {
|
||||
folderName = `${baseFolderName}-${count++}`;
|
||||
folderPath = path.join(parentPath, folderName);
|
||||
}
|
||||
@@ -1812,26 +1810,17 @@ export class Repository {
|
||||
}
|
||||
}
|
||||
|
||||
cleanupCommitEditMessage(message: string): string {
|
||||
// If the message is a single line starting with whitespace followed by `#`, just allow it.
|
||||
if (/^\s*#[^\n]*$/.test(message)) {
|
||||
return message;
|
||||
}
|
||||
|
||||
// Else, remove all lines starting with whitespace followed by `#`.
|
||||
// TODO: Support core.commentChar
|
||||
return message.replace(/^(\s*#)(.*)$(\n?)/gm, (_, prefix, content, suffix) => {
|
||||
// https://github.com/microsoft/vscode/issues/84201#issuecomment-552834814
|
||||
return /^\d/.test(content) ? `${prefix}${content}${suffix}` : '';
|
||||
}).trim();
|
||||
// TODO: Support core.commentChar
|
||||
stripCommitMessageComments(message: string): string {
|
||||
return message.replace(/^\s*#.*$\n?/gm, '').trim();
|
||||
}
|
||||
|
||||
async getMergeMessage(): Promise<string | undefined> {
|
||||
const mergeMsgPath = path.join(this.repositoryRoot, '.git', 'MERGE_MSG');
|
||||
|
||||
try {
|
||||
const raw = await readfile(mergeMsgPath, 'utf8');
|
||||
return raw.trim();
|
||||
const raw = await fs.readFile(mergeMsgPath, 'utf8');
|
||||
return this.stripCommitMessageComments(raw);
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
@@ -1854,9 +1843,8 @@ export class Repository {
|
||||
templatePath = path.join(this.repositoryRoot, templatePath);
|
||||
}
|
||||
|
||||
const raw = await readfile(templatePath, 'utf8');
|
||||
return raw.trim();
|
||||
|
||||
const raw = await fs.readFile(templatePath, 'utf8');
|
||||
return this.stripCommitMessageComments(raw);
|
||||
} catch (err) {
|
||||
return '';
|
||||
}
|
||||
@@ -1879,7 +1867,7 @@ export class Repository {
|
||||
const gitmodulesPath = path.join(this.root, '.gitmodules');
|
||||
|
||||
try {
|
||||
const gitmodulesRaw = await readfile(gitmodulesPath, 'utf8');
|
||||
const gitmodulesRaw = await fs.readFile(gitmodulesPath, 'utf8');
|
||||
return parseGitmodules(gitmodulesRaw);
|
||||
} catch (err) {
|
||||
if (/ENOENT/.test(err.message)) {
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as http from 'http';
|
||||
|
||||
export class IPCClient {
|
||||
|
||||
private ipcHandlePath: string;
|
||||
|
||||
constructor(private handlerName: string) {
|
||||
const ipcHandlePath = process.env['VSCODE_GIT_IPC_HANDLE'];
|
||||
|
||||
if (!ipcHandlePath) {
|
||||
throw new Error('Missing VSCODE_GIT_IPC_HANDLE');
|
||||
}
|
||||
|
||||
this.ipcHandlePath = ipcHandlePath;
|
||||
}
|
||||
|
||||
call(request: any): Promise<any> {
|
||||
const opts: http.RequestOptions = {
|
||||
socketPath: this.ipcHandlePath,
|
||||
path: `/${this.handlerName}`,
|
||||
method: 'POST'
|
||||
};
|
||||
|
||||
return new Promise((c, e) => {
|
||||
const req = http.request(opts, res => {
|
||||
if (res.statusCode !== 200) {
|
||||
return e(new Error(`Bad status code: ${res.statusCode}`));
|
||||
}
|
||||
|
||||
const chunks: Buffer[] = [];
|
||||
res.on('data', d => chunks.push(d));
|
||||
res.on('end', () => c(JSON.parse(Buffer.concat(chunks).toString('utf8'))));
|
||||
});
|
||||
|
||||
req.on('error', err => e(err));
|
||||
req.write(JSON.stringify(request));
|
||||
req.end();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Disposable } from 'vscode';
|
||||
import { toDisposable } from '../util';
|
||||
import * as path from 'path';
|
||||
import * as http from 'http';
|
||||
import * as os from 'os';
|
||||
import * as fs from 'fs';
|
||||
import * as crypto from 'crypto';
|
||||
|
||||
function getIPCHandlePath(nonce: string): string {
|
||||
if (process.platform === 'win32') {
|
||||
return `\\\\.\\pipe\\vscode-git-ipc-${nonce}-sock`;
|
||||
}
|
||||
|
||||
if (process.env['XDG_RUNTIME_DIR']) {
|
||||
return path.join(process.env['XDG_RUNTIME_DIR'] as string, `vscode-git-ipc-${nonce}.sock`);
|
||||
}
|
||||
|
||||
return path.join(os.tmpdir(), `vscode-git-ipc-${nonce}.sock`);
|
||||
}
|
||||
|
||||
export interface IIPCHandler {
|
||||
handle(request: any): Promise<any>;
|
||||
}
|
||||
|
||||
export async function createIPCServer(): Promise<IIPCServer> {
|
||||
const server = http.createServer();
|
||||
const buffer = await new Promise<Buffer>((c, e) => crypto.randomBytes(20, (err, buf) => err ? e(err) : c(buf)));
|
||||
const nonce = buffer.toString('hex');
|
||||
const ipcHandlePath = getIPCHandlePath(nonce);
|
||||
|
||||
return new Promise((c, e) => {
|
||||
try {
|
||||
server.on('error', err => e(err));
|
||||
server.listen(ipcHandlePath);
|
||||
c(new IPCServer(server, ipcHandlePath));
|
||||
} catch (err) {
|
||||
e(err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export interface IIPCServer extends Disposable {
|
||||
readonly ipcHandlePath: string | undefined;
|
||||
getEnv(): any;
|
||||
registerHandler(name: string, handler: IIPCHandler): Disposable;
|
||||
}
|
||||
|
||||
class IPCServer implements IIPCServer, Disposable {
|
||||
|
||||
private handlers = new Map<string, IIPCHandler>();
|
||||
get ipcHandlePath(): string { return this._ipcHandlePath; }
|
||||
|
||||
constructor(private server: http.Server, private _ipcHandlePath: string) {
|
||||
this.server.on('request', this.onRequest.bind(this));
|
||||
}
|
||||
|
||||
registerHandler(name: string, handler: IIPCHandler): Disposable {
|
||||
this.handlers.set(`/${name}`, handler);
|
||||
return toDisposable(() => this.handlers.delete(name));
|
||||
}
|
||||
|
||||
private onRequest(req: http.IncomingMessage, res: http.ServerResponse): void {
|
||||
if (!req.url) {
|
||||
console.warn(`Request lacks url`);
|
||||
return;
|
||||
}
|
||||
|
||||
const handler = this.handlers.get(req.url);
|
||||
|
||||
if (!handler) {
|
||||
console.warn(`IPC handler for ${req.url} not found`);
|
||||
return;
|
||||
}
|
||||
|
||||
const chunks: Buffer[] = [];
|
||||
req.on('data', d => chunks.push(d));
|
||||
req.on('end', () => {
|
||||
const request = JSON.parse(Buffer.concat(chunks).toString('utf8'));
|
||||
handler.handle(request).then(result => {
|
||||
res.writeHead(200);
|
||||
res.end(JSON.stringify(result));
|
||||
}, () => {
|
||||
res.writeHead(500);
|
||||
res.end();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getEnv(): any {
|
||||
return { VSCODE_GIT_IPC_HANDLE: this.ipcHandlePath };
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.handlers.clear();
|
||||
this.server.close();
|
||||
|
||||
if (this._ipcHandlePath && process.platform !== 'win32') {
|
||||
fs.unlinkSync(this._ipcHandlePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,8 +11,9 @@ import { findGit, Git, IGit } from './git';
|
||||
import { Model } from './model';
|
||||
import { CommandCenter } from './commands';
|
||||
import { GitContentProvider } from './contentProvider';
|
||||
import { GitFileSystemProvider } from './fileSystemProvider';
|
||||
import { GitDecorations } from './decorationProvider';
|
||||
import { Askpass } from './askpass';
|
||||
import { Askpass } from './askpass/askpass';
|
||||
import { toDisposable, filterEvent, eventToPromise } from './util';
|
||||
import TelemetryReporter from 'vscode-extension-telemetry';
|
||||
import { GitExtension } from './api/git';
|
||||
@@ -20,6 +21,7 @@ import { GitProtocolHandler } from './protocolHandler';
|
||||
import { GitExtensionImpl } from './api/extension';
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import { createIPCServer, IIPCServer } from './ipc/ipcServer';
|
||||
|
||||
const deactivateTasks: { (): Promise<any>; }[] = [];
|
||||
|
||||
@@ -32,10 +34,26 @@ export async function deactivate(): Promise<any> {
|
||||
async function createModel(context: ExtensionContext, outputChannel: OutputChannel, telemetryReporter: TelemetryReporter, disposables: Disposable[]): Promise<Model> {
|
||||
const pathHint = workspace.getConfiguration('git').get<string>('path');
|
||||
const info = await findGit(pathHint, path => outputChannel.appendLine(localize('looking', "Looking for git in: {0}", path)));
|
||||
const askpass = new Askpass();
|
||||
disposables.push(askpass);
|
||||
|
||||
const env = await askpass.getEnv();
|
||||
let env: any = {};
|
||||
let ipc: IIPCServer | undefined;
|
||||
|
||||
try {
|
||||
ipc = await createIPCServer();
|
||||
disposables.push(ipc);
|
||||
env = { ...env, ...ipc.getEnv() };
|
||||
} catch {
|
||||
// noop
|
||||
}
|
||||
|
||||
if (ipc) {
|
||||
const askpass = new Askpass(ipc);
|
||||
disposables.push(askpass);
|
||||
env = { ...env, ...askpass.getEnv() };
|
||||
} else {
|
||||
env = { ...env, ...Askpass.getDisabledEnv() };
|
||||
}
|
||||
|
||||
const git = new Git({ gitPath: info.path, version: info.version, env });
|
||||
const model = new Model(git, context.globalState, outputChannel);
|
||||
disposables.push(model);
|
||||
@@ -62,6 +80,7 @@ async function createModel(context: ExtensionContext, outputChannel: OutputChann
|
||||
disposables.push(
|
||||
new CommandCenter(git, model, outputChannel, telemetryReporter),
|
||||
new GitContentProvider(model),
|
||||
new GitFileSystemProvider(model),
|
||||
new GitDecorations(model),
|
||||
new GitProtocolHandler()
|
||||
);
|
||||
|
||||
@@ -844,15 +844,7 @@ export class Repository implements Disposable {
|
||||
return mergeMessage;
|
||||
}
|
||||
|
||||
let template = await this.repository.getCommitTemplate();
|
||||
|
||||
const config = workspace.getConfiguration('git', Uri.file(this.root));
|
||||
|
||||
if (!config.get<boolean>('restoreCommitTemplateComments')) {
|
||||
template = this.cleanUpCommitEditMessage(template);
|
||||
}
|
||||
|
||||
return template;
|
||||
return await this.repository.getCommitTemplate();
|
||||
}
|
||||
|
||||
getConfigs(): Promise<{ key: string; value: string; }[]> {
|
||||
@@ -1286,10 +1278,6 @@ export class Repository implements Disposable {
|
||||
return await this.run(Operation.GetCommitTemplate, async () => this.repository.getCommitTemplate());
|
||||
}
|
||||
|
||||
cleanUpCommitEditMessage(editMessage: string): string {
|
||||
return this.repository.cleanupCommitEditMessage(editMessage);
|
||||
}
|
||||
|
||||
async ignore(files: Uri[]): Promise<void> {
|
||||
return await this.run(Operation.Ignore, async () => {
|
||||
const ignoreFile = `${this.repository.root}${path.sep}.gitignore`;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Uri } from 'vscode';
|
||||
import * as qs from 'querystring';
|
||||
|
||||
export interface GitUriParams {
|
||||
path: string;
|
||||
@@ -11,8 +12,26 @@ export interface GitUriParams {
|
||||
submoduleOf?: string;
|
||||
}
|
||||
|
||||
export function isGitUri(uri: Uri): boolean {
|
||||
return /^git(fs)?$/.test(uri.scheme);
|
||||
}
|
||||
|
||||
export function fromGitUri(uri: Uri): GitUriParams {
|
||||
return JSON.parse(uri.query);
|
||||
const result = qs.parse(uri.query) as any;
|
||||
|
||||
if (!result) {
|
||||
throw new Error('Invalid git URI: empty query');
|
||||
}
|
||||
|
||||
if (typeof result.path !== 'string') {
|
||||
throw new Error('Invalid git URI: missing path');
|
||||
}
|
||||
|
||||
if (typeof result.ref !== 'string') {
|
||||
throw new Error('Invalid git URI: missing ref');
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export interface GitUriOptions {
|
||||
@@ -42,8 +61,8 @@ export function toGitUri(uri: Uri, ref: string, options: GitUriOptions = {}): Ur
|
||||
}
|
||||
|
||||
return uri.with({
|
||||
scheme: 'git',
|
||||
scheme: 'gitfs',
|
||||
path,
|
||||
query: JSON.stringify(params)
|
||||
query: qs.stringify(params as any)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { Event } from 'vscode';
|
||||
import { dirname, sep } from 'path';
|
||||
import { Readable } from 'stream';
|
||||
import * as fs from 'fs';
|
||||
import { promises as fs, createReadStream } from 'fs';
|
||||
import * as byline from 'byline';
|
||||
|
||||
export function log(...args: any[]): void {
|
||||
@@ -140,25 +140,14 @@ export function groupBy<T>(arr: T[], fn: (el: T) => string): { [key: string]: T[
|
||||
}, Object.create(null));
|
||||
}
|
||||
|
||||
export function denodeify<A, B, C, R>(fn: Function): (a: A, b: B, c: C) => Promise<R>;
|
||||
export function denodeify<A, B, R>(fn: Function): (a: A, b: B) => Promise<R>;
|
||||
export function denodeify<A, R>(fn: Function): (a: A) => Promise<R>;
|
||||
export function denodeify<R>(fn: Function): (...args: any[]) => Promise<R>;
|
||||
export function denodeify<R>(fn: Function): (...args: any[]) => Promise<R> {
|
||||
return (...args) => new Promise<R>((c, e) => fn(...args, (err: any, r: any) => err ? e(err) : c(r)));
|
||||
}
|
||||
|
||||
export function nfcall<R>(fn: Function, ...args: any[]): Promise<R> {
|
||||
return new Promise<R>((c, e) => fn(...args, (err: any, r: any) => err ? e(err) : c(r)));
|
||||
}
|
||||
|
||||
export async function mkdirp(path: string, mode?: number): Promise<boolean> {
|
||||
const mkdir = async () => {
|
||||
try {
|
||||
await nfcall(fs.mkdir, path, mode);
|
||||
await fs.mkdir(path, mode);
|
||||
} catch (err) {
|
||||
if (err.code === 'EEXIST') {
|
||||
const stat = await nfcall<fs.Stats>(fs.stat, path);
|
||||
const stat = await fs.stat(path);
|
||||
|
||||
if (stat.isDirectory()) {
|
||||
return;
|
||||
@@ -232,7 +221,7 @@ export function find<T>(array: T[], fn: (t: T) => boolean): T | undefined {
|
||||
|
||||
export async function grep(filename: string, pattern: RegExp): Promise<boolean> {
|
||||
return new Promise<boolean>((c, e) => {
|
||||
const fileStream = fs.createReadStream(filename, { encoding: 'utf8' });
|
||||
const fileStream = createReadStream(filename, { encoding: 'utf8' });
|
||||
const stream = byline(fileStream);
|
||||
stream.on('data', (line: string) => {
|
||||
if (pattern.test(line)) {
|
||||
|
||||
@@ -14,10 +14,14 @@ import { EMPTY_ELEMENTS } from './htmlEmptyTagsShared';
|
||||
import { activateTagClosing } from './tagClosing';
|
||||
import TelemetryReporter from 'vscode-extension-telemetry';
|
||||
import { getCustomDataPathsInAllWorkspaces, getCustomDataPathsFromAllExtensions } from './customData';
|
||||
import { activateMatchingTagPosition as activateMatchingTagSelection } from './matchingTag';
|
||||
|
||||
namespace TagCloseRequest {
|
||||
export const type: RequestType<TextDocumentPositionParams, string, any, any> = new RequestType('html/tag');
|
||||
}
|
||||
namespace MatchingTagPositionRequest {
|
||||
export const type: RequestType<TextDocumentPositionParams, Position | null, any, any> = new RequestType('html/matchingTagPosition');
|
||||
}
|
||||
|
||||
interface IPackageInfo {
|
||||
name: string;
|
||||
@@ -84,6 +88,14 @@ export function activate(context: ExtensionContext) {
|
||||
disposable = activateTagClosing(tagRequestor, { html: true, handlebars: true }, 'html.autoClosingTags');
|
||||
toDispose.push(disposable);
|
||||
|
||||
const matchingTagPositionRequestor = (document: TextDocument, position: Position) => {
|
||||
let param = client.code2ProtocolConverter.asTextDocumentPositionParams(document, position);
|
||||
return client.sendRequest(MatchingTagPositionRequest.type, param);
|
||||
};
|
||||
|
||||
disposable = activateMatchingTagSelection(matchingTagPositionRequestor, { html: true, handlebars: true }, 'html.autoSelectingMatchingTags');
|
||||
toDispose.push(disposable);
|
||||
|
||||
disposable = client.onTelemetry(e => {
|
||||
if (telemetryReporter) {
|
||||
telemetryReporter.sendTelemetryEvent(e.key, e.data);
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import {
|
||||
window,
|
||||
workspace,
|
||||
Disposable,
|
||||
TextDocument,
|
||||
Position,
|
||||
TextEditorSelectionChangeEvent,
|
||||
Selection,
|
||||
Range,
|
||||
WorkspaceEdit
|
||||
} from 'vscode';
|
||||
|
||||
export function activateMatchingTagPosition(
|
||||
matchingTagPositionProvider: (document: TextDocument, position: Position) => Thenable<Position | null>,
|
||||
supportedLanguages: { [id: string]: boolean },
|
||||
configName: string
|
||||
): Disposable {
|
||||
let disposables: Disposable[] = [];
|
||||
|
||||
window.onDidChangeTextEditorSelection(event => onDidChangeTextEditorSelection(event), null, disposables);
|
||||
|
||||
let isEnabled = false;
|
||||
updateEnabledState();
|
||||
|
||||
window.onDidChangeActiveTextEditor(updateEnabledState, null, disposables);
|
||||
|
||||
function updateEnabledState() {
|
||||
isEnabled = false;
|
||||
let editor = window.activeTextEditor;
|
||||
if (!editor) {
|
||||
return;
|
||||
}
|
||||
let document = editor.document;
|
||||
if (!supportedLanguages[document.languageId]) {
|
||||
return;
|
||||
}
|
||||
if (!workspace.getConfiguration(undefined, document.uri).get<boolean>(configName)) {
|
||||
return;
|
||||
}
|
||||
isEnabled = true;
|
||||
}
|
||||
|
||||
let prevCursorCount = 0;
|
||||
let cursorCount = 0;
|
||||
let inMirrorMode = false;
|
||||
|
||||
function onDidChangeTextEditorSelection(event: TextEditorSelectionChangeEvent) {
|
||||
if (!isEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
prevCursorCount = cursorCount;
|
||||
cursorCount = event.selections.length;
|
||||
|
||||
if (cursorCount === 1) {
|
||||
if (inMirrorMode && prevCursorCount === 2) {
|
||||
return;
|
||||
}
|
||||
if (event.selections[0].isEmpty) {
|
||||
matchingTagPositionProvider(event.textEditor.document, event.selections[0].active).then(position => {
|
||||
if (position && window.activeTextEditor) {
|
||||
inMirrorMode = true;
|
||||
const newCursor = new Selection(position.line, position.character, position.line, position.character);
|
||||
window.activeTextEditor.selections = [...window.activeTextEditor.selections, newCursor];
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (cursorCount === 2 && inMirrorMode) {
|
||||
// Check two cases
|
||||
if (event.selections[0].isEmpty && event.selections[1].isEmpty) {
|
||||
const charBeforePrimarySelection = getCharBefore(event.textEditor.document, event.selections[0].anchor);
|
||||
const charAfterPrimarySelection = getCharAfter(event.textEditor.document, event.selections[0].anchor);
|
||||
const charBeforeSecondarySelection = getCharBefore(event.textEditor.document, event.selections[1].anchor);
|
||||
const charAfterSecondarySelection = getCharAfter(event.textEditor.document, event.selections[1].anchor);
|
||||
|
||||
// Exit mirror mode when cursor position no longer mirror
|
||||
// Unless it's in the case of `<|></|>`
|
||||
const charBeforeBothPositionRoughlyEqual =
|
||||
charBeforePrimarySelection === charBeforeSecondarySelection ||
|
||||
(charBeforePrimarySelection === '/' && charBeforeSecondarySelection === '<') ||
|
||||
(charBeforeSecondarySelection === '/' && charBeforePrimarySelection === '<');
|
||||
const charAfterBothPositionRoughlyEqual =
|
||||
charAfterPrimarySelection === charAfterSecondarySelection ||
|
||||
(charAfterPrimarySelection === ' ' && charAfterSecondarySelection === '>') ||
|
||||
(charAfterSecondarySelection === ' ' && charAfterPrimarySelection === '>');
|
||||
|
||||
if (!charBeforeBothPositionRoughlyEqual || !charAfterBothPositionRoughlyEqual) {
|
||||
inMirrorMode = false;
|
||||
window.activeTextEditor!.selections = [window.activeTextEditor!.selections[0]];
|
||||
return;
|
||||
} else {
|
||||
// Need to cleanup in the case of <div |></div |>
|
||||
if (
|
||||
charBeforePrimarySelection === ' ' &&
|
||||
charAfterPrimarySelection === '>' &&
|
||||
charBeforeSecondarySelection === ' ' &&
|
||||
charAfterSecondarySelection === '>'
|
||||
) {
|
||||
const primaryBeforeSecondary =
|
||||
event.textEditor.document.offsetAt(event.selections[0].anchor) <
|
||||
event.textEditor.document.offsetAt(event.selections[1].anchor);
|
||||
|
||||
if (primaryBeforeSecondary) {
|
||||
inMirrorMode = false;
|
||||
const cleanupEdit = new WorkspaceEdit();
|
||||
const cleanupRange = new Range(event.selections[1].anchor.translate(0, -1), event.selections[1].anchor);
|
||||
cleanupEdit.replace(event.textEditor.document.uri, cleanupRange, '');
|
||||
window.activeTextEditor!.selections = [window.activeTextEditor!.selections[0]];
|
||||
workspace.applyEdit(cleanupEdit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Disposable.from(...disposables);
|
||||
}
|
||||
|
||||
function getCharBefore(document: TextDocument, position: Position) {
|
||||
const offset = document.offsetAt(position);
|
||||
if (offset === 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return document.getText(new Range(document.positionAt(offset - 1), position));
|
||||
}
|
||||
|
||||
function getCharAfter(document: TextDocument, position: Position) {
|
||||
const offset = document.offsetAt(position);
|
||||
if (offset === document.getText().length) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return document.getText(new Range(position, document.positionAt(offset + 1)));
|
||||
}
|
||||
@@ -161,6 +161,12 @@
|
||||
"default": true,
|
||||
"description": "%html.autoClosingTags%"
|
||||
},
|
||||
"html.autoSelectingMatchingTags": {
|
||||
"type": "boolean",
|
||||
"scope": "resource",
|
||||
"default": true,
|
||||
"description": "%html.autoSelectingMatchingTags%"
|
||||
},
|
||||
"html.trace.server": {
|
||||
"type": "string",
|
||||
"scope": "window",
|
||||
|
||||
@@ -24,5 +24,6 @@
|
||||
"html.trace.server.desc": "Traces the communication between VS Code and the HTML language server.",
|
||||
"html.validate.scripts": "Controls whether the built-in HTML language support validates embedded scripts.",
|
||||
"html.validate.styles": "Controls whether the built-in HTML language support validates embedded styles.",
|
||||
"html.autoClosingTags": "Enable/disable autoclosing of HTML tags."
|
||||
"html.autoClosingTags": "Enable/disable autoclosing of HTML tags.",
|
||||
"html.autoSelectingMatchingTags": "Enable/disable auto selecting matching HTML tags."
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"main": "./out/htmlServerMain",
|
||||
"dependencies": {
|
||||
"vscode-css-languageservice": "^4.0.3-next.20",
|
||||
"vscode-html-languageservice": "^3.0.4-next.8",
|
||||
"vscode-html-languageservice": "^3.0.4-next.10",
|
||||
"vscode-languageserver": "^6.0.0-next.3",
|
||||
"vscode-nls": "^4.1.1",
|
||||
"vscode-uri": "^2.0.3"
|
||||
|
||||
@@ -24,6 +24,9 @@ import { getDataProviders } from './customData';
|
||||
namespace TagCloseRequest {
|
||||
export const type: RequestType<TextDocumentPositionParams, string | null, any, any> = new RequestType('html/tag');
|
||||
}
|
||||
namespace MatchingTagPositionRequest {
|
||||
export const type: RequestType<TextDocumentPositionParams, Position | null, any, any> = new RequestType('html/matchingTagPosition');
|
||||
}
|
||||
|
||||
// Create a connection for the server
|
||||
const connection: IConnection = createConnection();
|
||||
@@ -136,6 +139,7 @@ connection.onInitialize((params: InitializeParams): InitializeResult => {
|
||||
colorProvider: {},
|
||||
foldingRangeProvider: true,
|
||||
selectionRangeProvider: true,
|
||||
renameProvider: true
|
||||
};
|
||||
return { capabilities };
|
||||
});
|
||||
@@ -469,6 +473,36 @@ connection.onSelectionRanges((params, token) => {
|
||||
}, [], `Error while computing selection ranges for ${params.textDocument.uri}`, token);
|
||||
});
|
||||
|
||||
connection.onRenameRequest((params, token) => {
|
||||
return runSafe(() => {
|
||||
const document = documents.get(params.textDocument.uri);
|
||||
const position: Position = params.position;
|
||||
|
||||
if (document) {
|
||||
const htmlMode = languageModes.getMode('html');
|
||||
if (htmlMode && htmlMode.doRename) {
|
||||
return htmlMode.doRename(document, position, params.newName);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}, null, `Error while computing rename for ${params.textDocument.uri}`, token);
|
||||
});
|
||||
|
||||
connection.onRequest(MatchingTagPositionRequest.type, (params, token) => {
|
||||
return runSafe(() => {
|
||||
const document = documents.get(params.textDocument.uri);
|
||||
if (document) {
|
||||
const pos = params.position;
|
||||
if (pos.character > 0) {
|
||||
const mode = languageModes.getModeAtPosition(document, Position.create(pos.line, pos.character - 1));
|
||||
if (mode && mode.findMatchingTagPosition) {
|
||||
return mode.findMatchingTagPosition(document, pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}, null, `Error while computing matching tag position for ${params.textDocument.uri}`, token);
|
||||
});
|
||||
|
||||
// Listen on the connection
|
||||
connection.listen();
|
||||
|
||||
@@ -74,9 +74,17 @@ export function getHTMLMode(htmlLanguageService: HTMLLanguageService, workspace:
|
||||
}
|
||||
return null;
|
||||
},
|
||||
doRename(document: TextDocument, position: Position, newName: string) {
|
||||
const htmlDocument = htmlDocuments.get(document);
|
||||
return htmlLanguageService.doRename(document, position, newName, htmlDocument);
|
||||
},
|
||||
onDocumentRemoved(document: TextDocument) {
|
||||
htmlDocuments.onDocumentRemoved(document);
|
||||
},
|
||||
findMatchingTagPosition(document: TextDocument, position: Position) {
|
||||
const htmlDocument = htmlDocuments.get(document);
|
||||
return htmlLanguageService.findMatchingTagPosition(document, position, htmlDocument);
|
||||
},
|
||||
dispose() {
|
||||
htmlDocuments.dispose();
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
ClientCapabilities, DocumentContext, getLanguageService as getHTMLLanguageService, IHTMLDataProvider, SelectionRange,
|
||||
CompletionItem, CompletionList, Definition, Diagnostic, DocumentHighlight, DocumentLink, FoldingRange, FormattingOptions,
|
||||
Hover, Location, Position, Range, SignatureHelp, SymbolInformation, TextDocument, TextEdit,
|
||||
Color, ColorInformation, ColorPresentation
|
||||
Color, ColorInformation, ColorPresentation, WorkspaceEdit
|
||||
} from 'vscode-html-languageservice';
|
||||
import { WorkspaceFolder } from 'vscode-languageserver';
|
||||
import { getLanguageModelCache, LanguageModelCache } from '../languageModelCache';
|
||||
@@ -38,6 +38,7 @@ export interface LanguageMode {
|
||||
doResolve?: (document: TextDocument, item: CompletionItem) => CompletionItem;
|
||||
doHover?: (document: TextDocument, position: Position) => Hover | null;
|
||||
doSignatureHelp?: (document: TextDocument, position: Position) => SignatureHelp | null;
|
||||
doRename?: (document: TextDocument, position: Position, newName: string) => WorkspaceEdit | null;
|
||||
findDocumentHighlight?: (document: TextDocument, position: Position) => DocumentHighlight[];
|
||||
findDocumentSymbols?: (document: TextDocument) => SymbolInformation[];
|
||||
findDocumentLinks?: (document: TextDocument, documentContext: DocumentContext) => DocumentLink[];
|
||||
@@ -47,6 +48,7 @@ export interface LanguageMode {
|
||||
findDocumentColors?: (document: TextDocument) => ColorInformation[];
|
||||
getColorPresentations?: (document: TextDocument, color: Color, range: Range) => ColorPresentation[];
|
||||
doAutoClose?: (document: TextDocument, position: Position) => string | null;
|
||||
findMatchingTagPosition?: (document: TextDocument, position: Position) => Position | null;
|
||||
getFoldingRanges?: (document: TextDocument) => FoldingRange[];
|
||||
onDocumentRemoved(document: TextDocument): void;
|
||||
dispose(): void;
|
||||
|
||||
@@ -621,10 +621,10 @@ vscode-css-languageservice@^4.0.3-next.20:
|
||||
vscode-nls "^4.1.1"
|
||||
vscode-uri "^2.1.1"
|
||||
|
||||
vscode-html-languageservice@^3.0.4-next.8:
|
||||
version "3.0.4-next.8"
|
||||
resolved "https://registry.yarnpkg.com/vscode-html-languageservice/-/vscode-html-languageservice-3.0.4-next.8.tgz#b3df7b7e8f69c1bf76392c4fd4df4cf483e77e7d"
|
||||
integrity sha512-gT34wzCwM1rCJzd0EAFnuVe0FaaSr3eXaJpYcMj6rt1UspIJYaL4WtDLCcw4eBL906N1b1Vu+sapiRmV5PjZpg==
|
||||
vscode-html-languageservice@^3.0.4-next.10:
|
||||
version "3.0.4-next.10"
|
||||
resolved "https://registry.yarnpkg.com/vscode-html-languageservice/-/vscode-html-languageservice-3.0.4-next.10.tgz#da426326833770c51712abb2c7473b9b30bf1cbc"
|
||||
integrity sha512-8P0QBtMPJ9nDMhW8MF/z+5JGg6rK6UOa9po18KIleNuV0rDHU9CAqDyUjxW0CEfLrHYz6dQdkW12ZTClvQnNHw==
|
||||
dependencies:
|
||||
vscode-languageserver-textdocument "^1.0.0-next.4"
|
||||
vscode-languageserver-types "^3.15.0-next.6"
|
||||
|
||||
@@ -29,8 +29,7 @@
|
||||
"priority": "builtin",
|
||||
"selector": [
|
||||
{
|
||||
"filenamePattern": "*.{jpg,jpe,jpeg,png,bmp,gif,ico,webp}",
|
||||
"mime": "image/*"
|
||||
"filenamePattern": "*.{jpg,jpe,jpeg,png,bmp,gif,ico,webp}"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -240,9 +240,9 @@ class Preview extends Disposable implements vscode.WebviewEditorEditingCapabilit
|
||||
default:
|
||||
// Avoid adding cache busting if there is already a query string
|
||||
if (resource.query) {
|
||||
return encodeURI(webviewEditor.webview.asWebviewUri(resource).toString());
|
||||
return webviewEditor.webview.asWebviewUri(resource).toString(true);
|
||||
}
|
||||
return encodeURI(webviewEditor.webview.asWebviewUri(resource).toString() + `?version=${version}`);
|
||||
return webviewEditor.webview.asWebviewUri(resource).with({ query: `version=${version}` }).toString(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"If you want to provide a fix or improvement, please create a pull request against the original repository.",
|
||||
"Once accepted there, we are happy to receive an update request."
|
||||
],
|
||||
"version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/477c1b17e273b64af13040c064c9ed62c8b32fba",
|
||||
"version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/4daff7b8904bc549dfbee8df1e2f7c82194b9f45",
|
||||
"name": "JavaScript (with React support)",
|
||||
"scopeName": "source.js",
|
||||
"patterns": [
|
||||
@@ -2451,7 +2451,7 @@
|
||||
},
|
||||
{
|
||||
"name": "string.regexp.js",
|
||||
"begin": "(?<=\\))\\s*\\/(?![\\/*])(?=(?:[^\\/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+\\/[gimsuy]*(?!\\s*[a-zA-Z0-9_$]))",
|
||||
"begin": "(?<=\\))\\s*\\/(?![\\/*])(?=(?:[^\\/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+\\/([gimsuy]+|(?![\\/\\*])|(?=\\/\\*))(?!\\s*[a-zA-Z0-9_$]))",
|
||||
"beginCaptures": {
|
||||
"0": {
|
||||
"name": "punctuation.definition.string.begin.js"
|
||||
@@ -4572,7 +4572,7 @@
|
||||
"patterns": [
|
||||
{
|
||||
"name": "string.regexp.js",
|
||||
"begin": "(?<!\\+\\+|--|})(?<=[=(:,\\[?+!]|^return|[^\\._$[:alnum:]]return|^case|[^\\._$[:alnum:]]case|=>|&&|\\|\\||\\*\\/)\\s*(\\/)(?![\\/*])(?=(?:[^\\/\\\\\\[\\()]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\]|\\(([^\\)\\\\]|\\\\.)+\\))+\\/[gimsuy]*(?!\\s*[a-zA-Z0-9_$]))",
|
||||
"begin": "(?<!\\+\\+|--|})(?<=[=(:,\\[?+!]|^return|[^\\._$[:alnum:]]return|^case|[^\\._$[:alnum:]]case|=>|&&|\\|\\||\\*\\/)\\s*(\\/)(?![\\/*])(?=(?:[^\\/\\\\\\[\\()]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\]|\\(([^\\)\\\\]|\\\\.)+\\))+\\/([gimsuy]+|(?![\\/\\*])|(?=\\/\\*))(?!\\s*[a-zA-Z0-9_$]))",
|
||||
"beginCaptures": {
|
||||
"1": {
|
||||
"name": "punctuation.definition.string.begin.js"
|
||||
@@ -4595,7 +4595,7 @@
|
||||
},
|
||||
{
|
||||
"name": "string.regexp.js",
|
||||
"begin": "((?<![_$[:alnum:])\\]]|\\+\\+|--|}|\\*\\/)|((?<=^return|[^\\._$[:alnum:]]return|^case|[^\\._$[:alnum:]]case))\\s*)\\/(?![\\/*])(?=(?:[^\\/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+\\/[gimsuy]*(?!\\s*[a-zA-Z0-9_$]))",
|
||||
"begin": "((?<![_$[:alnum:])\\]]|\\+\\+|--|}|\\*\\/)|((?<=^return|[^\\._$[:alnum:]]return|^case|[^\\._$[:alnum:]]case))\\s*)\\/(?![\\/*])(?=(?:[^\\/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+\\/([gimsuy]+|(?![\\/\\*])|(?=\\/\\*))(?!\\s*[a-zA-Z0-9_$]))",
|
||||
"beginCaptures": {
|
||||
"0": {
|
||||
"name": "punctuation.definition.string.begin.js"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"If you want to provide a fix or improvement, please create a pull request against the original repository.",
|
||||
"Once accepted there, we are happy to receive an update request."
|
||||
],
|
||||
"version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/477c1b17e273b64af13040c064c9ed62c8b32fba",
|
||||
"version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/4daff7b8904bc549dfbee8df1e2f7c82194b9f45",
|
||||
"name": "JavaScript (with React support)",
|
||||
"scopeName": "source.js.jsx",
|
||||
"patterns": [
|
||||
@@ -2451,7 +2451,7 @@
|
||||
},
|
||||
{
|
||||
"name": "string.regexp.js.jsx",
|
||||
"begin": "(?<=\\))\\s*\\/(?![\\/*])(?=(?:[^\\/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+\\/[gimsuy]*(?!\\s*[a-zA-Z0-9_$]))",
|
||||
"begin": "(?<=\\))\\s*\\/(?![\\/*])(?=(?:[^\\/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+\\/([gimsuy]+|(?![\\/\\*])|(?=\\/\\*))(?!\\s*[a-zA-Z0-9_$]))",
|
||||
"beginCaptures": {
|
||||
"0": {
|
||||
"name": "punctuation.definition.string.begin.js.jsx"
|
||||
@@ -4572,7 +4572,7 @@
|
||||
"patterns": [
|
||||
{
|
||||
"name": "string.regexp.js.jsx",
|
||||
"begin": "(?<!\\+\\+|--|})(?<=[=(:,\\[?+!]|^return|[^\\._$[:alnum:]]return|^case|[^\\._$[:alnum:]]case|=>|&&|\\|\\||\\*\\/)\\s*(\\/)(?![\\/*])(?=(?:[^\\/\\\\\\[\\()]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\]|\\(([^\\)\\\\]|\\\\.)+\\))+\\/[gimsuy]*(?!\\s*[a-zA-Z0-9_$]))",
|
||||
"begin": "(?<!\\+\\+|--|})(?<=[=(:,\\[?+!]|^return|[^\\._$[:alnum:]]return|^case|[^\\._$[:alnum:]]case|=>|&&|\\|\\||\\*\\/)\\s*(\\/)(?![\\/*])(?=(?:[^\\/\\\\\\[\\()]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\]|\\(([^\\)\\\\]|\\\\.)+\\))+\\/([gimsuy]+|(?![\\/\\*])|(?=\\/\\*))(?!\\s*[a-zA-Z0-9_$]))",
|
||||
"beginCaptures": {
|
||||
"1": {
|
||||
"name": "punctuation.definition.string.begin.js.jsx"
|
||||
@@ -4595,7 +4595,7 @@
|
||||
},
|
||||
{
|
||||
"name": "string.regexp.js.jsx",
|
||||
"begin": "((?<![_$[:alnum:])\\]]|\\+\\+|--|}|\\*\\/)|((?<=^return|[^\\._$[:alnum:]]return|^case|[^\\._$[:alnum:]]case))\\s*)\\/(?![\\/*])(?=(?:[^\\/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+\\/[gimsuy]*(?!\\s*[a-zA-Z0-9_$]))",
|
||||
"begin": "((?<![_$[:alnum:])\\]]|\\+\\+|--|}|\\*\\/)|((?<=^return|[^\\._$[:alnum:]]return|^case|[^\\._$[:alnum:]]case))\\s*)\\/(?![\\/*])(?=(?:[^\\/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+\\/([gimsuy]+|(?![\\/\\*])|(?=\\/\\*))(?!\\s*[a-zA-Z0-9_$]))",
|
||||
"beginCaptures": {
|
||||
"0": {
|
||||
"name": "punctuation.definition.string.begin.js.jsx"
|
||||
|
||||
@@ -41,13 +41,21 @@ export class Logger {
|
||||
|
||||
public log(message: string, data?: any): void {
|
||||
if (this.trace === Trace.Verbose) {
|
||||
this.appendLine(`[Log - ${(new Date().toTimeString())}] ${message}`);
|
||||
this.appendLine(`[Log - ${this.now()}] ${message}`);
|
||||
if (data) {
|
||||
this.appendLine(Logger.data2String(data));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private now(): string {
|
||||
const now = new Date();
|
||||
return padLeft(now.getUTCHours() + '', 2, '0')
|
||||
+ ':' + padLeft(now.getMinutes() + '', 2, '0')
|
||||
+ ':' + padLeft(now.getUTCSeconds() + '', 2, '0') + '.' + now.getMilliseconds();
|
||||
}
|
||||
|
||||
public updateConfiguration() {
|
||||
this.trace = this.readTrace();
|
||||
}
|
||||
@@ -73,3 +81,7 @@ export class Logger {
|
||||
return JSON.stringify(data, undefined, 2);
|
||||
}
|
||||
}
|
||||
|
||||
function padLeft(s: string, n: number, pad = ' ') {
|
||||
return pad.repeat(Math.max(0, n - s.length)) + s;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"version": "0.0.1",
|
||||
"description": "Dependencies shared by all extensions",
|
||||
"dependencies": {
|
||||
"typescript": "3.7.2"
|
||||
"typescript": "3.7.3-insiders.20191118"
|
||||
},
|
||||
"scripts": {
|
||||
"postinstall": "node ./postinstall"
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
"git": {
|
||||
"name": "language-php",
|
||||
"repositoryUrl": "https://github.com/atom/language-php",
|
||||
"commitHash": "43a7b842fb58ac7561184db142344a1b127e0d52"
|
||||
"commitHash": "b95dc79f30084c25547397ab41388af154e69895"
|
||||
}
|
||||
},
|
||||
"license": "MIT",
|
||||
"version": "0.44.2"
|
||||
"version": "0.44.3"
|
||||
}
|
||||
],
|
||||
"version": 1
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"If you want to provide a fix or improvement, please create a pull request against the original repository.",
|
||||
"Once accepted there, we are happy to receive an update request."
|
||||
],
|
||||
"version": "https://github.com/atom/language-php/commit/43a7b842fb58ac7561184db142344a1b127e0d52",
|
||||
"version": "https://github.com/atom/language-php/commit/b95dc79f30084c25547397ab41388af154e69895",
|
||||
"scopeName": "source.php",
|
||||
"patterns": [
|
||||
{
|
||||
@@ -439,22 +439,25 @@
|
||||
"name": "keyword.control.exception.php"
|
||||
},
|
||||
{
|
||||
"begin": "(?i)\\b(function)\\s*(?=\\()",
|
||||
"begin": "(?i)\\b(function)\\s*(?=&?\\s*\\()",
|
||||
"beginCaptures": {
|
||||
"1": {
|
||||
"name": "storage.type.function.php"
|
||||
}
|
||||
},
|
||||
"end": "(?={)",
|
||||
"end": "(?=\\s*{)",
|
||||
"name": "meta.function.closure.php",
|
||||
"patterns": [
|
||||
{
|
||||
"include": "#comments"
|
||||
},
|
||||
{
|
||||
"begin": "\\(",
|
||||
"begin": "(&)?\\s*(\\()",
|
||||
"beginCaptures": {
|
||||
"0": {
|
||||
"1": {
|
||||
"name": "storage.modifier.reference.php"
|
||||
},
|
||||
"2": {
|
||||
"name": "punctuation.definition.parameters.begin.bracket.round.php"
|
||||
}
|
||||
},
|
||||
@@ -504,11 +507,25 @@
|
||||
"name": "meta.function.closure.use.php"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"match": "(:)\\s*(\\?)?\\s*((?:\\\\?[a-zA-Z_\\x{7f}-\\x{7fffffff}][a-zA-Z0-9_\\x{7f}-\\x{7fffffff}]*)+)",
|
||||
"captures": {
|
||||
"1": {
|
||||
"name": "keyword.operator.return-value.php"
|
||||
},
|
||||
"2": {
|
||||
"name": "keyword.operator.nullable-type.php"
|
||||
},
|
||||
"3": {
|
||||
"name": "storage.type.php"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"begin": "(?x)\n((?:(?:final|abstract|public|private|protected|static)\\s+)*)\n(function)\\s+\n(?i:\n (__(?:call|construct|debugInfo|destruct|get|set|isset|unset|toString|\n clone|set_state|sleep|wakeup|autoload|invoke|callStatic))\n |([a-zA-Z_\\x{7f}-\\x{7fffffff}][a-zA-Z0-9_\\x{7f}-\\x{7fffffff}]*)\n)\n\\s*(\\()",
|
||||
"begin": "(?x)\n((?:(?:final|abstract|public|private|protected|static)\\s+)*)\n(function)\\s+\n(?i:\n (__(?:call|construct|debugInfo|destruct|get|set|isset|unset|toString|\n clone|set_state|sleep|wakeup|autoload|invoke|callStatic))\n |(?:(&)?\\s*([a-zA-Z_\\x{7f}-\\x{7fffffff}][a-zA-Z0-9_\\x{7f}-\\x{7fffffff}]*))\n)\n\\s*(\\()",
|
||||
"beginCaptures": {
|
||||
"1": {
|
||||
"patterns": [
|
||||
@@ -525,14 +542,17 @@
|
||||
"name": "support.function.magic.php"
|
||||
},
|
||||
"4": {
|
||||
"name": "entity.name.function.php"
|
||||
"name": "storage.modifier.reference.php"
|
||||
},
|
||||
"5": {
|
||||
"name": "entity.name.function.php"
|
||||
},
|
||||
"6": {
|
||||
"name": "punctuation.definition.parameters.begin.bracket.round.php"
|
||||
}
|
||||
},
|
||||
"contentName": "meta.function.parameters.php",
|
||||
"end": "(\\))(?:\\s*(:)\\s*(\\?)?\\s*([a-zA-Z_\\x{7f}-\\x{7fffffff}][a-zA-Z0-9_\\x{7f}-\\x{7fffffff}]*))?",
|
||||
"end": "(\\))(?:\\s*(:)\\s*(\\?)?\\s*((?:\\\\?[a-zA-Z_\\x{7f}-\\x{7fffffff}][a-zA-Z0-9_\\x{7f}-\\x{7fffffff}]*)+))?",
|
||||
"endCaptures": {
|
||||
"1": {
|
||||
"name": "punctuation.definition.parameters.end.bracket.round.php"
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"git": {
|
||||
"name": "TypeScript-TmLanguage",
|
||||
"repositoryUrl": "https://github.com/Microsoft/TypeScript-TmLanguage",
|
||||
"commitHash": "477c1b17e273b64af13040c064c9ed62c8b32fba"
|
||||
"commitHash": "4daff7b8904bc549dfbee8df1e2f7c82194b9f45"
|
||||
}
|
||||
},
|
||||
"license": "MIT",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"If you want to provide a fix or improvement, please create a pull request against the original repository.",
|
||||
"Once accepted there, we are happy to receive an update request."
|
||||
],
|
||||
"version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/477c1b17e273b64af13040c064c9ed62c8b32fba",
|
||||
"version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/4daff7b8904bc549dfbee8df1e2f7c82194b9f45",
|
||||
"name": "TypeScript",
|
||||
"scopeName": "source.ts",
|
||||
"patterns": [
|
||||
@@ -2448,7 +2448,7 @@
|
||||
},
|
||||
{
|
||||
"name": "string.regexp.ts",
|
||||
"begin": "(?<=\\))\\s*\\/(?![\\/*])(?=(?:[^\\/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+\\/[gimsuy]*(?!\\s*[a-zA-Z0-9_$]))",
|
||||
"begin": "(?<=\\))\\s*\\/(?![\\/*])(?=(?:[^\\/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+\\/([gimsuy]+|(?![\\/\\*])|(?=\\/\\*))(?!\\s*[a-zA-Z0-9_$]))",
|
||||
"beginCaptures": {
|
||||
"0": {
|
||||
"name": "punctuation.definition.string.begin.ts"
|
||||
@@ -4621,7 +4621,7 @@
|
||||
"patterns": [
|
||||
{
|
||||
"name": "string.regexp.ts",
|
||||
"begin": "(?<!\\+\\+|--|})(?<=[=(:,\\[?+!]|^return|[^\\._$[:alnum:]]return|^case|[^\\._$[:alnum:]]case|=>|&&|\\|\\||\\*\\/)\\s*(\\/)(?![\\/*])(?=(?:[^\\/\\\\\\[\\()]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\]|\\(([^\\)\\\\]|\\\\.)+\\))+\\/[gimsuy]*(?!\\s*[a-zA-Z0-9_$]))",
|
||||
"begin": "(?<!\\+\\+|--|})(?<=[=(:,\\[?+!]|^return|[^\\._$[:alnum:]]return|^case|[^\\._$[:alnum:]]case|=>|&&|\\|\\||\\*\\/)\\s*(\\/)(?![\\/*])(?=(?:[^\\/\\\\\\[\\()]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\]|\\(([^\\)\\\\]|\\\\.)+\\))+\\/([gimsuy]+|(?![\\/\\*])|(?=\\/\\*))(?!\\s*[a-zA-Z0-9_$]))",
|
||||
"beginCaptures": {
|
||||
"1": {
|
||||
"name": "punctuation.definition.string.begin.ts"
|
||||
@@ -4644,7 +4644,7 @@
|
||||
},
|
||||
{
|
||||
"name": "string.regexp.ts",
|
||||
"begin": "((?<![_$[:alnum:])\\]]|\\+\\+|--|}|\\*\\/)|((?<=^return|[^\\._$[:alnum:]]return|^case|[^\\._$[:alnum:]]case))\\s*)\\/(?![\\/*])(?=(?:[^\\/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+\\/[gimsuy]*(?!\\s*[a-zA-Z0-9_$]))",
|
||||
"begin": "((?<![_$[:alnum:])\\]]|\\+\\+|--|}|\\*\\/)|((?<=^return|[^\\._$[:alnum:]]return|^case|[^\\._$[:alnum:]]case))\\s*)\\/(?![\\/*])(?=(?:[^\\/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+\\/([gimsuy]+|(?![\\/\\*])|(?=\\/\\*))(?!\\s*[a-zA-Z0-9_$]))",
|
||||
"beginCaptures": {
|
||||
"0": {
|
||||
"name": "punctuation.definition.string.begin.ts"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"If you want to provide a fix or improvement, please create a pull request against the original repository.",
|
||||
"Once accepted there, we are happy to receive an update request."
|
||||
],
|
||||
"version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/477c1b17e273b64af13040c064c9ed62c8b32fba",
|
||||
"version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/4daff7b8904bc549dfbee8df1e2f7c82194b9f45",
|
||||
"name": "TypeScriptReact",
|
||||
"scopeName": "source.tsx",
|
||||
"patterns": [
|
||||
@@ -2451,7 +2451,7 @@
|
||||
},
|
||||
{
|
||||
"name": "string.regexp.tsx",
|
||||
"begin": "(?<=\\))\\s*\\/(?![\\/*])(?=(?:[^\\/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+\\/[gimsuy]*(?!\\s*[a-zA-Z0-9_$]))",
|
||||
"begin": "(?<=\\))\\s*\\/(?![\\/*])(?=(?:[^\\/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+\\/([gimsuy]+|(?![\\/\\*])|(?=\\/\\*))(?!\\s*[a-zA-Z0-9_$]))",
|
||||
"beginCaptures": {
|
||||
"0": {
|
||||
"name": "punctuation.definition.string.begin.tsx"
|
||||
@@ -4572,7 +4572,7 @@
|
||||
"patterns": [
|
||||
{
|
||||
"name": "string.regexp.tsx",
|
||||
"begin": "(?<!\\+\\+|--|})(?<=[=(:,\\[?+!]|^return|[^\\._$[:alnum:]]return|^case|[^\\._$[:alnum:]]case|=>|&&|\\|\\||\\*\\/)\\s*(\\/)(?![\\/*])(?=(?:[^\\/\\\\\\[\\()]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\]|\\(([^\\)\\\\]|\\\\.)+\\))+\\/[gimsuy]*(?!\\s*[a-zA-Z0-9_$]))",
|
||||
"begin": "(?<!\\+\\+|--|})(?<=[=(:,\\[?+!]|^return|[^\\._$[:alnum:]]return|^case|[^\\._$[:alnum:]]case|=>|&&|\\|\\||\\*\\/)\\s*(\\/)(?![\\/*])(?=(?:[^\\/\\\\\\[\\()]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\]|\\(([^\\)\\\\]|\\\\.)+\\))+\\/([gimsuy]+|(?![\\/\\*])|(?=\\/\\*))(?!\\s*[a-zA-Z0-9_$]))",
|
||||
"beginCaptures": {
|
||||
"1": {
|
||||
"name": "punctuation.definition.string.begin.tsx"
|
||||
@@ -4595,7 +4595,7 @@
|
||||
},
|
||||
{
|
||||
"name": "string.regexp.tsx",
|
||||
"begin": "((?<![_$[:alnum:])\\]]|\\+\\+|--|}|\\*\\/)|((?<=^return|[^\\._$[:alnum:]]return|^case|[^\\._$[:alnum:]]case))\\s*)\\/(?![\\/*])(?=(?:[^\\/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+\\/[gimsuy]*(?!\\s*[a-zA-Z0-9_$]))",
|
||||
"begin": "((?<![_$[:alnum:])\\]]|\\+\\+|--|}|\\*\\/)|((?<=^return|[^\\._$[:alnum:]]return|^case|[^\\._$[:alnum:]]case))\\s*)\\/(?![\\/*])(?=(?:[^\\/\\\\\\[]|\\\\.|\\[([^\\]\\\\]|\\\\.)+\\])+\\/([gimsuy]+|(?![\\/\\*])|(?=\\/\\*))(?!\\s*[a-zA-Z0-9_$]))",
|
||||
"beginCaptures": {
|
||||
"0": {
|
||||
"name": "punctuation.definition.string.begin.tsx"
|
||||
|
||||
@@ -859,10 +859,10 @@
|
||||
"background": {
|
||||
"activeOnStart": true,
|
||||
"beginsPattern": {
|
||||
"regexp": "^\\s*(?:message TS6032:|\\[?\\d{1,2}:\\d{1,2}:\\d{1,2}(?: AM| PM| a\\.m\\.| p\\.m\\.)?(?:\\]| -)) File change detected\\. Starting incremental compilation\\.\\.\\."
|
||||
"regexp": "^\\s*(?:message TS6032:|\\[?\\D*\\d{1,2}:\\d{1,2}:\\d{1,2}\\D*(?:\\]| -)) File change detected\\. Starting incremental compilation\\.\\.\\."
|
||||
},
|
||||
"endsPattern": {
|
||||
"regexp": "^\\s*(?:message TS6042:|\\[?\\d{1,2}:\\d{1,2}:\\d{1,2}(?: AM| PM| a\\.m\\.| p\\.m\\.)?(?:\\]| -)) (?:Compilation complete\\.|Found \\d+ errors?\\.) Watching for file changes\\."
|
||||
"regexp": "^\\s*(?:message TS6042:|\\[?\\D*\\d{1,2}:\\d{1,2}:\\d{1,2}\\D*(?:\\]| -)) (?:Compilation complete\\.|Found \\d+ errors?\\.) Watching for file changes\\."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,9 +238,14 @@ class TypeScriptRefactorProvider implements vscode.CodeActionProvider {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return this.convertApplicableRefactors(response.body, document, rangeOrSelection);
|
||||
const actions = this.convertApplicableRefactors(response.body, document, rangeOrSelection);
|
||||
if (!context.only) {
|
||||
return actions;
|
||||
}
|
||||
return this.appendInvalidActions(actions);
|
||||
}
|
||||
|
||||
|
||||
private convertApplicableRefactors(
|
||||
body: Proto.ApplicableRefactorInfo[],
|
||||
document: vscode.TextDocument,
|
||||
@@ -305,6 +310,16 @@ class TypeScriptRefactorProvider implements vscode.CodeActionProvider {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private appendInvalidActions(actions: vscode.CodeAction[]): vscode.CodeAction[] {
|
||||
if (!actions.some(action => action.kind && Extract_Constant.kind.contains(action.kind))) {
|
||||
const disabledAction = new vscode.CodeAction('Extract to constant', Extract_Constant.kind);
|
||||
disabledAction.disabled = localize('extract.disabled', "The current selection cannot be extracted");
|
||||
disabledAction.isPreferred = true;
|
||||
actions.push(disabledAction);
|
||||
}
|
||||
return actions;
|
||||
}
|
||||
}
|
||||
|
||||
export function register(
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
const nulTokenSource = new vscode.CancellationTokenSource();
|
||||
const noopDisposable = vscode.Disposable.from();
|
||||
|
||||
export const nulToken = nulTokenSource.token;
|
||||
export const nulToken: vscode.CancellationToken = {
|
||||
isCancellationRequested: false,
|
||||
onCancellationRequested: () => noopDisposable
|
||||
};
|
||||
|
||||
@@ -41,9 +41,20 @@ export default class Logger {
|
||||
}
|
||||
|
||||
public logLevel(level: LogLevel, message: string, data?: any): void {
|
||||
this.output.appendLine(`[${level} - ${(new Date().toTimeString())}] ${message}`);
|
||||
this.output.appendLine(`[${level} - ${this.now()}] ${message}`);
|
||||
if (data) {
|
||||
this.output.appendLine(this.data2String(data));
|
||||
}
|
||||
}
|
||||
|
||||
private now(): string {
|
||||
const now = new Date();
|
||||
return padLeft(now.getUTCHours() + '', 2, '0')
|
||||
+ ':' + padLeft(now.getMinutes() + '', 2, '0')
|
||||
+ ':' + padLeft(now.getUTCSeconds() + '', 2, '0') + '.' + now.getMilliseconds();
|
||||
}
|
||||
}
|
||||
|
||||
function padLeft(s: string, n: number, pad = ' ') {
|
||||
return pad.repeat(Math.max(0, n - s.length)) + s;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
"enableProposedApi": true,
|
||||
"private": true,
|
||||
"activationEvents": [
|
||||
"onFileSystem:memfs"
|
||||
"onFileSystem:memfs",
|
||||
"onDebug"
|
||||
],
|
||||
"main": "./out/extension",
|
||||
"engines": {
|
||||
@@ -46,23 +47,70 @@
|
||||
}
|
||||
},
|
||||
"taskDefinitions": [
|
||||
{
|
||||
"type": "custombuildscript",
|
||||
"required": [
|
||||
"flavor"
|
||||
],
|
||||
"properties": {
|
||||
"flavor": {
|
||||
"type": "string",
|
||||
"description": "The build flavor. Should be either '32' or '64'."
|
||||
},
|
||||
"flags": {
|
||||
"type": "array",
|
||||
"description": "Additional build flags."
|
||||
}
|
||||
{
|
||||
"type": "custombuildscript",
|
||||
"required": [
|
||||
"flavor"
|
||||
],
|
||||
"properties": {
|
||||
"flavor": {
|
||||
"type": "string",
|
||||
"description": "The build flavor. Should be either '32' or '64'."
|
||||
},
|
||||
"flags": {
|
||||
"type": "array",
|
||||
"description": "Additional build flags."
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"breakpoints": [
|
||||
{
|
||||
"language": "markdown"
|
||||
}
|
||||
],
|
||||
"debuggers": [
|
||||
{
|
||||
"type": "mock",
|
||||
"label": "Mock Debug",
|
||||
"languages": [
|
||||
"markdown"
|
||||
],
|
||||
|
||||
"configurationAttributes": {
|
||||
"launch": {
|
||||
"required": [
|
||||
"program"
|
||||
],
|
||||
"properties": {
|
||||
"program": {
|
||||
"type": "string",
|
||||
"description": "Absolute path to a text file.",
|
||||
"default": "${workspaceFolder}/file.md"
|
||||
},
|
||||
"stopOnEntry": {
|
||||
"type": "boolean",
|
||||
"description": "Automatically stop after launch.",
|
||||
"default": true
|
||||
},
|
||||
"trace": {
|
||||
"type": "boolean",
|
||||
"description": "Enable logging of the Debug Adapter Protocol.",
|
||||
"default": true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"initialConfigurations": [
|
||||
{
|
||||
"type": "mock",
|
||||
"request": "launch",
|
||||
"name": "Debug file.md",
|
||||
"program": "${workspaceFolder}/file.md"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"compile": "node ./node_modules/vscode/bin/compile -watch -p ./",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -55,7 +55,7 @@ suite('window namespace tests', () => {
|
||||
}
|
||||
terminal.processId.then(id => {
|
||||
try {
|
||||
ok(id > 0);
|
||||
ok(id && id > 0);
|
||||
} catch (e) {
|
||||
done(e);
|
||||
}
|
||||
|
||||
@@ -5,12 +5,20 @@
|
||||
"publisher": "vscode",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"activationEvents": [
|
||||
"onLanguage:json"
|
||||
],
|
||||
"main": "./out/colorizerTestMain",
|
||||
"enableProposedApi": true,
|
||||
"engines": {
|
||||
"vscode": "*"
|
||||
},
|
||||
"scripts": {
|
||||
"vscode:prepublish": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:vscode-colorize-tests ./tsconfig.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"jsonc-parser": "2.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^12.11.7",
|
||||
"mocha-junit-reporter": "^1.17.0",
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import * as jsoncParser from 'jsonc-parser';
|
||||
|
||||
export function activate(context: vscode.ExtensionContext): any {
|
||||
console.log('activates');
|
||||
|
||||
const tokenModifiers = ['static', 'abstract', 'deprecated'];
|
||||
const tokenTypes = ['strings', 'types', 'structs', 'classes', 'functions', 'variables'];
|
||||
const legend = new vscode.SemanticColoringLegend(tokenTypes, tokenModifiers);
|
||||
|
||||
/*
|
||||
* A certain token (at index `i` is encoded using 5 uint32 integers):
|
||||
* - at index `5*i` - `deltaLine`: token line number, relative to `SemanticColoringArea.line`
|
||||
* - at index `5*i+1` - `startCharacter`: token start character offset inside the line (inclusive)
|
||||
* - at index `5*i+2` - `endCharacter`: token end character offset inside the line (exclusive)
|
||||
* - at index `5*i+3` - `tokenType`: will be looked up in `SemanticColoringLegend.tokenTypes`
|
||||
* - at index `5*i+4` - `tokenModifiers`: each set bit will be looked up in `SemanticColoringLegend.tokenModifiers`
|
||||
*/
|
||||
|
||||
const semanticHighlightProvider: vscode.SemanticColoringProvider = {
|
||||
provideSemanticColoring(document: vscode.TextDocument): vscode.ProviderResult<vscode.SemanticColoring> {
|
||||
const result: number[] = [];
|
||||
console.log('provideSemanticColoring');
|
||||
|
||||
const visitor: jsoncParser.JSONVisitor = {
|
||||
onObjectProperty: (property: string, _offset: number, length: number, startLine: number, startCharacter: number) => {
|
||||
result.push(startLine);
|
||||
result.push(startCharacter);
|
||||
result.push(startCharacter + length);
|
||||
|
||||
|
||||
const [type, ...modifiers] = property.split('.');
|
||||
let tokenType = legend.tokenTypes.indexOf(type);
|
||||
if (tokenType === -1) {
|
||||
tokenType = 0;
|
||||
}
|
||||
result.push(tokenType);
|
||||
|
||||
let tokenModifiers = 0;
|
||||
for (let i = 0; i < modifiers.length; i++) {
|
||||
const index = legend.tokenModifiers.indexOf(modifiers[i]);
|
||||
if (index !== -1) {
|
||||
tokenModifiers = tokenModifiers | 1 << index;
|
||||
}
|
||||
}
|
||||
result.push(tokenModifiers);
|
||||
}
|
||||
};
|
||||
jsoncParser.visit(document.getText(), visitor);
|
||||
return new vscode.SemanticColoring([new vscode.SemanticColoringArea(0, new Uint32Array(result))]);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
context.subscriptions.push(vscode.languages.registerSemanticColoringProvider({ pattern: '**/color-test.json' }, semanticHighlightProvider, legend));
|
||||
|
||||
}
|
||||
+3
-1
@@ -3,5 +3,7 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
/// <reference path="../../../../src/vs/vscode.d.ts" />
|
||||
/// <reference path="../../../../src/vs/vscode.proposed.d.ts" />
|
||||
/// <reference types='@types/node'/>
|
||||
/// <reference path='../../../../src/vs/vscode.d.ts'/>
|
||||
|
||||
|
||||
@@ -1042,6 +1042,11 @@ json3@3.3.2:
|
||||
resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1"
|
||||
integrity sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=
|
||||
|
||||
jsonc-parser@2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.2.0.tgz#f206f87f9d49d644b7502052c04e82dd6392e9ef"
|
||||
integrity sha512-4fLQxW1j/5fWj6p78vAlAafoCKtuBm6ghv+Ij5W2DrDx0qE+ZdEl2c6Ko1mgJNF5ftX1iEWQQ4Ap7+3GlhjkOA==
|
||||
|
||||
jsonify@~0.0.0:
|
||||
version "0.0.0"
|
||||
resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
typescript@3.7.2:
|
||||
version "3.7.2"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.2.tgz#27e489b95fa5909445e9fef5ee48d81697ad18fb"
|
||||
integrity sha512-ml7V7JfiN2Xwvcer+XAf2csGO1bPBdRbFCkYBczNZggrBZ9c7G3riSUeJmqEU5uOtXNPMhE3n+R4FA/3YOAWOQ==
|
||||
typescript@3.7.3-insiders.20191118:
|
||||
version "3.7.3-insiders.20191118"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.3-insiders.20191118.tgz#86d3b1de1859d70b0a081b708a223f8f3c6a4d46"
|
||||
integrity sha512-r06UsJwJzLwgRkf3Or2T5tBnUmp8RD5gOHkC6ax9mLHu5r7voo1WAUpvG09R92GvdEQsgZXxOUhdEJWEoc/5sA==
|
||||
|
||||
+5
-5
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "code-oss-dev",
|
||||
"version": "1.41.0",
|
||||
"distro": "b2b71bcd54560577429f8ee10aa270a41036a09c",
|
||||
"distro": "531a9666cfe4c178d84b8540af753fa5ee456f33",
|
||||
"author": {
|
||||
"name": "Microsoft Corporation"
|
||||
},
|
||||
@@ -39,10 +39,10 @@
|
||||
"jschardet": "2.1.1",
|
||||
"keytar": "^4.11.0",
|
||||
"native-is-elevated": "0.4.1",
|
||||
"native-keymap": "2.0.0",
|
||||
"native-watchdog": "1.2.0",
|
||||
"native-keymap": "2.1.0",
|
||||
"native-watchdog": "1.3.0",
|
||||
"node-pty": "^0.10.0-beta2",
|
||||
"onigasm-umd": "^2.2.4",
|
||||
"onigasm-umd": "2.2.5",
|
||||
"semver-umd": "^5.5.3",
|
||||
"spdlog": "^0.11.1",
|
||||
"sudo-prompt": "9.1.1",
|
||||
@@ -52,7 +52,7 @@
|
||||
"vscode-proxy-agent": "^0.5.2",
|
||||
"vscode-ripgrep": "^1.5.7",
|
||||
"vscode-sqlite3": "4.0.9",
|
||||
"vscode-textmate": "^4.3.0",
|
||||
"vscode-textmate": "4.4.0",
|
||||
"xterm": "4.3.0-beta17",
|
||||
"xterm-addon-search": "0.4.0-beta4",
|
||||
"xterm-addon-web-links": "0.2.1",
|
||||
|
||||
+3
-3
@@ -10,16 +10,16 @@
|
||||
"https-proxy-agent": "^2.2.3",
|
||||
"iconv-lite": "0.5.0",
|
||||
"jschardet": "2.1.1",
|
||||
"native-watchdog": "1.2.0",
|
||||
"native-watchdog": "1.3.0",
|
||||
"node-pty": "^0.10.0-beta2",
|
||||
"onigasm-umd": "^2.2.4",
|
||||
"onigasm-umd": "2.2.5",
|
||||
"semver-umd": "^5.5.3",
|
||||
"spdlog": "^0.11.1",
|
||||
"vscode-minimist": "^1.2.2",
|
||||
"vscode-nsfw": "1.2.8",
|
||||
"vscode-proxy-agent": "^0.5.2",
|
||||
"vscode-ripgrep": "^1.5.7",
|
||||
"vscode-textmate": "^4.3.0",
|
||||
"vscode-textmate": "4.4.0",
|
||||
"xterm": "4.3.0-beta17",
|
||||
"xterm-addon-search": "0.4.0-beta4",
|
||||
"xterm-addon-web-links": "0.2.1",
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
"name": "vscode-web",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"onigasm-umd": "^2.2.4",
|
||||
"onigasm-umd": "2.2.5",
|
||||
"semver-umd": "^5.5.3",
|
||||
"vscode-textmate": "^4.3.0",
|
||||
"vscode-textmate": "4.4.0",
|
||||
"xterm": "4.3.0-beta17",
|
||||
"xterm-addon-search": "0.4.0-beta4",
|
||||
"xterm-addon-web-links": "0.2.1",
|
||||
|
||||
@@ -7,10 +7,10 @@ nan@^2.14.0:
|
||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c"
|
||||
integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==
|
||||
|
||||
onigasm-umd@^2.2.4:
|
||||
version "2.2.4"
|
||||
resolved "https://registry.yarnpkg.com/onigasm-umd/-/onigasm-umd-2.2.4.tgz#27ee87f7496c66ad40cebfbc0d418c19bb7db5ec"
|
||||
integrity sha512-N9VqCUhl9KBuzm47vcK8T/xUnbYylIhMN45Rwltlo1sZc3QUDda6SxIlyVB8r0SJQwURv8JOHjyXjjCriGvzRg==
|
||||
onigasm-umd@2.2.5:
|
||||
version "2.2.5"
|
||||
resolved "https://registry.yarnpkg.com/onigasm-umd/-/onigasm-umd-2.2.5.tgz#f104247334a543accd3f8d641a4d99b3d908d6a1"
|
||||
integrity sha512-R3qD7hq6i2bBklF+QyjqZl/G4fe7GwtukI28YLH2vuiatqx52tb9vpg2sxwemKc3nF76SgkeyOKJLchBmTm0Aw==
|
||||
|
||||
oniguruma@^7.2.0:
|
||||
version "7.2.0"
|
||||
@@ -24,10 +24,10 @@ semver-umd@^5.5.3:
|
||||
resolved "https://registry.yarnpkg.com/semver-umd/-/semver-umd-5.5.3.tgz#b64d7a2d4f5a717b369d56e31940a38e47e34d1e"
|
||||
integrity sha512-HOnQrn2iKnVe/xlqCTzMXQdvSz3rPbD0DmQXYuQ+oK1dpptGFfPghonQrx5JHl2O7EJwDqtQnjhE7ME23q6ngw==
|
||||
|
||||
vscode-textmate@^4.3.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-4.3.0.tgz#6e1f0f273d84148cfa1e9c7ed85bd16c974f9f61"
|
||||
integrity sha512-MhEZ3hvxOVuYGsrRzW/PZLDR2VdtG2+V6TIKPvmE9JT+RAq/OtPlrFd1+ZQwBefoHEhjRNuRJ0OktcFezuxPmg==
|
||||
vscode-textmate@4.4.0:
|
||||
version "4.4.0"
|
||||
resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-4.4.0.tgz#14032afeb50152e8f53258c95643e555f2948305"
|
||||
integrity sha512-dFpm2eK0HwEjeFSD1DDh3j0q47bDSVuZt20RiJWxGqjtm73Wu2jip3C2KaZI3dQx/fSeeXCr/uEN4LNaNj7Ytw==
|
||||
dependencies:
|
||||
oniguruma "^7.2.0"
|
||||
|
||||
|
||||
+12
-12
@@ -261,10 +261,10 @@ nan@^2.10.0, nan@^2.14.0:
|
||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c"
|
||||
integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==
|
||||
|
||||
native-watchdog@1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/native-watchdog/-/native-watchdog-1.2.0.tgz#9c710093ac6e9e60b19517cb1ef4ac9d7c997395"
|
||||
integrity sha512-jOOoA3PLSxt1adaeuEW7ymV9cApZiDxn4y4iFs7b4sP73EG+5Lsz+OgUNFcGMyrtznTw6ZvlLcilIN4jeAIgaQ==
|
||||
native-watchdog@1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/native-watchdog/-/native-watchdog-1.3.0.tgz#88cee94c9dc766b85c8506eda14c8bd8c9618e27"
|
||||
integrity sha512-WOjGRNGkYZ5MXsntcvCYrKtSYMaewlbCFplbcUVo9bE80LPVt8TAVFHYWB8+a6fWCGYheq21+Wtt6CJrUaCJhw==
|
||||
|
||||
node-addon-api@1.6.2:
|
||||
version "1.6.2"
|
||||
@@ -283,10 +283,10 @@ normalize-path@^3.0.0, normalize-path@~3.0.0:
|
||||
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
|
||||
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
|
||||
|
||||
onigasm-umd@^2.2.4:
|
||||
version "2.2.4"
|
||||
resolved "https://registry.yarnpkg.com/onigasm-umd/-/onigasm-umd-2.2.4.tgz#27ee87f7496c66ad40cebfbc0d418c19bb7db5ec"
|
||||
integrity sha512-N9VqCUhl9KBuzm47vcK8T/xUnbYylIhMN45Rwltlo1sZc3QUDda6SxIlyVB8r0SJQwURv8JOHjyXjjCriGvzRg==
|
||||
onigasm-umd@2.2.5:
|
||||
version "2.2.5"
|
||||
resolved "https://registry.yarnpkg.com/onigasm-umd/-/onigasm-umd-2.2.5.tgz#f104247334a543accd3f8d641a4d99b3d908d6a1"
|
||||
integrity sha512-R3qD7hq6i2bBklF+QyjqZl/G4fe7GwtukI28YLH2vuiatqx52tb9vpg2sxwemKc3nF76SgkeyOKJLchBmTm0Aw==
|
||||
|
||||
oniguruma@^7.2.0:
|
||||
version "7.2.0"
|
||||
@@ -399,10 +399,10 @@ vscode-ripgrep@^1.5.7:
|
||||
resolved "https://registry.yarnpkg.com/vscode-ripgrep/-/vscode-ripgrep-1.5.7.tgz#acb6b548af488a4bca5d0f1bb5faf761343289ce"
|
||||
integrity sha512-/Vsz/+k8kTvui0q3O74pif9FK0nKopgFTiGNVvxicZANxtSA8J8gUE9GQ/4dpi7D/2yI/YVORszwVskFbz46hQ==
|
||||
|
||||
vscode-textmate@^4.3.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-4.3.0.tgz#6e1f0f273d84148cfa1e9c7ed85bd16c974f9f61"
|
||||
integrity sha512-MhEZ3hvxOVuYGsrRzW/PZLDR2VdtG2+V6TIKPvmE9JT+RAq/OtPlrFd1+ZQwBefoHEhjRNuRJ0OktcFezuxPmg==
|
||||
vscode-textmate@4.4.0:
|
||||
version "4.4.0"
|
||||
resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-4.4.0.tgz#14032afeb50152e8f53258c95643e555f2948305"
|
||||
integrity sha512-dFpm2eK0HwEjeFSD1DDh3j0q47bDSVuZt20RiJWxGqjtm73Wu2jip3C2KaZI3dQx/fSeeXCr/uEN4LNaNj7Ytw==
|
||||
dependencies:
|
||||
oniguruma "^7.2.0"
|
||||
|
||||
|
||||
@@ -227,6 +227,14 @@ function getMediaMime(forPath) {
|
||||
*/
|
||||
async function serveFile(req, res, filePath, responseHeaders = Object.create(null)) {
|
||||
try {
|
||||
|
||||
// Sanity checks
|
||||
filePath = path.normalize(filePath); // ensure no "." and ".."
|
||||
if (filePath.indexOf(`${APP_ROOT}${path.sep}`) !== 0) {
|
||||
// invalid location outside of APP_ROOT
|
||||
return serveError(req, res, 400, `Bad request.`);
|
||||
}
|
||||
|
||||
const stat = await util.promisify(fs.stat)(filePath);
|
||||
|
||||
// Check if file modified since
|
||||
|
||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
||||
// Type definitions for Electron 6.1.4
|
||||
// Type definitions for Electron 6.1.5
|
||||
// Project: http://electronjs.org/
|
||||
// Definitions by: The Electron Team <https://github.com/electron/electron>
|
||||
// Definitions: https://github.com/electron/electron-typescript-definitions
|
||||
|
||||
Vendored
-93
@@ -1,93 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
declare module 'native-keymap' {
|
||||
|
||||
export interface IWindowsKeyMapping {
|
||||
vkey: string;
|
||||
value: string;
|
||||
withShift: string;
|
||||
withAltGr: string;
|
||||
withShiftAltGr: string;
|
||||
}
|
||||
export interface IWindowsKeyboardMapping {
|
||||
[code: string]: IWindowsKeyMapping;
|
||||
}
|
||||
export interface ILinuxKeyMapping {
|
||||
value: string;
|
||||
withShift: string;
|
||||
withAltGr: string;
|
||||
withShiftAltGr: string;
|
||||
}
|
||||
export interface ILinuxKeyboardMapping {
|
||||
[code: string]: ILinuxKeyMapping;
|
||||
}
|
||||
export interface IMacKeyMapping {
|
||||
value: string;
|
||||
withShift: string;
|
||||
withAltGr: string;
|
||||
withShiftAltGr: string;
|
||||
valueIsDeadKey: boolean;
|
||||
withShiftIsDeadKey: boolean;
|
||||
withAltGrIsDeadKey: boolean;
|
||||
withShiftAltGrIsDeadKey: boolean;
|
||||
}
|
||||
export interface IMacKeyboardMapping {
|
||||
[code: string]: IMacKeyMapping;
|
||||
}
|
||||
|
||||
export type IKeyboardMapping = IWindowsKeyboardMapping | ILinuxKeyboardMapping | IMacKeyboardMapping;
|
||||
|
||||
export function getKeyMap(): IKeyboardMapping;
|
||||
|
||||
/* __GDPR__FRAGMENT__
|
||||
"IKeyboardLayoutInfo" : {
|
||||
"name" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
|
||||
"id": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
|
||||
"text": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
}
|
||||
*/
|
||||
export interface IWindowsKeyboardLayoutInfo {
|
||||
name: string;
|
||||
id: string;
|
||||
text: string;
|
||||
}
|
||||
|
||||
/* __GDPR__FRAGMENT__
|
||||
"IKeyboardLayoutInfo" : {
|
||||
"model" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
|
||||
"layout": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
|
||||
"variant": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
|
||||
"options": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
|
||||
"rules": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
}
|
||||
*/
|
||||
export interface ILinuxKeyboardLayoutInfo {
|
||||
model: string;
|
||||
layout: string;
|
||||
variant: string;
|
||||
options: string;
|
||||
rules: string;
|
||||
}
|
||||
|
||||
/* __GDPR__FRAGMENT__
|
||||
"IKeyboardLayoutInfo" : {
|
||||
"id" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
|
||||
"lang": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
}
|
||||
*/
|
||||
export interface IMacKeyboardLayoutInfo {
|
||||
id: string;
|
||||
lang: string;
|
||||
}
|
||||
|
||||
export type IKeyboardLayoutInfo = IWindowsKeyboardLayoutInfo | ILinuxKeyboardLayoutInfo | IMacKeyboardLayoutInfo;
|
||||
|
||||
export function getCurrentKeyboardLayout(): IKeyboardLayoutInfo;
|
||||
|
||||
export function onDidChangeKeyboardLayout(callback: () => void): void;
|
||||
|
||||
export function isISOKeyboard(): boolean;
|
||||
}
|
||||
Vendored
-17
@@ -1,17 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
declare module 'native-watchdog' {
|
||||
|
||||
/**
|
||||
* Start monitoring for a certain pid to exist.
|
||||
* If the process indicated by pid ceases to execute,
|
||||
* the current process will exit in 6 seconds with exit code 87
|
||||
*/
|
||||
export function start(pid: number): void;
|
||||
|
||||
export function exit(exitCode: number): void;
|
||||
|
||||
}
|
||||
Vendored
-33
@@ -1,33 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
declare module "onigasm-umd" {
|
||||
|
||||
function loadWASM(data: string | ArrayBuffer): Promise<void>;
|
||||
|
||||
class OnigString {
|
||||
constructor(content: string);
|
||||
readonly content: string;
|
||||
readonly dispose?: () => void;
|
||||
}
|
||||
|
||||
class OnigScanner {
|
||||
constructor(patterns: string[]);
|
||||
findNextMatchSync(string: string | OnigString, startPosition: number): IOnigMatch;
|
||||
}
|
||||
|
||||
export interface IOnigCaptureIndex {
|
||||
index: number
|
||||
start: number
|
||||
end: number
|
||||
length: number
|
||||
}
|
||||
|
||||
export interface IOnigMatch {
|
||||
index: number
|
||||
captureIndices: IOnigCaptureIndex[]
|
||||
scanner: OnigScanner
|
||||
}
|
||||
}
|
||||
Vendored
-256
@@ -1,256 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
declare module "vscode-textmate" {
|
||||
/**
|
||||
* A single theme setting.
|
||||
*/
|
||||
export interface IRawThemeSetting {
|
||||
readonly name?: string;
|
||||
readonly scope?: string | string[];
|
||||
readonly settings: {
|
||||
readonly fontStyle?: string;
|
||||
readonly foreground?: string;
|
||||
readonly background?: string;
|
||||
};
|
||||
}
|
||||
/**
|
||||
* A TextMate theme.
|
||||
*/
|
||||
export interface IRawTheme {
|
||||
readonly name?: string;
|
||||
readonly settings: IRawThemeSetting[];
|
||||
}
|
||||
export interface Thenable<T> extends PromiseLike<T> {
|
||||
}
|
||||
/**
|
||||
* A registry helper that can locate grammar file paths given scope names.
|
||||
*/
|
||||
export interface RegistryOptions {
|
||||
theme?: IRawTheme;
|
||||
loadGrammar(scopeName: string): Thenable<IRawGrammar | undefined | null>;
|
||||
getInjections?(scopeName: string): string[];
|
||||
getOnigLib?(): Thenable<IOnigLib>;
|
||||
}
|
||||
/**
|
||||
* A map from scope name to a language id. Please do not use language id 0.
|
||||
*/
|
||||
export interface IEmbeddedLanguagesMap {
|
||||
[scopeName: string]: number;
|
||||
}
|
||||
/**
|
||||
* A map from selectors to token types.
|
||||
*/
|
||||
export interface ITokenTypeMap {
|
||||
[selector: string]: StandardTokenType;
|
||||
}
|
||||
export const enum StandardTokenType {
|
||||
Other = 0,
|
||||
Comment = 1,
|
||||
String = 2,
|
||||
RegEx = 4,
|
||||
}
|
||||
export interface IGrammarConfiguration {
|
||||
embeddedLanguages?: IEmbeddedLanguagesMap;
|
||||
tokenTypes?: ITokenTypeMap;
|
||||
}
|
||||
/**
|
||||
* The registry that will hold all grammars.
|
||||
*/
|
||||
export class Registry {
|
||||
private readonly _locator;
|
||||
private readonly _syncRegistry;
|
||||
constructor(locator?: RegistryOptions);
|
||||
/**
|
||||
* Change the theme. Once called, no previous `ruleStack` should be used anymore.
|
||||
*/
|
||||
setTheme(theme: IRawTheme): void;
|
||||
/**
|
||||
* Returns a lookup array for color ids.
|
||||
*/
|
||||
getColorMap(): string[];
|
||||
/**
|
||||
* Load the grammar for `scopeName` and all referenced included grammars asynchronously.
|
||||
* Please do not use language id 0.
|
||||
*/
|
||||
loadGrammarWithEmbeddedLanguages(initialScopeName: string, initialLanguage: number, embeddedLanguages: IEmbeddedLanguagesMap): Thenable<IGrammar>;
|
||||
/**
|
||||
* Load the grammar for `scopeName` and all referenced included grammars asynchronously.
|
||||
* Please do not use language id 0.
|
||||
*/
|
||||
loadGrammarWithConfiguration(initialScopeName: string, initialLanguage: number, configuration: IGrammarConfiguration): Thenable<IGrammar>;
|
||||
/**
|
||||
* Load the grammar for `scopeName` and all referenced included grammars asynchronously.
|
||||
*/
|
||||
loadGrammar(initialScopeName: string): Thenable<IGrammar>;
|
||||
private _loadGrammar;
|
||||
/**
|
||||
* Adds a rawGrammar.
|
||||
*/
|
||||
addGrammar(rawGrammar: IRawGrammar, injections?: string[], initialLanguage?: number, embeddedLanguages?: IEmbeddedLanguagesMap): Thenable<IGrammar>;
|
||||
/**
|
||||
* Get the grammar for `scopeName`. The grammar must first be created via `loadGrammar` or `addGrammar`.
|
||||
*/
|
||||
grammarForScopeName(scopeName: string, initialLanguage?: number, embeddedLanguages?: IEmbeddedLanguagesMap, tokenTypes?: ITokenTypeMap): Thenable<IGrammar>;
|
||||
}
|
||||
/**
|
||||
* A grammar
|
||||
*/
|
||||
export interface IGrammar {
|
||||
/**
|
||||
* Tokenize `lineText` using previous line state `prevState`.
|
||||
*/
|
||||
tokenizeLine(lineText: string, prevState: StackElement | null): ITokenizeLineResult;
|
||||
/**
|
||||
* Tokenize `lineText` using previous line state `prevState`.
|
||||
* The result contains the tokens in binary format, resolved with the following information:
|
||||
* - language
|
||||
* - token type (regex, string, comment, other)
|
||||
* - font style
|
||||
* - foreground color
|
||||
* - background color
|
||||
* e.g. for getting the languageId: `(metadata & MetadataConsts.LANGUAGEID_MASK) >>> MetadataConsts.LANGUAGEID_OFFSET`
|
||||
*/
|
||||
tokenizeLine2(lineText: string, prevState: StackElement | null): ITokenizeLineResult2;
|
||||
}
|
||||
export interface ITokenizeLineResult {
|
||||
readonly tokens: IToken[];
|
||||
/**
|
||||
* The `prevState` to be passed on to the next line tokenization.
|
||||
*/
|
||||
readonly ruleStack: StackElement;
|
||||
}
|
||||
/**
|
||||
* Helpers to manage the "collapsed" metadata of an entire StackElement stack.
|
||||
* The following assumptions have been made:
|
||||
* - languageId < 256 => needs 8 bits
|
||||
* - unique color count < 512 => needs 9 bits
|
||||
*
|
||||
* The binary format is:
|
||||
* - -------------------------------------------
|
||||
* 3322 2222 2222 1111 1111 1100 0000 0000
|
||||
* 1098 7654 3210 9876 5432 1098 7654 3210
|
||||
* - -------------------------------------------
|
||||
* xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx
|
||||
* bbbb bbbb bfff ffff ffFF FTTT LLLL LLLL
|
||||
* - -------------------------------------------
|
||||
* - L = LanguageId (8 bits)
|
||||
* - T = StandardTokenType (3 bits)
|
||||
* - F = FontStyle (3 bits)
|
||||
* - f = foreground color (9 bits)
|
||||
* - b = background color (9 bits)
|
||||
*/
|
||||
export const enum MetadataConsts {
|
||||
LANGUAGEID_MASK = 255,
|
||||
TOKEN_TYPE_MASK = 1792,
|
||||
FONT_STYLE_MASK = 14336,
|
||||
FOREGROUND_MASK = 8372224,
|
||||
BACKGROUND_MASK = 4286578688,
|
||||
LANGUAGEID_OFFSET = 0,
|
||||
TOKEN_TYPE_OFFSET = 8,
|
||||
FONT_STYLE_OFFSET = 11,
|
||||
FOREGROUND_OFFSET = 14,
|
||||
BACKGROUND_OFFSET = 23,
|
||||
}
|
||||
export interface ITokenizeLineResult2 {
|
||||
/**
|
||||
* The tokens in binary format. Each token occupies two array indices. For token i:
|
||||
* - at offset 2*i => startIndex
|
||||
* - at offset 2*i + 1 => metadata
|
||||
*
|
||||
*/
|
||||
readonly tokens: Uint32Array;
|
||||
/**
|
||||
* The `prevState` to be passed on to the next line tokenization.
|
||||
*/
|
||||
readonly ruleStack: StackElement;
|
||||
}
|
||||
export interface IToken {
|
||||
startIndex: number;
|
||||
readonly endIndex: number;
|
||||
readonly scopes: string[];
|
||||
}
|
||||
/**
|
||||
* **IMPORTANT** - Immutable!
|
||||
*/
|
||||
export interface StackElement {
|
||||
_stackElementBrand: void;
|
||||
readonly depth: number;
|
||||
clone(): StackElement;
|
||||
equals(other: StackElement): boolean;
|
||||
}
|
||||
export const INITIAL: StackElement;
|
||||
export const parseRawGrammar: (content: string, filePath?: string) => IRawGrammar;
|
||||
export interface ILocation {
|
||||
readonly filename: string;
|
||||
readonly line: number;
|
||||
readonly char: number;
|
||||
}
|
||||
export interface ILocatable {
|
||||
readonly $vscodeTextmateLocation?: ILocation;
|
||||
}
|
||||
export interface IRawGrammar extends ILocatable {
|
||||
repository: IRawRepository;
|
||||
readonly scopeName: string;
|
||||
readonly patterns: IRawRule[];
|
||||
readonly injections?: {
|
||||
[expression: string]: IRawRule;
|
||||
};
|
||||
readonly injectionSelector?: string;
|
||||
readonly fileTypes?: string[];
|
||||
readonly name?: string;
|
||||
readonly firstLineMatch?: string;
|
||||
}
|
||||
export interface IRawRepositoryMap {
|
||||
[name: string]: IRawRule;
|
||||
$self: IRawRule;
|
||||
$base: IRawRule;
|
||||
}
|
||||
export type IRawRepository = IRawRepositoryMap & ILocatable;
|
||||
export interface IRawRule extends ILocatable {
|
||||
id?: number;
|
||||
readonly include?: string;
|
||||
readonly name?: string;
|
||||
readonly contentName?: string;
|
||||
readonly match?: string;
|
||||
readonly captures?: IRawCaptures;
|
||||
readonly begin?: string;
|
||||
readonly beginCaptures?: IRawCaptures;
|
||||
readonly end?: string;
|
||||
readonly endCaptures?: IRawCaptures;
|
||||
readonly while?: string;
|
||||
readonly whileCaptures?: IRawCaptures;
|
||||
readonly patterns?: IRawRule[];
|
||||
readonly repository?: IRawRepository;
|
||||
readonly applyEndPatternLast?: boolean;
|
||||
}
|
||||
export interface IRawCapturesMap {
|
||||
[captureId: string]: IRawRule;
|
||||
}
|
||||
export type IRawCaptures = IRawCapturesMap & ILocatable;
|
||||
export interface IOnigLib {
|
||||
createOnigScanner(sources: string[]): OnigScanner;
|
||||
createOnigString(sources: string): OnigString;
|
||||
}
|
||||
export interface IOnigCaptureIndex {
|
||||
start: number;
|
||||
end: number;
|
||||
length: number;
|
||||
}
|
||||
export interface IOnigMatch {
|
||||
index: number;
|
||||
captureIndices: IOnigCaptureIndex[];
|
||||
scanner: OnigScanner;
|
||||
}
|
||||
export interface OnigScanner {
|
||||
findNextMatchSync(string: string | OnigString, startPosition: number): IOnigMatch;
|
||||
}
|
||||
export interface OnigString {
|
||||
readonly content: string;
|
||||
readonly dispose?: () => void;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -19,7 +19,7 @@ export const BrowserFeatures = {
|
||||
clipboard: {
|
||||
writeText: (
|
||||
platform.isNative
|
||||
|| document.queryCommandSupported('copy')
|
||||
|| (document.queryCommandSupported && document.queryCommandSupported('copy'))
|
||||
|| !!(navigator && navigator.clipboard && navigator.clipboard.writeText)
|
||||
),
|
||||
readText: (
|
||||
|
||||
@@ -267,10 +267,20 @@ export let addStandardDisposableListener: IAddStandardDisposableListenerSignatur
|
||||
return addDisposableListener(node, type, wrapHandler, useCapture);
|
||||
};
|
||||
|
||||
export let addStandardDisposableGenericMouseDownListner = function addStandardDisposableListener(node: HTMLElement, handler: (event: any) => void, useCapture?: boolean): IDisposable {
|
||||
let wrapHandler = _wrapAsStandardMouseEvent(handler);
|
||||
|
||||
return addDisposableGenericMouseDownListner(node, wrapHandler, useCapture);
|
||||
};
|
||||
|
||||
export function addDisposableGenericMouseDownListner(node: EventTarget, handler: (event: any) => void, useCapture?: boolean): IDisposable {
|
||||
return addDisposableListener(node, platform.isIOS && BrowserFeatures.pointerEvents ? EventType.POINTER_DOWN : EventType.MOUSE_DOWN, handler, useCapture);
|
||||
}
|
||||
|
||||
export function addDisposableGenericMouseMoveListner(node: EventTarget, handler: (event: any) => void, useCapture?: boolean): IDisposable {
|
||||
return addDisposableListener(node, platform.isIOS && BrowserFeatures.pointerEvents ? EventType.POINTER_MOVE : EventType.MOUSE_MOVE, handler, useCapture);
|
||||
}
|
||||
|
||||
export function addDisposableGenericMouseUpListner(node: EventTarget, handler: (event: any) => void, useCapture?: boolean): IDisposable {
|
||||
return addDisposableListener(node, platform.isIOS && BrowserFeatures.pointerEvents ? EventType.POINTER_UP : EventType.MOUSE_UP, handler, useCapture);
|
||||
}
|
||||
@@ -502,7 +512,16 @@ export function getClientArea(element: HTMLElement): Dimension {
|
||||
|
||||
// If visual view port exits and it's on mobile, it should be used instead of window innerWidth / innerHeight, or document.body.clientWidth / document.body.clientHeight
|
||||
if (platform.isIOS && (<any>window).visualViewport) {
|
||||
return new Dimension((<any>window).visualViewport.width, (<any>window).visualViewport.height);
|
||||
const width = (<any>window).visualViewport.width;
|
||||
const height = (<any>window).visualViewport.height - (
|
||||
browser.isStandalone
|
||||
// in PWA mode, the visual viewport always includes the safe-area-inset-bottom (which is for the home indicator)
|
||||
// even when you are using the onscreen monitor, the visual viewport will include the area between system statusbar and the onscreen keyboard
|
||||
// plus the area between onscreen keyboard and the bottom bezel, which is 20px on iOS.
|
||||
? (20 + 4) // + 4px for body margin
|
||||
: 0
|
||||
);
|
||||
return new Dimension(width, height);
|
||||
}
|
||||
|
||||
// Try innerWidth / innerHeight
|
||||
@@ -882,6 +901,7 @@ export const EventType = {
|
||||
MOUSE_LEAVE: 'mouseleave',
|
||||
POINTER_UP: 'pointerup',
|
||||
POINTER_DOWN: 'pointerdown',
|
||||
POINTER_MOVE: 'pointermove',
|
||||
CONTEXT_MENU: 'contextmenu',
|
||||
WHEEL: 'wheel',
|
||||
// Keyboard
|
||||
|
||||
@@ -33,6 +33,7 @@ export interface GestureEvent extends MouseEvent {
|
||||
translationY: number;
|
||||
pageX: number;
|
||||
pageY: number;
|
||||
tapCount: number;
|
||||
}
|
||||
|
||||
interface Touch {
|
||||
@@ -76,6 +77,11 @@ export class Gesture extends Disposable {
|
||||
|
||||
private activeTouches: { [id: number]: TouchData; };
|
||||
|
||||
private _lastSetTapCountTime: number;
|
||||
|
||||
private static readonly CLEAR_TAP_COUNT_TIME = 400; // ms
|
||||
|
||||
|
||||
private constructor() {
|
||||
super();
|
||||
|
||||
@@ -83,6 +89,7 @@ export class Gesture extends Disposable {
|
||||
this.handle = null;
|
||||
this.targets = [];
|
||||
this.ignoreTargets = [];
|
||||
this._lastSetTapCountTime = 0;
|
||||
this._register(DomUtils.addDisposableListener(document, 'touchstart', (e: TouchEvent) => this.onTouchStart(e)));
|
||||
this._register(DomUtils.addDisposableListener(document, 'touchend', (e: TouchEvent) => this.onTouchEnd(e)));
|
||||
this._register(DomUtils.addDisposableListener(document, 'touchmove', (e: TouchEvent) => this.onTouchMove(e)));
|
||||
@@ -243,10 +250,27 @@ export class Gesture extends Disposable {
|
||||
let event = <GestureEvent>(<any>document.createEvent('CustomEvent'));
|
||||
event.initEvent(type, false, true);
|
||||
event.initialTarget = initialTarget;
|
||||
event.tapCount = 0;
|
||||
return event;
|
||||
}
|
||||
|
||||
private dispatchEvent(event: GestureEvent): void {
|
||||
if (event.type === EventType.Tap) {
|
||||
const currentTime = (new Date()).getTime();
|
||||
let setTapCount = 0;
|
||||
if (currentTime - this._lastSetTapCountTime > Gesture.CLEAR_TAP_COUNT_TIME) {
|
||||
setTapCount = 1;
|
||||
} else {
|
||||
setTapCount = 2;
|
||||
}
|
||||
|
||||
this._lastSetTapCountTime = currentTime;
|
||||
event.tapCount = setTapCount;
|
||||
} else if (event.type === EventType.Change || event.type === EventType.Contextmenu) {
|
||||
// tap is canceled by scrolling or context menu
|
||||
this._lastSetTapCountTime = 0;
|
||||
}
|
||||
|
||||
for (let i = 0; i < this.ignoreTargets.length; i++) {
|
||||
if (event.initialTarget instanceof Node && this.ignoreTargets[i].contains(event.initialTarget)) {
|
||||
return;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
@font-face {
|
||||
font-family: "codicon";
|
||||
src: url("./codicon.ttf?34cea5159eda573d2422092d6f8c2c77") format("truetype");
|
||||
src: url("./codicon.ttf?c4e66586cd3ad4acc55fc456c0760dec") format("truetype");
|
||||
}
|
||||
|
||||
.codicon[class*='codicon-'] {
|
||||
@@ -401,4 +401,8 @@
|
||||
.codicon-debug-breakpoint-stackframe-focused:before { content: "\eb8b" }
|
||||
.codicon-debug-breakpoint-unsupported:before { content: "\eb8c" }
|
||||
.codicon-symbol-string:before { content: "\eb8d" }
|
||||
.codicon-debug-step-back:before { content: "\f101" }
|
||||
.codicon-debug-reverse-continue:before { content: "\eb8e" }
|
||||
.codicon-debug-step-back:before { content: "\eb8f" }
|
||||
.codicon-debug-restart-frame:before { content: "\eb90" }
|
||||
.codicon-debug-alternate:before { content: "\eb91" }
|
||||
.codicon-debug-alt:before { content: "\f101" }
|
||||
|
||||
Binary file not shown.
@@ -171,7 +171,7 @@ export class InputBox extends Widget {
|
||||
this.maxHeight = typeof this.options.flexibleMaxHeight === 'number' ? this.options.flexibleMaxHeight : Number.POSITIVE_INFINITY;
|
||||
|
||||
this.mirror = dom.append(wrapper, $('div.mirror'));
|
||||
this.mirror.innerHTML = ' ';
|
||||
this.mirror.innerHTML = ' ';
|
||||
|
||||
this.scrollableElement = new ScrollableElement(this.element, { vertical: ScrollbarVisibility.Auto });
|
||||
|
||||
@@ -305,6 +305,7 @@ export class InputBox extends Widget {
|
||||
}
|
||||
|
||||
public disable(): void {
|
||||
this.blur();
|
||||
this.input.disabled = true;
|
||||
this._hideMessage();
|
||||
}
|
||||
@@ -529,7 +530,7 @@ export class InputBox extends Widget {
|
||||
if (mirrorTextContent) {
|
||||
this.mirror.textContent = value + suffix;
|
||||
} else {
|
||||
this.mirror.innerHTML = ' ';
|
||||
this.mirror.innerHTML = ' ';
|
||||
}
|
||||
|
||||
this.layout();
|
||||
|
||||
@@ -856,7 +856,11 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
|
||||
|
||||
if (feedback[0] === -1) { // entire list feedback
|
||||
DOM.addClass(this.domNode, 'drop-target');
|
||||
this.currentDragFeedbackDisposable = toDisposable(() => DOM.removeClass(this.domNode, 'drop-target'));
|
||||
DOM.addClass(this.rowsContainer, 'drop-target');
|
||||
this.currentDragFeedbackDisposable = toDisposable(() => {
|
||||
DOM.removeClass(this.domNode, 'drop-target');
|
||||
DOM.removeClass(this.rowsContainer, 'drop-target');
|
||||
});
|
||||
} else {
|
||||
for (const index of feedback) {
|
||||
const item = this.items[index]!;
|
||||
|
||||
@@ -715,7 +715,7 @@ export class DefaultStyleController implements IStyleController {
|
||||
if (styles.listBackground) {
|
||||
if (styles.listBackground.isOpaque()) {
|
||||
content.push(`.monaco-list${suffix} .monaco-list-rows { background: ${styles.listBackground}; }`);
|
||||
} else {
|
||||
} else if (!platform.isMacintosh) { // subpixel AA doesn't exist in macOS
|
||||
console.warn(`List with id '${this.selectorSuffix}' was styled with a non-opaque background color. This will break sub-pixel antialiasing.`);
|
||||
}
|
||||
}
|
||||
@@ -796,6 +796,7 @@ export class DefaultStyleController implements IStyleController {
|
||||
if (styles.listDropBackground) {
|
||||
content.push(`
|
||||
.monaco-list${suffix}.drop-target,
|
||||
.monaco-list${suffix} .monaco-list-rows.drop-target,
|
||||
.monaco-list${suffix} .monaco-list-row.drop-target { background-color: ${styles.listDropBackground} !important; color: inherit !important; }
|
||||
`);
|
||||
}
|
||||
|
||||
+23
-23
@@ -3,12 +3,12 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
.monaco-panel-view {
|
||||
.monaco-pane-view {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.monaco-panel-view .panel {
|
||||
.monaco-pane-view .pane {
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@@ -16,7 +16,7 @@
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.monaco-panel-view .panel > .panel-header {
|
||||
.monaco-pane-view .pane > .pane-header {
|
||||
font-size: 11px;
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
@@ -26,7 +26,7 @@
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.monaco-panel-view .panel > .panel-header > .twisties {
|
||||
.monaco-pane-view .pane > .pane-header > .twisties {
|
||||
width: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -36,26 +36,26 @@
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.monaco-panel-view .panel > .panel-header.expanded > .twisties::before {
|
||||
.monaco-pane-view .pane > .pane-header.expanded > .twisties::before {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
/* TODO: actions should be part of the panel, but they aren't yet */
|
||||
.monaco-panel-view .panel > .panel-header > .actions {
|
||||
/* TODO: actions should be part of the pane, but they aren't yet */
|
||||
.monaco-pane-view .pane > .pane-header > .actions {
|
||||
display: none;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
/* TODO: actions should be part of the panel, but they aren't yet */
|
||||
.monaco-panel-view .panel:hover > .panel-header.expanded > .actions,
|
||||
.monaco-panel-view .panel > .panel-header.actions-always-visible.expanded > .actions,
|
||||
.monaco-panel-view .panel > .panel-header.focused.expanded > .actions {
|
||||
/* TODO: actions should be part of the pane, but they aren't yet */
|
||||
.monaco-pane-view .pane:hover > .pane-header.expanded > .actions,
|
||||
.monaco-pane-view .pane > .pane-header.actions-always-visible.expanded > .actions,
|
||||
.monaco-pane-view .pane > .pane-header.focused.expanded > .actions {
|
||||
display: initial;
|
||||
}
|
||||
|
||||
/* TODO: actions should be part of the panel, but they aren't yet */
|
||||
.monaco-panel-view .panel > .panel-header > .actions .action-label.icon,
|
||||
.monaco-panel-view .panel > .panel-header > .actions .action-label.codicon {
|
||||
/* TODO: actions should be part of the pane, but they aren't yet */
|
||||
.monaco-pane-view .pane > .pane-header > .actions .action-label.icon,
|
||||
.monaco-pane-view .pane > .pane-header > .actions .action-label.codicon {
|
||||
width: 28px;
|
||||
height: 22px;
|
||||
background-size: 16px;
|
||||
@@ -69,33 +69,33 @@
|
||||
}
|
||||
|
||||
/* Bold font style does not go well with CJK fonts */
|
||||
.monaco-panel-view:lang(zh-Hans) .panel > .panel-header,
|
||||
.monaco-panel-view:lang(zh-Hant) .panel > .panel-header,
|
||||
.monaco-panel-view:lang(ja) .panel > .panel-header,
|
||||
.monaco-panel-view:lang(ko) .panel > .panel-header {
|
||||
.monaco-pane-view:lang(zh-Hans) .pane > .pane-header,
|
||||
.monaco-pane-view:lang(zh-Hant) .pane > .pane-header,
|
||||
.monaco-pane-view:lang(ja) .pane > .pane-header,
|
||||
.monaco-pane-view:lang(ko) .pane > .pane-header {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.monaco-panel-view .panel > .panel-header.hidden {
|
||||
.monaco-pane-view .pane > .pane-header.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.monaco-panel-view .panel > .panel-body {
|
||||
.monaco-pane-view .pane > .pane-body {
|
||||
overflow: hidden;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
/* Animation */
|
||||
|
||||
.monaco-panel-view.animated .split-view-view {
|
||||
.monaco-pane-view.animated .split-view-view {
|
||||
transition-duration: 0.15s;
|
||||
transition-timing-function: ease-out;
|
||||
}
|
||||
|
||||
.monaco-panel-view.animated.vertical .split-view-view {
|
||||
.monaco-pane-view.animated.vertical .split-view-view {
|
||||
transition-property: height;
|
||||
}
|
||||
|
||||
.monaco-panel-view.animated.horizontal .split-view-view {
|
||||
.monaco-pane-view.animated.horizontal .split-view-view {
|
||||
transition-property: width;
|
||||
}
|
||||
+72
-72
@@ -3,7 +3,7 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'vs/css!./panelview';
|
||||
import 'vs/css!./paneview';
|
||||
import { IDisposable, Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { domEvent } from 'vs/base/browser/event';
|
||||
@@ -16,14 +16,14 @@ import { SplitView, IView } from './splitview';
|
||||
import { isFirefox } from 'vs/base/browser/browser';
|
||||
import { DataTransfers } from 'vs/base/browser/dnd';
|
||||
|
||||
export interface IPanelOptions {
|
||||
export interface IPaneOptions {
|
||||
ariaHeaderLabel?: string;
|
||||
minimumBodySize?: number;
|
||||
maximumBodySize?: number;
|
||||
expanded?: boolean;
|
||||
}
|
||||
|
||||
export interface IPanelStyles {
|
||||
export interface IPaneStyles {
|
||||
dropBackground?: Color;
|
||||
headerForeground?: Color;
|
||||
headerBackground?: Color;
|
||||
@@ -31,7 +31,7 @@ export interface IPanelStyles {
|
||||
}
|
||||
|
||||
/**
|
||||
* A Panel is a structured SplitView view.
|
||||
* A Pane is a structured SplitView view.
|
||||
*
|
||||
* WARNING: You must call `render()` after you contruct it.
|
||||
* It can't be done automatically at the end of the ctor
|
||||
@@ -39,7 +39,7 @@ export interface IPanelStyles {
|
||||
* Subclasses wouldn't be able to set own properties
|
||||
* before the `render()` call, thus forbiding their use.
|
||||
*/
|
||||
export abstract class Panel extends Disposable implements IView {
|
||||
export abstract class Pane extends Disposable implements IView {
|
||||
|
||||
private static readonly HEADER_SIZE = 22;
|
||||
|
||||
@@ -54,7 +54,7 @@ export abstract class Panel extends Disposable implements IView {
|
||||
private _minimumBodySize: number;
|
||||
private _maximumBodySize: number;
|
||||
private ariaHeaderLabel: string;
|
||||
private styles: IPanelStyles = {};
|
||||
private styles: IPaneStyles = {};
|
||||
private animationTimer: number | undefined = undefined;
|
||||
|
||||
private readonly _onDidChange = this._register(new Emitter<number | undefined>());
|
||||
@@ -95,7 +95,7 @@ export abstract class Panel extends Disposable implements IView {
|
||||
}
|
||||
|
||||
private get headerSize(): number {
|
||||
return this.headerVisible ? Panel.HEADER_SIZE : 0;
|
||||
return this.headerVisible ? Pane.HEADER_SIZE : 0;
|
||||
}
|
||||
|
||||
get minimumSize(): number {
|
||||
@@ -116,14 +116,14 @@ export abstract class Panel extends Disposable implements IView {
|
||||
|
||||
width: number = 0;
|
||||
|
||||
constructor(options: IPanelOptions = {}) {
|
||||
constructor(options: IPaneOptions = {}) {
|
||||
super();
|
||||
this._expanded = typeof options.expanded === 'undefined' ? true : !!options.expanded;
|
||||
this.ariaHeaderLabel = options.ariaHeaderLabel || '';
|
||||
this._minimumBodySize = typeof options.minimumBodySize === 'number' ? options.minimumBodySize : 120;
|
||||
this._maximumBodySize = typeof options.maximumBodySize === 'number' ? options.maximumBodySize : Number.POSITIVE_INFINITY;
|
||||
|
||||
this.element = $('.panel');
|
||||
this.element = $('.pane');
|
||||
}
|
||||
|
||||
isExpanded(): boolean {
|
||||
@@ -169,7 +169,7 @@ export abstract class Panel extends Disposable implements IView {
|
||||
}
|
||||
|
||||
render(): void {
|
||||
this.header = $('.panel-header');
|
||||
this.header = $('.pane-header');
|
||||
append(this.element, this.header);
|
||||
this.header.setAttribute('tabindex', '0');
|
||||
this.header.setAttribute('role', 'toolbar');
|
||||
@@ -198,12 +198,12 @@ export abstract class Panel extends Disposable implements IView {
|
||||
this._register(domEvent(this.header, 'click')
|
||||
(() => this.setExpanded(!this.isExpanded()), null));
|
||||
|
||||
this.body = append(this.element, $('.panel-body'));
|
||||
this.body = append(this.element, $('.pane-body'));
|
||||
this.renderBody(this.body);
|
||||
}
|
||||
|
||||
layout(height: number): void {
|
||||
const headerSize = this.headerVisible ? Panel.HEADER_SIZE : 0;
|
||||
const headerSize = this.headerVisible ? Pane.HEADER_SIZE : 0;
|
||||
|
||||
if (this.isExpanded()) {
|
||||
this.layoutBody(height - headerSize, this.width);
|
||||
@@ -211,7 +211,7 @@ export abstract class Panel extends Disposable implements IView {
|
||||
}
|
||||
}
|
||||
|
||||
style(styles: IPanelStyles): void {
|
||||
style(styles: IPaneStyles): void {
|
||||
this.styles = styles;
|
||||
|
||||
if (!this.header) {
|
||||
@@ -242,31 +242,31 @@ export abstract class Panel extends Disposable implements IView {
|
||||
}
|
||||
|
||||
interface IDndContext {
|
||||
draggable: PanelDraggable | null;
|
||||
draggable: PaneDraggable | null;
|
||||
}
|
||||
|
||||
class PanelDraggable extends Disposable {
|
||||
class PaneDraggable extends Disposable {
|
||||
|
||||
private static readonly DefaultDragOverBackgroundColor = new Color(new RGBA(128, 128, 128, 0.5));
|
||||
|
||||
private dragOverCounter = 0; // see https://github.com/Microsoft/vscode/issues/14470
|
||||
|
||||
private _onDidDrop = this._register(new Emitter<{ from: Panel, to: Panel }>());
|
||||
private _onDidDrop = this._register(new Emitter<{ from: Pane, to: Pane }>());
|
||||
readonly onDidDrop = this._onDidDrop.event;
|
||||
|
||||
constructor(private panel: Panel, private dnd: IPanelDndController, private context: IDndContext) {
|
||||
constructor(private pane: Pane, private dnd: IPaneDndController, private context: IDndContext) {
|
||||
super();
|
||||
|
||||
panel.draggableElement.draggable = true;
|
||||
this._register(domEvent(panel.draggableElement, 'dragstart')(this.onDragStart, this));
|
||||
this._register(domEvent(panel.dropTargetElement, 'dragenter')(this.onDragEnter, this));
|
||||
this._register(domEvent(panel.dropTargetElement, 'dragleave')(this.onDragLeave, this));
|
||||
this._register(domEvent(panel.dropTargetElement, 'dragend')(this.onDragEnd, this));
|
||||
this._register(domEvent(panel.dropTargetElement, 'drop')(this.onDrop, this));
|
||||
pane.draggableElement.draggable = true;
|
||||
this._register(domEvent(pane.draggableElement, 'dragstart')(this.onDragStart, this));
|
||||
this._register(domEvent(pane.dropTargetElement, 'dragenter')(this.onDragEnter, this));
|
||||
this._register(domEvent(pane.dropTargetElement, 'dragleave')(this.onDragLeave, this));
|
||||
this._register(domEvent(pane.dropTargetElement, 'dragend')(this.onDragEnd, this));
|
||||
this._register(domEvent(pane.dropTargetElement, 'drop')(this.onDrop, this));
|
||||
}
|
||||
|
||||
private onDragStart(e: DragEvent): void {
|
||||
if (!this.dnd.canDrag(this.panel) || !e.dataTransfer) {
|
||||
if (!this.dnd.canDrag(this.pane) || !e.dataTransfer) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
return;
|
||||
@@ -276,10 +276,10 @@ class PanelDraggable extends Disposable {
|
||||
|
||||
if (isFirefox) {
|
||||
// Firefox: requires to set a text data transfer to get going
|
||||
e.dataTransfer?.setData(DataTransfers.TEXT, this.panel.draggableElement.textContent || '');
|
||||
e.dataTransfer?.setData(DataTransfers.TEXT, this.pane.draggableElement.textContent || '');
|
||||
}
|
||||
|
||||
const dragImage = append(document.body, $('.monaco-drag-image', {}, this.panel.draggableElement.textContent || ''));
|
||||
const dragImage = append(document.body, $('.monaco-drag-image', {}, this.pane.draggableElement.textContent || ''));
|
||||
e.dataTransfer.setDragImage(dragImage, -10, -10);
|
||||
setTimeout(() => document.body.removeChild(dragImage), 0);
|
||||
|
||||
@@ -291,7 +291,7 @@ class PanelDraggable extends Disposable {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.dnd.canDrop(this.context.draggable.panel, this.panel)) {
|
||||
if (!this.dnd.canDrop(this.context.draggable.pane, this.pane)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -304,7 +304,7 @@ class PanelDraggable extends Disposable {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.dnd.canDrop(this.context.draggable.panel, this.panel)) {
|
||||
if (!this.dnd.canDrop(this.context.draggable.pane, this.pane)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -335,8 +335,8 @@ class PanelDraggable extends Disposable {
|
||||
this.dragOverCounter = 0;
|
||||
this.render();
|
||||
|
||||
if (this.dnd.canDrop(this.context.draggable.panel, this.panel) && this.context.draggable !== this) {
|
||||
this._onDidDrop.fire({ from: this.context.draggable.panel, to: this.panel });
|
||||
if (this.dnd.canDrop(this.context.draggable.pane, this.pane) && this.context.draggable !== this) {
|
||||
this._onDidDrop.fire({ from: this.context.draggable.pane, to: this.pane });
|
||||
}
|
||||
|
||||
this.context.draggable = null;
|
||||
@@ -346,106 +346,106 @@ class PanelDraggable extends Disposable {
|
||||
let backgroundColor: string | null = null;
|
||||
|
||||
if (this.dragOverCounter > 0) {
|
||||
backgroundColor = (this.panel.dropBackground || PanelDraggable.DefaultDragOverBackgroundColor).toString();
|
||||
backgroundColor = (this.pane.dropBackground || PaneDraggable.DefaultDragOverBackgroundColor).toString();
|
||||
}
|
||||
|
||||
this.panel.dropTargetElement.style.backgroundColor = backgroundColor || '';
|
||||
this.pane.dropTargetElement.style.backgroundColor = backgroundColor || '';
|
||||
}
|
||||
}
|
||||
|
||||
export interface IPanelDndController {
|
||||
canDrag(panel: Panel): boolean;
|
||||
canDrop(panel: Panel, overPanel: Panel): boolean;
|
||||
export interface IPaneDndController {
|
||||
canDrag(pane: Pane): boolean;
|
||||
canDrop(pane: Pane, overPane: Pane): boolean;
|
||||
}
|
||||
|
||||
export class DefaultPanelDndController implements IPanelDndController {
|
||||
export class DefaultPaneDndController implements IPaneDndController {
|
||||
|
||||
canDrag(panel: Panel): boolean {
|
||||
canDrag(pane: Pane): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
canDrop(panel: Panel, overPanel: Panel): boolean {
|
||||
canDrop(pane: Pane, overPane: Pane): boolean {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export interface IPanelViewOptions {
|
||||
dnd?: IPanelDndController;
|
||||
export interface IPaneViewOptions {
|
||||
dnd?: IPaneDndController;
|
||||
}
|
||||
|
||||
interface IPanelItem {
|
||||
panel: Panel;
|
||||
interface IPaneItem {
|
||||
pane: Pane;
|
||||
disposable: IDisposable;
|
||||
}
|
||||
|
||||
export class PanelView extends Disposable {
|
||||
export class PaneView extends Disposable {
|
||||
|
||||
private dnd: IPanelDndController | undefined;
|
||||
private dnd: IPaneDndController | undefined;
|
||||
private dndContext: IDndContext = { draggable: null };
|
||||
private el: HTMLElement;
|
||||
private panelItems: IPanelItem[] = [];
|
||||
private paneItems: IPaneItem[] = [];
|
||||
private width: number = 0;
|
||||
private splitview: SplitView;
|
||||
private animationTimer: number | undefined = undefined;
|
||||
|
||||
private _onDidDrop = this._register(new Emitter<{ from: Panel, to: Panel }>());
|
||||
readonly onDidDrop: Event<{ from: Panel, to: Panel }> = this._onDidDrop.event;
|
||||
private _onDidDrop = this._register(new Emitter<{ from: Pane, to: Pane }>());
|
||||
readonly onDidDrop: Event<{ from: Pane, to: Pane }> = this._onDidDrop.event;
|
||||
|
||||
readonly onDidSashChange: Event<number>;
|
||||
|
||||
constructor(container: HTMLElement, options: IPanelViewOptions = {}) {
|
||||
constructor(container: HTMLElement, options: IPaneViewOptions = {}) {
|
||||
super();
|
||||
|
||||
this.dnd = options.dnd;
|
||||
this.el = append(container, $('.monaco-panel-view'));
|
||||
this.el = append(container, $('.monaco-pane-view'));
|
||||
this.splitview = this._register(new SplitView(this.el));
|
||||
this.onDidSashChange = this.splitview.onDidSashChange;
|
||||
}
|
||||
|
||||
addPanel(panel: Panel, size: number, index = this.splitview.length): void {
|
||||
addPane(pane: Pane, size: number, index = this.splitview.length): void {
|
||||
const disposables = new DisposableStore();
|
||||
panel.onDidChangeExpansionState(this.setupAnimation, this, disposables);
|
||||
pane.onDidChangeExpansionState(this.setupAnimation, this, disposables);
|
||||
|
||||
const panelItem = { panel, disposable: disposables };
|
||||
this.panelItems.splice(index, 0, panelItem);
|
||||
panel.width = this.width;
|
||||
this.splitview.addView(panel, size, index);
|
||||
const paneItem = { pane: pane, disposable: disposables };
|
||||
this.paneItems.splice(index, 0, paneItem);
|
||||
pane.width = this.width;
|
||||
this.splitview.addView(pane, size, index);
|
||||
|
||||
if (this.dnd) {
|
||||
const draggable = new PanelDraggable(panel, this.dnd, this.dndContext);
|
||||
const draggable = new PaneDraggable(pane, this.dnd, this.dndContext);
|
||||
disposables.add(draggable);
|
||||
disposables.add(draggable.onDidDrop(this._onDidDrop.fire, this._onDidDrop));
|
||||
}
|
||||
}
|
||||
|
||||
removePanel(panel: Panel): void {
|
||||
const index = firstIndex(this.panelItems, item => item.panel === panel);
|
||||
removePane(pane: Pane): void {
|
||||
const index = firstIndex(this.paneItems, item => item.pane === pane);
|
||||
|
||||
if (index === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.splitview.removeView(index);
|
||||
const panelItem = this.panelItems.splice(index, 1)[0];
|
||||
panelItem.disposable.dispose();
|
||||
const paneItem = this.paneItems.splice(index, 1)[0];
|
||||
paneItem.disposable.dispose();
|
||||
}
|
||||
|
||||
movePanel(from: Panel, to: Panel): void {
|
||||
const fromIndex = firstIndex(this.panelItems, item => item.panel === from);
|
||||
const toIndex = firstIndex(this.panelItems, item => item.panel === to);
|
||||
movePane(from: Pane, to: Pane): void {
|
||||
const fromIndex = firstIndex(this.paneItems, item => item.pane === from);
|
||||
const toIndex = firstIndex(this.paneItems, item => item.pane === to);
|
||||
|
||||
if (fromIndex === -1 || toIndex === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
const [panelItem] = this.panelItems.splice(fromIndex, 1);
|
||||
this.panelItems.splice(toIndex, 0, panelItem);
|
||||
const [paneItem] = this.paneItems.splice(fromIndex, 1);
|
||||
this.paneItems.splice(toIndex, 0, paneItem);
|
||||
|
||||
this.splitview.moveView(fromIndex, toIndex);
|
||||
}
|
||||
|
||||
resizePanel(panel: Panel, size: number): void {
|
||||
const index = firstIndex(this.panelItems, item => item.panel === panel);
|
||||
resizePane(pane: Pane, size: number): void {
|
||||
const index = firstIndex(this.paneItems, item => item.pane === pane);
|
||||
|
||||
if (index === -1) {
|
||||
return;
|
||||
@@ -454,8 +454,8 @@ export class PanelView extends Disposable {
|
||||
this.splitview.resizeView(index, size);
|
||||
}
|
||||
|
||||
getPanelSize(panel: Panel): number {
|
||||
const index = firstIndex(this.panelItems, item => item.panel === panel);
|
||||
getPaneSize(pane: Pane): number {
|
||||
const index = firstIndex(this.paneItems, item => item.pane === pane);
|
||||
|
||||
if (index === -1) {
|
||||
return -1;
|
||||
@@ -467,8 +467,8 @@ export class PanelView extends Disposable {
|
||||
layout(height: number, width: number): void {
|
||||
this.width = width;
|
||||
|
||||
for (const panelItem of this.panelItems) {
|
||||
panelItem.panel.width = width;
|
||||
for (const paneItem of this.paneItems) {
|
||||
paneItem.pane.width = width;
|
||||
}
|
||||
|
||||
this.splitview.layout(height);
|
||||
@@ -490,6 +490,6 @@ export class PanelView extends Disposable {
|
||||
dispose(): void {
|
||||
super.dispose();
|
||||
|
||||
this.panelItems.forEach(i => i.disposable.dispose());
|
||||
this.paneItems.forEach(i => i.disposable.dispose());
|
||||
}
|
||||
}
|
||||
@@ -336,7 +336,7 @@ class TreeRenderer<T, TFilterData, TRef, TTemplateData> implements IListRenderer
|
||||
}
|
||||
|
||||
const indent = TreeRenderer.DefaultIndent + (node.depth - 1) * this.indent;
|
||||
templateData.twistie.style.marginLeft = `${indent}px`;
|
||||
templateData.twistie.style.paddingLeft = `${indent}px`;
|
||||
templateData.indent.style.width = `${indent + this.indent - 16}px`;
|
||||
|
||||
this.renderTwistie(node, templateData);
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
.monaco-panel-view .panel > .panel-header h3.title {
|
||||
.monaco-pane-view .pane > .pane-header h3.title {
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
@@ -41,7 +41,7 @@
|
||||
.monaco-tl-twistie {
|
||||
font-size: 10px;
|
||||
text-align: right;
|
||||
margin-right: 6px;
|
||||
padding-right: 6px;
|
||||
flex-shrink: 0;
|
||||
width: 16px;
|
||||
display: flex !important;
|
||||
|
||||
+23
-10
@@ -7,6 +7,7 @@ import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { once as onceFn } from 'vs/base/common/functional';
|
||||
import { Disposable, IDisposable, toDisposable, combinedDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { LinkedList } from 'vs/base/common/linkedList';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
|
||||
/**
|
||||
* To an event a function with one or zero parameters
|
||||
@@ -653,27 +654,39 @@ export interface IWaitUntil {
|
||||
|
||||
export class AsyncEmitter<T extends IWaitUntil> extends Emitter<T> {
|
||||
|
||||
private _asyncDeliveryQueue?: [Listener<T>, T, Promise<any>[]][];
|
||||
private _asyncDeliveryQueue?: LinkedList<[Listener<T>, Omit<T, 'waitUntil'>]>;
|
||||
|
||||
async fireAsync(eventFn: (thenables: Promise<any>[], listener: Function) => T): Promise<void> {
|
||||
async fireAsync(data: Omit<T, 'waitUntil'>, token: CancellationToken, promiseJoin?: (p: Promise<any>, listener: Function) => Promise<any>): Promise<void> {
|
||||
if (!this._listeners) {
|
||||
return;
|
||||
}
|
||||
|
||||
// put all [listener,event]-pairs into delivery queue
|
||||
// then emit all event. an inner/nested event might be
|
||||
// the driver of this
|
||||
if (!this._asyncDeliveryQueue) {
|
||||
this._asyncDeliveryQueue = [];
|
||||
this._asyncDeliveryQueue = new LinkedList();
|
||||
}
|
||||
|
||||
for (let iter = this._listeners.iterator(), e = iter.next(); !e.done; e = iter.next()) {
|
||||
const thenables: Promise<void>[] = [];
|
||||
this._asyncDeliveryQueue.push([e.value, eventFn(thenables, typeof e.value === 'function' ? e.value : e.value[0]), thenables]);
|
||||
this._asyncDeliveryQueue.push([e.value, data]);
|
||||
}
|
||||
|
||||
while (this._asyncDeliveryQueue.length > 0) {
|
||||
const [listener, event, thenables] = this._asyncDeliveryQueue.shift()!;
|
||||
while (this._asyncDeliveryQueue.size > 0 && !token.isCancellationRequested) {
|
||||
|
||||
const [listener, data] = this._asyncDeliveryQueue.shift()!;
|
||||
const thenables: Promise<any>[] = [];
|
||||
|
||||
const event = <T>{
|
||||
...data,
|
||||
waitUntil: (p: Promise<any>): void => {
|
||||
if (Object.isFrozen(thenables)) {
|
||||
throw new Error('waitUntil can NOT be called asynchronous');
|
||||
}
|
||||
if (promiseJoin) {
|
||||
p = promiseJoin(p, typeof listener === 'function' ? listener : listener[0]);
|
||||
}
|
||||
thenables.push(p);
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
if (typeof listener === 'function') {
|
||||
listener.call(undefined, event);
|
||||
|
||||
@@ -167,7 +167,7 @@ function toNodeEncoding(enc: string | null): string {
|
||||
return enc;
|
||||
}
|
||||
|
||||
export function detectEncodingByBOMFromBuffer(buffer: Buffer | VSBuffer | null, bytesRead: number): string | null {
|
||||
export function detectEncodingByBOMFromBuffer(buffer: Buffer | VSBuffer | null, bytesRead: number): typeof UTF8_with_bom | typeof UTF16le | typeof UTF16be | null {
|
||||
if (!buffer || bytesRead < UTF16be_BOM.length) {
|
||||
return null;
|
||||
}
|
||||
@@ -193,7 +193,7 @@ export function detectEncodingByBOMFromBuffer(buffer: Buffer | VSBuffer | null,
|
||||
|
||||
// UTF-8
|
||||
if (b0 === UTF8_BOM[0] && b1 === UTF8_BOM[1] && b2 === UTF8_BOM[2]) {
|
||||
return UTF8;
|
||||
return UTF8_with_bom;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -10,7 +10,7 @@ import { normalizeNFC } from 'vs/base/common/normalization';
|
||||
import { toDisposable, IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { exists, readdir } from 'vs/base/node/pfs';
|
||||
|
||||
export function watchFile(path: string, onChange: (type: 'changed' | 'deleted', path: string) => void, onError: (error: string) => void): IDisposable {
|
||||
export function watchFile(path: string, onChange: (type: 'added' | 'changed' | 'deleted', path: string) => void, onError: (error: string) => void): IDisposable {
|
||||
return doWatchNonRecursive({ path, isDirectory: false }, onChange, onError);
|
||||
}
|
||||
|
||||
@@ -189,4 +189,4 @@ function doWatchNonRecursive(file: { path: string, isDirectory: boolean }, onCha
|
||||
|
||||
watcherDisposables = dispose(watcherDisposables);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,10 +3,11 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import * as assert from 'assert';
|
||||
import { Event, Emitter, EventBufferer, EventMultiplexer, AsyncEmitter, IWaitUntil, PauseableEmitter } from 'vs/base/common/event';
|
||||
import { Event, Emitter, EventBufferer, EventMultiplexer, IWaitUntil, PauseableEmitter, AsyncEmitter } from 'vs/base/common/event';
|
||||
import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import * as Errors from 'vs/base/common/errors';
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
|
||||
namespace Samples {
|
||||
|
||||
@@ -174,7 +175,7 @@ suite('Event', function () {
|
||||
test('Debounce Event', function (done: () => void) {
|
||||
let doc = new Samples.Document3();
|
||||
|
||||
let onDocDidChange = Event.debounce(doc.onDidChange, (prev: string[], cur) => {
|
||||
let onDocDidChange = Event.debounce(doc.onDidChange, (prev: string[] | undefined, cur) => {
|
||||
if (!prev) {
|
||||
prev = [cur];
|
||||
} else if (prev.indexOf(cur) < 0) {
|
||||
@@ -272,11 +273,7 @@ suite('AsyncEmitter', function () {
|
||||
assert.equal(typeof e.waitUntil, 'function');
|
||||
});
|
||||
|
||||
emitter.fireAsync(thenables => ({
|
||||
foo: true,
|
||||
bar: 1,
|
||||
waitUntil(t: Promise<void>) { thenables.push(t); }
|
||||
}));
|
||||
emitter.fireAsync({ foo: true, bar: 1, }, CancellationToken.None);
|
||||
emitter.dispose();
|
||||
});
|
||||
|
||||
@@ -303,12 +300,7 @@ suite('AsyncEmitter', function () {
|
||||
}));
|
||||
});
|
||||
|
||||
await emitter.fireAsync(thenables => ({
|
||||
foo: true,
|
||||
waitUntil(t) {
|
||||
thenables.push(t);
|
||||
}
|
||||
}));
|
||||
await emitter.fireAsync({ foo: true }, CancellationToken.None);
|
||||
assert.equal(globalState, 2);
|
||||
});
|
||||
|
||||
@@ -324,12 +316,7 @@ suite('AsyncEmitter', function () {
|
||||
emitter.event(e => {
|
||||
e.waitUntil(timeout(10).then(async _ => {
|
||||
if (e.foo === 1) {
|
||||
await emitter.fireAsync(thenables => ({
|
||||
foo: 2,
|
||||
waitUntil(t) {
|
||||
thenables.push(t);
|
||||
}
|
||||
}));
|
||||
await emitter.fireAsync({ foo: 2 }, CancellationToken.None);
|
||||
assert.deepEqual(events, [1, 2]);
|
||||
done = true;
|
||||
}
|
||||
@@ -342,12 +329,7 @@ suite('AsyncEmitter', function () {
|
||||
e.waitUntil(timeout(7));
|
||||
});
|
||||
|
||||
await emitter.fireAsync(thenables => ({
|
||||
foo: 1,
|
||||
waitUntil(t) {
|
||||
thenables.push(t);
|
||||
}
|
||||
}));
|
||||
await emitter.fireAsync({ foo: 1 }, CancellationToken.None);
|
||||
assert.ok(done);
|
||||
});
|
||||
|
||||
@@ -372,12 +354,7 @@ suite('AsyncEmitter', function () {
|
||||
e.waitUntil(timeout(10));
|
||||
});
|
||||
|
||||
await emitter.fireAsync(thenables => ({
|
||||
foo: true,
|
||||
waitUntil(t) {
|
||||
thenables.push(t);
|
||||
}
|
||||
})).then(() => {
|
||||
await emitter.fireAsync({ foo: true }, CancellationToken.None).then(() => {
|
||||
assert.equal(globalState, 2);
|
||||
}).catch(e => {
|
||||
console.log(e);
|
||||
|
||||
@@ -9,7 +9,7 @@ import * as encoding from 'vs/base/node/encoding';
|
||||
import { Readable } from 'stream';
|
||||
import { getPathFromAmdModule } from 'vs/base/common/amd';
|
||||
|
||||
export async function detectEncodingByBOM(file: string): Promise<string | null> {
|
||||
export async function detectEncodingByBOM(file: string): Promise<typeof encoding.UTF16be | typeof encoding.UTF16le | typeof encoding.UTF8_with_bom | null> {
|
||||
try {
|
||||
const { buffer, bytesRead } = await readExactlyByFile(file, 3);
|
||||
|
||||
@@ -86,7 +86,7 @@ suite('Encoding', () => {
|
||||
const file = getPathFromAmdModule(require, './fixtures/some_utf8.css');
|
||||
|
||||
const detectedEncoding = await detectEncodingByBOM(file);
|
||||
assert.equal(detectedEncoding, 'utf8');
|
||||
assert.equal(detectedEncoding, 'utf8bom');
|
||||
});
|
||||
|
||||
test('detectBOM UTF-16 LE', async () => {
|
||||
|
||||
@@ -345,8 +345,8 @@ export class IssueReporter extends Disposable {
|
||||
|
||||
const showInfoElements = document.getElementsByClassName('showInfo');
|
||||
for (let i = 0; i < showInfoElements.length; i++) {
|
||||
const showInfo = showInfoElements.item(i);
|
||||
showInfo!.addEventListener('click', (e: MouseEvent) => {
|
||||
const showInfo = showInfoElements.item(i)!;
|
||||
(showInfo as HTMLAnchorElement).addEventListener('click', (e: MouseEvent) => {
|
||||
e.preventDefault();
|
||||
const label = (<HTMLDivElement>e.target);
|
||||
if (label) {
|
||||
@@ -432,9 +432,9 @@ export class IssueReporter extends Disposable {
|
||||
sendWorkbenchCommand('workbench.action.reloadWindowWithExtensionsDisabled');
|
||||
});
|
||||
|
||||
this.addEventListener('disableExtensions', 'keydown', (e: KeyboardEvent) => {
|
||||
this.addEventListener('disableExtensions', 'keydown', (e: Event) => {
|
||||
e.stopPropagation();
|
||||
if (e.keyCode === 13 || e.keyCode === 32) {
|
||||
if ((e as KeyboardEvent).keyCode === 13 || (e as KeyboardEvent).keyCode === 32) {
|
||||
sendWorkbenchCommand('workbench.extensions.action.disableAll');
|
||||
sendWorkbenchCommand('workbench.action.reloadWindow');
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ class DomCharWidthReader {
|
||||
|
||||
private static _render(testElement: HTMLElement, request: CharWidthRequest): void {
|
||||
if (request.chr === ' ') {
|
||||
let htmlString = ' ';
|
||||
let htmlString = ' ';
|
||||
// Repeat character 256 (2^8) times
|
||||
for (let i = 0; i < 8; i++) {
|
||||
htmlString += htmlString;
|
||||
|
||||
@@ -1753,7 +1753,7 @@ registerCommand(new EditorOrNativeTextInputCommand({
|
||||
kbExpr: null,
|
||||
primary: KeyMod.CtrlCmd | KeyCode.KEY_A
|
||||
},
|
||||
menubarOpts: {
|
||||
menuOpts: {
|
||||
menuId: MenuId.MenubarSelectionMenu,
|
||||
group: '1_basic',
|
||||
title: nls.localize({ key: 'miSelectAll', comment: ['&& denotes a mnemonic'] }, "&&Select All"),
|
||||
@@ -1771,7 +1771,7 @@ registerCommand(new EditorOrNativeTextInputCommand({
|
||||
kbExpr: EditorContextKeys.textInputFocus,
|
||||
primary: KeyMod.CtrlCmd | KeyCode.KEY_Z
|
||||
},
|
||||
menubarOpts: {
|
||||
menuOpts: {
|
||||
menuId: MenuId.MenubarEditMenu,
|
||||
group: '1_do',
|
||||
title: nls.localize({ key: 'miUndo', comment: ['&& denotes a mnemonic'] }, "&&Undo"),
|
||||
@@ -1792,7 +1792,7 @@ registerCommand(new EditorOrNativeTextInputCommand({
|
||||
secondary: [KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_Z],
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_Z }
|
||||
},
|
||||
menubarOpts: {
|
||||
menuOpts: {
|
||||
menuId: MenuId.MenubarEditMenu,
|
||||
group: '1_do',
|
||||
title: nls.localize({ key: 'miRedo', comment: ['&& denotes a mnemonic'] }, "&&Redo"),
|
||||
|
||||
@@ -202,7 +202,7 @@ export class PointerEventHandler extends MouseHandler {
|
||||
|
||||
this._lastPointerType = 'mouse';
|
||||
|
||||
this.viewHelper.linesContentDomNode.addEventListener('pointerdown', (e: any) => {
|
||||
this._register(dom.addDisposableListener(this.viewHelper.linesContentDomNode, 'pointerdown', (e: any) => {
|
||||
const pointerType = <any>e.pointerType;
|
||||
if (pointerType === 'mouse') {
|
||||
this._lastPointerType = 'mouse';
|
||||
@@ -212,7 +212,7 @@ export class PointerEventHandler extends MouseHandler {
|
||||
} else {
|
||||
this._lastPointerType = 'pen';
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
// PonterEvents
|
||||
const pointerEvents = new EditorPointerEventFactory(this.viewHelper.viewDomNode);
|
||||
@@ -226,12 +226,30 @@ export class PointerEventHandler extends MouseHandler {
|
||||
}
|
||||
|
||||
private onTap(event: GestureEvent): void {
|
||||
if (!event.initialTarget || !this.viewHelper.linesContentDomNode.contains(<any>event.initialTarget)) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
this.viewHelper.focusTextArea();
|
||||
const target = this._createMouseTarget(new EditorMouseEvent(event, this.viewHelper.viewDomNode), false);
|
||||
|
||||
if (target.position) {
|
||||
this.viewController.moveTo(target.position);
|
||||
// this.viewController.moveTo(target.position);
|
||||
this.viewController.dispatchMouse({
|
||||
position: target.position,
|
||||
mouseColumn: target.position.column,
|
||||
startedOnLineNumbers: false,
|
||||
mouseDownCount: event.tapCount,
|
||||
inSelectionMode: false,
|
||||
altKey: false,
|
||||
ctrlKey: false,
|
||||
metaKey: false,
|
||||
shiftKey: false,
|
||||
|
||||
leftButton: false,
|
||||
middleButton: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,9 +260,11 @@ export class PointerEventHandler extends MouseHandler {
|
||||
}
|
||||
|
||||
public _onMouseDown(e: EditorMouseEvent): void {
|
||||
if (this._lastPointerType !== 'touch') {
|
||||
super._onMouseDown(e);
|
||||
if (e.target && this.viewHelper.linesContentDomNode.contains(e.target) && this._lastPointerType === 'touch') {
|
||||
return;
|
||||
}
|
||||
|
||||
super._onMouseDown(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { IMouseEvent, IMouseWheelEvent } from 'vs/base/browser/mouseEvent';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { OverviewRulerPosition, ConfigurationChangedEvent, EditorLayoutInfo, IComputedEditorOptions, EditorOption, FindComputedEditorOptionValueById, IEditorOptions } from 'vs/editor/common/config/editorOptions';
|
||||
import { OverviewRulerPosition, ConfigurationChangedEvent, EditorLayoutInfo, IComputedEditorOptions, EditorOption, FindComputedEditorOptionValueById, IEditorOptions, IDiffEditorOptions } from 'vs/editor/common/config/editorOptions';
|
||||
import { ICursors } from 'vs/editor/common/controller/cursorCommon';
|
||||
import { ICursorPositionChangedEvent, ICursorSelectionChangedEvent } from 'vs/editor/common/controller/cursorEvents';
|
||||
import { IPosition, Position } from 'vs/editor/common/core/position';
|
||||
@@ -938,6 +938,11 @@ export interface IDiffEditor extends editorCommon.IEditor {
|
||||
* If the diff computation is not finished or the model is missing, will return null.
|
||||
*/
|
||||
getDiffLineInformationForModified(lineNumber: number): IDiffLineInformation | null;
|
||||
|
||||
/**
|
||||
* Update the editor's options after the editor has been created.
|
||||
*/
|
||||
updateOptions(newOptions: IDiffEditorOptions): void;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -42,7 +42,7 @@ export interface ICommandKeybindingsOptions extends IKeybindings {
|
||||
kbExpr?: ContextKeyExpr | null;
|
||||
weight: number;
|
||||
}
|
||||
export interface ICommandMenubarOptions {
|
||||
export interface ICommandMenuOptions {
|
||||
menuId: MenuId;
|
||||
group: string;
|
||||
order: number;
|
||||
@@ -54,36 +54,29 @@ export interface ICommandOptions {
|
||||
precondition: ContextKeyExpr | undefined;
|
||||
kbOpts?: ICommandKeybindingsOptions;
|
||||
description?: ICommandHandlerDescription;
|
||||
menubarOpts?: ICommandMenubarOptions;
|
||||
menuOpts?: ICommandMenuOptions | ICommandMenuOptions[];
|
||||
}
|
||||
export abstract class Command {
|
||||
public readonly id: string;
|
||||
public readonly precondition: ContextKeyExpr | undefined;
|
||||
private readonly _kbOpts: ICommandKeybindingsOptions | undefined;
|
||||
private readonly _menubarOpts: ICommandMenubarOptions | undefined;
|
||||
private readonly _menuOpts: ICommandMenuOptions | ICommandMenuOptions[] | undefined;
|
||||
private readonly _description: ICommandHandlerDescription | undefined;
|
||||
|
||||
constructor(opts: ICommandOptions) {
|
||||
this.id = opts.id;
|
||||
this.precondition = opts.precondition;
|
||||
this._kbOpts = opts.kbOpts;
|
||||
this._menubarOpts = opts.menubarOpts;
|
||||
this._menuOpts = opts.menuOpts;
|
||||
this._description = opts.description;
|
||||
}
|
||||
|
||||
public register(): void {
|
||||
|
||||
if (this._menubarOpts) {
|
||||
MenuRegistry.appendMenuItem(this._menubarOpts.menuId, {
|
||||
group: this._menubarOpts.group,
|
||||
command: {
|
||||
id: this.id,
|
||||
title: this._menubarOpts.title,
|
||||
// precondition: this.precondition
|
||||
},
|
||||
when: this._menubarOpts.when,
|
||||
order: this._menubarOpts.order
|
||||
});
|
||||
if (Array.isArray(this._menuOpts)) {
|
||||
this._menuOpts.forEach(this._registerMenuItem, this);
|
||||
} else if (this._menuOpts) {
|
||||
this._registerMenuItem(this._menuOpts);
|
||||
}
|
||||
|
||||
if (this._kbOpts) {
|
||||
@@ -119,6 +112,19 @@ export abstract class Command {
|
||||
}
|
||||
}
|
||||
|
||||
private _registerMenuItem(item: ICommandMenuOptions): void {
|
||||
MenuRegistry.appendMenuItem(item.menuId, {
|
||||
group: item.group,
|
||||
command: {
|
||||
id: this.id,
|
||||
title: item.title,
|
||||
// precondition: this.precondition
|
||||
},
|
||||
when: item.when,
|
||||
order: item.order
|
||||
});
|
||||
}
|
||||
|
||||
public abstract runCommand(accessor: ServicesAccessor, args: any): void | Promise<void>;
|
||||
}
|
||||
|
||||
@@ -184,44 +190,59 @@ export abstract class EditorCommand extends Command {
|
||||
|
||||
//#region EditorAction
|
||||
|
||||
export interface IEditorCommandMenuOptions {
|
||||
export interface IEditorActionContextMenuOptions {
|
||||
group: string;
|
||||
order: number;
|
||||
when?: ContextKeyExpr;
|
||||
menuId?: MenuId;
|
||||
}
|
||||
export interface IActionOptions extends ICommandOptions {
|
||||
label: string;
|
||||
alias: string;
|
||||
menuOpts?: IEditorCommandMenuOptions;
|
||||
contextMenuOpts?: IEditorActionContextMenuOptions | IEditorActionContextMenuOptions[];
|
||||
}
|
||||
|
||||
export abstract class EditorAction extends EditorCommand {
|
||||
|
||||
private static convertOptions(opts: IActionOptions): ICommandOptions {
|
||||
|
||||
let menuOpts: ICommandMenuOptions[];
|
||||
if (Array.isArray(opts.menuOpts)) {
|
||||
menuOpts = opts.menuOpts;
|
||||
} else if (opts.menuOpts) {
|
||||
menuOpts = [opts.menuOpts];
|
||||
} else {
|
||||
menuOpts = [];
|
||||
}
|
||||
|
||||
function withDefaults(item: Partial<ICommandMenuOptions>): ICommandMenuOptions {
|
||||
if (!item.menuId) {
|
||||
item.menuId = MenuId.EditorContext;
|
||||
}
|
||||
if (!item.title) {
|
||||
item.title = opts.label;
|
||||
}
|
||||
item.when = ContextKeyExpr.and(opts.precondition, item.when);
|
||||
return <ICommandMenuOptions>item;
|
||||
}
|
||||
|
||||
if (Array.isArray(opts.contextMenuOpts)) {
|
||||
menuOpts.push(...opts.contextMenuOpts.map(withDefaults));
|
||||
} else if (opts.contextMenuOpts) {
|
||||
menuOpts.push(withDefaults(opts.contextMenuOpts));
|
||||
}
|
||||
|
||||
opts.menuOpts = menuOpts;
|
||||
return <ICommandOptions>opts;
|
||||
}
|
||||
|
||||
public readonly label: string;
|
||||
public readonly alias: string;
|
||||
private readonly menuOpts: IEditorCommandMenuOptions | undefined;
|
||||
|
||||
constructor(opts: IActionOptions) {
|
||||
super(opts);
|
||||
super(EditorAction.convertOptions(opts));
|
||||
this.label = opts.label;
|
||||
this.alias = opts.alias;
|
||||
this.menuOpts = opts.menuOpts;
|
||||
}
|
||||
|
||||
public register(): void {
|
||||
|
||||
if (this.menuOpts) {
|
||||
MenuRegistry.appendMenuItem(MenuId.EditorContext, {
|
||||
command: {
|
||||
id: this.id,
|
||||
title: this.label
|
||||
},
|
||||
when: ContextKeyExpr.and(this.precondition, this.menuOpts.when),
|
||||
group: this.menuOpts.group,
|
||||
order: this.menuOpts.order
|
||||
});
|
||||
}
|
||||
|
||||
super.register();
|
||||
}
|
||||
|
||||
public runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void | Promise<void> {
|
||||
|
||||
@@ -1109,7 +1109,7 @@ export class Minimap extends ViewPart {
|
||||
if (renderMinimap === RenderMinimap.Blocks) {
|
||||
minimapCharRenderer.blockRenderChar(target, dx, dy, tokenColor, backgroundColor, useLighterFont);
|
||||
} else { // RenderMinimap.Text
|
||||
minimapCharRenderer.renderChar(target, dx, dy, charCode, tokenColor, backgroundColor, useLighterFont);
|
||||
minimapCharRenderer.renderChar(target, dx, dy, charCode, tokenColor, backgroundColor, fontScale, useLighterFont);
|
||||
}
|
||||
|
||||
dx += charWidth;
|
||||
|
||||
@@ -32,6 +32,7 @@ export class MinimapCharRenderer {
|
||||
chCode: number,
|
||||
color: RGBA8,
|
||||
backgroundColor: RGBA8,
|
||||
fontScale: number,
|
||||
useLighterFont: boolean
|
||||
): void {
|
||||
const charWidth = Constants.BASE_CHAR_WIDTH * this.scale;
|
||||
@@ -42,7 +43,7 @@ export class MinimapCharRenderer {
|
||||
}
|
||||
|
||||
const charData = useLighterFont ? this.charDataLight : this.charDataNormal;
|
||||
const charIndex = getCharIndex(chCode);
|
||||
const charIndex = getCharIndex(chCode, fontScale);
|
||||
|
||||
const destWidth = target.width * Constants.RGBA_CHANNELS_CNT;
|
||||
|
||||
|
||||
@@ -29,9 +29,13 @@ export const allCharCodes: ReadonlyArray<number> = (() => {
|
||||
return v;
|
||||
})();
|
||||
|
||||
export const getCharIndex = (chCode: number) => {
|
||||
export const getCharIndex = (chCode: number, fontScale: number) => {
|
||||
chCode -= Constants.START_CH_CODE;
|
||||
if (chCode < 0 || chCode > Constants.CHAR_COUNT) {
|
||||
if (fontScale <= 2) {
|
||||
// for smaller scales, we can get away with using any ASCII character...
|
||||
return (chCode + Constants.CHAR_COUNT) % Constants.CHAR_COUNT;
|
||||
}
|
||||
return Constants.CHAR_COUNT - 1; // unknown symbol
|
||||
}
|
||||
|
||||
|
||||
@@ -695,7 +695,7 @@ export class DiffReview extends Disposable {
|
||||
if (originalLine !== 0) {
|
||||
originalLineNumber.appendChild(document.createTextNode(String(originalLine)));
|
||||
} else {
|
||||
originalLineNumber.innerHTML = ' ';
|
||||
originalLineNumber.innerHTML = ' ';
|
||||
}
|
||||
cell.appendChild(originalLineNumber);
|
||||
|
||||
@@ -707,13 +707,13 @@ export class DiffReview extends Disposable {
|
||||
if (modifiedLine !== 0) {
|
||||
modifiedLineNumber.appendChild(document.createTextNode(String(modifiedLine)));
|
||||
} else {
|
||||
modifiedLineNumber.innerHTML = ' ';
|
||||
modifiedLineNumber.innerHTML = ' ';
|
||||
}
|
||||
cell.appendChild(modifiedLineNumber);
|
||||
|
||||
const spacer = document.createElement('span');
|
||||
spacer.className = spacerClassName;
|
||||
spacer.innerHTML = ' ';
|
||||
spacer.innerHTML = '  ';
|
||||
cell.appendChild(spacer);
|
||||
|
||||
let lineContent: string;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user