mirror of
https://github.com/Microsoft/vscode
synced 2024-08-27 21:09:43 +00:00
Merge branch 'main' into joh/voluminous-lobster
This commit is contained in:
commit
3622010b64
1
.github/workflows/pr-chat.yml
vendored
1
.github/workflows/pr-chat.yml
vendored
|
@ -21,5 +21,6 @@ jobs:
|
||||||
with:
|
with:
|
||||||
token: ${{secrets.VSCODE_ISSUE_TRIAGE_BOT_PAT}}
|
token: ${{secrets.VSCODE_ISSUE_TRIAGE_BOT_PAT}}
|
||||||
slack_token: ${{ secrets.SLACK_TOKEN }}
|
slack_token: ${{ secrets.SLACK_TOKEN }}
|
||||||
|
slack_user_token: ${{ secrets.SLACK_USER_TOKEN }}
|
||||||
slack_bot_name: "VSCodeBot"
|
slack_bot_name: "VSCodeBot"
|
||||||
notification_channel: codereview
|
notification_channel: codereview
|
||||||
|
|
7
.vscode/launch.json
vendored
7
.vscode/launch.json
vendored
|
@ -16,11 +16,7 @@
|
||||||
"request": "attach",
|
"request": "attach",
|
||||||
"restart": true,
|
"restart": true,
|
||||||
"name": "Attach to Extension Host",
|
"name": "Attach to Extension Host",
|
||||||
// set to a large number: if there is an issue we're debugging that keeps
|
"timeout": 0,
|
||||||
// the extension host from coming up, or the renderer is paused/crashes
|
|
||||||
// before it happens, developers will get an annoying alert, e.g. #126826.
|
|
||||||
// This can be set to 0 in 1.59.
|
|
||||||
"timeout": 999999999,
|
|
||||||
"port": 5870,
|
"port": 5870,
|
||||||
"outFiles": [
|
"outFiles": [
|
||||||
"${workspaceFolder}/out/**/*.js",
|
"${workspaceFolder}/out/**/*.js",
|
||||||
|
@ -244,6 +240,7 @@
|
||||||
"runtimeArgs": [
|
"runtimeArgs": [
|
||||||
"--inspect=5875",
|
"--inspect=5875",
|
||||||
"--no-cached-data",
|
"--no-cached-data",
|
||||||
|
"--crash-reporter-directory=${workspaceFolder}/.profile-oss/crashes",
|
||||||
// for general runtime freezes: https://github.com/microsoft/vscode/issues/127861#issuecomment-904144910
|
// for general runtime freezes: https://github.com/microsoft/vscode/issues/127861#issuecomment-904144910
|
||||||
"--disable-features=CalculateNativeWinOcclusion",
|
"--disable-features=CalculateNativeWinOcclusion",
|
||||||
],
|
],
|
||||||
|
|
2
.vscode/notebooks/api.github-issues
vendored
2
.vscode/notebooks/api.github-issues
vendored
|
@ -7,7 +7,7 @@
|
||||||
{
|
{
|
||||||
"kind": 2,
|
"kind": 2,
|
||||||
"language": "github-issues",
|
"language": "github-issues",
|
||||||
"value": "$repo=repo:microsoft/vscode\n$milestone=milestone:\"May 2022\""
|
"value": "$repo=repo:microsoft/vscode\n$milestone=milestone:\"June 2022\""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"kind": 1,
|
"kind": 1,
|
||||||
|
|
2
.vscode/notebooks/my-work.github-issues
vendored
2
.vscode/notebooks/my-work.github-issues
vendored
|
@ -7,7 +7,7 @@
|
||||||
{
|
{
|
||||||
"kind": 2,
|
"kind": 2,
|
||||||
"language": "github-issues",
|
"language": "github-issues",
|
||||||
"value": "// list of repos we work in\n$repos=repo:microsoft/vscode repo:microsoft/vscode-remote-release repo:microsoft/vscode-js-debug repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-dev repo:microsoft/vscode-unpkg repo:microsoft/vscode-references-view repo:microsoft/vscode-anycode repo:microsoft/vscode-hexeditor repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-livepreview repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-remote-repositories-github repo:microsoft/monaco-editor repo:microsoft/vscode-vsce\n\n// current milestone name\n$milestone=milestone:\"May 2022\""
|
"value": "// list of repos we work in\n$repos=repo:microsoft/vscode repo:microsoft/vscode-remote-release repo:microsoft/vscode-js-debug repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-dev repo:microsoft/vscode-unpkg repo:microsoft/vscode-references-view repo:microsoft/vscode-anycode repo:microsoft/vscode-hexeditor repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-livepreview repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-remote-repositories-github repo:microsoft/monaco-editor repo:microsoft/vscode-vsce\n\n// current milestone name\n$milestone=milestone:\"June 2022\""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"kind": 1,
|
"kind": 1,
|
||||||
|
|
|
@ -500,7 +500,7 @@ export async function webpackExtensions(taskName: string, isWatch: boolean, webp
|
||||||
function addConfig(configOrFn: webpack.Configuration | Function) {
|
function addConfig(configOrFn: webpack.Configuration | Function) {
|
||||||
let config;
|
let config;
|
||||||
if (typeof configOrFn === 'function') {
|
if (typeof configOrFn === 'function') {
|
||||||
config = configOrFn({}, {});
|
config = (configOrFn as Function)({}, {});
|
||||||
webpackConfigs.push(config);
|
webpackConfigs.push(config);
|
||||||
} else {
|
} else {
|
||||||
config = configOrFn;
|
config = configOrFn;
|
||||||
|
|
|
@ -13,6 +13,7 @@ module.exports = withDefaults({
|
||||||
context: __dirname,
|
context: __dirname,
|
||||||
entry: {
|
entry: {
|
||||||
main: './src/main.ts',
|
main: './src/main.ts',
|
||||||
['askpass-main']: './src/askpass-main.ts'
|
['askpass-main']: './src/askpass-main.ts',
|
||||||
|
['git-editor-main']: './src/git-editor-main.ts'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
"contribMergeEditorToolbar",
|
"contribMergeEditorToolbar",
|
||||||
"contribViewsWelcome",
|
"contribViewsWelcome",
|
||||||
"scmActionButton",
|
"scmActionButton",
|
||||||
|
"scmInput",
|
||||||
"scmSelectedProvider",
|
"scmSelectedProvider",
|
||||||
"scmValidation",
|
"scmValidation",
|
||||||
"timeline"
|
"timeline"
|
||||||
|
@ -213,83 +214,99 @@
|
||||||
"command": "git.commit",
|
"command": "git.commit",
|
||||||
"title": "%command.commit%",
|
"title": "%command.commit%",
|
||||||
"category": "Git",
|
"category": "Git",
|
||||||
"icon": "$(check)"
|
"icon": "$(check)",
|
||||||
|
"enablement": "!commitInProgress"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.commitStaged",
|
"command": "git.commitStaged",
|
||||||
"title": "%command.commitStaged%",
|
"title": "%command.commitStaged%",
|
||||||
"category": "Git"
|
"category": "Git",
|
||||||
|
"enablement": "!commitInProgress"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.commitEmpty",
|
"command": "git.commitEmpty",
|
||||||
"title": "%command.commitEmpty%",
|
"title": "%command.commitEmpty%",
|
||||||
"category": "Git"
|
"category": "Git",
|
||||||
|
"enablement": "!commitInProgress"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.commitStagedSigned",
|
"command": "git.commitStagedSigned",
|
||||||
"title": "%command.commitStagedSigned%",
|
"title": "%command.commitStagedSigned%",
|
||||||
"category": "Git"
|
"category": "Git",
|
||||||
|
"enablement": "!commitInProgress"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.commitStagedAmend",
|
"command": "git.commitStagedAmend",
|
||||||
"title": "%command.commitStagedAmend%",
|
"title": "%command.commitStagedAmend%",
|
||||||
"category": "Git"
|
"category": "Git",
|
||||||
|
"enablement": "!commitInProgress"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.commitAll",
|
"command": "git.commitAll",
|
||||||
"title": "%command.commitAll%",
|
"title": "%command.commitAll%",
|
||||||
"category": "Git"
|
"category": "Git",
|
||||||
|
"enablement": "!commitInProgress"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.commitAllSigned",
|
"command": "git.commitAllSigned",
|
||||||
"title": "%command.commitAllSigned%",
|
"title": "%command.commitAllSigned%",
|
||||||
"category": "Git"
|
"category": "Git",
|
||||||
|
"enablement": "!commitInProgress"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.commitAllAmend",
|
"command": "git.commitAllAmend",
|
||||||
"title": "%command.commitAllAmend%",
|
"title": "%command.commitAllAmend%",
|
||||||
"category": "Git"
|
"category": "Git",
|
||||||
|
"enablement": "!commitInProgress"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.commitNoVerify",
|
"command": "git.commitNoVerify",
|
||||||
"title": "%command.commitNoVerify%",
|
"title": "%command.commitNoVerify%",
|
||||||
"category": "Git",
|
"category": "Git",
|
||||||
"icon": "$(check)"
|
"icon": "$(check)",
|
||||||
|
"enablement": "!commitInProgress"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.commitStagedNoVerify",
|
"command": "git.commitStagedNoVerify",
|
||||||
"title": "%command.commitStagedNoVerify%",
|
"title": "%command.commitStagedNoVerify%",
|
||||||
"category": "Git"
|
"category": "Git",
|
||||||
|
"enablement": "!commitInProgress"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.commitEmptyNoVerify",
|
"command": "git.commitEmptyNoVerify",
|
||||||
"title": "%command.commitEmptyNoVerify%",
|
"title": "%command.commitEmptyNoVerify%",
|
||||||
"category": "Git"
|
"category": "Git",
|
||||||
|
"enablement": "!commitInProgress"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.commitStagedSignedNoVerify",
|
"command": "git.commitStagedSignedNoVerify",
|
||||||
"title": "%command.commitStagedSignedNoVerify%",
|
"title": "%command.commitStagedSignedNoVerify%",
|
||||||
"category": "Git"
|
"category": "Git",
|
||||||
|
"enablement": "!commitInProgress"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.commitStagedAmendNoVerify",
|
"command": "git.commitStagedAmendNoVerify",
|
||||||
"title": "%command.commitStagedAmendNoVerify%",
|
"title": "%command.commitStagedAmendNoVerify%",
|
||||||
"category": "Git"
|
"category": "Git",
|
||||||
|
"enablement": "!commitInProgress"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.commitAllNoVerify",
|
"command": "git.commitAllNoVerify",
|
||||||
"title": "%command.commitAllNoVerify%",
|
"title": "%command.commitAllNoVerify%",
|
||||||
"category": "Git"
|
"category": "Git",
|
||||||
|
"enablement": "!commitInProgress"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.commitAllSignedNoVerify",
|
"command": "git.commitAllSignedNoVerify",
|
||||||
"title": "%command.commitAllSignedNoVerify%",
|
"title": "%command.commitAllSignedNoVerify%",
|
||||||
"category": "Git"
|
"category": "Git",
|
||||||
|
"enablement": "!commitInProgress"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.commitAllAmendNoVerify",
|
"command": "git.commitAllAmendNoVerify",
|
||||||
"title": "%command.commitAllAmendNoVerify%",
|
"title": "%command.commitAllAmendNoVerify%",
|
||||||
"category": "Git"
|
"category": "Git",
|
||||||
|
"enablement": "!commitInProgress"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "git.restoreCommitTemplate",
|
"command": "git.restoreCommitTemplate",
|
||||||
|
@ -2013,6 +2030,18 @@
|
||||||
"scope": "machine",
|
"scope": "machine",
|
||||||
"description": "%config.defaultCloneDirectory%"
|
"description": "%config.defaultCloneDirectory%"
|
||||||
},
|
},
|
||||||
|
"git.useEditorAsCommitInput": {
|
||||||
|
"type": "boolean",
|
||||||
|
"scope": "resource",
|
||||||
|
"description": "%config.useEditorAsCommitInput%",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"git.verboseCommit": {
|
||||||
|
"type": "boolean",
|
||||||
|
"scope": "resource",
|
||||||
|
"markdownDescription": "%config.verboseCommit%",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
"git.enableSmartCommit": {
|
"git.enableSmartCommit": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"scope": "resource",
|
"scope": "resource",
|
||||||
|
|
|
@ -140,6 +140,8 @@
|
||||||
"config.ignoreLimitWarning": "Ignores the warning when there are too many changes in a repository.",
|
"config.ignoreLimitWarning": "Ignores the warning when there are too many changes in a repository.",
|
||||||
"config.ignoreRebaseWarning": "Ignores the warning when it looks like the branch might have been rebased when pulling.",
|
"config.ignoreRebaseWarning": "Ignores the warning when it looks like the branch might have been rebased when pulling.",
|
||||||
"config.defaultCloneDirectory": "The default location to clone a git repository.",
|
"config.defaultCloneDirectory": "The default location to clone a git repository.",
|
||||||
|
"config.useEditorAsCommitInput": "Use an editor to author the commit message.",
|
||||||
|
"config.verboseCommit": "Enable verbose output when `#git.useEditorAsCommitInput#` is enabled.",
|
||||||
"config.enableSmartCommit": "Commit all changes when there are no staged changes.",
|
"config.enableSmartCommit": "Commit all changes when there are no staged changes.",
|
||||||
"config.smartCommitChanges": "Control which changes are automatically staged by Smart Commit.",
|
"config.smartCommitChanges": "Control which changes are automatically staged by Smart Commit.",
|
||||||
"config.smartCommitChanges.all": "Automatically stage all changes.",
|
"config.smartCommitChanges.all": "Automatically stage all changes.",
|
||||||
|
|
3
extensions/git/src/api/git.d.ts
vendored
3
extensions/git/src/api/git.d.ts
vendored
|
@ -137,6 +137,8 @@ export interface CommitOptions {
|
||||||
empty?: boolean;
|
empty?: boolean;
|
||||||
noVerify?: boolean;
|
noVerify?: boolean;
|
||||||
requireUserConfig?: boolean;
|
requireUserConfig?: boolean;
|
||||||
|
useEditor?: boolean;
|
||||||
|
verbose?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FetchOptions {
|
export interface FetchOptions {
|
||||||
|
@ -336,4 +338,5 @@ export const enum GitErrorCodes {
|
||||||
PatchDoesNotApply = 'PatchDoesNotApply',
|
PatchDoesNotApply = 'PatchDoesNotApply',
|
||||||
NoPathFound = 'NoPathFound',
|
NoPathFound = 'NoPathFound',
|
||||||
UnknownPath = 'UnknownPath',
|
UnknownPath = 'UnknownPath',
|
||||||
|
EmptyCommitMessage = 'EmptyCommitMessage'
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,8 @@
|
||||||
import { window, InputBoxOptions, Uri, Disposable, workspace } from 'vscode';
|
import { window, InputBoxOptions, Uri, Disposable, workspace } from 'vscode';
|
||||||
import { IDisposable, EmptyDisposable, toDisposable } from './util';
|
import { IDisposable, EmptyDisposable, toDisposable } from './util';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { IIPCHandler, IIPCServer, createIPCServer } from './ipc/ipcServer';
|
import { IIPCHandler, IIPCServer } from './ipc/ipcServer';
|
||||||
import { CredentialsProvider, Credentials } from './api/git';
|
import { CredentialsProvider, Credentials } from './api/git';
|
||||||
import { OutputChannelLogger } from './log';
|
|
||||||
|
|
||||||
export class Askpass implements IIPCHandler {
|
export class Askpass implements IIPCHandler {
|
||||||
|
|
||||||
|
@ -16,16 +15,7 @@ export class Askpass implements IIPCHandler {
|
||||||
private cache = new Map<string, Credentials>();
|
private cache = new Map<string, Credentials>();
|
||||||
private credentialsProviders = new Set<CredentialsProvider>();
|
private credentialsProviders = new Set<CredentialsProvider>();
|
||||||
|
|
||||||
static async create(outputChannelLogger: OutputChannelLogger, context?: string): Promise<Askpass> {
|
constructor(private ipc?: IIPCServer) {
|
||||||
try {
|
|
||||||
return new Askpass(await createIPCServer(context));
|
|
||||||
} catch (err) {
|
|
||||||
outputChannelLogger.logError(`Failed to create git askpass IPC: ${err}`);
|
|
||||||
return new Askpass();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private constructor(private ipc?: IIPCServer) {
|
|
||||||
if (ipc) {
|
if (ipc) {
|
||||||
this.disposable = ipc.registerHandler('askpass', this);
|
this.disposable = ipc.registerHandler('askpass', this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1516,6 +1516,14 @@ export class CommandCenter {
|
||||||
opts.signoff = true;
|
opts.signoff = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (config.get<boolean>('useEditorAsCommitInput')) {
|
||||||
|
opts.useEditor = true;
|
||||||
|
|
||||||
|
if (config.get<boolean>('verboseCommit')) {
|
||||||
|
opts.verbose = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const smartCommitChanges = config.get<'all' | 'tracked'>('smartCommitChanges');
|
const smartCommitChanges = config.get<'all' | 'tracked'>('smartCommitChanges');
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
@ -1563,7 +1571,7 @@ export class CommandCenter {
|
||||||
|
|
||||||
const message = await getCommitMessage();
|
const message = await getCommitMessage();
|
||||||
|
|
||||||
if (!message && !opts.amend) {
|
if (!message && !opts.amend && !opts.useEditor) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1623,10 +1631,13 @@ export class CommandCenter {
|
||||||
|
|
||||||
private async commitWithAnyInput(repository: Repository, opts?: CommitOptions): Promise<void> {
|
private async commitWithAnyInput(repository: Repository, opts?: CommitOptions): Promise<void> {
|
||||||
const message = repository.inputBox.value;
|
const message = repository.inputBox.value;
|
||||||
|
const root = Uri.file(repository.root);
|
||||||
|
const config = workspace.getConfiguration('git', root);
|
||||||
|
|
||||||
const getCommitMessage = async () => {
|
const getCommitMessage = async () => {
|
||||||
let _message: string | undefined = message;
|
let _message: string | undefined = message;
|
||||||
|
|
||||||
if (!_message) {
|
if (!_message && !config.get<boolean>('useEditorAsCommitInput')) {
|
||||||
const value: string | undefined = undefined;
|
const value: string | undefined = undefined;
|
||||||
|
|
||||||
if (opts && opts.amend && repository.HEAD && repository.HEAD.commit) {
|
if (opts && opts.amend && repository.HEAD && repository.HEAD.commit) {
|
||||||
|
@ -3010,7 +3021,7 @@ export class CommandCenter {
|
||||||
};
|
};
|
||||||
|
|
||||||
let message: string;
|
let message: string;
|
||||||
let type: 'error' | 'warning' = 'error';
|
let type: 'error' | 'warning' | 'information' = 'error';
|
||||||
|
|
||||||
const choices = new Map<string, () => void>();
|
const choices = new Map<string, () => void>();
|
||||||
const openOutputChannelChoice = localize('open git log', "Open Git Log");
|
const openOutputChannelChoice = localize('open git log', "Open Git Log");
|
||||||
|
@ -3073,6 +3084,12 @@ export class CommandCenter {
|
||||||
message = localize('missing user info', "Make sure you configure your 'user.name' and 'user.email' in git.");
|
message = localize('missing user info', "Make sure you configure your 'user.name' and 'user.email' in git.");
|
||||||
choices.set(localize('learn more', "Learn More"), () => commands.executeCommand('vscode.open', Uri.parse('https://aka.ms/vscode-setup-git')));
|
choices.set(localize('learn more', "Learn More"), () => commands.executeCommand('vscode.open', Uri.parse('https://aka.ms/vscode-setup-git')));
|
||||||
break;
|
break;
|
||||||
|
case GitErrorCodes.EmptyCommitMessage:
|
||||||
|
message = localize('empty commit', "Commit operation was cancelled due to empty commit message.");
|
||||||
|
choices.clear();
|
||||||
|
type = 'information';
|
||||||
|
options.modal = false;
|
||||||
|
break;
|
||||||
default: {
|
default: {
|
||||||
const hint = (err.stderr || err.message || String(err))
|
const hint = (err.stderr || err.message || String(err))
|
||||||
.replace(/^error: /mi, '')
|
.replace(/^error: /mi, '')
|
||||||
|
@ -3094,10 +3111,20 @@ export class CommandCenter {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let result: string | undefined;
|
||||||
const allChoices = Array.from(choices.keys());
|
const allChoices = Array.from(choices.keys());
|
||||||
const result = type === 'error'
|
|
||||||
? await window.showErrorMessage(message, options, ...allChoices)
|
switch (type) {
|
||||||
: await window.showWarningMessage(message, options, ...allChoices);
|
case 'error':
|
||||||
|
result = await window.showErrorMessage(message, options, ...allChoices);
|
||||||
|
break;
|
||||||
|
case 'warning':
|
||||||
|
result = await window.showWarningMessage(message, options, ...allChoices);
|
||||||
|
break;
|
||||||
|
case 'information':
|
||||||
|
result = await window.showInformationMessage(message, options, ...allChoices);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
const resultFn = choices.get(result);
|
const resultFn = choices.get(result);
|
||||||
|
|
1
extensions/git/src/git-editor-empty.sh
Executable file
1
extensions/git/src/git-editor-empty.sh
Executable file
|
@ -0,0 +1 @@
|
||||||
|
#!/bin/sh
|
21
extensions/git/src/git-editor-main.ts
Normal file
21
extensions/git/src/git-editor-main.ts
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
import { IPCClient } from './ipc/ipcClient';
|
||||||
|
|
||||||
|
function fatal(err: any): void {
|
||||||
|
console.error(err);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function main(argv: string[]): void {
|
||||||
|
const ipcClient = new IPCClient('git-editor');
|
||||||
|
const commitMessagePath = argv[argv.length - 1];
|
||||||
|
|
||||||
|
ipcClient.call({ commitMessagePath }).then(() => {
|
||||||
|
setTimeout(() => process.exit(0), 0);
|
||||||
|
}).catch(err => fatal(err));
|
||||||
|
}
|
||||||
|
|
||||||
|
main(process.argv);
|
4
extensions/git/src/git-editor.sh
Executable file
4
extensions/git/src/git-editor.sh
Executable file
|
@ -0,0 +1,4 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
ELECTRON_RUN_AS_NODE="1" \
|
||||||
|
"$VSCODE_GIT_EDITOR_NODE" "$VSCODE_GIT_EDITOR_MAIN" $VSCODE_GIT_EDITOR_EXTRA_ARGS $@
|
|
@ -1400,20 +1400,37 @@ export class Repository {
|
||||||
}
|
}
|
||||||
|
|
||||||
async commit(message: string | undefined, opts: CommitOptions = Object.create(null)): Promise<void> {
|
async commit(message: string | undefined, opts: CommitOptions = Object.create(null)): Promise<void> {
|
||||||
const args = ['commit', '--quiet', '--allow-empty-message'];
|
const args = ['commit', '--quiet'];
|
||||||
|
const options: SpawnOptions = {};
|
||||||
|
|
||||||
|
if (message) {
|
||||||
|
options.input = message;
|
||||||
|
args.push('--file', '-');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts.verbose) {
|
||||||
|
args.push('--verbose');
|
||||||
|
}
|
||||||
|
|
||||||
if (opts.all) {
|
if (opts.all) {
|
||||||
args.push('--all');
|
args.push('--all');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts.amend && message) {
|
if (opts.amend) {
|
||||||
args.push('--amend');
|
args.push('--amend');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts.amend && !message) {
|
if (!opts.useEditor) {
|
||||||
args.push('--amend', '--no-edit');
|
if (!message) {
|
||||||
} else {
|
if (opts.amend) {
|
||||||
args.push('--file', '-');
|
args.push('--no-edit');
|
||||||
|
} else {
|
||||||
|
options.input = '';
|
||||||
|
args.push('--file', '-');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
args.push('--allow-empty-message');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts.signoff) {
|
if (opts.signoff) {
|
||||||
|
@ -1438,7 +1455,7 @@ export class Repository {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.exec(args, !opts.amend || message ? { input: message || '' } : {});
|
await this.exec(args, options);
|
||||||
} catch (commitErr) {
|
} catch (commitErr) {
|
||||||
await this.handleCommitError(commitErr);
|
await this.handleCommitError(commitErr);
|
||||||
}
|
}
|
||||||
|
@ -1462,6 +1479,9 @@ export class Repository {
|
||||||
if (/not possible because you have unmerged files/.test(commitErr.stderr || '')) {
|
if (/not possible because you have unmerged files/.test(commitErr.stderr || '')) {
|
||||||
commitErr.gitErrorCode = GitErrorCodes.UnmergedChanges;
|
commitErr.gitErrorCode = GitErrorCodes.UnmergedChanges;
|
||||||
throw commitErr;
|
throw commitErr;
|
||||||
|
} else if (/Aborting commit due to empty commit message/.test(commitErr.stderr || '')) {
|
||||||
|
commitErr.gitErrorCode = GitErrorCodes.EmptyCommitMessage;
|
||||||
|
throw commitErr;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
65
extensions/git/src/gitEditor.ts
Normal file
65
extensions/git/src/gitEditor.ts
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
import * as path from 'path';
|
||||||
|
import { TabInputText, Uri, window, workspace } from 'vscode';
|
||||||
|
import { IIPCHandler, IIPCServer } from './ipc/ipcServer';
|
||||||
|
import { EmptyDisposable, IDisposable } from './util';
|
||||||
|
|
||||||
|
interface GitEditorRequest {
|
||||||
|
commitMessagePath?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class GitEditor implements IIPCHandler {
|
||||||
|
|
||||||
|
private disposable: IDisposable = EmptyDisposable;
|
||||||
|
|
||||||
|
constructor(private ipc?: IIPCServer) {
|
||||||
|
if (ipc) {
|
||||||
|
this.disposable = ipc.registerHandler('git-editor', this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async handle({ commitMessagePath }: GitEditorRequest): Promise<any> {
|
||||||
|
if (commitMessagePath) {
|
||||||
|
const uri = Uri.file(commitMessagePath);
|
||||||
|
const doc = await workspace.openTextDocument(uri);
|
||||||
|
await window.showTextDocument(doc, { preview: false });
|
||||||
|
|
||||||
|
return new Promise((c) => {
|
||||||
|
const onDidClose = window.tabGroups.onDidChangeTabs(async (tabs) => {
|
||||||
|
if (tabs.closed.some(t => t.input instanceof TabInputText && t.input.uri.toString() === uri.toString())) {
|
||||||
|
onDidClose.dispose();
|
||||||
|
return c(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getEnv(): { [key: string]: string } {
|
||||||
|
if (!this.ipc) {
|
||||||
|
return {
|
||||||
|
GIT_EDITOR: `"${path.join(__dirname, 'git-editor-empty.sh')}"`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let env: { [key: string]: string } = {
|
||||||
|
VSCODE_GIT_EDITOR_NODE: process.execPath,
|
||||||
|
VSCODE_GIT_EDITOR_EXTRA_ARGS: (process.versions['electron'] && process.versions['microsoft-build']) ? '--ms-enable-electron-run-as-node' : '',
|
||||||
|
VSCODE_GIT_EDITOR_MAIN: path.join(__dirname, 'git-editor-main.js')
|
||||||
|
};
|
||||||
|
|
||||||
|
const config = workspace.getConfiguration('git');
|
||||||
|
if (config.get<boolean>('useEditorAsCommitInput')) {
|
||||||
|
env.GIT_EDITOR = `"${path.join(__dirname, 'git-editor.sh')}"`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return env;
|
||||||
|
}
|
||||||
|
|
||||||
|
dispose(): void {
|
||||||
|
this.disposable.dispose();
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,6 +25,8 @@ import { GitTimelineProvider } from './timelineProvider';
|
||||||
import { registerAPICommands } from './api/api1';
|
import { registerAPICommands } from './api/api1';
|
||||||
import { TerminalEnvironmentManager } from './terminal';
|
import { TerminalEnvironmentManager } from './terminal';
|
||||||
import { OutputChannelLogger } from './log';
|
import { OutputChannelLogger } from './log';
|
||||||
|
import { createIPCServer, IIPCServer } from './ipc/ipcServer';
|
||||||
|
import { GitEditor } from './gitEditor';
|
||||||
|
|
||||||
const deactivateTasks: { (): Promise<any> }[] = [];
|
const deactivateTasks: { (): Promise<any> }[] = [];
|
||||||
|
|
||||||
|
@ -60,10 +62,21 @@ async function createModel(context: ExtensionContext, outputChannelLogger: Outpu
|
||||||
return !skip;
|
return !skip;
|
||||||
});
|
});
|
||||||
|
|
||||||
const askpass = await Askpass.create(outputChannelLogger, context.storagePath);
|
let ipc: IIPCServer | undefined = undefined;
|
||||||
|
|
||||||
|
try {
|
||||||
|
ipc = await createIPCServer(context.storagePath);
|
||||||
|
} catch (err) {
|
||||||
|
outputChannelLogger.logError(`Failed to create git IPC: ${err}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const askpass = new Askpass(ipc);
|
||||||
disposables.push(askpass);
|
disposables.push(askpass);
|
||||||
|
|
||||||
const environment = askpass.getEnv();
|
const gitEditor = new GitEditor(ipc);
|
||||||
|
disposables.push(gitEditor);
|
||||||
|
|
||||||
|
const environment = { ...askpass.getEnv(), ...gitEditor.getEnv() };
|
||||||
const terminalEnvironmentManager = new TerminalEnvironmentManager(context, environment);
|
const terminalEnvironmentManager = new TerminalEnvironmentManager(context, environment);
|
||||||
disposables.push(terminalEnvironmentManager);
|
disposables.push(terminalEnvironmentManager);
|
||||||
|
|
||||||
|
|
|
@ -454,6 +454,13 @@ class ProgressManager {
|
||||||
const onDidChange = filterEvent(workspace.onDidChangeConfiguration, e => e.affectsConfiguration('git', Uri.file(this.repository.root)));
|
const onDidChange = filterEvent(workspace.onDidChangeConfiguration, e => e.affectsConfiguration('git', Uri.file(this.repository.root)));
|
||||||
onDidChange(_ => this.updateEnablement());
|
onDidChange(_ => this.updateEnablement());
|
||||||
this.updateEnablement();
|
this.updateEnablement();
|
||||||
|
|
||||||
|
this.repository.onDidChangeOperations(() => {
|
||||||
|
const commitInProgress = this.repository.operations.isRunning(Operation.Commit);
|
||||||
|
|
||||||
|
this.repository.sourceControl.inputBox.enabled = !commitInProgress;
|
||||||
|
commands.executeCommand('setContext', 'commitInProgress', commitInProgress);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateEnablement(): void {
|
private updateEnablement(): void {
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
"../../src/vscode-dts/vscode.d.ts",
|
"../../src/vscode-dts/vscode.d.ts",
|
||||||
"../../src/vscode-dts/vscode.proposed.diffCommand.d.ts",
|
"../../src/vscode-dts/vscode.proposed.diffCommand.d.ts",
|
||||||
"../../src/vscode-dts/vscode.proposed.scmActionButton.d.ts",
|
"../../src/vscode-dts/vscode.proposed.scmActionButton.d.ts",
|
||||||
|
"../../src/vscode-dts/vscode.proposed.scmInput.d.ts",
|
||||||
"../../src/vscode-dts/vscode.proposed.scmSelectedProvider.d.ts",
|
"../../src/vscode-dts/vscode.proposed.scmSelectedProvider.d.ts",
|
||||||
"../../src/vscode-dts/vscode.proposed.scmValidation.d.ts",
|
"../../src/vscode-dts/vscode.proposed.scmValidation.d.ts",
|
||||||
"../../src/vscode-dts/vscode.proposed.tabs.d.ts",
|
"../../src/vscode-dts/vscode.proposed.tabs.d.ts",
|
||||||
|
|
|
@ -4,23 +4,29 @@
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import { tryInsertUriList } from './dropIntoEditor';
|
import { tryGetUriListSnippet } from './dropIntoEditor';
|
||||||
|
|
||||||
export function registerPasteProvider(selector: vscode.DocumentSelector) {
|
export function registerPasteProvider(selector: vscode.DocumentSelector) {
|
||||||
return vscode.languages.registerDocumentPasteEditProvider(selector, new class implements vscode.DocumentPasteEditProvider {
|
return vscode.languages.registerDocumentPasteEditProvider(selector, new class implements vscode.DocumentPasteEditProvider {
|
||||||
|
|
||||||
async provideDocumentPasteEdits(
|
async provideDocumentPasteEdits(
|
||||||
document: vscode.TextDocument,
|
document: vscode.TextDocument,
|
||||||
range: vscode.Range,
|
_ranges: readonly vscode.Range[],
|
||||||
dataTransfer: vscode.DataTransfer,
|
dataTransfer: vscode.DataTransfer,
|
||||||
token: vscode.CancellationToken,
|
token: vscode.CancellationToken,
|
||||||
): Promise<vscode.SnippetTextEdit | undefined> {
|
): Promise<vscode.DocumentPasteEdit | undefined> {
|
||||||
const enabled = vscode.workspace.getConfiguration('markdown', document).get('experimental.editor.pasteLinks.enabled', false);
|
const enabled = vscode.workspace.getConfiguration('markdown', document).get('experimental.editor.pasteLinks.enabled', false);
|
||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return tryInsertUriList(document, range, dataTransfer, token);
|
const snippet = await tryGetUriListSnippet(document, dataTransfer, token);
|
||||||
|
if (snippet) {
|
||||||
|
return { insertText: snippet };
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
}
|
}
|
||||||
|
}, {
|
||||||
|
pasteMimeTypes: ['text/uri-list']
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,19 +25,22 @@ const imageFileExtensions = new Set<string>([
|
||||||
|
|
||||||
export function registerDropIntoEditor(selector: vscode.DocumentSelector) {
|
export function registerDropIntoEditor(selector: vscode.DocumentSelector) {
|
||||||
return vscode.languages.registerDocumentOnDropEditProvider(selector, new class implements vscode.DocumentOnDropEditProvider {
|
return vscode.languages.registerDocumentOnDropEditProvider(selector, new class implements vscode.DocumentOnDropEditProvider {
|
||||||
async provideDocumentOnDropEdits(document: vscode.TextDocument, position: vscode.Position, dataTransfer: vscode.DataTransfer, token: vscode.CancellationToken): Promise<vscode.SnippetTextEdit | undefined> {
|
async provideDocumentOnDropEdits(document: vscode.TextDocument, _position: vscode.Position, dataTransfer: vscode.DataTransfer, token: vscode.CancellationToken): Promise<vscode.DocumentDropEdit | undefined> {
|
||||||
const enabled = vscode.workspace.getConfiguration('markdown', document).get('editor.drop.enabled', true);
|
const enabled = vscode.workspace.getConfiguration('markdown', document).get('editor.drop.enabled', true);
|
||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
return;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const replacementRange = new vscode.Range(position, position);
|
const snippet = await tryGetUriListSnippet(document, dataTransfer, token);
|
||||||
return tryInsertUriList(document, replacementRange, dataTransfer, token);
|
if (snippet) {
|
||||||
|
return { insertText: snippet };
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function tryInsertUriList(document: vscode.TextDocument, replacementRange: vscode.Range, dataTransfer: vscode.DataTransfer, token: vscode.CancellationToken): Promise<vscode.SnippetTextEdit | undefined> {
|
export async function tryGetUriListSnippet(document: vscode.TextDocument, dataTransfer: vscode.DataTransfer, token: vscode.CancellationToken): Promise<vscode.SnippetString | undefined> {
|
||||||
const urlList = await dataTransfer.get('text/uri-list')?.asString();
|
const urlList = await dataTransfer.get('text/uri-list')?.asString();
|
||||||
if (!urlList || token.isCancellationRequested) {
|
if (!urlList || token.isCancellationRequested) {
|
||||||
return undefined;
|
return undefined;
|
||||||
|
@ -72,5 +75,5 @@ export async function tryInsertUriList(document: vscode.TextDocument, replacemen
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return new vscode.SnippetTextEdit(replacementRange, snippet);
|
return snippet;
|
||||||
}
|
}
|
||||||
|
|
|
@ -142,7 +142,7 @@ export class MdRenameProvider extends Disposable implements vscode.RenameProvide
|
||||||
return this.renameExternalLink(allRefsInfo, newName);
|
return this.renameExternalLink(allRefsInfo, newName);
|
||||||
} else if (triggerRef.kind === 'header' || (triggerRef.kind === 'link' && triggerRef.link.source.fragmentRange?.contains(position) && (triggerRef.link.kind === 'definition' || triggerRef.link.kind === 'link' && triggerRef.link.href.kind === 'internal'))) {
|
} else if (triggerRef.kind === 'header' || (triggerRef.kind === 'link' && triggerRef.link.source.fragmentRange?.contains(position) && (triggerRef.link.kind === 'definition' || triggerRef.link.kind === 'link' && triggerRef.link.href.kind === 'internal'))) {
|
||||||
return this.renameFragment(allRefsInfo, newName);
|
return this.renameFragment(allRefsInfo, newName);
|
||||||
} else if (triggerRef.kind === 'link' && !triggerRef.link.source.fragmentRange?.contains(position) && triggerRef.link.kind === 'link' && triggerRef.link.href.kind === 'internal') {
|
} else if (triggerRef.kind === 'link' && !triggerRef.link.source.fragmentRange?.contains(position) && (triggerRef.link.kind === 'link' || triggerRef.link.kind === 'definition') && triggerRef.link.href.kind === 'internal') {
|
||||||
return this.renameFilePath(triggerRef.link.source.resource, triggerRef.link.href, allRefsInfo, newName);
|
return this.renameFilePath(triggerRef.link.source.resource, triggerRef.link.href, allRefsInfo, newName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -614,4 +614,79 @@ suite('markdown: rename', () => {
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Rename on definition path should update all references to path', async () => {
|
||||||
|
const uri = workspacePath('doc.md');
|
||||||
|
const doc = new InMemoryDocument(uri, joinLines(
|
||||||
|
`[ref text][ref]`,
|
||||||
|
`[direct](/file)`,
|
||||||
|
`[ref]: /file`, // rename here
|
||||||
|
));
|
||||||
|
|
||||||
|
const workspace = new InMemoryWorkspaceMarkdownDocuments([doc]);
|
||||||
|
|
||||||
|
const preparedInfo = await prepareRename(doc, new vscode.Position(2, 10), workspace);
|
||||||
|
assert.strictEqual(preparedInfo!.placeholder, '/file');
|
||||||
|
assertRangeEqual(preparedInfo!.range, new vscode.Range(2, 7, 2, 12));
|
||||||
|
|
||||||
|
const edit = await getRenameEdits(doc, new vscode.Position(2, 10), "/newFile", workspace);
|
||||||
|
assertEditsEqual(edit!, {
|
||||||
|
uri, edits: [
|
||||||
|
new vscode.TextEdit(new vscode.Range(1, 9, 1, 14), '/newFile'),
|
||||||
|
new vscode.TextEdit(new vscode.Range(2, 7, 2, 12), '/newFile'),
|
||||||
|
]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Rename on definition path where file exists should also update file', async () => {
|
||||||
|
const uri1 = workspacePath('doc.md');
|
||||||
|
const doc1 = new InMemoryDocument(uri1, joinLines(
|
||||||
|
`[ref text][ref]`,
|
||||||
|
`[direct](/doc2)`,
|
||||||
|
`[ref]: /doc2`, // rename here
|
||||||
|
));
|
||||||
|
|
||||||
|
const uri2 = workspacePath('doc2.md');
|
||||||
|
const doc2 = new InMemoryDocument(uri2, joinLines());
|
||||||
|
|
||||||
|
const workspace = new InMemoryWorkspaceMarkdownDocuments([doc1, doc2]);
|
||||||
|
|
||||||
|
const preparedInfo = await prepareRename(doc1, new vscode.Position(2, 10), workspace);
|
||||||
|
assert.strictEqual(preparedInfo!.placeholder, '/doc2');
|
||||||
|
assertRangeEqual(preparedInfo!.range, new vscode.Range(2, 7, 2, 12));
|
||||||
|
|
||||||
|
const edit = await getRenameEdits(doc1, new vscode.Position(2, 10), "/new-doc", workspace);
|
||||||
|
assertEditsEqual(edit!, {
|
||||||
|
uri: uri1, edits: [
|
||||||
|
new vscode.TextEdit(new vscode.Range(1, 9, 1, 14), '/new-doc'),
|
||||||
|
new vscode.TextEdit(new vscode.Range(2, 7, 2, 12), '/new-doc'),
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
originalUri: uri2,
|
||||||
|
newUri: workspacePath('new-doc.md')
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Rename on definition path header should update all references to header', async () => {
|
||||||
|
const uri = workspacePath('doc.md');
|
||||||
|
const doc = new InMemoryDocument(uri, joinLines(
|
||||||
|
`[ref text][ref]`,
|
||||||
|
`[direct](/file#header)`,
|
||||||
|
`[ref]: /file#header`, // rename here
|
||||||
|
));
|
||||||
|
|
||||||
|
const workspace = new InMemoryWorkspaceMarkdownDocuments([doc]);
|
||||||
|
|
||||||
|
const preparedInfo = await prepareRename(doc, new vscode.Position(2, 16), workspace);
|
||||||
|
assert.strictEqual(preparedInfo!.placeholder, 'header');
|
||||||
|
assertRangeEqual(preparedInfo!.range, new vscode.Range(2, 13, 2, 19));
|
||||||
|
|
||||||
|
const edit = await getRenameEdits(doc, new vscode.Position(2, 16), "New Header", workspace);
|
||||||
|
assertEditsEqual(edit!, {
|
||||||
|
uri, edits: [
|
||||||
|
new vscode.TextEdit(new vscode.Range(1, 15, 1, 21), 'new-header'),
|
||||||
|
new vscode.TextEdit(new vscode.Range(2, 13, 2, 19), 'new-header'),
|
||||||
|
]
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -12,10 +12,12 @@ import * as path from 'path';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as minimatch from 'minimatch';
|
import * as minimatch from 'minimatch';
|
||||||
import * as nls from 'vscode-nls';
|
import * as nls from 'vscode-nls';
|
||||||
|
import { Utils } from 'vscode-uri';
|
||||||
import { findPreferredPM } from './preferred-pm';
|
import { findPreferredPM } from './preferred-pm';
|
||||||
import { readScripts } from './readScripts';
|
import { readScripts } from './readScripts';
|
||||||
|
|
||||||
const localize = nls.loadMessageBundle();
|
const localize = nls.loadMessageBundle();
|
||||||
|
const excludeRegex = new RegExp('^(node_modules|.vscode-test)$', 'i');
|
||||||
|
|
||||||
export interface INpmTaskDefinition extends TaskDefinition {
|
export interface INpmTaskDefinition extends TaskDefinition {
|
||||||
script: string;
|
script: string;
|
||||||
|
@ -156,7 +158,7 @@ export async function hasNpmScripts(): Promise<boolean> {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
for (const folder of folders) {
|
for (const folder of folders) {
|
||||||
if (isAutoDetectionEnabled(folder)) {
|
if (isAutoDetectionEnabled(folder) && !excludeRegex.test(Utils.basename(folder.uri))) {
|
||||||
const relativePattern = new RelativePattern(folder, '**/package.json');
|
const relativePattern = new RelativePattern(folder, '**/package.json');
|
||||||
const paths = await workspace.findFiles(relativePattern, '**/node_modules/**');
|
const paths = await workspace.findFiles(relativePattern, '**/node_modules/**');
|
||||||
if (paths.length > 0) {
|
if (paths.length > 0) {
|
||||||
|
@ -182,7 +184,7 @@ async function detectNpmScripts(context: ExtensionContext, showWarning: boolean)
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
for (const folder of folders) {
|
for (const folder of folders) {
|
||||||
if (isAutoDetectionEnabled(folder)) {
|
if (isAutoDetectionEnabled(folder) && !excludeRegex.test(Utils.basename(folder.uri))) {
|
||||||
const relativePattern = new RelativePattern(folder, '**/package.json');
|
const relativePattern = new RelativePattern(folder, '**/package.json');
|
||||||
const paths = await workspace.findFiles(relativePattern, '**/{node_modules,.vscode-test}/**');
|
const paths = await workspace.findFiles(relativePattern, '**/{node_modules,.vscode-test}/**');
|
||||||
for (const path of paths) {
|
for (const path of paths) {
|
||||||
|
@ -206,6 +208,9 @@ export async function detectNpmScriptsForFolder(context: ExtensionContext, folde
|
||||||
const folderTasks: IFolderTaskItem[] = [];
|
const folderTasks: IFolderTaskItem[] = [];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
if (excludeRegex.test(Utils.basename(folder))) {
|
||||||
|
return folderTasks;
|
||||||
|
}
|
||||||
const relativePattern = new RelativePattern(folder.fsPath, '**/package.json');
|
const relativePattern = new RelativePattern(folder.fsPath, '**/package.json');
|
||||||
const paths = await workspace.findFiles(relativePattern, '**/node_modules/**');
|
const paths = await workspace.findFiles(relativePattern, '**/node_modules/**');
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"scope": ["meta.embedded", "source.groovy.embedded"],
|
"scope": ["meta.embedded", "source.groovy.embedded", "meta.jsx.children"],
|
||||||
"settings": {
|
"settings": {
|
||||||
//"background": "#002451",
|
//"background": "#002451",
|
||||||
"foreground": "#FFFFFF"
|
"foreground": "#FFFFFF"
|
||||||
|
|
|
@ -174,6 +174,7 @@ export default class FileConfigurationManager extends Disposable {
|
||||||
document);
|
document);
|
||||||
|
|
||||||
const preferences: Proto.UserPreferences = {
|
const preferences: Proto.UserPreferences = {
|
||||||
|
...config.get('unstable'),
|
||||||
quotePreference: this.getQuoteStylePreference(preferencesConfig),
|
quotePreference: this.getQuoteStylePreference(preferencesConfig),
|
||||||
importModuleSpecifierPreference: getImportModuleSpecifierPreference(preferencesConfig),
|
importModuleSpecifierPreference: getImportModuleSpecifierPreference(preferencesConfig),
|
||||||
importModuleSpecifierEnding: getImportModuleSpecifierEndingPreference(preferencesConfig),
|
importModuleSpecifierEnding: getImportModuleSpecifierEndingPreference(preferencesConfig),
|
||||||
|
|
|
@ -18,9 +18,9 @@ import * as vscode from 'vscode';
|
||||||
const notebookEditor = vscode.window.activeNotebookEditor;
|
const notebookEditor = vscode.window.activeNotebookEditor;
|
||||||
assert.ok(notebookEditor);
|
assert.ok(notebookEditor);
|
||||||
|
|
||||||
assert.strictEqual(notebookEditor.document.cellCount, 2);
|
assert.strictEqual(notebookEditor.notebook.cellCount, 2);
|
||||||
assert.strictEqual(notebookEditor.document.cellAt(0).kind, vscode.NotebookCellKind.Markup);
|
assert.strictEqual(notebookEditor.notebook.cellAt(0).kind, vscode.NotebookCellKind.Markup);
|
||||||
assert.strictEqual(notebookEditor.document.cellAt(1).kind, vscode.NotebookCellKind.Code);
|
assert.strictEqual(notebookEditor.notebook.cellAt(1).kind, vscode.NotebookCellKind.Code);
|
||||||
assert.strictEqual(notebookEditor.document.cellAt(1).outputs.length, 1);
|
assert.strictEqual(notebookEditor.notebook.cellAt(1).outputs.length, 1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -75,11 +75,11 @@ import * as utils from '../utils';
|
||||||
const uri = await utils.createRandomFile(undefined, undefined, '.nbdtest');
|
const uri = await utils.createRandomFile(undefined, undefined, '.nbdtest');
|
||||||
|
|
||||||
const editor = await vscode.window.showNotebookDocument(uri);
|
const editor = await vscode.window.showNotebookDocument(uri);
|
||||||
assert.strictEqual(uri.toString(), editor.document.uri.toString());
|
assert.strictEqual(uri.toString(), editor.notebook.uri.toString());
|
||||||
|
|
||||||
assert.strictEqual(notebookDocumentsFromOnDidOpen.has(editor.document), true);
|
assert.strictEqual(notebookDocumentsFromOnDidOpen.has(editor.notebook), true);
|
||||||
|
|
||||||
const includes = vscode.workspace.notebookDocuments.includes(editor.document);
|
const includes = vscode.workspace.notebookDocuments.includes(editor.notebook);
|
||||||
assert.strictEqual(true, includes);
|
assert.strictEqual(true, includes);
|
||||||
|
|
||||||
sub.dispose();
|
sub.dispose();
|
||||||
|
@ -104,7 +104,7 @@ import * as utils from '../utils';
|
||||||
const resource = await utils.createRandomFile(undefined, undefined, '.nbdtest');
|
const resource = await utils.createRandomFile(undefined, undefined, '.nbdtest');
|
||||||
const editor = await vscode.window.showNotebookDocument(resource);
|
const editor = await vscode.window.showNotebookDocument(resource);
|
||||||
assert.ok(await openedEditor);
|
assert.ok(await openedEditor);
|
||||||
assert.strictEqual(editor.document.uri.toString(), resource.toString());
|
assert.strictEqual(editor.notebook.uri.toString(), resource.toString());
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Active/Visible Editor', async function () {
|
test('Active/Visible Editor', async function () {
|
||||||
|
|
|
@ -77,7 +77,7 @@ export class Kernel {
|
||||||
|
|
||||||
|
|
||||||
function getFocusedCell(editor?: vscode.NotebookEditor) {
|
function getFocusedCell(editor?: vscode.NotebookEditor) {
|
||||||
return editor ? editor.document.cellAt(editor.selections[0].start) : undefined;
|
return editor ? editor.notebook.cellAt(editor.selections[0].start) : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function assertKernel(kernel: Kernel, notebook: vscode.NotebookDocument): Promise<void> {
|
async function assertKernel(kernel: Kernel, notebook: vscode.NotebookDocument): Promise<void> {
|
||||||
|
@ -204,12 +204,12 @@ const apiTestContentProvider: vscode.NotebookContentProvider = {
|
||||||
const cellsChangeEvent = asPromise<vscode.NotebookDocumentChangeEvent>(vscode.workspace.onDidChangeNotebookDocument);
|
const cellsChangeEvent = asPromise<vscode.NotebookDocumentChangeEvent>(vscode.workspace.onDidChangeNotebookDocument);
|
||||||
await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
|
await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
|
||||||
const cellChangeEventRet = await cellsChangeEvent;
|
const cellChangeEventRet = await cellsChangeEvent;
|
||||||
assert.strictEqual(cellChangeEventRet.notebook, editor.document);
|
assert.strictEqual(cellChangeEventRet.notebook, editor.notebook);
|
||||||
assert.strictEqual(cellChangeEventRet.contentChanges.length, 1);
|
assert.strictEqual(cellChangeEventRet.contentChanges.length, 1);
|
||||||
assert.deepStrictEqual(cellChangeEventRet.contentChanges[0], <vscode.NotebookDocumentContentChange>{
|
assert.deepStrictEqual(cellChangeEventRet.contentChanges[0], <vscode.NotebookDocumentContentChange>{
|
||||||
range: new vscode.NotebookRange(1, 1),
|
range: new vscode.NotebookRange(1, 1),
|
||||||
removedCells: [],
|
removedCells: [],
|
||||||
addedCells: [editor.document.cellAt(1)]
|
addedCells: [editor.notebook.cellAt(1)]
|
||||||
});
|
});
|
||||||
|
|
||||||
const moveCellEvent = asPromise<vscode.NotebookDocumentChangeEvent>(vscode.workspace.onDidChangeNotebookDocument);
|
const moveCellEvent = asPromise<vscode.NotebookDocumentChangeEvent>(vscode.workspace.onDidChangeNotebookDocument);
|
||||||
|
@ -220,11 +220,11 @@ const apiTestContentProvider: vscode.NotebookContentProvider = {
|
||||||
await vscode.commands.executeCommand('notebook.cell.execute');
|
await vscode.commands.executeCommand('notebook.cell.execute');
|
||||||
const cellOutputsAddedRet = await cellOutputChange;
|
const cellOutputsAddedRet = await cellOutputChange;
|
||||||
|
|
||||||
assert.strictEqual(cellOutputsAddedRet.notebook.uri.toString(), editor.document.uri.toString());
|
assert.strictEqual(cellOutputsAddedRet.notebook.uri.toString(), editor.notebook.uri.toString());
|
||||||
assert.strictEqual(cellOutputsAddedRet.metadata, undefined);
|
assert.strictEqual(cellOutputsAddedRet.metadata, undefined);
|
||||||
assert.strictEqual(cellOutputsAddedRet.contentChanges.length, 0);
|
assert.strictEqual(cellOutputsAddedRet.contentChanges.length, 0);
|
||||||
assert.strictEqual(cellOutputsAddedRet.cellChanges.length, 1);
|
assert.strictEqual(cellOutputsAddedRet.cellChanges.length, 1);
|
||||||
assert.deepStrictEqual(cellOutputsAddedRet.cellChanges[0].cell, editor.document.cellAt(0));
|
assert.deepStrictEqual(cellOutputsAddedRet.cellChanges[0].cell, editor.notebook.cellAt(0));
|
||||||
assert.deepStrictEqual(cellOutputsAddedRet.cellChanges[0].executionSummary, { executionOrder: undefined, success: undefined, timing: undefined }); // TODO@jrieken should this be undefined instead all empty?
|
assert.deepStrictEqual(cellOutputsAddedRet.cellChanges[0].executionSummary, { executionOrder: undefined, success: undefined, timing: undefined }); // TODO@jrieken should this be undefined instead all empty?
|
||||||
assert.strictEqual(cellOutputsAddedRet.cellChanges[0].document, undefined);
|
assert.strictEqual(cellOutputsAddedRet.cellChanges[0].document, undefined);
|
||||||
assert.strictEqual(cellOutputsAddedRet.cellChanges[0].metadata, undefined);
|
assert.strictEqual(cellOutputsAddedRet.cellChanges[0].metadata, undefined);
|
||||||
|
@ -235,15 +235,15 @@ const apiTestContentProvider: vscode.NotebookContentProvider = {
|
||||||
await vscode.commands.executeCommand('notebook.cell.clearOutputs');
|
await vscode.commands.executeCommand('notebook.cell.clearOutputs');
|
||||||
const cellOutputsCleardRet = await cellOutputClear;
|
const cellOutputsCleardRet = await cellOutputClear;
|
||||||
assert.deepStrictEqual(cellOutputsCleardRet, <vscode.NotebookDocumentChangeEvent>{
|
assert.deepStrictEqual(cellOutputsCleardRet, <vscode.NotebookDocumentChangeEvent>{
|
||||||
notebook: editor.document,
|
notebook: editor.notebook,
|
||||||
metadata: undefined,
|
metadata: undefined,
|
||||||
contentChanges: [],
|
contentChanges: [],
|
||||||
cellChanges: [{
|
cellChanges: [{
|
||||||
cell: editor.document.cellAt(0),
|
cell: editor.notebook.cellAt(0),
|
||||||
document: undefined,
|
document: undefined,
|
||||||
executionSummary: undefined,
|
executionSummary: undefined,
|
||||||
metadata: undefined,
|
metadata: undefined,
|
||||||
outputs: editor.document.cellAt(0).outputs
|
outputs: editor.notebook.cellAt(0).outputs
|
||||||
}],
|
}],
|
||||||
});
|
});
|
||||||
assert.strictEqual(cellOutputsCleardRet.cellChanges[0].cell.outputs.length, 0);
|
assert.strictEqual(cellOutputsCleardRet.cellChanges[0].cell.outputs.length, 0);
|
||||||
|
@ -289,21 +289,21 @@ const apiTestContentProvider: vscode.NotebookContentProvider = {
|
||||||
const editor = await vscode.window.showNotebookDocument(notebook);
|
const editor = await vscode.window.showNotebookDocument(notebook);
|
||||||
|
|
||||||
const notebookChangeEvent = asPromise<vscode.NotebookDocumentChangeEvent>(vscode.workspace.onDidChangeNotebookDocument);
|
const notebookChangeEvent = asPromise<vscode.NotebookDocumentChangeEvent>(vscode.workspace.onDidChangeNotebookDocument);
|
||||||
const version = editor.document.version;
|
const version = editor.notebook.version;
|
||||||
await editor.edit(editBuilder => {
|
await editor.edit(editBuilder => {
|
||||||
editBuilder.replaceCells(1, 0, [{ kind: vscode.NotebookCellKind.Code, languageId: 'javascript', value: 'test 2', outputs: [], metadata: undefined }]);
|
editBuilder.replaceCells(1, 0, [{ kind: vscode.NotebookCellKind.Code, languageId: 'javascript', value: 'test 2', outputs: [], metadata: undefined }]);
|
||||||
editBuilder.replaceCellMetadata(0, { inputCollapsed: false });
|
editBuilder.replaceCellMetadata(0, { inputCollapsed: false });
|
||||||
});
|
});
|
||||||
|
|
||||||
await notebookChangeEvent;
|
await notebookChangeEvent;
|
||||||
assert.strictEqual(editor.document.cellCount, 3);
|
assert.strictEqual(editor.notebook.cellCount, 3);
|
||||||
assert.strictEqual(editor.document.cellAt(0)?.metadata.inputCollapsed, false);
|
assert.strictEqual(editor.notebook.cellAt(0)?.metadata.inputCollapsed, false);
|
||||||
assert.strictEqual(version + 1, editor.document.version);
|
assert.strictEqual(version + 1, editor.notebook.version);
|
||||||
|
|
||||||
await vscode.commands.executeCommand('undo');
|
await vscode.commands.executeCommand('undo');
|
||||||
assert.strictEqual(version + 2, editor.document.version);
|
assert.strictEqual(version + 2, editor.notebook.version);
|
||||||
assert.strictEqual(editor.document.cellAt(0)?.metadata.inputCollapsed, undefined);
|
assert.strictEqual(editor.notebook.cellAt(0)?.metadata.inputCollapsed, undefined);
|
||||||
assert.strictEqual(editor.document.cellCount, 2);
|
assert.strictEqual(editor.notebook.cellCount, 2);
|
||||||
});
|
});
|
||||||
|
|
||||||
// #126371
|
// #126371
|
||||||
|
@ -326,7 +326,7 @@ const apiTestContentProvider: vscode.NotebookContentProvider = {
|
||||||
assert.strictEqual(getFocusedCell(editor)?.document.getText(), 'test');
|
assert.strictEqual(getFocusedCell(editor)?.document.getText(), 'test');
|
||||||
assert.strictEqual(getFocusedCell(editor)?.document.languageId, 'typescript');
|
assert.strictEqual(getFocusedCell(editor)?.document.languageId, 'typescript');
|
||||||
|
|
||||||
const secondCell = editor.document.cellAt(1);
|
const secondCell = editor.notebook.cellAt(1);
|
||||||
assert.strictEqual(secondCell.outputs.length, 1);
|
assert.strictEqual(secondCell.outputs.length, 1);
|
||||||
assert.deepStrictEqual(secondCell.outputs[0].metadata, { testOutputMetadata: true, ['text/plain']: { testOutputItemMetadata: true } });
|
assert.deepStrictEqual(secondCell.outputs[0].metadata, { testOutputMetadata: true, ['text/plain']: { testOutputItemMetadata: true } });
|
||||||
assert.strictEqual(secondCell.outputs[0].items.length, 1);
|
assert.strictEqual(secondCell.outputs[0].items.length, 1);
|
||||||
|
@ -353,22 +353,22 @@ const apiTestContentProvider: vscode.NotebookContentProvider = {
|
||||||
let activeCell = getFocusedCell(editor);
|
let activeCell = getFocusedCell(editor);
|
||||||
assert.notStrictEqual(getFocusedCell(editor), undefined);
|
assert.notStrictEqual(getFocusedCell(editor), undefined);
|
||||||
assert.strictEqual(activeCell!.document.getText(), '');
|
assert.strictEqual(activeCell!.document.getText(), '');
|
||||||
assert.strictEqual(editor.document.cellCount, 4);
|
assert.strictEqual(editor.notebook.cellCount, 4);
|
||||||
assert.strictEqual(editor.document.getCells().indexOf(activeCell!), 1);
|
assert.strictEqual(editor.notebook.getCells().indexOf(activeCell!), 1);
|
||||||
|
|
||||||
// ---- focus bottom ---- //
|
// ---- focus bottom ---- //
|
||||||
await vscode.commands.executeCommand('notebook.focusBottom');
|
await vscode.commands.executeCommand('notebook.focusBottom');
|
||||||
activeCell = getFocusedCell(editor);
|
activeCell = getFocusedCell(editor);
|
||||||
assert.strictEqual(editor.document.getCells().indexOf(activeCell!), 3);
|
assert.strictEqual(editor.notebook.getCells().indexOf(activeCell!), 3);
|
||||||
|
|
||||||
// ---- focus top and then copy down ---- //
|
// ---- focus top and then copy down ---- //
|
||||||
await vscode.commands.executeCommand('notebook.focusTop');
|
await vscode.commands.executeCommand('notebook.focusTop');
|
||||||
activeCell = getFocusedCell(editor);
|
activeCell = getFocusedCell(editor);
|
||||||
assert.strictEqual(editor.document.getCells().indexOf(activeCell!), 0);
|
assert.strictEqual(editor.notebook.getCells().indexOf(activeCell!), 0);
|
||||||
|
|
||||||
await vscode.commands.executeCommand('notebook.cell.copyDown');
|
await vscode.commands.executeCommand('notebook.cell.copyDown');
|
||||||
activeCell = getFocusedCell(editor);
|
activeCell = getFocusedCell(editor);
|
||||||
assert.strictEqual(editor.document.getCells().indexOf(activeCell!), 1);
|
assert.strictEqual(editor.notebook.getCells().indexOf(activeCell!), 1);
|
||||||
assert.strictEqual(activeCell?.document.getText(), 'test');
|
assert.strictEqual(activeCell?.document.getText(), 'test');
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -381,25 +381,25 @@ const apiTestContentProvider: vscode.NotebookContentProvider = {
|
||||||
}
|
}
|
||||||
|
|
||||||
activeCell = getFocusedCell(editor);
|
activeCell = getFocusedCell(editor);
|
||||||
assert.strictEqual(editor.document.getCells().indexOf(activeCell!), 1);
|
assert.strictEqual(editor.notebook.getCells().indexOf(activeCell!), 1);
|
||||||
assert.strictEqual(activeCell?.document.getText(), '');
|
assert.strictEqual(activeCell?.document.getText(), '');
|
||||||
|
|
||||||
// ---- focus top and then copy up ---- //
|
// ---- focus top and then copy up ---- //
|
||||||
await vscode.commands.executeCommand('notebook.focusTop');
|
await vscode.commands.executeCommand('notebook.focusTop');
|
||||||
await vscode.commands.executeCommand('notebook.cell.copyUp');
|
await vscode.commands.executeCommand('notebook.cell.copyUp');
|
||||||
assert.strictEqual(editor.document.cellCount, 5);
|
assert.strictEqual(editor.notebook.cellCount, 5);
|
||||||
assert.strictEqual(editor.document.cellAt(0).document.getText(), 'test');
|
assert.strictEqual(editor.notebook.cellAt(0).document.getText(), 'test');
|
||||||
assert.strictEqual(editor.document.cellAt(1).document.getText(), 'test');
|
assert.strictEqual(editor.notebook.cellAt(1).document.getText(), 'test');
|
||||||
assert.strictEqual(editor.document.cellAt(2).document.getText(), '');
|
assert.strictEqual(editor.notebook.cellAt(2).document.getText(), '');
|
||||||
assert.strictEqual(editor.document.cellAt(3).document.getText(), '');
|
assert.strictEqual(editor.notebook.cellAt(3).document.getText(), '');
|
||||||
activeCell = getFocusedCell(editor);
|
activeCell = getFocusedCell(editor);
|
||||||
assert.strictEqual(editor.document.getCells().indexOf(activeCell!), 0);
|
assert.strictEqual(editor.notebook.getCells().indexOf(activeCell!), 0);
|
||||||
|
|
||||||
|
|
||||||
// ---- move up and down ---- //
|
// ---- move up and down ---- //
|
||||||
|
|
||||||
await vscode.commands.executeCommand('notebook.cell.moveDown');
|
await vscode.commands.executeCommand('notebook.cell.moveDown');
|
||||||
assert.strictEqual(editor.document.getCells().indexOf(getFocusedCell(editor)!), 1,
|
assert.strictEqual(editor.notebook.getCells().indexOf(getFocusedCell(editor)!), 1,
|
||||||
`first move down, active cell ${getFocusedCell(editor)!.document.uri.toString()}, ${getFocusedCell(editor)!.document.getText()}`);
|
`first move down, active cell ${getFocusedCell(editor)!.document.uri.toString()}, ${getFocusedCell(editor)!.document.getText()}`);
|
||||||
|
|
||||||
await vscode.commands.executeCommand('workbench.action.files.save');
|
await vscode.commands.executeCommand('workbench.action.files.save');
|
||||||
|
@ -427,7 +427,7 @@ const apiTestContentProvider: vscode.NotebookContentProvider = {
|
||||||
// assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
|
// assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
|
||||||
// const editor = vscode.window.activeNotebookEditor!;
|
// const editor = vscode.window.activeNotebookEditor!;
|
||||||
|
|
||||||
// const cell = editor.document.cellAt(0);
|
// const cell = editor.notebook.cellAt(0);
|
||||||
// assert.strictEqual(cell.outputs.length, 0);
|
// assert.strictEqual(cell.outputs.length, 0);
|
||||||
|
|
||||||
// currentKernelProvider.setHasKernels(false);
|
// currentKernelProvider.setHasKernels(false);
|
||||||
|
@ -452,7 +452,7 @@ const apiTestContentProvider: vscode.NotebookContentProvider = {
|
||||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||||
assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
|
assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
|
||||||
const editor = vscode.window.activeNotebookEditor!;
|
const editor = vscode.window.activeNotebookEditor!;
|
||||||
const cell = editor.document.cellAt(0);
|
const cell = editor.notebook.cellAt(0);
|
||||||
|
|
||||||
await vscode.commands.executeCommand('notebook.execute');
|
await vscode.commands.executeCommand('notebook.execute');
|
||||||
assert.strictEqual(cell.outputs.length, 0, 'should not execute'); // not runnable, didn't work
|
assert.strictEqual(cell.outputs.length, 0, 'should not execute'); // not runnable, didn't work
|
||||||
|
@ -463,7 +463,7 @@ const apiTestContentProvider: vscode.NotebookContentProvider = {
|
||||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||||
assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
|
assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
|
||||||
const editor = vscode.window.activeNotebookEditor!;
|
const editor = vscode.window.activeNotebookEditor!;
|
||||||
const cell = editor.document.cellAt(0);
|
const cell = editor.notebook.cellAt(0);
|
||||||
|
|
||||||
await withEvent(vscode.workspace.onDidChangeNotebookDocument, async (event) => {
|
await withEvent(vscode.workspace.onDidChangeNotebookDocument, async (event) => {
|
||||||
await vscode.commands.executeCommand('notebook.execute');
|
await vscode.commands.executeCommand('notebook.execute');
|
||||||
|
@ -484,7 +484,7 @@ const apiTestContentProvider: vscode.NotebookContentProvider = {
|
||||||
await vscode.commands.executeCommand('notebook.cell.execute', { start: 0, end: 1 }, resource);
|
await vscode.commands.executeCommand('notebook.cell.execute', { start: 0, end: 1 }, resource);
|
||||||
await event;
|
await event;
|
||||||
assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked
|
assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked
|
||||||
assert.strictEqual(vscode.window.activeNotebookEditor?.document.uri.fsPath, secondResource.fsPath);
|
assert.strictEqual(vscode.window.activeNotebookEditor?.notebook.uri.fsPath, secondResource.fsPath);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -524,7 +524,7 @@ const apiTestContentProvider: vscode.NotebookContentProvider = {
|
||||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||||
assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
|
assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
|
||||||
const editor = vscode.window.activeNotebookEditor!;
|
const editor = vscode.window.activeNotebookEditor!;
|
||||||
const cell = editor.document.cellAt(0);
|
const cell = editor.notebook.cellAt(0);
|
||||||
|
|
||||||
await withEvent<vscode.NotebookDocumentChangeEvent>(vscode.workspace.onDidChangeNotebookDocument, async (event) => {
|
await withEvent<vscode.NotebookDocumentChangeEvent>(vscode.workspace.onDidChangeNotebookDocument, async (event) => {
|
||||||
await vscode.commands.executeCommand('notebook.execute');
|
await vscode.commands.executeCommand('notebook.execute');
|
||||||
|
@ -544,7 +544,7 @@ const apiTestContentProvider: vscode.NotebookContentProvider = {
|
||||||
await vscode.commands.executeCommand('notebook.execute', resource);
|
await vscode.commands.executeCommand('notebook.execute', resource);
|
||||||
await event;
|
await event;
|
||||||
assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked
|
assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked
|
||||||
assert.strictEqual(vscode.window.activeNotebookEditor?.document.uri.fsPath, secondResource.fsPath);
|
assert.strictEqual(vscode.window.activeNotebookEditor?.notebook.uri.fsPath, secondResource.fsPath);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -553,7 +553,7 @@ const apiTestContentProvider: vscode.NotebookContentProvider = {
|
||||||
const editor = await vscode.window.showNotebookDocument(notebook);
|
const editor = await vscode.window.showNotebookDocument(notebook);
|
||||||
assert.strictEqual(vscode.window.activeNotebookEditor === editor, true, 'notebook first');
|
assert.strictEqual(vscode.window.activeNotebookEditor === editor, true, 'notebook first');
|
||||||
|
|
||||||
const cell = editor.document.cellAt(0);
|
const cell = editor.notebook.cellAt(0);
|
||||||
|
|
||||||
const alternativeKernel = new class extends Kernel {
|
const alternativeKernel = new class extends Kernel {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -597,7 +597,7 @@ const apiTestContentProvider: vscode.NotebookContentProvider = {
|
||||||
const resource = await createRandomNotebookFile();
|
const resource = await createRandomNotebookFile();
|
||||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||||
const editor = vscode.window.activeNotebookEditor!;
|
const editor = vscode.window.activeNotebookEditor!;
|
||||||
const cell = editor.document.cellAt(0);
|
const cell = editor.notebook.cellAt(0);
|
||||||
|
|
||||||
vscode.commands.executeCommand('notebook.cell.execute');
|
vscode.commands.executeCommand('notebook.cell.execute');
|
||||||
let eventCount = 0;
|
let eventCount = 0;
|
||||||
|
@ -636,8 +636,8 @@ const apiTestContentProvider: vscode.NotebookContentProvider = {
|
||||||
const activeCell = getFocusedCell(editor);
|
const activeCell = getFocusedCell(editor);
|
||||||
assert.notStrictEqual(getFocusedCell(editor), undefined);
|
assert.notStrictEqual(getFocusedCell(editor), undefined);
|
||||||
assert.strictEqual(activeCell!.document.getText(), '');
|
assert.strictEqual(activeCell!.document.getText(), '');
|
||||||
assert.strictEqual(editor.document.cellCount, 4);
|
assert.strictEqual(editor.notebook.cellCount, 4);
|
||||||
assert.strictEqual(editor.document.getCells().indexOf(activeCell!), 1);
|
assert.strictEqual(editor.notebook.getCells().indexOf(activeCell!), 1);
|
||||||
|
|
||||||
await withEvent(vscode.workspace.onDidChangeTextDocument, async event => {
|
await withEvent(vscode.workspace.onDidChangeTextDocument, async event => {
|
||||||
const edit = new vscode.WorkspaceEdit();
|
const edit = new vscode.WorkspaceEdit();
|
||||||
|
@ -645,7 +645,7 @@ const apiTestContentProvider: vscode.NotebookContentProvider = {
|
||||||
await vscode.workspace.applyEdit(edit);
|
await vscode.workspace.applyEdit(edit);
|
||||||
await event;
|
await event;
|
||||||
assert.strictEqual(vscode.window.activeNotebookEditor === editor, true);
|
assert.strictEqual(vscode.window.activeNotebookEditor === editor, true);
|
||||||
assert.deepStrictEqual(editor.document.cellAt(1), getFocusedCell(editor));
|
assert.deepStrictEqual(editor.notebook.cellAt(1), getFocusedCell(editor));
|
||||||
assert.strictEqual(getFocusedCell(editor)?.document.getText(), 'var abc = 0;');
|
assert.strictEqual(getFocusedCell(editor)?.document.getText(), 'var abc = 0;');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -667,8 +667,8 @@ const apiTestContentProvider: vscode.NotebookContentProvider = {
|
||||||
|
|
||||||
// make sure that the previous dirty editor is still restored in the extension host and no data loss
|
// make sure that the previous dirty editor is still restored in the extension host and no data loss
|
||||||
assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true);
|
assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true);
|
||||||
assert.deepStrictEqual(vscode.window.activeNotebookEditor?.document.cellAt(1), getFocusedCell(vscode.window.activeNotebookEditor));
|
assert.deepStrictEqual(vscode.window.activeNotebookEditor?.notebook.cellAt(1), getFocusedCell(vscode.window.activeNotebookEditor));
|
||||||
assert.deepStrictEqual(vscode.window.activeNotebookEditor?.document.cellCount, 4);
|
assert.deepStrictEqual(vscode.window.activeNotebookEditor?.notebook.cellCount, 4);
|
||||||
assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.getText(), 'var abc = 0;');
|
assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.getText(), 'var abc = 0;');
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -692,15 +692,15 @@ const apiTestContentProvider: vscode.NotebookContentProvider = {
|
||||||
// switch to the first editor
|
// switch to the first editor
|
||||||
await vscode.window.showNotebookDocument(notebook);
|
await vscode.window.showNotebookDocument(notebook);
|
||||||
assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true);
|
assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true);
|
||||||
assert.deepStrictEqual(vscode.window.activeNotebookEditor?.document.cellAt(1), getFocusedCell(vscode.window.activeNotebookEditor));
|
assert.deepStrictEqual(vscode.window.activeNotebookEditor?.notebook.cellAt(1), getFocusedCell(vscode.window.activeNotebookEditor));
|
||||||
assert.deepStrictEqual(vscode.window.activeNotebookEditor?.document.cellCount, 4);
|
assert.deepStrictEqual(vscode.window.activeNotebookEditor?.notebook.cellCount, 4);
|
||||||
assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.getText(), 'var abc = 0;');
|
assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.getText(), 'var abc = 0;');
|
||||||
|
|
||||||
// switch to the second editor
|
// switch to the second editor
|
||||||
await vscode.window.showNotebookDocument(secondNotebook);
|
await vscode.window.showNotebookDocument(secondNotebook);
|
||||||
assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true);
|
assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true);
|
||||||
assert.deepStrictEqual(vscode.window.activeNotebookEditor?.document.cellAt(1), getFocusedCell(vscode.window.activeNotebookEditor));
|
assert.deepStrictEqual(vscode.window.activeNotebookEditor?.notebook.cellAt(1), getFocusedCell(vscode.window.activeNotebookEditor));
|
||||||
assert.deepStrictEqual(vscode.window.activeNotebookEditor?.document.cellCount, 3);
|
assert.deepStrictEqual(vscode.window.activeNotebookEditor?.notebook.cellCount, 3);
|
||||||
assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.getText(), '');
|
assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.getText(), '');
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -721,7 +721,7 @@ const apiTestContentProvider: vscode.NotebookContentProvider = {
|
||||||
assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor!)?.document.languageId, 'typescript');
|
assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor!)?.document.languageId, 'typescript');
|
||||||
|
|
||||||
assert.notStrictEqual(firstNotebookEditor, secondNotebookEditor);
|
assert.notStrictEqual(firstNotebookEditor, secondNotebookEditor);
|
||||||
assert.strictEqual(firstNotebookEditor?.document, secondNotebookEditor?.document, 'split notebook editors share the same document');
|
assert.strictEqual(firstNotebookEditor?.notebook, secondNotebookEditor?.notebook, 'split notebook editors share the same document');
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -737,7 +737,7 @@ const apiTestContentProvider: vscode.NotebookContentProvider = {
|
||||||
// await vscode.commands.executeCommand('vscode.open', cell.document.uri, vscode.ViewColumn.Active);
|
// await vscode.commands.executeCommand('vscode.open', cell.document.uri, vscode.ViewColumn.Active);
|
||||||
|
|
||||||
assert.strictEqual(!!vscode.window.activeNotebookEditor, true);
|
assert.strictEqual(!!vscode.window.activeNotebookEditor, true);
|
||||||
assert.strictEqual(vscode.window.activeNotebookEditor!.document.uri.toString(), document.uri.toString());
|
assert.strictEqual(vscode.window.activeNotebookEditor!.notebook.uri.toString(), document.uri.toString());
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Cannot open notebook from cell-uri with vscode.open-command', async function () {
|
test('Cannot open notebook from cell-uri with vscode.open-command', async function () {
|
||||||
|
@ -752,7 +752,7 @@ const apiTestContentProvider: vscode.NotebookContentProvider = {
|
||||||
// removes the fragment if it matches something numeric. For notebooks that's not wanted...
|
// removes the fragment if it matches something numeric. For notebooks that's not wanted...
|
||||||
await vscode.commands.executeCommand('vscode.open', cell.document.uri);
|
await vscode.commands.executeCommand('vscode.open', cell.document.uri);
|
||||||
|
|
||||||
assert.strictEqual(vscode.window.activeNotebookEditor!.document.uri.toString(), document.uri.toString());
|
assert.strictEqual(vscode.window.activeNotebookEditor!.notebook.uri.toString(), document.uri.toString());
|
||||||
});
|
});
|
||||||
|
|
||||||
test('#97830, #97764. Support switch to other editor types', async function () {
|
test('#97830, #97764. Support switch to other editor types', async function () {
|
||||||
|
@ -805,15 +805,15 @@ const apiTestContentProvider: vscode.NotebookContentProvider = {
|
||||||
await vscode.commands.executeCommand('notebook.cell.copyDown');
|
await vscode.commands.executeCommand('notebook.cell.copyDown');
|
||||||
await vscode.commands.executeCommand('notebook.cell.edit');
|
await vscode.commands.executeCommand('notebook.cell.edit');
|
||||||
activeCell = getFocusedCell(vscode.window.activeNotebookEditor);
|
activeCell = getFocusedCell(vscode.window.activeNotebookEditor);
|
||||||
assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(activeCell!), 1);
|
assert.strictEqual(vscode.window.activeNotebookEditor!.notebook.getCells().indexOf(activeCell!), 1);
|
||||||
assert.strictEqual(activeCell?.document.getText(), 'test');
|
assert.strictEqual(activeCell?.document.getText(), 'test');
|
||||||
|
|
||||||
const edit = new vscode.WorkspaceEdit();
|
const edit = new vscode.WorkspaceEdit();
|
||||||
edit.insert(getFocusedCell(vscode.window.activeNotebookEditor)!.document.uri, new vscode.Position(0, 0), 'var abc = 0;');
|
edit.insert(getFocusedCell(vscode.window.activeNotebookEditor)!.document.uri, new vscode.Position(0, 0), 'var abc = 0;');
|
||||||
await vscode.workspace.applyEdit(edit);
|
await vscode.workspace.applyEdit(edit);
|
||||||
|
|
||||||
assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().length, 3);
|
assert.strictEqual(vscode.window.activeNotebookEditor!.notebook.getCells().length, 3);
|
||||||
assert.notStrictEqual(vscode.window.activeNotebookEditor!.document.cellAt(0).document.getText(), vscode.window.activeNotebookEditor!.document.cellAt(1).document.getText());
|
assert.notStrictEqual(vscode.window.activeNotebookEditor!.notebook.cellAt(0).document.getText(), vscode.window.activeNotebookEditor!.notebook.cellAt(1).document.getText());
|
||||||
|
|
||||||
await closeAllEditors();
|
await closeAllEditors();
|
||||||
});
|
});
|
||||||
|
@ -876,7 +876,7 @@ const apiTestContentProvider: vscode.NotebookContentProvider = {
|
||||||
const resource = await createRandomNotebookFile();
|
const resource = await createRandomNotebookFile();
|
||||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||||
const editor = vscode.window.activeNotebookEditor!;
|
const editor = vscode.window.activeNotebookEditor!;
|
||||||
const cell = editor.document.cellAt(0);
|
const cell = editor.notebook.cellAt(0);
|
||||||
|
|
||||||
assert.strictEqual(cell.executionSummary?.success, undefined);
|
assert.strictEqual(cell.executionSummary?.success, undefined);
|
||||||
assert.strictEqual(cell.executionSummary?.executionOrder, undefined);
|
assert.strictEqual(cell.executionSummary?.executionOrder, undefined);
|
||||||
|
@ -999,7 +999,7 @@ const apiTestContentProvider: vscode.NotebookContentProvider = {
|
||||||
const notebook = await openRandomNotebookDocument();
|
const notebook = await openRandomNotebookDocument();
|
||||||
const editor = await vscode.window.showNotebookDocument(notebook);
|
const editor = await vscode.window.showNotebookDocument(notebook);
|
||||||
|
|
||||||
assert.strictEqual(editor.document.metadata.custom?.testMetadata, false);
|
assert.strictEqual(editor.notebook.metadata.custom?.testMetadata, false);
|
||||||
assert.strictEqual(getFocusedCell(editor)?.metadata.custom?.testCellMetadata, 123);
|
assert.strictEqual(getFocusedCell(editor)?.metadata.custom?.testCellMetadata, 123);
|
||||||
assert.strictEqual(getFocusedCell(editor)?.document.languageId, 'typescript');
|
assert.strictEqual(getFocusedCell(editor)?.document.languageId, 'typescript');
|
||||||
});
|
});
|
||||||
|
|
|
@ -200,7 +200,7 @@
|
||||||
"style-loader": "^1.0.0",
|
"style-loader": "^1.0.0",
|
||||||
"ts-loader": "^9.2.7",
|
"ts-loader": "^9.2.7",
|
||||||
"tsec": "0.1.4",
|
"tsec": "0.1.4",
|
||||||
"typescript": "^4.8.0-dev.20220518",
|
"typescript": "^4.8.0-dev.20220608",
|
||||||
"typescript-formatter": "7.1.0",
|
"typescript-formatter": "7.1.0",
|
||||||
"underscore": "^1.12.1",
|
"underscore": "^1.12.1",
|
||||||
"util": "^0.12.4",
|
"util": "^0.12.4",
|
||||||
|
|
|
@ -724,10 +724,21 @@ export interface CodeActionProvider {
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
export interface DocumentPasteEditProvider {
|
export interface DocumentPasteEdit {
|
||||||
prepareDocumentPaste?(model: model.ITextModel, selection: Selection, dataTransfer: VSDataTransfer, token: CancellationToken): Promise<undefined | VSDataTransfer>;
|
insertText: string | { snippet: string };
|
||||||
|
additionalEdit?: WorkspaceEdit;
|
||||||
|
}
|
||||||
|
|
||||||
provideDocumentPasteEdits(model: model.ITextModel, selection: Selection, dataTransfer: VSDataTransfer, token: CancellationToken): Promise<WorkspaceEdit | SnippetTextEdit | undefined>;
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export interface DocumentPasteEditProvider {
|
||||||
|
|
||||||
|
readonly pasteMimeTypes: readonly string[];
|
||||||
|
|
||||||
|
prepareDocumentPaste?(model: model.ITextModel, selections: readonly Selection[], dataTransfer: VSDataTransfer, token: CancellationToken): Promise<undefined | VSDataTransfer>;
|
||||||
|
|
||||||
|
provideDocumentPasteEdits(model: model.ITextModel, selections: readonly Selection[], dataTransfer: VSDataTransfer, token: CancellationToken): Promise<DocumentPasteEdit | undefined>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1123,11 +1134,6 @@ export interface DocumentSymbolProvider {
|
||||||
|
|
||||||
export type TextEdit = { range: IRange; text: string; eol?: model.EndOfLineSequence };
|
export type TextEdit = { range: IRange; text: string; eol?: model.EndOfLineSequence };
|
||||||
|
|
||||||
export interface SnippetTextEdit {
|
|
||||||
range: IRange;
|
|
||||||
snippet: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface used to format a model
|
* Interface used to format a model
|
||||||
*/
|
*/
|
||||||
|
@ -1800,10 +1806,17 @@ export enum ExternalUriOpenerPriority {
|
||||||
Preferred = 3,
|
Preferred = 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export interface DocumentOnDropEdit {
|
||||||
|
insertText: string | { snippet: string };
|
||||||
|
additionalEdit?: WorkspaceEdit;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
export interface DocumentOnDropEditProvider {
|
export interface DocumentOnDropEditProvider {
|
||||||
provideDocumentOnDropEdits(model: model.ITextModel, position: IPosition, dataTransfer: VSDataTransfer, token: CancellationToken): ProviderResult<SnippetTextEdit>;
|
provideDocumentOnDropEdits(model: model.ITextModel, position: IPosition, dataTransfer: VSDataTransfer, token: CancellationToken): ProviderResult<DocumentOnDropEdit>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import { DataTransfers } from 'vs/base/browser/dnd';
|
||||||
import { addDisposableListener } from 'vs/base/browser/dom';
|
import { addDisposableListener } from 'vs/base/browser/dom';
|
||||||
import { CancelablePromise, createCancelablePromise } from 'vs/base/common/async';
|
import { CancelablePromise, createCancelablePromise } from 'vs/base/common/async';
|
||||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||||
|
@ -15,26 +16,26 @@ import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||||
import { IBulkEditService, ResourceEdit } from 'vs/editor/browser/services/bulkEditService';
|
import { IBulkEditService, ResourceEdit } from 'vs/editor/browser/services/bulkEditService';
|
||||||
import { Selection } from 'vs/editor/common/core/selection';
|
import { Selection } from 'vs/editor/common/core/selection';
|
||||||
import { IEditorContribution } from 'vs/editor/common/editorCommon';
|
import { IEditorContribution } from 'vs/editor/common/editorCommon';
|
||||||
import { DocumentPasteEditProvider, SnippetTextEdit, WorkspaceEdit } from 'vs/editor/common/languages';
|
import { DocumentPasteEdit, DocumentPasteEditProvider } from 'vs/editor/common/languages';
|
||||||
import { ITextModel } from 'vs/editor/common/model';
|
import { ITextModel } from 'vs/editor/common/model';
|
||||||
import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures';
|
import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures';
|
||||||
import { CodeEditorStateFlag, EditorStateCancellationTokenSource } from 'vs/editor/contrib/editorState/browser/editorState';
|
import { CodeEditorStateFlag, EditorStateCancellationTokenSource } from 'vs/editor/contrib/editorState/browser/editorState';
|
||||||
import { performSnippetEdit } from 'vs/editor/contrib/snippet/browser/snippetController2';
|
import { performSnippetEdit } from 'vs/editor/contrib/snippet/browser/snippetController2';
|
||||||
|
import { SnippetParser } from 'vs/editor/contrib/snippet/browser/snippetParser';
|
||||||
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
||||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||||
|
|
||||||
const vscodeClipboardMime = 'application/vnd.code.copyId';
|
const vscodeClipboardMime = 'application/vnd.code.copyId';
|
||||||
|
|
||||||
const defaultPasteEditProvider = new class implements DocumentPasteEditProvider {
|
const defaultPasteEditProvider = new class implements DocumentPasteEditProvider {
|
||||||
async provideDocumentPasteEdits(model: ITextModel, selection: Selection, dataTransfer: VSDataTransfer, _token: CancellationToken): Promise<WorkspaceEdit | undefined> {
|
pasteMimeTypes = [Mimes.text, 'text'];
|
||||||
|
|
||||||
|
async provideDocumentPasteEdits(model: ITextModel, selections: Selection[], dataTransfer: VSDataTransfer, _token: CancellationToken): Promise<DocumentPasteEdit | undefined> {
|
||||||
const textDataTransfer = dataTransfer.get(Mimes.text) ?? dataTransfer.get('text');
|
const textDataTransfer = dataTransfer.get(Mimes.text) ?? dataTransfer.get('text');
|
||||||
if (textDataTransfer) {
|
if (textDataTransfer) {
|
||||||
const text = await textDataTransfer.asString();
|
const text = await textDataTransfer.asString();
|
||||||
return {
|
return {
|
||||||
edits: [{
|
insertText: text
|
||||||
resource: model.uri,
|
|
||||||
edit: { range: selection, text },
|
|
||||||
}]
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,8 +77,8 @@ export class CopyPasteController extends Disposable implements IEditorContributi
|
||||||
}
|
}
|
||||||
|
|
||||||
const model = editor.getModel();
|
const model = editor.getModel();
|
||||||
const selection = this._editor.getSelection();
|
const selections = this._editor.getSelections();
|
||||||
if (!model || !selection) {
|
if (!model || !selections?.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +99,7 @@ export class CopyPasteController extends Disposable implements IEditorContributi
|
||||||
|
|
||||||
const promise = createCancelablePromise(async token => {
|
const promise = createCancelablePromise(async token => {
|
||||||
const results = await Promise.all(providers.map(provider => {
|
const results = await Promise.all(providers.map(provider => {
|
||||||
return provider.prepareDocumentPaste!(model, selection, dataTransfer, token);
|
return provider.prepareDocumentPaste!(model, selections, dataTransfer, token);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
for (const result of results) {
|
for (const result of results) {
|
||||||
|
@ -115,8 +116,8 @@ export class CopyPasteController extends Disposable implements IEditorContributi
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this._register(addDisposableListener(container, 'paste', async (e: ClipboardEvent) => {
|
this._register(addDisposableListener(container, 'paste', async (e: ClipboardEvent) => {
|
||||||
const selection = this._editor.getSelection();
|
const selections = this._editor.getSelections();
|
||||||
if (!e.clipboardData || !selection || !editor.hasModel()) {
|
if (!e.clipboardData || !selections?.length || !editor.hasModel()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,21 +126,20 @@ export class CopyPasteController extends Disposable implements IEditorContributi
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const originalDocVersion = model.getVersionId();
|
const handle = e.clipboardData?.getData(vscodeClipboardMime);
|
||||||
|
if (typeof handle !== 'string') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const providers = this._languageFeaturesService.documentPasteEditProvider.ordered(model);
|
const providers = this._languageFeaturesService.documentPasteEditProvider.ordered(model);
|
||||||
if (!providers.length) {
|
if (!providers.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const handle = e.clipboardData?.getData(vscodeClipboardMime);
|
|
||||||
if (typeof handle !== 'string') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopImmediatePropagation();
|
e.stopImmediatePropagation();
|
||||||
|
|
||||||
|
const originalDocVersion = model.getVersionId();
|
||||||
const tokenSource = new EditorStateCancellationTokenSource(editor, CodeEditorStateFlag.Value | CodeEditorStateFlag.Selection);
|
const tokenSource = new EditorStateCancellationTokenSource(editor, CodeEditorStateFlag.Value | CodeEditorStateFlag.Selection);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -148,7 +148,7 @@ export class CopyPasteController extends Disposable implements IEditorContributi
|
||||||
if (handle && this._currentClipboardItem?.handle === handle) {
|
if (handle && this._currentClipboardItem?.handle === handle) {
|
||||||
const toMergeDataTransfer = await this._currentClipboardItem.dataTransferPromise;
|
const toMergeDataTransfer = await this._currentClipboardItem.dataTransferPromise;
|
||||||
toMergeDataTransfer.forEach((value, key) => {
|
toMergeDataTransfer.forEach((value, key) => {
|
||||||
dataTransfer.append(key, value);
|
dataTransfer.replace(key, value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,16 +163,25 @@ export class CopyPasteController extends Disposable implements IEditorContributi
|
||||||
dataTransfer.delete(vscodeClipboardMime);
|
dataTransfer.delete(vscodeClipboardMime);
|
||||||
|
|
||||||
for (const provider of [...providers, defaultPasteEditProvider]) {
|
for (const provider of [...providers, defaultPasteEditProvider]) {
|
||||||
const edit = await provider.provideDocumentPasteEdits(model, selection, dataTransfer, tokenSource.token);
|
if (!provider.pasteMimeTypes.some(type => {
|
||||||
|
if (type.toLowerCase() === DataTransfers.FILES.toLowerCase()) {
|
||||||
|
return [...dataTransfer.values()].some(item => item.asFile());
|
||||||
|
}
|
||||||
|
return dataTransfer.has(type);
|
||||||
|
})) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const edit = await provider.provideDocumentPasteEdits(model, selections, dataTransfer, tokenSource.token);
|
||||||
if (originalDocVersion !== model.getVersionId()) {
|
if (originalDocVersion !== model.getVersionId()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (edit) {
|
if (edit) {
|
||||||
if ((edit as WorkspaceEdit).edits) {
|
performSnippetEdit(editor, typeof edit.insertText === 'string' ? SnippetParser.escape(edit.insertText) : edit.insertText.snippet, selections);
|
||||||
await this._bulkEditService.apply(ResourceEdit.convert(edit as WorkspaceEdit), { editor });
|
|
||||||
} else {
|
if (edit.additionalEdit) {
|
||||||
performSnippetEdit(editor, edit as SnippetTextEdit);
|
await this._bulkEditService.apply(ResourceEdit.convert(edit.additionalEdit), { editor });
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,14 +13,17 @@ import { URI } from 'vs/base/common/uri';
|
||||||
import { toVSDataTransfer } from 'vs/editor/browser/dnd';
|
import { toVSDataTransfer } from 'vs/editor/browser/dnd';
|
||||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||||
import { registerEditorContribution } from 'vs/editor/browser/editorExtensions';
|
import { registerEditorContribution } from 'vs/editor/browser/editorExtensions';
|
||||||
|
import { IBulkEditService, ResourceEdit } from 'vs/editor/browser/services/bulkEditService';
|
||||||
import { IPosition } from 'vs/editor/common/core/position';
|
import { IPosition } from 'vs/editor/common/core/position';
|
||||||
import { Range } from 'vs/editor/common/core/range';
|
import { Range } from 'vs/editor/common/core/range';
|
||||||
|
import { Selection, SelectionDirection } from 'vs/editor/common/core/selection';
|
||||||
import { IEditorContribution } from 'vs/editor/common/editorCommon';
|
import { IEditorContribution } from 'vs/editor/common/editorCommon';
|
||||||
import { DocumentOnDropEditProvider, SnippetTextEdit } from 'vs/editor/common/languages';
|
import { DocumentOnDropEdit, DocumentOnDropEditProvider } from 'vs/editor/common/languages';
|
||||||
import { ITextModel } from 'vs/editor/common/model';
|
import { ITextModel } from 'vs/editor/common/model';
|
||||||
import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures';
|
import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures';
|
||||||
import { CodeEditorStateFlag, EditorStateCancellationTokenSource } from 'vs/editor/contrib/editorState/browser/editorState';
|
import { CodeEditorStateFlag, EditorStateCancellationTokenSource } from 'vs/editor/contrib/editorState/browser/editorState';
|
||||||
import { performSnippetEdit } from 'vs/editor/contrib/snippet/browser/snippetController2';
|
import { performSnippetEdit } from 'vs/editor/contrib/snippet/browser/snippetController2';
|
||||||
|
import { SnippetParser } from 'vs/editor/contrib/snippet/browser/snippetParser';
|
||||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||||
import { extractEditorsDropData } from 'vs/platform/dnd/browser/dnd';
|
import { extractEditorsDropData } from 'vs/platform/dnd/browser/dnd';
|
||||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
|
@ -37,6 +40,7 @@ export class DropIntoEditorController extends Disposable implements IEditorContr
|
||||||
@IInstantiationService private readonly _instantiationService: IInstantiationService,
|
@IInstantiationService private readonly _instantiationService: IInstantiationService,
|
||||||
@ILanguageFeaturesService private readonly _languageFeaturesService: ILanguageFeaturesService,
|
@ILanguageFeaturesService private readonly _languageFeaturesService: ILanguageFeaturesService,
|
||||||
@IConfigurationService private readonly _configurationService: IConfigurationService,
|
@IConfigurationService private readonly _configurationService: IConfigurationService,
|
||||||
|
@IBulkEditService private readonly _bulkEditService: IBulkEditService,
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
@ -87,7 +91,12 @@ export class DropIntoEditorController extends Disposable implements IEditorContr
|
||||||
}
|
}
|
||||||
|
|
||||||
if (edit) {
|
if (edit) {
|
||||||
performSnippetEdit(editor, edit);
|
const range = new Range(position.lineNumber, position.column, position.lineNumber, position.column);
|
||||||
|
performSnippetEdit(editor, typeof edit.insertText === 'string' ? SnippetParser.escape(edit.insertText) : edit.insertText.snippet, [Selection.fromRange(range, SelectionDirection.LTR)]);
|
||||||
|
|
||||||
|
if (edit.additionalEdit) {
|
||||||
|
await this._bulkEditService.apply(ResourceEdit.convert(edit.additionalEdit), { editor });
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -121,24 +130,26 @@ class DefaultOnDropProvider implements DocumentOnDropEditProvider {
|
||||||
@IWorkspaceContextService private readonly _workspaceContextService: IWorkspaceContextService,
|
@IWorkspaceContextService private readonly _workspaceContextService: IWorkspaceContextService,
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
async provideDocumentOnDropEdits(model: ITextModel, position: IPosition, dataTransfer: VSDataTransfer, _token: CancellationToken): Promise<SnippetTextEdit | undefined> {
|
async provideDocumentOnDropEdits(_model: ITextModel, _position: IPosition, dataTransfer: VSDataTransfer, _token: CancellationToken): Promise<DocumentOnDropEdit | undefined> {
|
||||||
const range = new Range(position.lineNumber, position.column, position.lineNumber, position.column);
|
|
||||||
|
|
||||||
const urlListEntry = dataTransfer.get('text/uri-list');
|
const urlListEntry = dataTransfer.get('text/uri-list');
|
||||||
if (urlListEntry) {
|
if (urlListEntry) {
|
||||||
const urlList = await urlListEntry.asString();
|
const urlList = await urlListEntry.asString();
|
||||||
return this.doUriListDrop(range, urlList);
|
const snippet = this.getUriListInsertText(urlList);
|
||||||
|
if (snippet) {
|
||||||
|
return { insertText: snippet };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const textEntry = dataTransfer.get('text') ?? dataTransfer.get(Mimes.text);
|
const textEntry = dataTransfer.get('text') ?? dataTransfer.get(Mimes.text);
|
||||||
if (textEntry) {
|
if (textEntry) {
|
||||||
const text = await textEntry.asString();
|
const text = await textEntry.asString();
|
||||||
return { range, snippet: text };
|
return { insertText: text };
|
||||||
}
|
}
|
||||||
|
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
private doUriListDrop(range: Range, urlList: string): SnippetTextEdit | undefined {
|
private getUriListInsertText(urlList: string): string | undefined {
|
||||||
const uris: URI[] = [];
|
const uris: URI[] = [];
|
||||||
for (const resource of urlList.split('\n')) {
|
for (const resource of urlList.split('\n')) {
|
||||||
try {
|
try {
|
||||||
|
@ -152,7 +163,7 @@ class DefaultOnDropProvider implements DocumentOnDropEditProvider {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const snippet = uris
|
return uris
|
||||||
.map(uri => {
|
.map(uri => {
|
||||||
const root = this._workspaceContextService.getWorkspaceFolder(uri);
|
const root = this._workspaceContextService.getWorkspaceFolder(uri);
|
||||||
if (root) {
|
if (root) {
|
||||||
|
@ -164,8 +175,6 @@ class DefaultOnDropProvider implements DocumentOnDropEditProvider {
|
||||||
return uri.fsPath;
|
return uri.fsPath;
|
||||||
})
|
})
|
||||||
.join(' ');
|
.join(' ');
|
||||||
|
|
||||||
return { range, snippet };
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,9 +9,10 @@ import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||||
import { EditorCommand, registerEditorCommand, registerEditorContribution } from 'vs/editor/browser/editorExtensions';
|
import { EditorCommand, registerEditorCommand, registerEditorContribution } from 'vs/editor/browser/editorExtensions';
|
||||||
import { Position } from 'vs/editor/common/core/position';
|
import { Position } from 'vs/editor/common/core/position';
|
||||||
import { Range } from 'vs/editor/common/core/range';
|
import { Range } from 'vs/editor/common/core/range';
|
||||||
|
import { ISelection } from 'vs/editor/common/core/selection';
|
||||||
import { IEditorContribution } from 'vs/editor/common/editorCommon';
|
import { IEditorContribution } from 'vs/editor/common/editorCommon';
|
||||||
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
|
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
|
||||||
import { CompletionItem, CompletionItemKind, CompletionItemProvider, SnippetTextEdit } from 'vs/editor/common/languages';
|
import { CompletionItem, CompletionItemKind, CompletionItemProvider } from 'vs/editor/common/languages';
|
||||||
import { ILanguageConfigurationService } from 'vs/editor/common/languages/languageConfigurationRegistry';
|
import { ILanguageConfigurationService } from 'vs/editor/common/languages/languageConfigurationRegistry';
|
||||||
import { ITextModel } from 'vs/editor/common/model';
|
import { ITextModel } from 'vs/editor/common/model';
|
||||||
import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures';
|
import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures';
|
||||||
|
@ -335,13 +336,13 @@ registerEditorCommand(new CommandCtor({
|
||||||
|
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
export function performSnippetEdit(editor: ICodeEditor, edit: SnippetTextEdit) {
|
export function performSnippetEdit(editor: ICodeEditor, snippet: string, selections: ISelection[]): boolean {
|
||||||
const controller = SnippetController2.get(editor);
|
const controller = SnippetController2.get(editor);
|
||||||
if (!controller) {
|
if (!controller) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
editor.focus();
|
editor.focus();
|
||||||
editor.setSelection(edit.range);
|
editor.setSelections(selections ?? []);
|
||||||
controller.insert(edit.snippet);
|
controller.insert(snippet);
|
||||||
return controller.isInSnippet();
|
return controller.isInSnippet();
|
||||||
}
|
}
|
||||||
|
|
5
src/vs/monaco.d.ts
vendored
5
src/vs/monaco.d.ts
vendored
|
@ -6758,11 +6758,6 @@ declare namespace monaco.languages {
|
||||||
eol?: editor.EndOfLineSequence;
|
eol?: editor.EndOfLineSequence;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface SnippetTextEdit {
|
|
||||||
range: IRange;
|
|
||||||
snippet: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface used to format a model
|
* Interface used to format a model
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -9,7 +9,7 @@ import { RemoteAuthorities } from 'vs/base/common/network';
|
||||||
import { URI } from 'vs/base/common/uri';
|
import { URI } from 'vs/base/common/uri';
|
||||||
import { IProductService } from 'vs/platform/product/common/productService';
|
import { IProductService } from 'vs/platform/product/common/productService';
|
||||||
import { IRemoteAuthorityResolverService, IRemoteConnectionData, ResolvedAuthority, ResolverResult } from 'vs/platform/remote/common/remoteAuthorityResolver';
|
import { IRemoteAuthorityResolverService, IRemoteConnectionData, ResolvedAuthority, ResolverResult } from 'vs/platform/remote/common/remoteAuthorityResolver';
|
||||||
import { getRemoteServerRootPath } from 'vs/platform/remote/common/remoteHosts';
|
import { getRemoteServerRootPath, parseAuthorityWithOptionalPort } from 'vs/platform/remote/common/remoteHosts';
|
||||||
|
|
||||||
export class RemoteAuthorityResolverService extends Disposable implements IRemoteAuthorityResolverService {
|
export class RemoteAuthorityResolverService extends Disposable implements IRemoteAuthorityResolverService {
|
||||||
|
|
||||||
|
@ -62,12 +62,9 @@ export class RemoteAuthorityResolverService extends Disposable implements IRemot
|
||||||
|
|
||||||
private _doResolveAuthority(authority: string): ResolverResult {
|
private _doResolveAuthority(authority: string): ResolverResult {
|
||||||
const connectionToken = this._connectionTokens.get(authority) || this._connectionToken;
|
const connectionToken = this._connectionTokens.get(authority) || this._connectionToken;
|
||||||
if (authority.indexOf(':') >= 0) {
|
const defaultPort = (/^https:/.test(window.location.href) ? 443 : 80);
|
||||||
const pieces = authority.split(':');
|
const { host, port } = parseAuthorityWithOptionalPort(authority, defaultPort);
|
||||||
return { authority: { authority, host: pieces[0], port: parseInt(pieces[1], 10), connectionToken } };
|
return { authority: { authority, host: host, port: port, connectionToken } };
|
||||||
}
|
|
||||||
const port = (/^https:/.test(window.location.href) ? 443 : 80);
|
|
||||||
return { authority: { authority, host: authority, port: port, connectionToken } };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_clearResolvedAuthority(authority: string): void {
|
_clearResolvedAuthority(authority: string): void {
|
||||||
|
|
|
@ -33,3 +33,46 @@ export function getRemoteName(authority: string | undefined): string | undefined
|
||||||
export function getRemoteServerRootPath(product: { quality?: string; commit?: string }): string {
|
export function getRemoteServerRootPath(product: { quality?: string; commit?: string }): string {
|
||||||
return `/${product.quality ?? 'oss'}-${product.commit ?? 'dev'}`;
|
return `/${product.quality ?? 'oss'}-${product.commit ?? 'dev'}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function parseAuthorityWithPort(authority: string): { host: string; port: number } {
|
||||||
|
const { host, port } = parseAuthority(authority);
|
||||||
|
if (typeof port === 'undefined') {
|
||||||
|
throw new Error(`Remote authority doesn't contain a port!`);
|
||||||
|
}
|
||||||
|
return { host, port };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function parseAuthorityWithOptionalPort(authority: string, defaultPort: number): { host: string; port: number } {
|
||||||
|
let { host, port } = parseAuthority(authority);
|
||||||
|
if (typeof port === 'undefined') {
|
||||||
|
port = defaultPort;
|
||||||
|
}
|
||||||
|
return { host, port };
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseAuthority(authority: string): { host: string; port: number | undefined } {
|
||||||
|
if (authority.indexOf('+') >= 0) {
|
||||||
|
throw new Error(`Remote authorities containing '+' need to be resolved!`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for ipv6 with port
|
||||||
|
const m1 = authority.match(/^(\[[0-9a-z:]+\]):(\d+)$/);
|
||||||
|
if (m1) {
|
||||||
|
return { host: m1[1], port: parseInt(m1[2], 10) };
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for ipv6 without port
|
||||||
|
const m2 = authority.match(/^(\[[0-9a-z:]+\])$/);
|
||||||
|
if (m2) {
|
||||||
|
return { host: m2[1], port: undefined };
|
||||||
|
}
|
||||||
|
|
||||||
|
// anything with a trailing port
|
||||||
|
const m3 = authority.match(/(.*):(\d+)$/);
|
||||||
|
if (m3) {
|
||||||
|
return { host: m3[1], port: parseInt(m3[2], 10) };
|
||||||
|
}
|
||||||
|
|
||||||
|
// doesn't contain a port
|
||||||
|
return { host: authority, port: undefined };
|
||||||
|
}
|
||||||
|
|
38
src/vs/platform/remote/test/common/remoteHosts.test.ts
Normal file
38
src/vs/platform/remote/test/common/remoteHosts.test.ts
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import * as assert from 'assert';
|
||||||
|
import { parseAuthorityWithOptionalPort, parseAuthorityWithPort } from 'vs/platform/remote/common/remoteHosts';
|
||||||
|
|
||||||
|
suite('remoteHosts', () => {
|
||||||
|
|
||||||
|
test('parseAuthority hostname', () => {
|
||||||
|
assert.deepStrictEqual(parseAuthorityWithPort('localhost:8080'), { host: 'localhost', port: 8080 });
|
||||||
|
});
|
||||||
|
|
||||||
|
test('parseAuthority ipv4', () => {
|
||||||
|
assert.deepStrictEqual(parseAuthorityWithPort('127.0.0.1:8080'), { host: '127.0.0.1', port: 8080 });
|
||||||
|
});
|
||||||
|
|
||||||
|
test('parseAuthority ipv6', () => {
|
||||||
|
assert.deepStrictEqual(parseAuthorityWithPort('[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:8080'), { host: '[2001:0db8:85a3:0000:0000:8a2e:0370:7334]', port: 8080 });
|
||||||
|
});
|
||||||
|
|
||||||
|
test('parseAuthorityWithOptionalPort hostname', () => {
|
||||||
|
assert.deepStrictEqual(parseAuthorityWithOptionalPort('localhost:8080', 123), { host: 'localhost', port: 8080 });
|
||||||
|
assert.deepStrictEqual(parseAuthorityWithOptionalPort('localhost', 123), { host: 'localhost', port: 123 });
|
||||||
|
});
|
||||||
|
|
||||||
|
test('parseAuthorityWithOptionalPort ipv4', () => {
|
||||||
|
assert.deepStrictEqual(parseAuthorityWithOptionalPort('127.0.0.1:8080', 123), { host: '127.0.0.1', port: 8080 });
|
||||||
|
assert.deepStrictEqual(parseAuthorityWithOptionalPort('127.0.0.1', 123), { host: '127.0.0.1', port: 123 });
|
||||||
|
});
|
||||||
|
|
||||||
|
test('parseAuthorityWithOptionalPort ipv6', () => {
|
||||||
|
assert.deepStrictEqual(parseAuthorityWithOptionalPort('[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:8080', 123), { host: '[2001:0db8:85a3:0000:0000:8a2e:0370:7334]', port: 8080 });
|
||||||
|
assert.deepStrictEqual(parseAuthorityWithOptionalPort('[2001:0db8:85a3:0000:0000:8a2e:0370:7334]', 123), { host: '[2001:0db8:85a3:0000:0000:8a2e:0370:7334]', port: 123 });
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
|
@ -30,7 +30,7 @@ import * as callh from 'vs/workbench/contrib/callHierarchy/common/callHierarchy'
|
||||||
import * as search from 'vs/workbench/contrib/search/common/search';
|
import * as search from 'vs/workbench/contrib/search/common/search';
|
||||||
import * as typeh from 'vs/workbench/contrib/typeHierarchy/common/typeHierarchy';
|
import * as typeh from 'vs/workbench/contrib/typeHierarchy/common/typeHierarchy';
|
||||||
import { extHostNamedCustomer, IExtHostContext } from 'vs/workbench/services/extensions/common/extHostCustomers';
|
import { extHostNamedCustomer, IExtHostContext } from 'vs/workbench/services/extensions/common/extHostCustomers';
|
||||||
import { ExtHostContext, ExtHostLanguageFeaturesShape, ICallHierarchyItemDto, ICodeActionDto, ICodeActionProviderMetadataDto, IdentifiableInlineCompletion, IdentifiableInlineCompletions, IDocumentFilterDto, IIndentationRuleDto, IInlayHintDto, ILanguageConfigurationDto, ILanguageWordDefinitionDto, ILinkDto, ILocationDto, ILocationLinkDto, IOnEnterRuleDto, IRegExpDto, ISignatureHelpProviderMetadataDto, ISuggestDataDto, ISuggestDataDtoField, ISuggestResultDtoField, ITypeHierarchyItemDto, IWorkspaceEditDto, IWorkspaceSymbolDto, MainContext, MainThreadLanguageFeaturesShape, reviveWorkspaceEditDto } from '../common/extHost.protocol';
|
import { ExtHostContext, ExtHostLanguageFeaturesShape, ICallHierarchyItemDto, ICodeActionDto, ICodeActionProviderMetadataDto, IdentifiableInlineCompletion, IdentifiableInlineCompletions, IDocumentFilterDto, IIndentationRuleDto, IInlayHintDto, ILanguageConfigurationDto, ILanguageWordDefinitionDto, ILinkDto, ILocationDto, ILocationLinkDto, IOnEnterRuleDto, IRegExpDto, ISignatureHelpProviderMetadataDto, ISuggestDataDto, ISuggestDataDtoField, ISuggestResultDtoField, ITypeHierarchyItemDto, IWorkspaceSymbolDto, MainContext, MainThreadLanguageFeaturesShape, reviveWorkspaceEditDto } from '../common/extHost.protocol';
|
||||||
|
|
||||||
@extHostNamedCustomer(MainContext.MainThreadLanguageFeatures)
|
@extHostNamedCustomer(MainContext.MainThreadLanguageFeatures)
|
||||||
export class MainThreadLanguageFeatures extends Disposable implements MainThreadLanguageFeaturesShape {
|
export class MainThreadLanguageFeatures extends Disposable implements MainThreadLanguageFeaturesShape {
|
||||||
|
@ -368,21 +368,22 @@ export class MainThreadLanguageFeatures extends Disposable implements MainThread
|
||||||
|
|
||||||
// --- copy paste action provider
|
// --- copy paste action provider
|
||||||
|
|
||||||
$registerPasteEditProvider(handle: number, selector: IDocumentFilterDto[], supportsCopy: boolean): void {
|
$registerPasteEditProvider(handle: number, selector: IDocumentFilterDto[], supportsCopy: boolean, pasteMimeTypes: readonly string[]): void {
|
||||||
const provider: languages.DocumentPasteEditProvider = {
|
const provider: languages.DocumentPasteEditProvider = {
|
||||||
|
pasteMimeTypes: pasteMimeTypes,
|
||||||
|
|
||||||
prepareDocumentPaste: supportsCopy
|
prepareDocumentPaste: supportsCopy
|
||||||
? async (model: ITextModel, selection: Selection, dataTransfer: VSDataTransfer, token: CancellationToken): Promise<VSDataTransfer | undefined> => {
|
? async (model: ITextModel, selections: Selection[], dataTransfer: VSDataTransfer, token: CancellationToken): Promise<VSDataTransfer | undefined> => {
|
||||||
const dataTransferDto = await typeConvert.DataTransfer.toDataTransferDTO(dataTransfer);
|
const dataTransferDto = await typeConvert.DataTransfer.toDataTransferDTO(dataTransfer);
|
||||||
if (token.isCancellationRequested) {
|
if (token.isCancellationRequested) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await this._proxy.$prepareDocumentPaste(handle, model.uri, selection, dataTransferDto, token);
|
const result = await this._proxy.$prepareDocumentPaste(handle, model.uri, selections, dataTransferDto, token);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const dataTransferOut = new VSDataTransfer();
|
const dataTransferOut = new VSDataTransfer();
|
||||||
result.items.forEach(([type, item]) => {
|
result.items.forEach(([type, item]) => {
|
||||||
dataTransferOut.replace(type, createStringDataTransferItem(item.asString));
|
dataTransferOut.replace(type, createStringDataTransferItem(item.asString));
|
||||||
|
@ -391,16 +392,17 @@ export class MainThreadLanguageFeatures extends Disposable implements MainThread
|
||||||
}
|
}
|
||||||
: undefined,
|
: undefined,
|
||||||
|
|
||||||
provideDocumentPasteEdits: async (model: ITextModel, selection: Selection, dataTransfer: VSDataTransfer, token: CancellationToken) => {
|
provideDocumentPasteEdits: async (model: ITextModel, selections: Selection[], dataTransfer: VSDataTransfer, token: CancellationToken) => {
|
||||||
const d = await typeConvert.DataTransfer.toDataTransferDTO(dataTransfer);
|
const d = await typeConvert.DataTransfer.toDataTransferDTO(dataTransfer);
|
||||||
const result = await this._proxy.$providePasteEdits(handle, model.uri, selection, d, token);
|
const result = await this._proxy.$providePasteEdits(handle, model.uri, selections, d, token);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
return;
|
return undefined;
|
||||||
} else if ((result as IWorkspaceEditDto).edits) {
|
|
||||||
return reviveWorkspaceEditDto(result as IWorkspaceEditDto);
|
|
||||||
} else {
|
|
||||||
return result as languages.SnippetTextEdit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
insertText: result.insertText,
|
||||||
|
additionalEdit: result.additionalEdit ? reviveWorkspaceEditDto(result.additionalEdit) : undefined,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -933,11 +935,18 @@ class MainThreadDocumentOnDropEditProvider implements languages.DocumentOnDropEd
|
||||||
private readonly _proxy: ExtHostLanguageFeaturesShape,
|
private readonly _proxy: ExtHostLanguageFeaturesShape,
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
async provideDocumentOnDropEdits(model: ITextModel, position: IPosition, dataTransfer: VSDataTransfer, token: CancellationToken): Promise<languages.SnippetTextEdit | null | undefined> {
|
async provideDocumentOnDropEdits(model: ITextModel, position: IPosition, dataTransfer: VSDataTransfer, token: CancellationToken): Promise<languages.DocumentOnDropEdit | null | undefined> {
|
||||||
const request = this.dataTransfers.add(dataTransfer);
|
const request = this.dataTransfers.add(dataTransfer);
|
||||||
try {
|
try {
|
||||||
const dataTransferDto = await typeConvert.DataTransfer.toDataTransferDTO(dataTransfer);
|
const dataTransferDto = await typeConvert.DataTransfer.toDataTransferDTO(dataTransfer);
|
||||||
return await this._proxy.$provideDocumentOnDropEdits(this.handle, request.id, model.uri, position, dataTransferDto, token);
|
const edit = await this._proxy.$provideDocumentOnDropEdits(this.handle, request.id, model.uri, position, dataTransferDto, token);
|
||||||
|
if (!edit) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
insertText: edit.insertText,
|
||||||
|
additionalEdit: reviveWorkspaceEditDto(edit.additionalEdit),
|
||||||
|
};
|
||||||
} finally {
|
} finally {
|
||||||
request.dispose();
|
request.dispose();
|
||||||
}
|
}
|
||||||
|
|
|
@ -457,9 +457,9 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||||
registerCodeActionsProvider(selector: vscode.DocumentSelector, provider: vscode.CodeActionProvider, metadata?: vscode.CodeActionProviderMetadata): vscode.Disposable {
|
registerCodeActionsProvider(selector: vscode.DocumentSelector, provider: vscode.CodeActionProvider, metadata?: vscode.CodeActionProviderMetadata): vscode.Disposable {
|
||||||
return extHostLanguageFeatures.registerCodeActionProvider(extension, checkSelector(selector), provider, metadata);
|
return extHostLanguageFeatures.registerCodeActionProvider(extension, checkSelector(selector), provider, metadata);
|
||||||
},
|
},
|
||||||
registerDocumentPasteEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentPasteEditProvider): vscode.Disposable {
|
registerDocumentPasteEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentPasteEditProvider, metadata: vscode.DocumentPasteProviderMetadata): vscode.Disposable {
|
||||||
checkProposedApiEnabled(extension, 'documentPaste');
|
checkProposedApiEnabled(extension, 'documentPaste');
|
||||||
return extHostLanguageFeatures.registerDocumentPasteEditProvider(extension, checkSelector(selector), provider);
|
return extHostLanguageFeatures.registerDocumentPasteEditProvider(extension, checkSelector(selector), provider, metadata);
|
||||||
},
|
},
|
||||||
registerCodeLensProvider(selector: vscode.DocumentSelector, provider: vscode.CodeLensProvider): vscode.Disposable {
|
registerCodeLensProvider(selector: vscode.DocumentSelector, provider: vscode.CodeLensProvider): vscode.Disposable {
|
||||||
return extHostLanguageFeatures.registerCodeLensProvider(extension, checkSelector(selector), provider);
|
return extHostLanguageFeatures.registerCodeLensProvider(extension, checkSelector(selector), provider);
|
||||||
|
@ -1267,7 +1267,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||||
SignatureHelpTriggerKind: extHostTypes.SignatureHelpTriggerKind,
|
SignatureHelpTriggerKind: extHostTypes.SignatureHelpTriggerKind,
|
||||||
SignatureInformation: extHostTypes.SignatureInformation,
|
SignatureInformation: extHostTypes.SignatureInformation,
|
||||||
SnippetString: extHostTypes.SnippetString,
|
SnippetString: extHostTypes.SnippetString,
|
||||||
SnippetTextEdit: extHostTypes.SnippetTextEdit,
|
|
||||||
SourceBreakpoint: extHostTypes.SourceBreakpoint,
|
SourceBreakpoint: extHostTypes.SourceBreakpoint,
|
||||||
StandardTokenType: extHostTypes.StandardTokenType,
|
StandardTokenType: extHostTypes.StandardTokenType,
|
||||||
StatusBarAlignment: extHostTypes.StatusBarAlignment,
|
StatusBarAlignment: extHostTypes.StatusBarAlignment,
|
||||||
|
|
|
@ -372,7 +372,7 @@ export interface MainThreadLanguageFeaturesShape extends IDisposable {
|
||||||
$registerLinkedEditingRangeProvider(handle: number, selector: IDocumentFilterDto[]): void;
|
$registerLinkedEditingRangeProvider(handle: number, selector: IDocumentFilterDto[]): void;
|
||||||
$registerReferenceSupport(handle: number, selector: IDocumentFilterDto[]): void;
|
$registerReferenceSupport(handle: number, selector: IDocumentFilterDto[]): void;
|
||||||
$registerQuickFixSupport(handle: number, selector: IDocumentFilterDto[], metadata: ICodeActionProviderMetadataDto, displayName: string, supportsResolve: boolean): void;
|
$registerQuickFixSupport(handle: number, selector: IDocumentFilterDto[], metadata: ICodeActionProviderMetadataDto, displayName: string, supportsResolve: boolean): void;
|
||||||
$registerPasteEditProvider(handle: number, selector: IDocumentFilterDto[], supportsCopy: boolean): void;
|
$registerPasteEditProvider(handle: number, selector: IDocumentFilterDto[], supportsCopy: boolean, pasteMimeTypes: readonly string[]): void;
|
||||||
$registerDocumentFormattingSupport(handle: number, selector: IDocumentFilterDto[], extensionId: ExtensionIdentifier, displayName: string): void;
|
$registerDocumentFormattingSupport(handle: number, selector: IDocumentFilterDto[], extensionId: ExtensionIdentifier, displayName: string): void;
|
||||||
$registerRangeFormattingSupport(handle: number, selector: IDocumentFilterDto[], extensionId: ExtensionIdentifier, displayName: string): void;
|
$registerRangeFormattingSupport(handle: number, selector: IDocumentFilterDto[], extensionId: ExtensionIdentifier, displayName: string): void;
|
||||||
$registerOnTypeFormattingSupport(handle: number, selector: IDocumentFilterDto[], autoFormatTriggerCharacters: string[], extensionId: ExtensionIdentifier): void;
|
$registerOnTypeFormattingSupport(handle: number, selector: IDocumentFilterDto[], autoFormatTriggerCharacters: string[], extensionId: ExtensionIdentifier): void;
|
||||||
|
@ -1713,6 +1713,16 @@ export interface IInlineValueContextDto {
|
||||||
|
|
||||||
export type ITypeHierarchyItemDto = Dto<TypeHierarchyItem>;
|
export type ITypeHierarchyItemDto = Dto<TypeHierarchyItem>;
|
||||||
|
|
||||||
|
export interface IPasteEditDto {
|
||||||
|
insertText: string | { snippet: string };
|
||||||
|
additionalEdit?: IWorkspaceEditDto;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IDocumentOnDropEditDto {
|
||||||
|
insertText: string | { snippet: string };
|
||||||
|
additionalEdit?: IWorkspaceEditDto;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ExtHostLanguageFeaturesShape {
|
export interface ExtHostLanguageFeaturesShape {
|
||||||
$provideDocumentSymbols(handle: number, resource: UriComponents, token: CancellationToken): Promise<languages.DocumentSymbol[] | undefined>;
|
$provideDocumentSymbols(handle: number, resource: UriComponents, token: CancellationToken): Promise<languages.DocumentSymbol[] | undefined>;
|
||||||
$provideCodeLenses(handle: number, resource: UriComponents, token: CancellationToken): Promise<ICodeLensListDto | undefined>;
|
$provideCodeLenses(handle: number, resource: UriComponents, token: CancellationToken): Promise<ICodeLensListDto | undefined>;
|
||||||
|
@ -1731,8 +1741,8 @@ export interface ExtHostLanguageFeaturesShape {
|
||||||
$provideCodeActions(handle: number, resource: UriComponents, rangeOrSelection: IRange | ISelection, context: languages.CodeActionContext, token: CancellationToken): Promise<ICodeActionListDto | undefined>;
|
$provideCodeActions(handle: number, resource: UriComponents, rangeOrSelection: IRange | ISelection, context: languages.CodeActionContext, token: CancellationToken): Promise<ICodeActionListDto | undefined>;
|
||||||
$resolveCodeAction(handle: number, id: ChainedCacheId, token: CancellationToken): Promise<IWorkspaceEditDto | undefined>;
|
$resolveCodeAction(handle: number, id: ChainedCacheId, token: CancellationToken): Promise<IWorkspaceEditDto | undefined>;
|
||||||
$releaseCodeActions(handle: number, cacheId: number): void;
|
$releaseCodeActions(handle: number, cacheId: number): void;
|
||||||
$prepareDocumentPaste(handle: number, uri: UriComponents, range: IRange, dataTransfer: DataTransferDTO, token: CancellationToken): Promise<DataTransferDTO | undefined>;
|
$prepareDocumentPaste(handle: number, uri: UriComponents, ranges: IRange[], dataTransfer: DataTransferDTO, token: CancellationToken): Promise<DataTransferDTO | undefined>;
|
||||||
$providePasteEdits(handle: number, uri: UriComponents, range: IRange, dataTransfer: DataTransferDTO, token: CancellationToken): Promise<IWorkspaceEditDto | Dto<languages.SnippetTextEdit> | undefined>;
|
$providePasteEdits(handle: number, uri: UriComponents, ranges: IRange[], dataTransfer: DataTransferDTO, token: CancellationToken): Promise<IPasteEditDto | undefined>;
|
||||||
$provideDocumentFormattingEdits(handle: number, resource: UriComponents, options: languages.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[] | undefined>;
|
$provideDocumentFormattingEdits(handle: number, resource: UriComponents, options: languages.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[] | undefined>;
|
||||||
$provideDocumentRangeFormattingEdits(handle: number, resource: UriComponents, range: IRange, options: languages.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[] | undefined>;
|
$provideDocumentRangeFormattingEdits(handle: number, resource: UriComponents, range: IRange, options: languages.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[] | undefined>;
|
||||||
$provideOnTypeFormattingEdits(handle: number, resource: UriComponents, position: IPosition, ch: string, options: languages.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[] | undefined>;
|
$provideOnTypeFormattingEdits(handle: number, resource: UriComponents, position: IPosition, ch: string, options: languages.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[] | undefined>;
|
||||||
|
@ -1771,7 +1781,7 @@ export interface ExtHostLanguageFeaturesShape {
|
||||||
$provideTypeHierarchySupertypes(handle: number, sessionId: string, itemId: string, token: CancellationToken): Promise<ITypeHierarchyItemDto[] | undefined>;
|
$provideTypeHierarchySupertypes(handle: number, sessionId: string, itemId: string, token: CancellationToken): Promise<ITypeHierarchyItemDto[] | undefined>;
|
||||||
$provideTypeHierarchySubtypes(handle: number, sessionId: string, itemId: string, token: CancellationToken): Promise<ITypeHierarchyItemDto[] | undefined>;
|
$provideTypeHierarchySubtypes(handle: number, sessionId: string, itemId: string, token: CancellationToken): Promise<ITypeHierarchyItemDto[] | undefined>;
|
||||||
$releaseTypeHierarchy(handle: number, sessionId: string): void;
|
$releaseTypeHierarchy(handle: number, sessionId: string): void;
|
||||||
$provideDocumentOnDropEdits(handle: number, requestId: number, resource: UriComponents, position: IPosition, dataTransferDto: DataTransferDTO, token: CancellationToken): Promise<Dto<languages.SnippetTextEdit> | undefined>;
|
$provideDocumentOnDropEdits(handle: number, requestId: number, resource: UriComponents, position: IPosition, dataTransferDto: DataTransferDTO, token: CancellationToken): Promise<IDocumentOnDropEditDto | undefined>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ExtHostQuickOpenShape {
|
export interface ExtHostQuickOpenShape {
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { URI, UriComponents } from 'vs/base/common/uri';
|
||||||
import { mixin } from 'vs/base/common/objects';
|
import { mixin } from 'vs/base/common/objects';
|
||||||
import type * as vscode from 'vscode';
|
import type * as vscode from 'vscode';
|
||||||
import * as typeConvert from 'vs/workbench/api/common/extHostTypeConverters';
|
import * as typeConvert from 'vs/workbench/api/common/extHostTypeConverters';
|
||||||
import { Range, Disposable, CompletionList, SnippetString, CodeActionKind, SymbolInformation, DocumentSymbol, SemanticTokensEdits, SemanticTokens, SemanticTokensEdit, Location, InlineCompletionTriggerKindNew, InlineCompletionTriggerKind, WorkspaceEdit } from 'vs/workbench/api/common/extHostTypes';
|
import { Range, Disposable, CompletionList, SnippetString, CodeActionKind, SymbolInformation, DocumentSymbol, SemanticTokensEdits, SemanticTokens, SemanticTokensEdit, Location, InlineCompletionTriggerKindNew, InlineCompletionTriggerKind } from 'vs/workbench/api/common/extHostTypes';
|
||||||
import { ISingleEditOperation } from 'vs/editor/common/core/editOperation';
|
import { ISingleEditOperation } from 'vs/editor/common/core/editOperation';
|
||||||
import * as languages from 'vs/editor/common/languages';
|
import * as languages from 'vs/editor/common/languages';
|
||||||
import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments';
|
import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments';
|
||||||
|
@ -34,7 +34,6 @@ import { StopWatch } from 'vs/base/common/stopwatch';
|
||||||
import { isCancellationError, NotImplementedError } from 'vs/base/common/errors';
|
import { isCancellationError, NotImplementedError } from 'vs/base/common/errors';
|
||||||
import { raceCancellationError } from 'vs/base/common/async';
|
import { raceCancellationError } from 'vs/base/common/async';
|
||||||
import { isProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
|
import { isProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
|
||||||
import { Dto } from 'vs/workbench/services/extensions/common/proxyIdentifier';
|
|
||||||
|
|
||||||
// --- adapter
|
// --- adapter
|
||||||
|
|
||||||
|
@ -494,40 +493,39 @@ class DocumentPasteEditProvider {
|
||||||
private readonly _handle: number,
|
private readonly _handle: number,
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
async prepareDocumentPaste(resource: URI, range: IRange, dataTransferDto: extHostProtocol.DataTransferDTO, token: CancellationToken): Promise<extHostProtocol.DataTransferDTO | undefined> {
|
async prepareDocumentPaste(resource: URI, ranges: IRange[], dataTransferDto: extHostProtocol.DataTransferDTO, token: CancellationToken): Promise<extHostProtocol.DataTransferDTO | undefined> {
|
||||||
if (!this._provider.prepareDocumentPaste) {
|
if (!this._provider.prepareDocumentPaste) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const doc = this._documents.getDocument(resource);
|
const doc = this._documents.getDocument(resource);
|
||||||
const vscodeRange = typeConvert.Range.to(range);
|
const vscodeRanges = ranges.map(range => typeConvert.Range.to(range));
|
||||||
|
|
||||||
const dataTransfer = typeConvert.DataTransfer.toDataTransfer(dataTransferDto, () => {
|
const dataTransfer = typeConvert.DataTransfer.toDataTransfer(dataTransferDto, () => {
|
||||||
throw new NotImplementedError();
|
throw new NotImplementedError();
|
||||||
});
|
});
|
||||||
await this._provider.prepareDocumentPaste(doc, vscodeRange, dataTransfer, token);
|
await this._provider.prepareDocumentPaste(doc, vscodeRanges, dataTransfer, token);
|
||||||
|
|
||||||
return typeConvert.DataTransfer.toDataTransferDTO(dataTransfer);
|
return typeConvert.DataTransfer.toDataTransferDTO(dataTransfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
async providePasteEdits(requestId: number, resource: URI, range: IRange, dataTransferDto: extHostProtocol.DataTransferDTO, token: CancellationToken): Promise<undefined | extHostProtocol.IWorkspaceEditDto | Dto<languages.SnippetTextEdit>> {
|
async providePasteEdits(requestId: number, resource: URI, ranges: IRange[], dataTransferDto: extHostProtocol.DataTransferDTO, token: CancellationToken): Promise<undefined | extHostProtocol.IPasteEditDto> {
|
||||||
const doc = this._documents.getDocument(resource);
|
const doc = this._documents.getDocument(resource);
|
||||||
const vscodeRange = typeConvert.Range.to(range);
|
const vscodeRanges = ranges.map(range => typeConvert.Range.to(range));
|
||||||
|
|
||||||
const dataTransfer = typeConvert.DataTransfer.toDataTransfer(dataTransferDto, async (index) => {
|
const dataTransfer = typeConvert.DataTransfer.toDataTransfer(dataTransferDto, async (index) => {
|
||||||
return (await this._proxy.$resolveDocumentOnDropFileData(this._handle, requestId, index)).buffer;
|
return (await this._proxy.$resolveDocumentOnDropFileData(this._handle, requestId, index)).buffer;
|
||||||
});
|
});
|
||||||
|
|
||||||
const edit = await this._provider.provideDocumentPasteEdits(doc, vscodeRange, dataTransfer, token);
|
const edit = await this._provider.provideDocumentPasteEdits(doc, vscodeRanges, dataTransfer, token);
|
||||||
if (!edit) {
|
if (!edit) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (edit instanceof WorkspaceEdit) {
|
return {
|
||||||
return typeConvert.WorkspaceEdit.from(edit);
|
insertText: typeof edit.insertText === 'string' ? edit.insertText : { snippet: edit.insertText.value },
|
||||||
} else {
|
additionalEdit: edit.additionalEdit ? typeConvert.WorkspaceEdit.from(edit.additionalEdit) : undefined,
|
||||||
return typeConvert.SnippetTextEdit.from(edit as vscode.SnippetTextEdit);
|
};
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1799,7 +1797,7 @@ class DocumentOnDropEditAdapter {
|
||||||
private readonly _handle: number,
|
private readonly _handle: number,
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
async provideDocumentOnDropEdits(requestId: number, uri: URI, position: IPosition, dataTransferDto: extHostProtocol.DataTransferDTO, token: CancellationToken): Promise<Dto<languages.SnippetTextEdit> | undefined> {
|
async provideDocumentOnDropEdits(requestId: number, uri: URI, position: IPosition, dataTransferDto: extHostProtocol.DataTransferDTO, token: CancellationToken): Promise<extHostProtocol.IDocumentOnDropEditDto | undefined> {
|
||||||
const doc = this._documents.getDocument(uri);
|
const doc = this._documents.getDocument(uri);
|
||||||
const pos = typeConvert.Position.to(position);
|
const pos = typeConvert.Position.to(position);
|
||||||
const dataTransfer = typeConvert.DataTransfer.toDataTransfer(dataTransferDto, async (index) => {
|
const dataTransfer = typeConvert.DataTransfer.toDataTransfer(dataTransferDto, async (index) => {
|
||||||
|
@ -1810,7 +1808,10 @@ class DocumentOnDropEditAdapter {
|
||||||
if (!edit) {
|
if (!edit) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
return typeConvert.SnippetTextEdit.from(edit);
|
return {
|
||||||
|
insertText: typeof edit.insertText === 'string' ? edit.insertText : { snippet: edit.insertText.value },
|
||||||
|
additionalEdit: edit.additionalEdit ? typeConvert.WorkspaceEdit.from(edit.additionalEdit) : undefined,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2454,26 +2455,26 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF
|
||||||
return this._createDisposable(handle);
|
return this._createDisposable(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
$provideDocumentOnDropEdits(handle: number, requestId: number, resource: UriComponents, position: IPosition, dataTransferDto: extHostProtocol.DataTransferDTO, token: CancellationToken): Promise<Dto<languages.SnippetTextEdit> | undefined> {
|
$provideDocumentOnDropEdits(handle: number, requestId: number, resource: UriComponents, position: IPosition, dataTransferDto: extHostProtocol.DataTransferDTO, token: CancellationToken): Promise<extHostProtocol.IDocumentOnDropEditDto | undefined> {
|
||||||
return this._withAdapter(handle, DocumentOnDropEditAdapter, adapter =>
|
return this._withAdapter(handle, DocumentOnDropEditAdapter, adapter =>
|
||||||
Promise.resolve(adapter.provideDocumentOnDropEdits(requestId, URI.revive(resource), position, dataTransferDto, token)), undefined, undefined);
|
Promise.resolve(adapter.provideDocumentOnDropEdits(requestId, URI.revive(resource), position, dataTransferDto, token)), undefined, undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- copy/paste actions
|
// --- copy/paste actions
|
||||||
|
|
||||||
registerDocumentPasteEditProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DocumentPasteEditProvider): vscode.Disposable {
|
registerDocumentPasteEditProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DocumentPasteEditProvider, metadata: vscode.DocumentPasteProviderMetadata): vscode.Disposable {
|
||||||
const handle = this._nextHandle();
|
const handle = this._nextHandle();
|
||||||
this._adapter.set(handle, new AdapterData(new DocumentPasteEditProvider(this._proxy, this._documents, provider, handle), extension));
|
this._adapter.set(handle, new AdapterData(new DocumentPasteEditProvider(this._proxy, this._documents, provider, handle), extension));
|
||||||
this._proxy.$registerPasteEditProvider(handle, this._transformDocumentSelector(selector), !!provider.prepareDocumentPaste);
|
this._proxy.$registerPasteEditProvider(handle, this._transformDocumentSelector(selector), !!provider.prepareDocumentPaste, metadata.pasteMimeTypes);
|
||||||
return this._createDisposable(handle);
|
return this._createDisposable(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
$prepareDocumentPaste(handle: number, resource: UriComponents, range: IRange, dataTransfer: extHostProtocol.DataTransferDTO, token: CancellationToken): Promise<extHostProtocol.DataTransferDTO | undefined> {
|
$prepareDocumentPaste(handle: number, resource: UriComponents, ranges: IRange[], dataTransfer: extHostProtocol.DataTransferDTO, token: CancellationToken): Promise<extHostProtocol.DataTransferDTO | undefined> {
|
||||||
return this._withAdapter(handle, DocumentPasteEditProvider, adapter => adapter.prepareDocumentPaste(URI.revive(resource), range, dataTransfer, token), undefined, token);
|
return this._withAdapter(handle, DocumentPasteEditProvider, adapter => adapter.prepareDocumentPaste(URI.revive(resource), ranges, dataTransfer, token), undefined, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
$providePasteEdits(handle: number, resource: UriComponents, range: IRange, dataTransferDto: extHostProtocol.DataTransferDTO, token: CancellationToken): Promise<extHostProtocol.IWorkspaceEditDto | Dto<languages.SnippetTextEdit> | undefined> {
|
$providePasteEdits(handle: number, resource: UriComponents, ranges: IRange[], dataTransferDto: extHostProtocol.DataTransferDTO, token: CancellationToken): Promise<extHostProtocol.IPasteEditDto | undefined> {
|
||||||
return this._withAdapter(handle, DocumentPasteEditProvider, adapter => adapter.providePasteEdits(0, URI.revive(resource), range, dataTransferDto, token), undefined, token);
|
return this._withAdapter(handle, DocumentPasteEditProvider, adapter => adapter.providePasteEdits(0, URI.revive(resource), ranges, dataTransferDto, token), undefined, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- configuration
|
// --- configuration
|
||||||
|
|
|
@ -562,15 +562,6 @@ export namespace TextEdit {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export namespace SnippetTextEdit {
|
|
||||||
export function from(edit: vscode.SnippetTextEdit): languages.SnippetTextEdit {
|
|
||||||
return {
|
|
||||||
range: Range.from(edit.range),
|
|
||||||
snippet: edit.snippet.value
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export namespace WorkspaceEdit {
|
export namespace WorkspaceEdit {
|
||||||
|
|
||||||
export interface IVersionInformationProvider {
|
export interface IVersionInformationProvider {
|
||||||
|
|
|
@ -647,17 +647,6 @@ export class NotebookEdit implements vscode.NotebookEdit {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SnippetTextEdit implements vscode.SnippetTextEdit {
|
|
||||||
|
|
||||||
range: vscode.Range;
|
|
||||||
snippet: vscode.SnippetString;
|
|
||||||
|
|
||||||
constructor(range: Range, snippet: SnippetString) {
|
|
||||||
this.range = range;
|
|
||||||
this.snippet = snippet;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IFileOperationOptions {
|
export interface IFileOperationOptions {
|
||||||
overwrite?: boolean;
|
overwrite?: boolean;
|
||||||
ignoreIfExists?: boolean;
|
ignoreIfExists?: boolean;
|
||||||
|
|
|
@ -23,7 +23,7 @@ import { TextDiffEditor } from 'vs/workbench/browser/parts/editor/textDiffEditor
|
||||||
import { BinaryResourceDiffEditor } from 'vs/workbench/browser/parts/editor/binaryDiffEditor';
|
import { BinaryResourceDiffEditor } from 'vs/workbench/browser/parts/editor/binaryDiffEditor';
|
||||||
import { ChangeEncodingAction, ChangeEOLAction, ChangeLanguageAction, EditorStatus } from 'vs/workbench/browser/parts/editor/editorStatus';
|
import { ChangeEncodingAction, ChangeEOLAction, ChangeLanguageAction, EditorStatus } from 'vs/workbench/browser/parts/editor/editorStatus';
|
||||||
import { IWorkbenchActionRegistry, Extensions as ActionExtensions, CATEGORIES } from 'vs/workbench/common/actions';
|
import { IWorkbenchActionRegistry, Extensions as ActionExtensions, CATEGORIES } from 'vs/workbench/common/actions';
|
||||||
import { SyncActionDescriptor, MenuRegistry, MenuId, IMenuItem } from 'vs/platform/actions/common/actions';
|
import { SyncActionDescriptor, MenuRegistry, MenuId, IMenuItem, registerAction2 } from 'vs/platform/actions/common/actions';
|
||||||
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
|
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
|
||||||
import { KeyMod, KeyChord, KeyCode } from 'vs/base/common/keyCodes';
|
import { KeyMod, KeyChord, KeyCode } from 'vs/base/common/keyCodes';
|
||||||
import {
|
import {
|
||||||
|
@ -244,8 +244,6 @@ registry.registerWorkbenchAction(SyncActionDescriptor.from(NewEditorGroupLeftAct
|
||||||
registry.registerWorkbenchAction(SyncActionDescriptor.from(NewEditorGroupRightAction), 'View: New Editor Group to the Right', CATEGORIES.View.value);
|
registry.registerWorkbenchAction(SyncActionDescriptor.from(NewEditorGroupRightAction), 'View: New Editor Group to the Right', CATEGORIES.View.value);
|
||||||
registry.registerWorkbenchAction(SyncActionDescriptor.from(NewEditorGroupAboveAction), 'View: New Editor Group Above', CATEGORIES.View.value);
|
registry.registerWorkbenchAction(SyncActionDescriptor.from(NewEditorGroupAboveAction), 'View: New Editor Group Above', CATEGORIES.View.value);
|
||||||
registry.registerWorkbenchAction(SyncActionDescriptor.from(NewEditorGroupBelowAction), 'View: New Editor Group Below', CATEGORIES.View.value);
|
registry.registerWorkbenchAction(SyncActionDescriptor.from(NewEditorGroupBelowAction), 'View: New Editor Group Below', CATEGORIES.View.value);
|
||||||
registry.registerWorkbenchAction(SyncActionDescriptor.from(NavigateForwardAction, { primary: 0, win: { primary: KeyMod.Alt | KeyCode.RightArrow }, mac: { primary: KeyMod.WinCtrl | KeyMod.Shift | KeyCode.Minus }, linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.Minus } }), 'Go Forward');
|
|
||||||
registry.registerWorkbenchAction(SyncActionDescriptor.from(NavigateBackwardsAction, { primary: 0, win: { primary: KeyMod.Alt | KeyCode.LeftArrow }, mac: { primary: KeyMod.WinCtrl | KeyCode.Minus }, linux: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.Minus } }), 'Go Back');
|
|
||||||
registry.registerWorkbenchAction(SyncActionDescriptor.from(NavigatePreviousAction), 'Go Previous');
|
registry.registerWorkbenchAction(SyncActionDescriptor.from(NavigatePreviousAction), 'Go Previous');
|
||||||
registry.registerWorkbenchAction(SyncActionDescriptor.from(NavigateForwardInEditsAction), 'Go Forward in Edit Locations');
|
registry.registerWorkbenchAction(SyncActionDescriptor.from(NavigateForwardInEditsAction), 'Go Forward in Edit Locations');
|
||||||
registry.registerWorkbenchAction(SyncActionDescriptor.from(NavigateBackwardsInEditsAction), 'Go Back in Edit Locations');
|
registry.registerWorkbenchAction(SyncActionDescriptor.from(NavigateBackwardsInEditsAction), 'Go Back in Edit Locations');
|
||||||
|
@ -273,6 +271,9 @@ registry.registerWorkbenchAction(SyncActionDescriptor.from(QuickAccessPreviousRe
|
||||||
registry.registerWorkbenchAction(SyncActionDescriptor.from(QuickAccessLeastRecentlyUsedEditorInGroupAction, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.Tab, mac: { primary: KeyMod.WinCtrl | KeyMod.Shift | KeyCode.Tab } }, ActiveEditorGroupEmptyContext.toNegated()), 'View: Quick Open Least Recently Used Editor in Group', CATEGORIES.View.value);
|
registry.registerWorkbenchAction(SyncActionDescriptor.from(QuickAccessLeastRecentlyUsedEditorInGroupAction, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.Tab, mac: { primary: KeyMod.WinCtrl | KeyMod.Shift | KeyCode.Tab } }, ActiveEditorGroupEmptyContext.toNegated()), 'View: Quick Open Least Recently Used Editor in Group', CATEGORIES.View.value);
|
||||||
registry.registerWorkbenchAction(SyncActionDescriptor.from(QuickAccessPreviousEditorFromHistoryAction), 'Quick Open Previous Editor from History');
|
registry.registerWorkbenchAction(SyncActionDescriptor.from(QuickAccessPreviousEditorFromHistoryAction), 'Quick Open Previous Editor from History');
|
||||||
|
|
||||||
|
registerAction2(NavigateForwardAction);
|
||||||
|
registerAction2(NavigateBackwardsAction);
|
||||||
|
|
||||||
const quickAccessNavigateNextInEditorPickerId = 'workbench.action.quickOpenNavigateNextInEditorPicker';
|
const quickAccessNavigateNextInEditorPickerId = 'workbench.action.quickOpenNavigateNextInEditorPicker';
|
||||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||||
id: quickAccessNavigateNextInEditorPickerId,
|
id: quickAccessNavigateNextInEditorPickerId,
|
||||||
|
@ -314,9 +315,6 @@ if (isMacintosh) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
MenuRegistry.appendMenuItem(MenuId.CommandCenter, { order: 1, command: { id: NavigateBackwardsAction.ID, title: NavigateBackwardsAction.LABEL, icon: Codicon.arrowLeft } });
|
|
||||||
MenuRegistry.appendMenuItem(MenuId.CommandCenter, { order: 2, command: { id: NavigateForwardAction.ID, title: NavigateForwardAction.LABEL, icon: Codicon.arrowRight } });
|
|
||||||
|
|
||||||
// Empty Editor Group Toolbar
|
// Empty Editor Group Toolbar
|
||||||
MenuRegistry.appendMenuItem(MenuId.EmptyEditorGroup, { command: { id: UNLOCK_GROUP_COMMAND_ID, title: localize('unlockGroupAction', "Unlock Group"), icon: Codicon.lock }, group: 'navigation', order: 10, when: ActiveEditorGroupLockedContext });
|
MenuRegistry.appendMenuItem(MenuId.EmptyEditorGroup, { command: { id: UNLOCK_GROUP_COMMAND_ID, title: localize('unlockGroupAction', "Unlock Group"), icon: Codicon.lock }, group: 'navigation', order: 10, when: ActiveEditorGroupLockedContext });
|
||||||
MenuRegistry.appendMenuItem(MenuId.EmptyEditorGroup, { command: { id: CLOSE_EDITOR_GROUP_COMMAND_ID, title: localize('closeGroupAction', "Close Group"), icon: Codicon.close }, group: 'navigation', order: 20 });
|
MenuRegistry.appendMenuItem(MenuId.EmptyEditorGroup, { command: { id: CLOSE_EDITOR_GROUP_COMMAND_ID, title: localize('closeGroupAction', "Close Group"), icon: Codicon.close }, group: 'navigation', order: 20 });
|
||||||
|
@ -775,27 +773,6 @@ MenuRegistry.appendMenuItem(MenuId.MenubarLayoutMenu, {
|
||||||
|
|
||||||
// Main Menu Bar Contributions:
|
// Main Menu Bar Contributions:
|
||||||
|
|
||||||
// Forward/Back
|
|
||||||
MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
|
|
||||||
group: '1_history_nav',
|
|
||||||
command: {
|
|
||||||
id: 'workbench.action.navigateBack',
|
|
||||||
title: localize({ key: 'miBack', comment: ['&& denotes a mnemonic'] }, "&&Back"),
|
|
||||||
precondition: ContextKeyExpr.has('canNavigateBack')
|
|
||||||
},
|
|
||||||
order: 1
|
|
||||||
});
|
|
||||||
|
|
||||||
MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
|
|
||||||
group: '1_history_nav',
|
|
||||||
command: {
|
|
||||||
id: 'workbench.action.navigateForward',
|
|
||||||
title: localize({ key: 'miForward', comment: ['&& denotes a mnemonic'] }, "&&Forward"),
|
|
||||||
precondition: ContextKeyExpr.has('canNavigateForward')
|
|
||||||
},
|
|
||||||
order: 2
|
|
||||||
});
|
|
||||||
|
|
||||||
MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
|
MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
|
||||||
group: '1_history_nav',
|
group: '1_history_nav',
|
||||||
command: {
|
command: {
|
||||||
|
|
|
@ -26,6 +26,11 @@ import { Codicon } from 'vs/base/common/codicons';
|
||||||
import { IFilesConfigurationService, AutoSaveMode } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService';
|
import { IFilesConfigurationService, AutoSaveMode } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService';
|
||||||
import { IEditorResolverService } from 'vs/workbench/services/editor/common/editorResolverService';
|
import { IEditorResolverService } from 'vs/workbench/services/editor/common/editorResolverService';
|
||||||
import { isLinux, isNative, isWindows } from 'vs/base/common/platform';
|
import { isLinux, isNative, isWindows } from 'vs/base/common/platform';
|
||||||
|
import { Action2, MenuId } from 'vs/platform/actions/common/actions';
|
||||||
|
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||||
|
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||||
|
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
|
||||||
|
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||||
|
|
||||||
export class ExecuteCommandAction extends Action {
|
export class ExecuteCommandAction extends Action {
|
||||||
|
|
||||||
|
@ -1258,39 +1263,67 @@ export class OpenLastEditorInGroup extends AbstractNavigateEditorAction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class NavigateForwardAction extends Action {
|
export class NavigateForwardAction extends Action2 {
|
||||||
|
|
||||||
static readonly ID = 'workbench.action.navigateForward';
|
static readonly ID = 'workbench.action.navigateForward';
|
||||||
static readonly LABEL = localize('navigateForward', "Go Forward");
|
static readonly LABEL = localize('navigateForward', "Go Forward");
|
||||||
|
|
||||||
constructor(
|
constructor() {
|
||||||
id: string,
|
super({
|
||||||
label: string,
|
id: NavigateForwardAction.ID,
|
||||||
@IHistoryService private readonly historyService: IHistoryService
|
title: { value: localize('navigateForward', "Go Forward"), original: 'Go Forward', mnemonicTitle: localize({ key: 'miForward', comment: ['&& denotes a mnemonic'] }, "&&Forward") },
|
||||||
) {
|
f1: true,
|
||||||
super(id, label);
|
icon: Codicon.arrowRight,
|
||||||
|
precondition: ContextKeyExpr.has('canNavigateForward'),
|
||||||
|
keybinding: {
|
||||||
|
weight: KeybindingWeight.WorkbenchContrib,
|
||||||
|
win: { primary: KeyMod.Alt | KeyCode.RightArrow },
|
||||||
|
mac: { primary: KeyMod.WinCtrl | KeyMod.Shift | KeyCode.Minus },
|
||||||
|
linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.Minus }
|
||||||
|
},
|
||||||
|
menu: [
|
||||||
|
{ id: MenuId.MenubarGoMenu, group: '1_history_nav', order: 2 },
|
||||||
|
{ id: MenuId.CommandCenter, order: 2 }
|
||||||
|
]
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
override async run(): Promise<void> {
|
async run(accessor: ServicesAccessor): Promise<void> {
|
||||||
await this.historyService.goForward(GoFilter.NONE);
|
const historyService = accessor.get(IHistoryService);
|
||||||
|
|
||||||
|
await historyService.goForward(GoFilter.NONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class NavigateBackwardsAction extends Action {
|
export class NavigateBackwardsAction extends Action2 {
|
||||||
|
|
||||||
static readonly ID = 'workbench.action.navigateBack';
|
static readonly ID = 'workbench.action.navigateBack';
|
||||||
static readonly LABEL = localize('navigateBack', "Go Back");
|
static readonly LABEL = localize('navigateBack', "Go Back");
|
||||||
|
|
||||||
constructor(
|
constructor() {
|
||||||
id: string,
|
super({
|
||||||
label: string,
|
id: NavigateBackwardsAction.ID,
|
||||||
@IHistoryService private readonly historyService: IHistoryService
|
title: { value: localize('navigateBack', "Go Back"), original: 'Go Back', mnemonicTitle: localize({ key: 'miBack', comment: ['&& denotes a mnemonic'] }, "&&Back") },
|
||||||
) {
|
f1: true,
|
||||||
super(id, label);
|
precondition: ContextKeyExpr.has('canNavigateBack'),
|
||||||
|
icon: Codicon.arrowLeft,
|
||||||
|
keybinding: {
|
||||||
|
weight: KeybindingWeight.WorkbenchContrib,
|
||||||
|
win: { primary: KeyMod.Alt | KeyCode.LeftArrow },
|
||||||
|
mac: { primary: KeyMod.WinCtrl | KeyCode.Minus },
|
||||||
|
linux: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.Minus }
|
||||||
|
},
|
||||||
|
menu: [
|
||||||
|
{ id: MenuId.MenubarGoMenu, group: '1_history_nav', order: 1 },
|
||||||
|
{ id: MenuId.CommandCenter, order: 1 }
|
||||||
|
]
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
override async run(): Promise<void> {
|
async run(accessor: ServicesAccessor): Promise<void> {
|
||||||
await this.historyService.goBack(GoFilter.NONE);
|
const historyService = accessor.get(IHistoryService);
|
||||||
|
|
||||||
|
await historyService.goBack(GoFilter.NONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -597,6 +597,7 @@ export class EditorDropTarget extends Themable {
|
||||||
private registerListeners(): void {
|
private registerListeners(): void {
|
||||||
this._register(addDisposableListener(this.container, EventType.DRAG_ENTER, e => this.onDragEnter(e)));
|
this._register(addDisposableListener(this.container, EventType.DRAG_ENTER, e => this.onDragEnter(e)));
|
||||||
this._register(addDisposableListener(this.container, EventType.DRAG_LEAVE, () => this.onDragLeave()));
|
this._register(addDisposableListener(this.container, EventType.DRAG_LEAVE, () => this.onDragLeave()));
|
||||||
|
this._register(addDisposableListener(this.container, EventType.DRAG_OVER, e => this.onDragEnter(e)));
|
||||||
[this.container, window].forEach(node => this._register(addDisposableListener(node as HTMLElement, EventType.DRAG_END, () => this.onDragEnd())));
|
[this.container, window].forEach(node => this._register(addDisposableListener(node as HTMLElement, EventType.DRAG_END, () => this.onDragEnd())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -690,8 +690,11 @@ export class DebugService implements IDebugService {
|
||||||
const dataBreakpoints = this.model.getDataBreakpoints().filter(dbp => !dbp.canPersist);
|
const dataBreakpoints = this.model.getDataBreakpoints().filter(dbp => !dbp.canPersist);
|
||||||
dataBreakpoints.forEach(dbp => this.model.removeDataBreakpoints(dbp.getId()));
|
dataBreakpoints.forEach(dbp => this.model.removeDataBreakpoints(dbp.getId()));
|
||||||
|
|
||||||
if (this.viewsService.isViewVisible(REPL_VIEW_ID) && this.configurationService.getValue<IDebugConfiguration>('debug').console.closeOnEnd) {
|
if (this.configurationService.getValue<IDebugConfiguration>('debug').console.closeOnEnd) {
|
||||||
this.viewsService.closeView(REPL_VIEW_ID);
|
const debugConsoleContainer = this.viewDescriptorService.getViewContainerByViewId(REPL_VIEW_ID);
|
||||||
|
if (debugConsoleContainer && this.viewsService.isViewContainerVisible(debugConsoleContainer.id)) {
|
||||||
|
this.viewsService.closeViewContainer(debugConsoleContainer.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
|
@ -96,10 +96,10 @@ export class VariablesView extends ViewPane {
|
||||||
const viewState = this.savedViewState.get(stackFrame.getId());
|
const viewState = this.savedViewState.get(stackFrame.getId());
|
||||||
await this.tree.setInput(stackFrame, viewState);
|
await this.tree.setInput(stackFrame, viewState);
|
||||||
|
|
||||||
// Automatically expand the first scope if it is not expensive and if all scopes are collapsed
|
// Automatically expand the first non-expensive scope
|
||||||
const scopes = await stackFrame.getScopes();
|
const scopes = await stackFrame.getScopes();
|
||||||
const toExpand = scopes.find(s => !s.expensive);
|
const toExpand = scopes.find(s => !s.expensive);
|
||||||
if (toExpand && (scopes.every(s => this.tree.isCollapsed(s)) || !this.autoExpandedScopes.has(toExpand.getId()))) {
|
if (toExpand) {
|
||||||
this.autoExpandedScopes.add(toExpand.getId());
|
this.autoExpandedScopes.add(toExpand.getId());
|
||||||
await this.tree.expand(toExpand);
|
await this.tree.expand(toExpand);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { distinct, lastIndex } from 'vs/base/common/arrays';
|
||||||
import { RunOnceScheduler } from 'vs/base/common/async';
|
import { RunOnceScheduler } from 'vs/base/common/async';
|
||||||
import { decodeBase64, encodeBase64, VSBuffer } from 'vs/base/common/buffer';
|
import { decodeBase64, encodeBase64, VSBuffer } from 'vs/base/common/buffer';
|
||||||
import { CancellationTokenSource } from 'vs/base/common/cancellation';
|
import { CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||||
|
import { stringHash } from 'vs/base/common/hash';
|
||||||
import { Emitter, Event } from 'vs/base/common/event';
|
import { Emitter, Event } from 'vs/base/common/event';
|
||||||
import { Disposable } from 'vs/base/common/lifecycle';
|
import { Disposable } from 'vs/base/common/lifecycle';
|
||||||
import { mixin } from 'vs/base/common/objects';
|
import { mixin } from 'vs/base/common/objects';
|
||||||
|
@ -351,7 +352,7 @@ export class Scope extends ExpressionContainer implements IScope {
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
stackFrame: IStackFrame,
|
stackFrame: IStackFrame,
|
||||||
index: number,
|
id: number,
|
||||||
public readonly name: string,
|
public readonly name: string,
|
||||||
reference: number,
|
reference: number,
|
||||||
public expensive: boolean,
|
public expensive: boolean,
|
||||||
|
@ -359,7 +360,7 @@ export class Scope extends ExpressionContainer implements IScope {
|
||||||
indexedVariables?: number,
|
indexedVariables?: number,
|
||||||
public readonly range?: IRange
|
public readonly range?: IRange
|
||||||
) {
|
) {
|
||||||
super(stackFrame.thread.session, stackFrame.thread.threadId, reference, `scope:${name}:${index}`, namedVariables, indexedVariables);
|
super(stackFrame.thread.session, stackFrame.thread.threadId, reference, `scope:${name}:${id}`, namedVariables, indexedVariables);
|
||||||
}
|
}
|
||||||
|
|
||||||
override toString(): string {
|
override toString(): string {
|
||||||
|
@ -417,12 +418,17 @@ export class StackFrame implements IStackFrame {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const scopeNameIndexes = new Map<string, number>();
|
const usedIds = new Set<number>();
|
||||||
return response.body.scopes.map(rs => {
|
return response.body.scopes.map(rs => {
|
||||||
const previousIndex = scopeNameIndexes.get(rs.name);
|
// form the id based on the name and location so that it's the
|
||||||
const index = typeof previousIndex === 'number' ? previousIndex + 1 : 0;
|
// same across multiple pauses to retain expansion state
|
||||||
scopeNameIndexes.set(rs.name, index);
|
let id = 0;
|
||||||
return new Scope(this, index, rs.name, rs.variablesReference, rs.expensive, rs.namedVariables, rs.indexedVariables,
|
do {
|
||||||
|
id = stringHash(`${rs.name}:${rs.line}:${rs.column}`, id);
|
||||||
|
} while (usedIds.has(id));
|
||||||
|
|
||||||
|
usedIds.add(id);
|
||||||
|
return new Scope(this, id, rs.name, rs.variablesReference, rs.expensive, rs.namedVariables, rs.indexedVariables,
|
||||||
rs.line && rs.column && rs.endLine && rs.endColumn ? new Range(rs.line, rs.column, rs.endLine, rs.endColumn) : undefined);
|
rs.line && rs.column && rs.endLine && rs.endColumn ? new Range(rs.line, rs.column, rs.endLine, rs.endColumn) : undefined);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -16,13 +16,13 @@ import { append, $, finalHandler, join, addDisposableListener, EventType, setPar
|
||||||
import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane';
|
import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane';
|
||||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||||
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||||
import { IExtensionIgnoredRecommendationsService, IExtensionRecommendationsService } from 'vs/workbench/services/extensionRecommendations/common/extensionRecommendations';
|
import { IExtensionRecommendationsService } from 'vs/workbench/services/extensionRecommendations/common/extensionRecommendations';
|
||||||
import { IExtensionManifest, IKeyBinding, IView, IViewContainer } from 'vs/platform/extensions/common/extensions';
|
import { IExtensionManifest, IKeyBinding, IView, IViewContainer } from 'vs/platform/extensions/common/extensions';
|
||||||
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
|
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
|
||||||
import { ResolvedKeybinding } from 'vs/base/common/keybindings';
|
import { ResolvedKeybinding } from 'vs/base/common/keybindings';
|
||||||
import { ExtensionsInput, IExtensionEditorOptions } from 'vs/workbench/contrib/extensions/common/extensionsInput';
|
import { ExtensionsInput, IExtensionEditorOptions } from 'vs/workbench/contrib/extensions/common/extensionsInput';
|
||||||
import { IExtensionsWorkbenchService, IExtensionsViewPaneContainer, VIEWLET_ID, IExtension, ExtensionContainers, ExtensionEditorTab, ExtensionState } from 'vs/workbench/contrib/extensions/common/extensions';
|
import { IExtensionsWorkbenchService, IExtensionsViewPaneContainer, VIEWLET_ID, IExtension, ExtensionContainers, ExtensionEditorTab, ExtensionState, IExtensionContainer } from 'vs/workbench/contrib/extensions/common/extensions';
|
||||||
import { RatingsWidget, InstallCountWidget, RemoteBadgeWidget, ExtensionWidget } from 'vs/workbench/contrib/extensions/browser/extensionsWidgets';
|
import { RatingsWidget, InstallCountWidget, RemoteBadgeWidget, ExtensionWidget, ExtensionStatusWidget, ExtensionRecommendationWidget } from 'vs/workbench/contrib/extensions/browser/extensionsWidgets';
|
||||||
import { IEditorOpenContext } from 'vs/workbench/common/editor';
|
import { IEditorOpenContext } from 'vs/workbench/common/editor';
|
||||||
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
|
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||||
import {
|
import {
|
||||||
|
@ -66,8 +66,7 @@ import { Delegate } from 'vs/workbench/contrib/extensions/browser/extensionsList
|
||||||
import { renderMarkdown } from 'vs/base/browser/markdownRenderer';
|
import { renderMarkdown } from 'vs/base/browser/markdownRenderer';
|
||||||
import { attachKeybindingLabelStyler } from 'vs/platform/theme/common/styler';
|
import { attachKeybindingLabelStyler } from 'vs/platform/theme/common/styler';
|
||||||
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||||
import { errorIcon, infoIcon, preReleaseIcon, starEmptyIcon, verifiedPublisherIcon as verifiedPublisherThemeIcon, warningIcon } from 'vs/workbench/contrib/extensions/browser/extensionsIcons';
|
import { errorIcon, infoIcon, preReleaseIcon, verifiedPublisherIcon as verifiedPublisherThemeIcon, warningIcon } from 'vs/workbench/contrib/extensions/browser/extensionsIcons';
|
||||||
import { MarkdownString } from 'vs/base/common/htmlContent';
|
|
||||||
import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite';
|
import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite';
|
||||||
import { ViewContainerLocation } from 'vs/workbench/common/views';
|
import { ViewContainerLocation } from 'vs/workbench/common/views';
|
||||||
import { IExtensionGalleryService, IGalleryExtension } from 'vs/platform/extensionManagement/common/extensionManagement';
|
import { IExtensionGalleryService, IGalleryExtension } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||||
|
@ -147,8 +146,6 @@ interface IExtensionEditorTemplate {
|
||||||
description: HTMLElement;
|
description: HTMLElement;
|
||||||
actionsAndStatusContainer: HTMLElement;
|
actionsAndStatusContainer: HTMLElement;
|
||||||
extensionActionBar: ActionBar;
|
extensionActionBar: ActionBar;
|
||||||
status: HTMLElement;
|
|
||||||
recommendation: HTMLElement;
|
|
||||||
navbar: NavBar;
|
navbar: NavBar;
|
||||||
content: HTMLElement;
|
content: HTMLElement;
|
||||||
header: HTMLElement;
|
header: HTMLElement;
|
||||||
|
@ -251,7 +248,6 @@ export class ExtensionEditor extends EditorPane {
|
||||||
@INotificationService private readonly notificationService: INotificationService,
|
@INotificationService private readonly notificationService: INotificationService,
|
||||||
@IOpenerService private readonly openerService: IOpenerService,
|
@IOpenerService private readonly openerService: IOpenerService,
|
||||||
@IExtensionRecommendationsService private readonly extensionRecommendationsService: IExtensionRecommendationsService,
|
@IExtensionRecommendationsService private readonly extensionRecommendationsService: IExtensionRecommendationsService,
|
||||||
@IExtensionIgnoredRecommendationsService private readonly extensionIgnoredRecommendationsService: IExtensionIgnoredRecommendationsService,
|
|
||||||
@IStorageService storageService: IStorageService,
|
@IStorageService storageService: IStorageService,
|
||||||
@IExtensionService private readonly extensionService: IExtensionService,
|
@IExtensionService private readonly extensionService: IExtensionService,
|
||||||
@IWebviewService private readonly webviewService: IWebviewService,
|
@IWebviewService private readonly webviewService: IWebviewService,
|
||||||
|
@ -310,7 +306,7 @@ export class ExtensionEditor extends EditorPane {
|
||||||
rating.setAttribute('role', 'link'); // #132645
|
rating.setAttribute('role', 'link'); // #132645
|
||||||
const ratingsWidget = this.instantiationService.createInstance(RatingsWidget, rating, false);
|
const ratingsWidget = this.instantiationService.createInstance(RatingsWidget, rating, false);
|
||||||
|
|
||||||
const widgets = [
|
const widgets: ExtensionWidget[] = [
|
||||||
remoteBadge,
|
remoteBadge,
|
||||||
versionWidget,
|
versionWidget,
|
||||||
preReleaseWidget,
|
preReleaseWidget,
|
||||||
|
@ -375,14 +371,30 @@ export class ExtensionEditor extends EditorPane {
|
||||||
extensionActionBar.setFocusable(true);
|
extensionActionBar.setFocusable(true);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const extensionContainers: ExtensionContainers = this.instantiationService.createInstance(ExtensionContainers, [...actions, ...widgets]);
|
const otherExtensionContainers: IExtensionContainer[] = [];
|
||||||
for (const disposable of [...actions, ...widgets, extensionContainers]) {
|
const extensionStatusAction = this.instantiationService.createInstance(ExtensionStatusAction);
|
||||||
|
const extensionStatusWidget = this._register(this.instantiationService.createInstance(ExtensionStatusWidget, append(actionsAndStatusContainer, $('.status')), extensionStatusAction));
|
||||||
|
|
||||||
|
otherExtensionContainers.push(extensionStatusAction, new class extends ExtensionWidget {
|
||||||
|
render() {
|
||||||
|
actionsAndStatusContainer.classList.toggle('list-layout', this.extension?.state === ExtensionState.Installed);
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
|
||||||
|
const recommendationWidget = this.instantiationService.createInstance(ExtensionRecommendationWidget, append(details, $('.recommendation')));
|
||||||
|
widgets.push(recommendationWidget);
|
||||||
|
|
||||||
|
this._register(Event.any(extensionStatusWidget.onDidRender, recommendationWidget.onDidRender)(() => {
|
||||||
|
if (this.dimension) {
|
||||||
|
this.layout(this.dimension);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
const extensionContainers: ExtensionContainers = this.instantiationService.createInstance(ExtensionContainers, [...actions, ...widgets, ...otherExtensionContainers]);
|
||||||
|
for (const disposable of [...actions, ...widgets, ...otherExtensionContainers, extensionContainers]) {
|
||||||
this._register(disposable);
|
this._register(disposable);
|
||||||
}
|
}
|
||||||
|
|
||||||
const status = append(actionsAndStatusContainer, $('.status'));
|
|
||||||
const recommendation = append(details, $('.recommendation'));
|
|
||||||
|
|
||||||
this._register(Event.chain(extensionActionBar.onDidRun)
|
this._register(Event.chain(extensionActionBar.onDidRun)
|
||||||
.map(({ error }) => error)
|
.map(({ error }) => error)
|
||||||
.filter(error => !!error)
|
.filter(error => !!error)
|
||||||
|
@ -411,8 +423,6 @@ export class ExtensionEditor extends EditorPane {
|
||||||
rating,
|
rating,
|
||||||
actionsAndStatusContainer,
|
actionsAndStatusContainer,
|
||||||
extensionActionBar,
|
extensionActionBar,
|
||||||
status,
|
|
||||||
recommendation,
|
|
||||||
set extension(extension: IExtension) {
|
set extension(extension: IExtension) {
|
||||||
extensionContainers.extension = extension;
|
extensionContainers.extension = extension;
|
||||||
},
|
},
|
||||||
|
@ -544,9 +554,6 @@ export class ExtensionEditor extends EditorPane {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setStatus(extension, template);
|
|
||||||
this.setRecommendationText(extension, template);
|
|
||||||
|
|
||||||
const manifest = await this.extensionManifest.get().promise;
|
const manifest = await this.extensionManifest.get().promise;
|
||||||
if (token.isCancellationRequested) {
|
if (token.isCancellationRequested) {
|
||||||
return;
|
return;
|
||||||
|
@ -620,72 +627,6 @@ export class ExtensionEditor extends EditorPane {
|
||||||
template.navbar.onChange(e => this.onNavbarChange(extension, e, template), this, this.transientDisposables);
|
template.navbar.onChange(e => this.onNavbarChange(extension, e, template), this, this.transientDisposables);
|
||||||
}
|
}
|
||||||
|
|
||||||
private setStatus(extension: IExtension, template: IExtensionEditorTemplate): void {
|
|
||||||
const disposables = this.transientDisposables.add(new DisposableStore());
|
|
||||||
const extensionStatus = disposables.add(this.instantiationService.createInstance(ExtensionStatusAction));
|
|
||||||
extensionStatus.extension = extension;
|
|
||||||
const updateStatus = (layout: boolean) => {
|
|
||||||
disposables.clear();
|
|
||||||
reset(template.status);
|
|
||||||
const status = extensionStatus.status;
|
|
||||||
if (status) {
|
|
||||||
if (status.icon) {
|
|
||||||
const statusIconActionBar = disposables.add(new ActionBar(template.status, { animated: false }));
|
|
||||||
statusIconActionBar.push(extensionStatus, { icon: true, label: false });
|
|
||||||
}
|
|
||||||
disposables.add(this.renderMarkdownText(status.message.value, append(template.status, $('.status-text'))));
|
|
||||||
}
|
|
||||||
if (layout && this.dimension) {
|
|
||||||
this.layout(this.dimension);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
updateStatus(false);
|
|
||||||
this.transientDisposables.add(extensionStatus.onDidChangeStatus(() => updateStatus(true)));
|
|
||||||
|
|
||||||
const updateActionLayout = () => template.actionsAndStatusContainer.classList.toggle('list-layout', extension.state === ExtensionState.Installed);
|
|
||||||
updateActionLayout();
|
|
||||||
this.transientDisposables.add(this.extensionsWorkbenchService.onChange(() => updateActionLayout()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private setRecommendationText(extension: IExtension, template: IExtensionEditorTemplate): void {
|
|
||||||
const updateRecommendationText = (layout: boolean) => {
|
|
||||||
reset(template.recommendation);
|
|
||||||
const extRecommendations = this.extensionRecommendationsService.getAllRecommendationsWithReason();
|
|
||||||
if (extRecommendations[extension.identifier.id.toLowerCase()]) {
|
|
||||||
const reasonText = extRecommendations[extension.identifier.id.toLowerCase()].reasonText;
|
|
||||||
if (reasonText) {
|
|
||||||
append(template.recommendation, $(`div${ThemeIcon.asCSSSelector(starEmptyIcon)}`));
|
|
||||||
append(template.recommendation, $(`div.recommendation-text`, undefined, reasonText));
|
|
||||||
}
|
|
||||||
} else if (this.extensionIgnoredRecommendationsService.globalIgnoredRecommendations.indexOf(extension.identifier.id.toLowerCase()) !== -1) {
|
|
||||||
append(template.recommendation, $(`div.recommendation-text`, undefined, localize('recommendationHasBeenIgnored', "You have chosen not to receive recommendations for this extension.")));
|
|
||||||
}
|
|
||||||
if (layout && this.dimension) {
|
|
||||||
this.layout(this.dimension);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if (extension.deprecationInfo || extension.state === ExtensionState.Installed) {
|
|
||||||
reset(template.recommendation);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
updateRecommendationText(false);
|
|
||||||
this.transientDisposables.add(this.extensionRecommendationsService.onDidChangeRecommendations(() => updateRecommendationText(true)));
|
|
||||||
}
|
|
||||||
|
|
||||||
private renderMarkdownText(markdownText: string, parent: HTMLElement): IDisposable {
|
|
||||||
const disposables = new DisposableStore();
|
|
||||||
const rendered = disposables.add(renderMarkdown(new MarkdownString(markdownText, { isTrusted: true, supportThemeIcons: true }), {
|
|
||||||
actionHandler: {
|
|
||||||
callback: (content) => {
|
|
||||||
this.openerService.open(content, { allowCommands: true }).catch(onUnexpectedError);
|
|
||||||
},
|
|
||||||
disposables: disposables
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
append(parent, rendered.element);
|
|
||||||
return disposables;
|
|
||||||
}
|
|
||||||
|
|
||||||
override clearInput(): void {
|
override clearInput(): void {
|
||||||
this.contentDisposables.clear();
|
this.contentDisposables.clear();
|
||||||
this.transientDisposables.clear();
|
this.transientDisposables.clear();
|
||||||
|
|
|
@ -2944,6 +2944,7 @@ registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) =
|
||||||
const errorColor = theme.getColor(editorErrorForeground);
|
const errorColor = theme.getColor(editorErrorForeground);
|
||||||
if (errorColor) {
|
if (errorColor) {
|
||||||
collector.addRule(`.monaco-action-bar .action-item .action-label.extension-action.extension-status-error { color: ${errorColor}; }`);
|
collector.addRule(`.monaco-action-bar .action-item .action-label.extension-action.extension-status-error { color: ${errorColor}; }`);
|
||||||
|
collector.addRule(`.extension-editor .header .actions-status-container > .status ${ThemeIcon.asCSSSelector(errorIcon)} { color: ${errorColor}; }`);
|
||||||
collector.addRule(`.extension-editor .body .subcontent .runtime-status ${ThemeIcon.asCSSSelector(errorIcon)} { color: ${errorColor}; }`);
|
collector.addRule(`.extension-editor .body .subcontent .runtime-status ${ThemeIcon.asCSSSelector(errorIcon)} { color: ${errorColor}; }`);
|
||||||
collector.addRule(`.monaco-hover.extension-hover .markdown-hover .hover-contents ${ThemeIcon.asCSSSelector(errorIcon)} { color: ${errorColor}; }`);
|
collector.addRule(`.monaco-hover.extension-hover .markdown-hover .hover-contents ${ThemeIcon.asCSSSelector(errorIcon)} { color: ${errorColor}; }`);
|
||||||
}
|
}
|
||||||
|
@ -2951,6 +2952,7 @@ registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) =
|
||||||
const warningColor = theme.getColor(editorWarningForeground);
|
const warningColor = theme.getColor(editorWarningForeground);
|
||||||
if (warningColor) {
|
if (warningColor) {
|
||||||
collector.addRule(`.monaco-action-bar .action-item .action-label.extension-action.extension-status-warning { color: ${warningColor}; }`);
|
collector.addRule(`.monaco-action-bar .action-item .action-label.extension-action.extension-status-warning { color: ${warningColor}; }`);
|
||||||
|
collector.addRule(`.extension-editor .header .actions-status-container > .status ${ThemeIcon.asCSSSelector(warningIcon)} { color: ${warningColor}; }`);
|
||||||
collector.addRule(`.extension-editor .body .subcontent .runtime-status ${ThemeIcon.asCSSSelector(warningIcon)} { color: ${warningColor}; }`);
|
collector.addRule(`.extension-editor .body .subcontent .runtime-status ${ThemeIcon.asCSSSelector(warningIcon)} { color: ${warningColor}; }`);
|
||||||
collector.addRule(`.monaco-hover.extension-hover .markdown-hover .hover-contents ${ThemeIcon.asCSSSelector(warningIcon)} { color: ${warningColor}; }`);
|
collector.addRule(`.monaco-hover.extension-hover .markdown-hover .hover-contents ${ThemeIcon.asCSSSelector(warningIcon)} { color: ${warningColor}; }`);
|
||||||
}
|
}
|
||||||
|
@ -2958,6 +2960,7 @@ registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) =
|
||||||
const infoColor = theme.getColor(editorInfoForeground);
|
const infoColor = theme.getColor(editorInfoForeground);
|
||||||
if (infoColor) {
|
if (infoColor) {
|
||||||
collector.addRule(`.monaco-action-bar .action-item .action-label.extension-action.extension-status-info { color: ${infoColor}; }`);
|
collector.addRule(`.monaco-action-bar .action-item .action-label.extension-action.extension-status-info { color: ${infoColor}; }`);
|
||||||
|
collector.addRule(`.extension-editor .header .actions-status-container > .status ${ThemeIcon.asCSSSelector(infoIcon)} { color: ${infoColor}; }`);
|
||||||
collector.addRule(`.extension-editor .body .subcontent .runtime-status ${ThemeIcon.asCSSSelector(infoIcon)} { color: ${infoColor}; }`);
|
collector.addRule(`.extension-editor .body .subcontent .runtime-status ${ThemeIcon.asCSSSelector(infoIcon)} { color: ${infoColor}; }`);
|
||||||
collector.addRule(`.monaco-hover.extension-hover .markdown-hover .hover-contents ${ThemeIcon.asCSSSelector(infoIcon)} { color: ${infoColor}; }`);
|
collector.addRule(`.monaco-hover.extension-hover .markdown-hover .hover-contents ${ThemeIcon.asCSSSelector(infoIcon)} { color: ${infoColor}; }`);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,16 +7,16 @@ import 'vs/css!./media/extensionsWidgets';
|
||||||
import * as semver from 'vs/base/common/semver/semver';
|
import * as semver from 'vs/base/common/semver/semver';
|
||||||
import { Disposable, toDisposable, DisposableStore, MutableDisposable, IDisposable } from 'vs/base/common/lifecycle';
|
import { Disposable, toDisposable, DisposableStore, MutableDisposable, IDisposable } from 'vs/base/common/lifecycle';
|
||||||
import { IExtension, IExtensionsWorkbenchService, IExtensionContainer, ExtensionState, ExtensionEditorTab } from 'vs/workbench/contrib/extensions/common/extensions';
|
import { IExtension, IExtensionsWorkbenchService, IExtensionContainer, ExtensionState, ExtensionEditorTab } from 'vs/workbench/contrib/extensions/common/extensions';
|
||||||
import { append, $ } from 'vs/base/browser/dom';
|
import { append, $, reset } from 'vs/base/browser/dom';
|
||||||
import * as platform from 'vs/base/common/platform';
|
import * as platform from 'vs/base/common/platform';
|
||||||
import { localize } from 'vs/nls';
|
import { localize } from 'vs/nls';
|
||||||
import { EnablementState, IExtensionManagementServerService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
import { EnablementState, IExtensionManagementServerService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||||
import { IExtensionRecommendationsService } from 'vs/workbench/services/extensionRecommendations/common/extensionRecommendations';
|
import { IExtensionIgnoredRecommendationsService, IExtensionRecommendationsService } from 'vs/workbench/services/extensionRecommendations/common/extensionRecommendations';
|
||||||
import { ILabelService } from 'vs/platform/label/common/label';
|
import { ILabelService } from 'vs/platform/label/common/label';
|
||||||
import { extensionButtonProminentBackground, extensionButtonProminentForeground, ExtensionStatusAction, ReloadAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
|
import { extensionButtonProminentBackground, extensionButtonProminentForeground, ExtensionStatusAction, ReloadAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
|
||||||
import { IThemeService, ThemeIcon, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
|
import { IThemeService, ThemeIcon, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
|
||||||
import { EXTENSION_BADGE_REMOTE_BACKGROUND, EXTENSION_BADGE_REMOTE_FOREGROUND } from 'vs/workbench/common/theme';
|
import { EXTENSION_BADGE_REMOTE_BACKGROUND, EXTENSION_BADGE_REMOTE_FOREGROUND } from 'vs/workbench/common/theme';
|
||||||
import { Event } from 'vs/base/common/event';
|
import { Emitter, Event } from 'vs/base/common/event';
|
||||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
import { CountBadge } from 'vs/base/browser/ui/countBadge/countBadge';
|
import { CountBadge } from 'vs/base/browser/ui/countBadge/countBadge';
|
||||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||||
|
@ -32,6 +32,9 @@ import { areSameExtensions } from 'vs/platform/extensionManagement/common/extens
|
||||||
import Severity from 'vs/base/common/severity';
|
import Severity from 'vs/base/common/severity';
|
||||||
import { setupCustomHover } from 'vs/base/browser/ui/iconLabel/iconLabelHover';
|
import { setupCustomHover } from 'vs/base/browser/ui/iconLabel/iconLabelHover';
|
||||||
import { Color } from 'vs/base/common/color';
|
import { Color } from 'vs/base/common/color';
|
||||||
|
import { renderMarkdown } from 'vs/base/browser/markdownRenderer';
|
||||||
|
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||||
|
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||||
|
|
||||||
export abstract class ExtensionWidget extends Disposable implements IExtensionContainer {
|
export abstract class ExtensionWidget extends Disposable implements IExtensionContainer {
|
||||||
private _extension: IExtension | null = null;
|
private _extension: IExtension | null = null;
|
||||||
|
@ -576,6 +579,93 @@ export class ExtensionHoverWidget extends ExtensionWidget {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class ExtensionStatusWidget extends ExtensionWidget {
|
||||||
|
|
||||||
|
private readonly renderDisposables = this._register(new DisposableStore());
|
||||||
|
|
||||||
|
private readonly _onDidRender = this._register(new Emitter<void>());
|
||||||
|
readonly onDidRender: Event<void> = this._onDidRender.event;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private readonly container: HTMLElement,
|
||||||
|
private readonly extensionStatusAction: ExtensionStatusAction,
|
||||||
|
@IOpenerService private readonly openerService: IOpenerService,
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
this.render();
|
||||||
|
this._register(extensionStatusAction.onDidChangeStatus(() => this.render()));
|
||||||
|
}
|
||||||
|
|
||||||
|
render(): void {
|
||||||
|
reset(this.container);
|
||||||
|
const extensionStatus = this.extensionStatusAction.status;
|
||||||
|
if (extensionStatus) {
|
||||||
|
const markdown = new MarkdownString('', { isTrusted: true, supportThemeIcons: true });
|
||||||
|
if (extensionStatus.icon) {
|
||||||
|
markdown.appendMarkdown(`$(${extensionStatus.icon.id}) `);
|
||||||
|
}
|
||||||
|
markdown.appendMarkdown(extensionStatus.message.value);
|
||||||
|
const rendered = this.renderDisposables.add(renderMarkdown(markdown, {
|
||||||
|
actionHandler: {
|
||||||
|
callback: (content) => {
|
||||||
|
this.openerService.open(content, { allowCommands: true }).catch(onUnexpectedError);
|
||||||
|
},
|
||||||
|
disposables: this.renderDisposables
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
append(this.container, rendered.element);
|
||||||
|
}
|
||||||
|
this._onDidRender.fire();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ExtensionRecommendationWidget extends ExtensionWidget {
|
||||||
|
|
||||||
|
private readonly _onDidRender = this._register(new Emitter<void>());
|
||||||
|
readonly onDidRender: Event<void> = this._onDidRender.event;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private readonly container: HTMLElement,
|
||||||
|
@IExtensionRecommendationsService private readonly extensionRecommendationsService: IExtensionRecommendationsService,
|
||||||
|
@IExtensionIgnoredRecommendationsService private readonly extensionIgnoredRecommendationsService: IExtensionIgnoredRecommendationsService,
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
this.render();
|
||||||
|
this._register(this.extensionRecommendationsService.onDidChangeRecommendations(() => this.render()));
|
||||||
|
}
|
||||||
|
|
||||||
|
render(): void {
|
||||||
|
reset(this.container);
|
||||||
|
const recommendationStatus = this.getRecommendationStatus();
|
||||||
|
if (recommendationStatus) {
|
||||||
|
if (recommendationStatus.icon) {
|
||||||
|
append(this.container, $(`div${ThemeIcon.asCSSSelector(recommendationStatus.icon)}`));
|
||||||
|
}
|
||||||
|
append(this.container, $(`div.recommendation-text`, undefined, recommendationStatus.message));
|
||||||
|
}
|
||||||
|
this._onDidRender.fire();
|
||||||
|
}
|
||||||
|
|
||||||
|
private getRecommendationStatus(): { icon: ThemeIcon | undefined; message: string } | undefined {
|
||||||
|
if (!this.extension
|
||||||
|
|| this.extension.deprecationInfo
|
||||||
|
|| this.extension.state === ExtensionState.Installed
|
||||||
|
) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const extRecommendations = this.extensionRecommendationsService.getAllRecommendationsWithReason();
|
||||||
|
if (extRecommendations[this.extension.identifier.id.toLowerCase()]) {
|
||||||
|
const reasonText = extRecommendations[this.extension.identifier.id.toLowerCase()].reasonText;
|
||||||
|
if (reasonText) {
|
||||||
|
return { icon: starEmptyIcon, message: reasonText };
|
||||||
|
}
|
||||||
|
} else if (this.extensionIgnoredRecommendationsService.globalIgnoredRecommendations.indexOf(this.extension.identifier.id.toLowerCase()) !== -1) {
|
||||||
|
return { icon: undefined, message: localize('recommendationHasBeenIgnored', "You have chosen not to receive recommendations for this extension.") };
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Rating icon
|
// Rating icon
|
||||||
export const extensionRatingIconColor = registerColor('extensionIcon.starForeground', { light: '#DF6100', dark: '#FF8E00', hcDark: '#FF8E00', hcLight: textLinkForeground }, localize('extensionIconStarForeground', "The icon color for extension ratings."), true);
|
export const extensionRatingIconColor = registerColor('extensionIcon.starForeground', { light: '#DF6100', dark: '#FF8E00', hcDark: '#FF8E00', hcLight: textLinkForeground }, localize('extensionIconStarForeground', "The icon color for extension ratings."), true);
|
||||||
export const extensionVerifiedPublisherIconColor = registerColor('extensionIcon.verifiedForeground', { dark: textLinkForeground, light: textLinkForeground, hcDark: textLinkForeground, hcLight: textLinkForeground }, localize('extensionIconVerifiedForeground', "The icon color for extension verified publisher."), true);
|
export const extensionVerifiedPublisherIconColor = registerColor('extensionIcon.verifiedForeground', { dark: textLinkForeground, light: textLinkForeground, hcDark: textLinkForeground, hcLight: textLinkForeground }, localize('extensionIconVerifiedForeground', "The icon color for extension verified publisher."), true);
|
||||||
|
|
|
@ -249,49 +249,36 @@
|
||||||
.extension-editor > .header > .details > .actions-status-container > .status {
|
.extension-editor > .header > .details > .actions-status-container > .status {
|
||||||
line-height: 22px;
|
line-height: 22px;
|
||||||
font-size: 90%;
|
font-size: 90%;
|
||||||
display: flex;
|
margin-top: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.extension-editor > .header > .details > .actions-status-container.list-layout > .status {
|
.extension-editor > .header > .details > .actions-status-container.list-layout > .status {
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.extension-editor > .header > .details > .actions-status-container > .status > .monaco-action-bar {
|
.extension-editor > .header > .details > .actions-status-container > .status .codicon {
|
||||||
height: 22px;
|
vertical-align: text-bottom;
|
||||||
margin-right: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.extension-editor > .header > .details > .actions-status-container > .status > .monaco-action-bar .extension-action {
|
|
||||||
margin-top: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.extension-editor > .header > .details > .actions-status-container.list-layout > .status > .monaco-action-bar .extension-action {
|
|
||||||
margin-top: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.extension-editor > .header > .details > .actions-status-container:not(.list-layout) > .status > .status-text {
|
|
||||||
margin-top: 2px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.extension-editor > .header > .details > .pre-release-text p,
|
.extension-editor > .header > .details > .pre-release-text p,
|
||||||
.extension-editor > .header > .details > .actions-status-container > .status > .status-text p {
|
.extension-editor > .header > .details > .actions-status-container > .status p {
|
||||||
margin-top: 0px;
|
margin-top: 0px;
|
||||||
margin-bottom: 0px;
|
margin-bottom: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.extension-editor > .header > .details > .pre-release-text a,
|
.extension-editor > .header > .details > .pre-release-text a,
|
||||||
.extension-editor > .header > .details > .actions-status-container > .status > .status-text a {
|
.extension-editor > .header > .details > .actions-status-container > .status a {
|
||||||
color: var(--vscode-textLink-foreground)
|
color: var(--vscode-textLink-foreground)
|
||||||
}
|
}
|
||||||
|
|
||||||
.extension-editor > .header > .details > .pre-release-text a:hover,
|
.extension-editor > .header > .details > .pre-release-text a:hover,
|
||||||
.extension-editor > .header > .details > .actions-status-container > .status > .status-text a:hover {
|
.extension-editor > .header > .details > .actions-status-container > .status a:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
color: var(--vscode-textLink-activeForeground)
|
color: var(--vscode-textLink-activeForeground)
|
||||||
}
|
}
|
||||||
|
|
||||||
.extension-editor > .header > .details > .pre-release-text a:active,
|
.extension-editor > .header > .details > .pre-release-text a:active,
|
||||||
.extension-editor > .header > .details > .actions-status-container > .status > .status-text a:active {
|
.extension-editor > .header > .details > .actions-status-container > .status a:active {
|
||||||
color: var(--vscode-textLink-activeForeground)
|
color: var(--vscode-textLink-activeForeground)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ import { IPager } from 'vs/base/common/paging';
|
||||||
import { IQueryOptions, ILocalExtension, IGalleryExtension, IExtensionIdentifier, InstallOptions, InstallVSIXOptions, IExtensionInfo, IExtensionQueryOptions, IDeprecationInfo } from 'vs/platform/extensionManagement/common/extensionManagement';
|
import { IQueryOptions, ILocalExtension, IGalleryExtension, IExtensionIdentifier, InstallOptions, InstallVSIXOptions, IExtensionInfo, IExtensionQueryOptions, IDeprecationInfo } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||||
import { EnablementState, IExtensionManagementServer } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
import { EnablementState, IExtensionManagementServer } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||||
import { Disposable } from 'vs/base/common/lifecycle';
|
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
|
||||||
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||||
import { IExtensionManifest, ExtensionType } from 'vs/platform/extensions/common/extensions';
|
import { IExtensionManifest, ExtensionType } from 'vs/platform/extensions/common/extensions';
|
||||||
import { URI } from 'vs/base/common/uri';
|
import { URI } from 'vs/base/common/uri';
|
||||||
|
@ -136,7 +136,7 @@ export interface IExtensionsConfiguration {
|
||||||
closeExtensionDetailsOnViewChange: boolean;
|
closeExtensionDetailsOnViewChange: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IExtensionContainer {
|
export interface IExtensionContainer extends IDisposable {
|
||||||
extension: IExtension | null;
|
extension: IExtension | null;
|
||||||
updateWhenCounterExtensionChanges?: boolean;
|
updateWhenCounterExtensionChanges?: boolean;
|
||||||
update(): void;
|
update(): void;
|
||||||
|
|
|
@ -65,10 +65,10 @@ export class ExplorerDecorationsProvider implements IDecorationsProvider {
|
||||||
return this._onDidChange.event;
|
return this._onDidChange.event;
|
||||||
}
|
}
|
||||||
|
|
||||||
provideDecorations(resource: URI): IDecorationData | undefined {
|
async provideDecorations(resource: URI): Promise<IDecorationData | undefined> {
|
||||||
const fileStat = this.explorerService.findClosest(resource);
|
const fileStat = this.explorerService.findClosest(resource);
|
||||||
if (!fileStat) {
|
if (!fileStat) {
|
||||||
return undefined;
|
throw new Error('ExplorerItem not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
return provideDecorations(fileStat);
|
return provideDecorations(fileStat);
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import { language } from 'vs/base/common/platform';
|
import { language } from 'vs/base/common/platform';
|
||||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
|
||||||
import { ILanguagePackItem } from 'vs/platform/languagePacks/common/languagePacks';
|
import { ILanguagePackItem } from 'vs/platform/languagePacks/common/languagePacks';
|
||||||
import { ILocaleService } from 'vs/workbench/contrib/localization/common/locale';
|
import { ILocaleService } from 'vs/workbench/contrib/localization/common/locale';
|
||||||
|
|
||||||
|
@ -32,5 +31,3 @@ export class WebLocaleService implements ILocaleService {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
registerSingleton(ILocaleService, WebLocaleService, true);
|
|
||||||
|
|
|
@ -4,7 +4,12 @@
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import { registerAction2 } from 'vs/platform/actions/common/actions';
|
import { registerAction2 } from 'vs/platform/actions/common/actions';
|
||||||
|
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||||
|
import { WebLocaleService } from 'vs/workbench/contrib/localization/browser/localeService';
|
||||||
import { ClearDisplayLanguageAction, ConfigureDisplayLanguageAction } from 'vs/workbench/contrib/localization/browser/localizationsActions';
|
import { ClearDisplayLanguageAction, ConfigureDisplayLanguageAction } from 'vs/workbench/contrib/localization/browser/localizationsActions';
|
||||||
|
import { ILocaleService } from 'vs/workbench/contrib/localization/common/locale';
|
||||||
|
|
||||||
|
registerSingleton(ILocaleService, WebLocaleService, true);
|
||||||
|
|
||||||
// Register action to configure locale and related settings
|
// Register action to configure locale and related settings
|
||||||
registerAction2(ConfigureDisplayLanguageAction);
|
registerAction2(ConfigureDisplayLanguageAction);
|
||||||
|
|
|
@ -45,7 +45,7 @@ export class ConfigureDisplayLanguageAction extends Action2 {
|
||||||
qp.placeholder = localize('chooseLocale', "Select Display Language");
|
qp.placeholder = localize('chooseLocale', "Select Display Language");
|
||||||
|
|
||||||
if (installedLanguages?.length) {
|
if (installedLanguages?.length) {
|
||||||
const items: Array<ILanguagePackItem | IQuickPickSeparator> = [{ type: 'separator', label: localize('installed', "Installed languages") }];
|
const items: Array<ILanguagePackItem | IQuickPickSeparator> = [{ type: 'separator', label: localize('installed', "Installed") }];
|
||||||
qp.items = items.concat(installedLanguages);
|
qp.items = items.concat(installedLanguages);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ export class ConfigureDisplayLanguageAction extends Action2 {
|
||||||
if (newLanguages.length) {
|
if (newLanguages.length) {
|
||||||
qp.items = [
|
qp.items = [
|
||||||
...qp.items,
|
...qp.items,
|
||||||
{ type: 'separator', label: localize('available', "Available languages") },
|
{ type: 'separator', label: localize('available', "Available") },
|
||||||
...newLanguages
|
...newLanguages
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
|
|
||||||
import { language } from 'vs/base/common/platform';
|
import { language } from 'vs/base/common/platform';
|
||||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
|
||||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||||
import { IJSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditing';
|
import { IJSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditing';
|
||||||
import { ILocaleService } from 'vs/workbench/contrib/localization/common/locale';
|
import { ILocaleService } from 'vs/workbench/contrib/localization/common/locale';
|
||||||
|
@ -14,6 +13,8 @@ import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/b
|
||||||
import { IExtensionsViewPaneContainer, VIEWLET_ID as EXTENSIONS_VIEWLET_ID } from 'vs/workbench/contrib/extensions/common/extensions';
|
import { IExtensionsViewPaneContainer, VIEWLET_ID as EXTENSIONS_VIEWLET_ID } from 'vs/workbench/contrib/extensions/common/extensions';
|
||||||
import { ViewContainerLocation } from 'vs/workbench/common/views';
|
import { ViewContainerLocation } from 'vs/workbench/common/views';
|
||||||
import { IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
import { IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||||
|
import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress';
|
||||||
|
import { localize } from 'vs/nls';
|
||||||
|
|
||||||
export class NativeLocaleService implements ILocaleService {
|
export class NativeLocaleService implements ILocaleService {
|
||||||
_serviceBrand: undefined;
|
_serviceBrand: undefined;
|
||||||
|
@ -25,6 +26,7 @@ export class NativeLocaleService implements ILocaleService {
|
||||||
@ILanguagePackService private readonly languagePackService: ILanguagePackService,
|
@ILanguagePackService private readonly languagePackService: ILanguagePackService,
|
||||||
@IPaneCompositePartService private readonly paneCompositePartService: IPaneCompositePartService,
|
@IPaneCompositePartService private readonly paneCompositePartService: IPaneCompositePartService,
|
||||||
@IExtensionManagementService private readonly extensionManagementService: IExtensionManagementService,
|
@IExtensionManagementService private readonly extensionManagementService: IExtensionManagementService,
|
||||||
|
@IProgressService private readonly progressService: IProgressService
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
private async writeLocaleValue(locale: string | undefined): Promise<void> {
|
private async writeLocaleValue(locale: string | undefined): Promise<void> {
|
||||||
|
@ -42,16 +44,26 @@ export class NativeLocaleService implements ILocaleService {
|
||||||
// Only Desktop has the concept of installing language packs so we only do this for Desktop
|
// Only Desktop has the concept of installing language packs so we only do this for Desktop
|
||||||
// and only if the language pack is not installed
|
// and only if the language pack is not installed
|
||||||
if (!installedLanguages.some(installedLanguage => installedLanguage.id === languagePackItem.id)) {
|
if (!installedLanguages.some(installedLanguage => installedLanguage.id === languagePackItem.id)) {
|
||||||
// Show the view so the user can see the language pack to be installed
|
|
||||||
const viewlet = await this.paneCompositePartService.openPaneComposite(EXTENSIONS_VIEWLET_ID, ViewContainerLocation.Sidebar);
|
|
||||||
(viewlet?.getViewPaneContainer() as IExtensionsViewPaneContainer).search(`@id:${languagePackItem.extensionId}`);
|
|
||||||
|
|
||||||
// Only actually install a language pack from Microsoft
|
// Only actually install a language pack from Microsoft
|
||||||
if (languagePackItem.galleryExtension?.publisher.toLowerCase() !== 'ms-ceintl') {
|
if (languagePackItem.galleryExtension?.publisher.toLowerCase() !== 'ms-ceintl') {
|
||||||
|
// Show the view so the user can see the language pack that they should install
|
||||||
|
// as of now, there are no 3rd party language packs available on the Marketplace.
|
||||||
|
const viewlet = await this.paneCompositePartService.openPaneComposite(EXTENSIONS_VIEWLET_ID, ViewContainerLocation.Sidebar);
|
||||||
|
(viewlet?.getViewPaneContainer() as IExtensionsViewPaneContainer).search(`@id:${languagePackItem.extensionId}`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.extensionManagementService.installFromGallery(languagePackItem.galleryExtension);
|
await this.progressService.withProgress(
|
||||||
|
{
|
||||||
|
location: ProgressLocation.Notification,
|
||||||
|
title: localize('installing', "Installing {0} language support...", languagePackItem.label),
|
||||||
|
},
|
||||||
|
progress => this.extensionManagementService.installFromGallery(languagePackItem.galleryExtension!, {
|
||||||
|
// Setting this to false is how you get the extension to be synced with Settings Sync (if enabled).
|
||||||
|
isMachineScoped: false,
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.writeLocaleValue(locale);
|
await this.writeLocaleValue(locale);
|
||||||
|
@ -75,5 +87,3 @@ export class NativeLocaleService implements ILocaleService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
registerSingleton(ILocaleService, NativeLocaleService, true);
|
|
||||||
|
|
|
@ -25,6 +25,11 @@ import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/b
|
||||||
import { ViewContainerLocation } from 'vs/workbench/common/views';
|
import { ViewContainerLocation } from 'vs/workbench/common/views';
|
||||||
import { registerAction2 } from 'vs/platform/actions/common/actions';
|
import { registerAction2 } from 'vs/platform/actions/common/actions';
|
||||||
import { ClearDisplayLanguageAction, ConfigureDisplayLanguageAction } from 'vs/workbench/contrib/localization/browser/localizationsActions';
|
import { ClearDisplayLanguageAction, ConfigureDisplayLanguageAction } from 'vs/workbench/contrib/localization/browser/localizationsActions';
|
||||||
|
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||||
|
import { ILocaleService } from 'vs/workbench/contrib/localization/common/locale';
|
||||||
|
import { NativeLocaleService } from 'vs/workbench/contrib/localization/electron-sandbox/localeService';
|
||||||
|
|
||||||
|
registerSingleton(ILocaleService, NativeLocaleService, true);
|
||||||
|
|
||||||
// Register action to configure locale and related settings
|
// Register action to configure locale and related settings
|
||||||
registerAction2(ConfigureDisplayLanguageAction);
|
registerAction2(ConfigureDisplayLanguageAction);
|
||||||
|
|
|
@ -11,7 +11,7 @@ import { LineRange } from 'vs/workbench/contrib/mergeEditor/browser/model';
|
||||||
|
|
||||||
export class EditorGutter<
|
export class EditorGutter<
|
||||||
T extends IGutterItemInfo = IGutterItemInfo
|
T extends IGutterItemInfo = IGutterItemInfo
|
||||||
> extends Disposable {
|
> extends Disposable {
|
||||||
private readonly scrollTop = observableFromEvent(
|
private readonly scrollTop = observableFromEvent(
|
||||||
this._editor.onDidScrollChange,
|
this._editor.onDidScrollChange,
|
||||||
(e) => this._editor.getScrollTop()
|
(e) => this._editor.getScrollTop()
|
||||||
|
|
|
@ -285,15 +285,15 @@ export class NotebookClipboardContribution extends Disposable {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PasteAction) {
|
if (PasteAction) {
|
||||||
PasteAction.addImplementation(PRIORITY, 'notebook-clipboard', accessor => {
|
this._register(PasteAction.addImplementation(PRIORITY, 'notebook-clipboard', accessor => {
|
||||||
return this.runPasteAction(accessor);
|
return this.runPasteAction(accessor);
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CutAction) {
|
if (CutAction) {
|
||||||
CutAction.addImplementation(PRIORITY, 'notebook-clipboard', accessor => {
|
this._register(CutAction.addImplementation(PRIORITY, 'notebook-clipboard', accessor => {
|
||||||
return this.runCutAction(accessor);
|
return this.runCutAction(accessor);
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -131,21 +131,20 @@ const notebookRendererContribution: IJSONSchema = {
|
||||||
{
|
{
|
||||||
type: 'string',
|
type: 'string',
|
||||||
},
|
},
|
||||||
// todo@connor4312 + @mjbvz: uncomment this once it's ready for external adoption
|
{
|
||||||
// {
|
type: 'object',
|
||||||
// type: 'object',
|
required: ['extends', 'path'],
|
||||||
// required: ['extends', 'path'],
|
properties: {
|
||||||
// properties: {
|
extends: {
|
||||||
// extends: {
|
type: 'string',
|
||||||
// type: 'string',
|
description: nls.localize('contributes.notebook.renderer.entrypoint.extends', 'Existing renderer that this one extends.'),
|
||||||
// description: nls.localize('contributes.notebook.renderer.entrypoint.extends', 'Existing renderer that this one extends.'),
|
},
|
||||||
// },
|
path: {
|
||||||
// path: {
|
type: 'string',
|
||||||
// type: 'string',
|
description: nls.localize('contributes.notebook.renderer.entrypoint', 'File to load in the webview to render the extension.'),
|
||||||
// description: nls.localize('contributes.notebook.renderer.entrypoint', 'File to load in the webview to render the extension.'),
|
},
|
||||||
// },
|
}
|
||||||
// }
|
}
|
||||||
// }
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
[NotebookRendererContribution.hardDependencies]: {
|
[NotebookRendererContribution.hardDependencies]: {
|
||||||
|
|
|
@ -75,7 +75,7 @@ export const RENDERER_EQUIVALENT_EXTENSIONS: ReadonlyMap<string, ReadonlySet<str
|
||||||
|
|
||||||
export const RENDERER_NOT_AVAILABLE = '_notAvailable';
|
export const RENDERER_NOT_AVAILABLE = '_notAvailable';
|
||||||
|
|
||||||
export type NotebookRendererEntrypoint = string | { extends: string; path: string };
|
export type NotebookRendererEntrypoint = string | { readonly extends: string; readonly path: string };
|
||||||
|
|
||||||
export enum NotebookRunState {
|
export enum NotebookRunState {
|
||||||
Running = 1,
|
Running = 1,
|
||||||
|
|
|
@ -109,15 +109,23 @@
|
||||||
/* padding must be on action-label because it has the bottom-border, because that's where the .checked class is */
|
/* padding must be on action-label because it has the bottom-border, because that's where the .checked class is */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.settings-editor > .settings-header > .settings-header-controls .settings-tabs-widget > .monaco-action-bar .action-item.focused {
|
||||||
|
outline-offset: -1.5px;
|
||||||
|
}
|
||||||
|
|
||||||
.settings-editor > .settings-header > .settings-header-controls .settings-tabs-widget > .monaco-action-bar .action-item .action-label {
|
.settings-editor > .settings-header > .settings-header-controls .settings-tabs-widget > .monaco-action-bar .action-item .action-label {
|
||||||
text-transform: none;
|
text-transform: none;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
padding-bottom: 7px;
|
padding-bottom: 6.5px;
|
||||||
padding-top: 7px;
|
padding-top: 7px;
|
||||||
padding-left: 8px;
|
padding-left: 8px;
|
||||||
padding-right: 8px;
|
padding-right: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.settings-editor > .settings-header > .settings-header-controls .settings-tabs-widget > .monaco-action-bar .action-item .action-label .dropdown-icon {
|
||||||
|
padding-top: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
.settings-editor > .settings-header > .settings-header-controls .settings-tabs-widget > .monaco-action-bar .action-item .action-label:not(.checked):not(:focus) {
|
.settings-editor > .settings-header > .settings-header-controls .settings-tabs-widget > .monaco-action-bar .action-item .action-label:not(.checked):not(:focus) {
|
||||||
/* Add an extra pixel due to it not getting the outline */
|
/* Add an extra pixel due to it not getting the outline */
|
||||||
padding-bottom: 8px;
|
padding-bottom: 8px;
|
||||||
|
|
|
@ -37,7 +37,7 @@ export function isSCMResource(element: any): element is ISCMResource {
|
||||||
return !!(element as ISCMResource).sourceUri && isSCMResourceGroup((element as ISCMResource).resourceGroup);
|
return !!(element as ISCMResource).sourceUri && isSCMResourceGroup((element as ISCMResource).resourceGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
const compareActions = (a: IAction, b: IAction) => a.id === b.id;
|
const compareActions = (a: IAction, b: IAction) => a.id === b.id && a.enabled === b.enabled;
|
||||||
|
|
||||||
export function connectPrimaryMenu(menu: IMenu, callback: (primary: IAction[], secondary: IAction[]) => void, primaryGroup?: string): IDisposable {
|
export function connectPrimaryMenu(menu: IMenu, callback: (primary: IAction[], secondary: IAction[]) => void, primaryGroup?: string): IDisposable {
|
||||||
let cachedDisposable: IDisposable = Disposable.None;
|
let cachedDisposable: IDisposable = Disposable.None;
|
||||||
|
|
|
@ -1480,7 +1480,7 @@ namespace ConfiguringTask {
|
||||||
for (const required of typeDeclaration.required) {
|
for (const required of typeDeclaration.required) {
|
||||||
const value = result.configures[required];
|
const value = result.configures[required];
|
||||||
if (value) {
|
if (value) {
|
||||||
label = label + ' ' + value;
|
label = label + ': ' + value;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,6 +71,14 @@ __vsc_command_complete() {
|
||||||
__vsc_update_cwd
|
__vsc_update_cwd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if [[ -o NOUNSET ]]; then
|
||||||
|
if [ -z "${RPROMPT-}" ]; then
|
||||||
|
RPROMPT=""
|
||||||
|
fi
|
||||||
|
if [ -z "${PREFIX-}" ]; then
|
||||||
|
PREFIX=""
|
||||||
|
fi
|
||||||
|
fi
|
||||||
__vsc_update_prompt() {
|
__vsc_update_prompt() {
|
||||||
__vsc_prior_prompt="$PS1"
|
__vsc_prior_prompt="$PS1"
|
||||||
__vsc_in_command_execution=""
|
__vsc_in_command_execution=""
|
||||||
|
|
|
@ -929,10 +929,12 @@ export class TerminalService implements ITerminalService {
|
||||||
// Await the initialization of available profiles as long as this is not a pty terminal or a
|
// Await the initialization of available profiles as long as this is not a pty terminal or a
|
||||||
// local terminal in a remote workspace as profile won't be used in those cases and these
|
// local terminal in a remote workspace as profile won't be used in those cases and these
|
||||||
// terminals need to be launched before remote connections are established.
|
// terminals need to be launched before remote connections are established.
|
||||||
const isPtyTerminal = options?.config && 'customPtyImplementation' in options.config;
|
if (this._terminalProfileService.availableProfiles.length === 0) {
|
||||||
const isLocalInRemoteTerminal = this._remoteAgentService.getConnection() && URI.isUri(options?.cwd) && options?.cwd.scheme === Schemas.vscodeFileResource;
|
const isPtyTerminal = options?.config && 'customPtyImplementation' in options.config;
|
||||||
if (!isPtyTerminal && !isLocalInRemoteTerminal) {
|
const isLocalInRemoteTerminal = this._remoteAgentService.getConnection() && URI.isUri(options?.cwd) && options?.cwd.scheme === Schemas.vscodeFileResource;
|
||||||
await this._terminalProfileService.profilesReady;
|
if (!isPtyTerminal && !isLocalInRemoteTerminal) {
|
||||||
|
await this._terminalProfileService.profilesReady;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const config = options?.config || this._terminalProfileService.availableProfiles?.find(p => p.profileName === this._terminalProfileService.getDefaultProfileName());
|
const config = options?.config || this._terminalProfileService.availableProfiles?.find(p => p.profileName === this._terminalProfileService.getDefaultProfileName());
|
||||||
|
|
|
@ -118,8 +118,11 @@ export class DecorationAddon extends Disposable implements ITerminalAddon {
|
||||||
}
|
}
|
||||||
|
|
||||||
public clearDecorations(): void {
|
public clearDecorations(): void {
|
||||||
this._placeholderDecoration?.dispose();
|
if (this._placeholderDecoration) {
|
||||||
this._placeholderDecoration?.marker.dispose();
|
this._placeholderDecoration.marker.dispose();
|
||||||
|
this._placeholderDecoration.dispose();
|
||||||
|
this._placeholderDecoration = undefined;
|
||||||
|
}
|
||||||
for (const value of this._decorations.values()) {
|
for (const value of this._decorations.values()) {
|
||||||
value.decoration.dispose();
|
value.decoration.dispose();
|
||||||
dispose(value.disposables);
|
dispose(value.disposables);
|
||||||
|
|
|
@ -398,7 +398,8 @@ export class DecorationsService implements IDecorationsService {
|
||||||
|
|
||||||
private _keepItem(map: DecorationEntry, provider: IDecorationsProvider, uri: URI, data: IDecorationData | undefined): IDecorationData | null {
|
private _keepItem(map: DecorationEntry, provider: IDecorationsProvider, uri: URI, data: IDecorationData | undefined): IDecorationData | null {
|
||||||
const deco = data ? data : null;
|
const deco = data ? data : null;
|
||||||
const old = map.set(provider, deco);
|
const old = map.get(provider);
|
||||||
|
map.set(provider, deco);
|
||||||
if (deco || old) {
|
if (deco || old) {
|
||||||
// only fire event when something changed
|
// only fire event when something changed
|
||||||
this._onDidChangeDecorationsDelayed.fire(uri);
|
this._onDidChangeDecorationsDelayed.fire(uri);
|
||||||
|
|
|
@ -30,7 +30,7 @@ import { flatten } from 'vs/base/common/arrays';
|
||||||
import { INativeHostService } from 'vs/platform/native/electron-sandbox/native';
|
import { INativeHostService } from 'vs/platform/native/electron-sandbox/native';
|
||||||
import { IRemoteExplorerService } from 'vs/workbench/services/remote/common/remoteExplorerService';
|
import { IRemoteExplorerService } from 'vs/workbench/services/remote/common/remoteExplorerService';
|
||||||
import { Action2, registerAction2 } from 'vs/platform/actions/common/actions';
|
import { Action2, registerAction2 } from 'vs/platform/actions/common/actions';
|
||||||
import { getRemoteName } from 'vs/platform/remote/common/remoteHosts';
|
import { getRemoteName, parseAuthorityWithPort } from 'vs/platform/remote/common/remoteHosts';
|
||||||
import { IRemoteAgentEnvironment } from 'vs/platform/remote/common/remoteAgentEnvironment';
|
import { IRemoteAgentEnvironment } from 'vs/platform/remote/common/remoteAgentEnvironment';
|
||||||
import { IWebWorkerExtensionHostDataProvider, IWebWorkerExtensionHostInitData, WebWorkerExtensionHost } from 'vs/workbench/services/extensions/browser/webWorkerExtensionHost';
|
import { IWebWorkerExtensionHostDataProvider, IWebWorkerExtensionHostInitData, WebWorkerExtensionHost } from 'vs/workbench/services/extensions/browser/webWorkerExtensionHost';
|
||||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||||
|
@ -349,12 +349,12 @@ export abstract class ElectronExtensionService extends AbstractExtensionService
|
||||||
const authorityPlusIndex = remoteAuthority.indexOf('+');
|
const authorityPlusIndex = remoteAuthority.indexOf('+');
|
||||||
if (authorityPlusIndex === -1) {
|
if (authorityPlusIndex === -1) {
|
||||||
// This authority does not need to be resolved, simply parse the port number
|
// This authority does not need to be resolved, simply parse the port number
|
||||||
const lastColon = remoteAuthority.lastIndexOf(':');
|
const { host, port } = parseAuthorityWithPort(remoteAuthority);
|
||||||
return {
|
return {
|
||||||
authority: {
|
authority: {
|
||||||
authority: remoteAuthority,
|
authority: remoteAuthority,
|
||||||
host: remoteAuthority.substring(0, lastColon),
|
host,
|
||||||
port: parseInt(remoteAuthority.substring(lastColon + 1), 10),
|
port,
|
||||||
connectionToken: undefined
|
connectionToken: undefined
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -83,7 +83,6 @@ import 'vs/workbench/services/files/electron-sandbox/elevatedFileService';
|
||||||
import 'vs/workbench/services/search/electron-sandbox/searchService';
|
import 'vs/workbench/services/search/electron-sandbox/searchService';
|
||||||
import 'vs/workbench/services/workingCopy/electron-sandbox/workingCopyHistoryService';
|
import 'vs/workbench/services/workingCopy/electron-sandbox/workingCopyHistoryService';
|
||||||
import 'vs/workbench/services/userDataSync/browser/userDataSyncEnablementService';
|
import 'vs/workbench/services/userDataSync/browser/userDataSyncEnablementService';
|
||||||
import 'vs/workbench/contrib/localization/electron-sandbox/localeService';
|
|
||||||
|
|
||||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||||
import { IUserDataInitializationService, UserDataInitializationService } from 'vs/workbench/services/userData/browser/userDataInit';
|
import { IUserDataInitializationService, UserDataInitializationService } from 'vs/workbench/services/userData/browser/userDataInit';
|
||||||
|
|
|
@ -62,7 +62,6 @@ import 'vs/workbench/services/files/browser/elevatedFileService';
|
||||||
import 'vs/workbench/services/workingCopy/browser/workingCopyHistoryService';
|
import 'vs/workbench/services/workingCopy/browser/workingCopyHistoryService';
|
||||||
import 'vs/workbench/services/userDataSync/browser/webUserDataSyncEnablementService';
|
import 'vs/workbench/services/userDataSync/browser/webUserDataSyncEnablementService';
|
||||||
import 'vs/workbench/services/configurationResolver/browser/configurationResolverService';
|
import 'vs/workbench/services/configurationResolver/browser/configurationResolverService';
|
||||||
import 'vs/workbench/contrib/localization/browser/localeService';
|
|
||||||
|
|
||||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||||
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
|
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
|
||||||
|
|
|
@ -19,11 +19,11 @@ declare module 'vscode' {
|
||||||
* a {@link DataTransfer} and is passed back to the provider in {@link provideDocumentPasteEdits}.
|
* a {@link DataTransfer} and is passed back to the provider in {@link provideDocumentPasteEdits}.
|
||||||
*
|
*
|
||||||
* @param document Document where the copy took place.
|
* @param document Document where the copy took place.
|
||||||
* @param range Range being copied in the `document`.
|
* @param ranges Ranges being copied in the `document`.
|
||||||
* @param dataTransfer The data transfer associated with the copy. You can store additional values on this for later use in {@link provideDocumentPasteEdits}.
|
* @param dataTransfer The data transfer associated with the copy. You can store additional values on this for later use in {@link provideDocumentPasteEdits}.
|
||||||
* @param token A cancellation token.
|
* @param token A cancellation token.
|
||||||
*/
|
*/
|
||||||
prepareDocumentPaste?(document: TextDocument, range: Range, dataTransfer: DataTransfer, token: CancellationToken): void | Thenable<void>;
|
prepareDocumentPaste?(document: TextDocument, ranges: readonly Range[], dataTransfer: DataTransfer, token: CancellationToken): void | Thenable<void>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoked before the user pastes into a document.
|
* Invoked before the user pastes into a document.
|
||||||
|
@ -31,16 +31,40 @@ declare module 'vscode' {
|
||||||
* In this method, extensions can return a workspace edit that replaces the standard pasting behavior.
|
* In this method, extensions can return a workspace edit that replaces the standard pasting behavior.
|
||||||
*
|
*
|
||||||
* @param document Document being pasted into
|
* @param document Document being pasted into
|
||||||
* @param range Currently selected range in the document.
|
* @param ranges Currently selected ranges in the document.
|
||||||
* @param dataTransfer The data transfer associated with the paste.
|
* @param dataTransfer The data transfer associated with the paste.
|
||||||
* @param token A cancellation token.
|
* @param token A cancellation token.
|
||||||
*
|
*
|
||||||
* @return Optional workspace edit that applies the paste. Return undefined to use standard pasting.
|
* @return Optional workspace edit that applies the paste. Return undefined to use standard pasting.
|
||||||
*/
|
*/
|
||||||
provideDocumentPasteEdits(document: TextDocument, range: Range, dataTransfer: DataTransfer, token: CancellationToken): ProviderResult<WorkspaceEdit | SnippetTextEdit>;
|
provideDocumentPasteEdits(document: TextDocument, ranges: readonly Range[], dataTransfer: DataTransfer, token: CancellationToken): ProviderResult<DocumentPasteEdit>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An operation applied on paste
|
||||||
|
*/
|
||||||
|
interface DocumentPasteEdit {
|
||||||
|
/**
|
||||||
|
* The text or snippet to insert at the pasted locations.
|
||||||
|
*/
|
||||||
|
readonly insertText: string | SnippetString;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An optional additional edit to apply on paste.
|
||||||
|
*/
|
||||||
|
readonly additionalEdit?: WorkspaceEdit;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DocumentPasteProviderMetadata {
|
||||||
|
/**
|
||||||
|
* Mime types that `provideDocumentPasteEdits` should be invoked for.
|
||||||
|
*
|
||||||
|
* Use the special `files` mimetype to indicate the provider should be invoked if any files are present in the `DataTransfer`.
|
||||||
|
*/
|
||||||
|
readonly pasteMimeTypes: readonly string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace languages {
|
namespace languages {
|
||||||
export function registerDocumentPasteEditProvider(selector: DocumentSelector, provider: DocumentPasteEditProvider): Disposable;
|
export function registerDocumentPasteEditProvider(selector: DocumentSelector, provider: DocumentPasteEditProvider, metadata: DocumentPasteProviderMetadata): Disposable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,12 +7,6 @@ declare module 'vscode' {
|
||||||
|
|
||||||
// https://github.com/microsoft/vscode/issues/142990
|
// https://github.com/microsoft/vscode/issues/142990
|
||||||
|
|
||||||
export class SnippetTextEdit {
|
|
||||||
snippet: SnippetString;
|
|
||||||
range: Range;
|
|
||||||
constructor(range: Range, snippet: SnippetString);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provider which handles dropping of resources into a text editor.
|
* Provider which handles dropping of resources into a text editor.
|
||||||
*
|
*
|
||||||
|
@ -27,10 +21,25 @@ declare module 'vscode' {
|
||||||
* @param dataTransfer A {@link DataTransfer} object that holds data about what is being dragged and dropped.
|
* @param dataTransfer A {@link DataTransfer} object that holds data about what is being dragged and dropped.
|
||||||
* @param token A cancellation token.
|
* @param token A cancellation token.
|
||||||
*
|
*
|
||||||
* @return A {@link SnippetTextEdit} or a thenable that resolves to such. The lack of a result can be
|
* @return A {@link DocumentDropEdit} or a thenable that resolves to such. The lack of a result can be
|
||||||
* signaled by returning `undefined` or `null`.
|
* signaled by returning `undefined` or `null`.
|
||||||
*/
|
*/
|
||||||
provideDocumentOnDropEdits(document: TextDocument, position: Position, dataTransfer: DataTransfer, token: CancellationToken): ProviderResult<SnippetTextEdit>;
|
provideDocumentOnDropEdits(document: TextDocument, position: Position, dataTransfer: DataTransfer, token: CancellationToken): ProviderResult<DocumentDropEdit>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An edit operation applied on drop.
|
||||||
|
*/
|
||||||
|
export interface DocumentDropEdit {
|
||||||
|
/**
|
||||||
|
* The text or snippet to insert at the drop location.
|
||||||
|
*/
|
||||||
|
readonly insertText: string | SnippetString;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An optional additional edit to apply on drop.
|
||||||
|
*/
|
||||||
|
readonly additionalEdit?: WorkspaceEdit;
|
||||||
}
|
}
|
||||||
|
|
||||||
export namespace languages {
|
export namespace languages {
|
||||||
|
|
|
@ -11390,10 +11390,10 @@ typescript@^2.6.2:
|
||||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.6.2.tgz#3c5b6fd7f6de0914269027f03c0946758f7673a4"
|
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.6.2.tgz#3c5b6fd7f6de0914269027f03c0946758f7673a4"
|
||||||
integrity sha1-PFtv1/beCRQmkCfwPAlGdY92c6Q=
|
integrity sha1-PFtv1/beCRQmkCfwPAlGdY92c6Q=
|
||||||
|
|
||||||
typescript@^4.8.0-dev.20220518:
|
typescript@^4.8.0-dev.20220608:
|
||||||
version "4.8.0-dev.20220518"
|
version "4.8.0-dev.20220608"
|
||||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.8.0-dev.20220518.tgz#3082c89c764daece904480552b9f2c3f5ce79c56"
|
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.8.0-dev.20220608.tgz#6da2ea3c79307b1dfc1cb3692b142cc13f974a98"
|
||||||
integrity sha512-yczRLiowXD4THxpe2DrClYXsmIRt9VPDft1dat4Le50mQwuUcmvdqD43o4hmlbNP7HpyeEYX51KXozGq1s7zlw==
|
integrity sha512-cayjhBae7omJ5MYxt4fO2PNW7kjYNCRqOOQbafxuzP0SWpqznzPROuNQqiBK1KJfgnRxBWeyqGBP52mdZDYZVw==
|
||||||
|
|
||||||
typical@^4.0.0:
|
typical@^4.0.0:
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
|
|
Loading…
Reference in a new issue