mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-08 09:08:48 +01:00
Merge branch 'master' into issue/88294
This commit is contained in:
@@ -447,6 +447,22 @@
|
||||
"command": "git.stashDrop",
|
||||
"title": "%command.stashDrop%",
|
||||
"category": "Git"
|
||||
},
|
||||
{
|
||||
"command": "git.timeline.openDiff",
|
||||
"title": "%command.timelineOpenDiff%",
|
||||
"icon": "$(compare-changes)",
|
||||
"category": "Git"
|
||||
},
|
||||
{
|
||||
"command": "git.timeline.copyCommitId",
|
||||
"title": "%command.timelineCopyCommitId%",
|
||||
"category": "Git"
|
||||
},
|
||||
{
|
||||
"command": "git.timeline.copyCommitMessage",
|
||||
"title": "%command.timelineCopyCommitMessage%",
|
||||
"category": "Git"
|
||||
}
|
||||
],
|
||||
"menus": {
|
||||
@@ -718,14 +734,21 @@
|
||||
{
|
||||
"command": "git.stashDrop",
|
||||
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
|
||||
},
|
||||
{
|
||||
"command": "git.timeline.openDiff",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "git.timeline.copyCommitId",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "git.timeline.copyCommitMessage",
|
||||
"when": "false"
|
||||
}
|
||||
],
|
||||
"scm/title": [
|
||||
{
|
||||
"command": "git.init",
|
||||
"group": "navigation",
|
||||
"when": "config.git.enabled && !scmProvider && gitOpenRepositoryCount == 0 && workspaceFolderCount != 0"
|
||||
},
|
||||
{
|
||||
"command": "git.commit",
|
||||
"group": "navigation",
|
||||
@@ -1248,6 +1271,28 @@
|
||||
"command": "git.revertChange",
|
||||
"when": "originalResourceScheme == git"
|
||||
}
|
||||
],
|
||||
"timeline/item/context": [
|
||||
{
|
||||
"command": "git.timeline.openDiff",
|
||||
"group": "inline",
|
||||
"when": "timelineItem =~ /git:file\\b/"
|
||||
},
|
||||
{
|
||||
"command": "git.timeline.openDiff",
|
||||
"group": "1_timeline",
|
||||
"when": "timelineItem =~ /git:file\\b/"
|
||||
},
|
||||
{
|
||||
"command": "git.timeline.copyCommitId",
|
||||
"group": "2_timeline@1",
|
||||
"when": "timelineItem =~ /git:file:commit\\b/"
|
||||
},
|
||||
{
|
||||
"command": "git.timeline.copyCommitMessage",
|
||||
"group": "2_timeline@2",
|
||||
"when": "timelineItem =~ /git:file:commit\\b/"
|
||||
}
|
||||
]
|
||||
},
|
||||
"configuration": {
|
||||
@@ -1761,7 +1806,34 @@
|
||||
72
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"viewsWelcome": [
|
||||
{
|
||||
"view": "workbench.scm",
|
||||
"contents": "%view.workbench.scm.disabled%",
|
||||
"when": "!config.git.enabled"
|
||||
},
|
||||
{
|
||||
"view": "workbench.scm",
|
||||
"contents": "%view.workbench.scm.missing%",
|
||||
"when": "config.git.enabled && git.missing"
|
||||
},
|
||||
{
|
||||
"view": "workbench.scm",
|
||||
"contents": "%view.workbench.scm.empty%",
|
||||
"when": "config.git.enabled && !git.missing && workbenchState == empty"
|
||||
},
|
||||
{
|
||||
"view": "workbench.scm",
|
||||
"contents": "%view.workbench.scm.folder%",
|
||||
"when": "config.git.enabled && !git.missing && workbenchState == folder"
|
||||
},
|
||||
{
|
||||
"view": "workbench.scm",
|
||||
"contents": "%view.workbench.scm.workspace%",
|
||||
"when": "config.git.enabled && !git.missing && workbenchState == workspace"
|
||||
}
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"byline": "^5.0.0",
|
||||
|
||||
@@ -70,6 +70,9 @@
|
||||
"command.stashApply": "Apply Stash...",
|
||||
"command.stashApplyLatest": "Apply Latest Stash",
|
||||
"command.stashDrop": "Drop Stash...",
|
||||
"command.timelineOpenDiff": "Open Changes",
|
||||
"command.timelineCopyCommitId": "Copy Commit ID",
|
||||
"command.timelineCopyCommitMessage": "Copy Commit Message",
|
||||
"config.enabled": "Whether git is enabled.",
|
||||
"config.path": "Path and filename of the git executable, e.g. `C:\\Program Files\\Git\\bin\\git.exe` (Windows).",
|
||||
"config.autoRepositoryDetection": "Configures when repositories should be automatically detected.",
|
||||
@@ -127,7 +130,7 @@
|
||||
"config.showProgress": "Controls whether git actions should show progress.",
|
||||
"config.rebaseWhenSync": "Force git to use rebase when running the sync command.",
|
||||
"config.confirmEmptyCommits": "Always confirm the creation of empty commits for the 'Git: Commit Empty' command.",
|
||||
"config.fetchOnPull": "Fetch all branches when pulling or just the current one.",
|
||||
"config.fetchOnPull": "When enabled, fetch all branches when pulling. Otherwise, fetch just the current one.",
|
||||
"config.pullTags": "Fetch all tags when pulling.",
|
||||
"config.autoStash": "Stash any changes before pulling and restore them after successful pull.",
|
||||
"config.allowForcePush": "Controls whether force push (with or without lease) is enabled.",
|
||||
@@ -146,5 +149,10 @@
|
||||
"colors.untracked": "Color for untracked resources.",
|
||||
"colors.ignored": "Color for ignored resources.",
|
||||
"colors.conflict": "Color for resources with conflicts.",
|
||||
"colors.submodule": "Color for submodule resources."
|
||||
"colors.submodule": "Color for submodule resources.",
|
||||
"view.workbench.scm.missing": "A valid git installation was not detected, more details can be found in the [git output](command:git.showOutput).\nPlease [install git](https://git-scm.com/), or learn more about how to use Git and source control in VS Code in [our docs](https://aka.ms/vscode-scm).\nIf you're using a different version control system, you can [search the Marketplace](command:workbench.extensions.search?%22%40category%3A%5C%22scm%20providers%5C%22%22) for additional extensions.",
|
||||
"view.workbench.scm.disabled": "If you would like to use git features, please enable git in your [settings](command:workbench.action.openSettings?%5B%22git.enabled%22%5D).\nTo learn more about how to use Git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).",
|
||||
"view.workbench.scm.empty": "In order to use git features, you can open a folder containing a git repository or clone from a URL.\n[Open Folder](command:vscode.openFolder)\n[Clone from URL](command:git.clone)\nTo learn more about how to use Git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).",
|
||||
"view.workbench.scm.folder": "The folder currently open doesn't have a git repository.\n[Initialize Repository](command:git.init)\nTo learn more about how to use Git and source control in VS Code [read our docs](https://aka.ms/vscode-scm).",
|
||||
"view.workbench.scm.workspace": "The workspace currently open doesn't have any folders containing git repositories.\n[Initialize Repository](command:git.init)\nTo learn more about how to use Git and source control in VS Code [read our docs](https://aka.ms/vscode-scm)."
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { lstat, Stats } from 'fs';
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import { commands, Disposable, LineChange, MessageOptions, OutputChannel, Position, ProgressLocation, QuickPickItem, Range, SourceControlResourceState, TextDocumentShowOptions, TextEditor, Uri, ViewColumn, window, workspace, WorkspaceEdit, WorkspaceFolder } from 'vscode';
|
||||
import { commands, Disposable, LineChange, MessageOptions, OutputChannel, Position, ProgressLocation, QuickPickItem, Range, SourceControlResourceState, TextDocumentShowOptions, TextEditor, Uri, ViewColumn, window, workspace, WorkspaceEdit, WorkspaceFolder, TimelineItem, env } from 'vscode';
|
||||
import TelemetryReporter from 'vscode-extension-telemetry';
|
||||
import * as nls from 'vscode-nls';
|
||||
import { Branch, GitErrorCodes, Ref, RefType, Status, CommitOptions } from './api/git';
|
||||
@@ -17,6 +17,7 @@ import { applyLineChanges, getModifiedRange, intersectDiffWithRange, invertLineC
|
||||
import { fromGitUri, toGitUri, isGitUri } from './uri';
|
||||
import { grep, isDescendant, pathEquals } from './util';
|
||||
import { Log, LogLevel } from './log';
|
||||
import { GitTimelineItem } from './timelineProvider';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
@@ -2331,23 +2332,47 @@ export class CommandCenter {
|
||||
return result && result.stash;
|
||||
}
|
||||
|
||||
@command('git.openDiff', { repository: false })
|
||||
async openDiff(uri: Uri, lhs: string, rhs: string) {
|
||||
@command('git.timeline.openDiff', { repository: false })
|
||||
async timelineOpenDiff(item: TimelineItem, uri: Uri | undefined, _source: string) {
|
||||
// eslint-disable-next-line eqeqeq
|
||||
if (uri == null || !GitTimelineItem.is(item)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const basename = path.basename(uri.fsPath);
|
||||
|
||||
let title;
|
||||
if ((lhs === 'HEAD' || lhs === '~') && rhs === '') {
|
||||
if ((item.previousRef === 'HEAD' || item.previousRef === '~') && item.ref === '') {
|
||||
title = `${basename} (Working Tree)`;
|
||||
}
|
||||
else if (lhs === 'HEAD' && rhs === '~') {
|
||||
else if (item.previousRef === 'HEAD' && item.ref === '~') {
|
||||
title = `${basename} (Index)`;
|
||||
} else {
|
||||
title = `${basename} (${lhs.endsWith('^') ? `${lhs.substr(0, 8)}^` : lhs.substr(0, 8)}) \u27f7 ${basename} (${rhs.endsWith('^') ? `${rhs.substr(0, 8)}^` : rhs.substr(0, 8)})`;
|
||||
title = `${basename} (${item.shortPreviousRef}) \u27f7 ${basename} (${item.shortRef})`;
|
||||
}
|
||||
|
||||
return commands.executeCommand('vscode.diff', toGitUri(uri, lhs), rhs === '' ? uri : toGitUri(uri, rhs), title);
|
||||
return commands.executeCommand('vscode.diff', toGitUri(uri, item.previousRef), item.ref === '' ? uri : toGitUri(uri, item.ref), title);
|
||||
}
|
||||
|
||||
@command('git.timeline.copyCommitId', { repository: false })
|
||||
async timelineCopyCommitId(item: TimelineItem, _uri: Uri | undefined, _source: string) {
|
||||
if (!GitTimelineItem.is(item)) {
|
||||
return;
|
||||
}
|
||||
|
||||
env.clipboard.writeText(item.ref);
|
||||
}
|
||||
|
||||
@command('git.timeline.copyCommitMessage', { repository: false })
|
||||
async timelineCopyCommitMessage(item: TimelineItem, _uri: Uri | undefined, _source: string) {
|
||||
if (!GitTimelineItem.is(item)) {
|
||||
return;
|
||||
}
|
||||
|
||||
env.clipboard.writeText(item.message);
|
||||
}
|
||||
|
||||
|
||||
private createCommand(id: string, key: string, method: Function, options: CommandOptions): (...args: any[]) => any {
|
||||
const result = (...args: any[]) => {
|
||||
let result: Promise<any>;
|
||||
|
||||
@@ -175,6 +175,7 @@ export async function activate(context: ExtensionContext): Promise<GitExtension>
|
||||
console.warn(err.message);
|
||||
outputChannel.appendLine(err.message);
|
||||
|
||||
commands.executeCommand('setContext', 'git.missing', true);
|
||||
warnAboutMissingGit();
|
||||
|
||||
return new GitExtensionImpl();
|
||||
|
||||
@@ -5,19 +5,62 @@
|
||||
|
||||
import * as dayjs from 'dayjs';
|
||||
import * as advancedFormat from 'dayjs/plugin/advancedFormat';
|
||||
import * as relativeTime from 'dayjs/plugin/relativeTime';
|
||||
import { CancellationToken, Disposable, Event, EventEmitter, ThemeIcon, TimelineItem, TimelineProvider, Uri, workspace, TimelineChangeEvent } from 'vscode';
|
||||
import { CancellationToken, Disposable, Event, EventEmitter, ThemeIcon, Timeline, TimelineChangeEvent, TimelineCursor, TimelineItem, TimelineProvider, Uri, workspace } from 'vscode';
|
||||
import { Model } from './model';
|
||||
import { Repository } from './repository';
|
||||
import { debounce } from './decorators';
|
||||
import { Status } from './api/git';
|
||||
|
||||
dayjs.extend(advancedFormat);
|
||||
dayjs.extend(relativeTime);
|
||||
|
||||
// TODO[ECA]: Localize all the strings
|
||||
// TODO[ECA]: Localize or use a setting for date format
|
||||
|
||||
export class GitTimelineItem extends TimelineItem {
|
||||
static is(item: TimelineItem): item is GitTimelineItem {
|
||||
return item instanceof GitTimelineItem;
|
||||
}
|
||||
|
||||
readonly ref: string;
|
||||
readonly previousRef: string;
|
||||
readonly message: string;
|
||||
|
||||
constructor(
|
||||
ref: string,
|
||||
previousRef: string,
|
||||
message: string,
|
||||
timestamp: number,
|
||||
id: string,
|
||||
contextValue: string
|
||||
) {
|
||||
const index = message.indexOf('\n');
|
||||
const label = index !== -1 ? `${message.substring(0, index)} \u2026` : message;
|
||||
|
||||
super(label, timestamp);
|
||||
|
||||
this.ref = ref;
|
||||
this.previousRef = previousRef;
|
||||
this.message = message;
|
||||
this.id = id;
|
||||
this.contextValue = contextValue;
|
||||
}
|
||||
|
||||
get shortRef() {
|
||||
return this.shortenRef(this.ref);
|
||||
}
|
||||
|
||||
get shortPreviousRef() {
|
||||
return this.shortenRef(this.previousRef);
|
||||
}
|
||||
|
||||
private shortenRef(ref: string): string {
|
||||
if (ref === '' || ref === '~' || ref === 'HEAD') {
|
||||
return ref;
|
||||
}
|
||||
return ref.endsWith('^') ? `${ref.substr(0, 8)}^` : ref.substr(0, 8);
|
||||
}
|
||||
}
|
||||
|
||||
export class GitTimelineProvider implements TimelineProvider {
|
||||
private _onDidChange = new EventEmitter<TimelineChangeEvent>();
|
||||
get onDidChange(): Event<TimelineChangeEvent> {
|
||||
@@ -44,7 +87,7 @@ export class GitTimelineProvider implements TimelineProvider {
|
||||
this._disposable.dispose();
|
||||
}
|
||||
|
||||
async provideTimeline(uri: Uri, _token: CancellationToken): Promise<TimelineItem[]> {
|
||||
async provideTimeline(uri: Uri, _cursor: TimelineCursor, _token: CancellationToken): Promise<Timeline> {
|
||||
// console.log(`GitTimelineProvider.provideTimeline: uri=${uri} state=${this._model.state}`);
|
||||
|
||||
const repo = this._model.getRepository(uri);
|
||||
@@ -53,7 +96,7 @@ export class GitTimelineProvider implements TimelineProvider {
|
||||
this._repoStatusDate = undefined;
|
||||
this._repo = undefined;
|
||||
|
||||
return [];
|
||||
return { items: [] };
|
||||
}
|
||||
|
||||
if (this._repo?.root !== repo.root) {
|
||||
@@ -72,25 +115,17 @@ export class GitTimelineProvider implements TimelineProvider {
|
||||
const commits = await repo.logFile(uri);
|
||||
|
||||
let dateFormatter: dayjs.Dayjs;
|
||||
const items = commits.map<TimelineItem>(c => {
|
||||
let message = c.message;
|
||||
|
||||
const index = message.indexOf('\n');
|
||||
if (index !== -1) {
|
||||
message = `${message.substring(0, index)} \u2026`;
|
||||
}
|
||||
|
||||
const items = commits.map<GitTimelineItem>(c => {
|
||||
dateFormatter = dayjs(c.authorDate);
|
||||
|
||||
const item = new TimelineItem(message, c.authorDate?.getTime() ?? 0);
|
||||
item.id = c.hash;
|
||||
const item = new GitTimelineItem(c.hash, `${c.hash}^`, c.message, c.authorDate?.getTime() ?? 0, c.hash, 'git:file:commit');
|
||||
item.iconPath = new (ThemeIcon as any)('git-commit');
|
||||
item.description = `${dateFormatter.fromNow()} \u2022 ${c.authorName}`;
|
||||
item.detail = `${c.authorName} (${c.authorEmail}) \u2014 ${c.hash.substr(0, 8)}\n${dateFormatter.fromNow()} (${dateFormatter.format('MMMM Do, YYYY h:mma')})\n\n${c.message}`;
|
||||
item.description = c.authorName;
|
||||
item.detail = `${c.authorName} (${c.authorEmail}) \u2014 ${c.hash.substr(0, 8)}\n${dateFormatter.format('MMMM Do, YYYY h:mma')}\n\n${c.message}`;
|
||||
item.command = {
|
||||
title: 'Open Diff',
|
||||
command: 'git.openDiff',
|
||||
arguments: [uri, `${c.hash}^`, c.hash]
|
||||
title: 'Open Comparison',
|
||||
command: 'git.timeline.openDiff',
|
||||
arguments: [uri, this.id, item]
|
||||
};
|
||||
|
||||
return item;
|
||||
@@ -123,16 +158,15 @@ export class GitTimelineProvider implements TimelineProvider {
|
||||
break;
|
||||
}
|
||||
|
||||
const item = new TimelineItem('Staged Changes', date.getTime());
|
||||
item.id = 'index';
|
||||
const item = new GitTimelineItem('~', 'HEAD', 'Staged Changes', date.getTime(), 'index', 'git:file:index');
|
||||
// TODO[ECA]: Replace with a better icon -- reflecting its status maybe?
|
||||
item.iconPath = new (ThemeIcon as any)('git-commit');
|
||||
item.description = `${dateFormatter.fromNow()} \u2022 You`;
|
||||
item.detail = `You \u2014 Index\n${dateFormatter.fromNow()} (${dateFormatter.format('MMMM Do, YYYY h:mma')})\n${status}`;
|
||||
item.description = 'You';
|
||||
item.detail = `You \u2014 Index\n${dateFormatter.format('MMMM Do, YYYY h:mma')}\n${status}`;
|
||||
item.command = {
|
||||
title: 'Open Comparison',
|
||||
command: 'git.openDiff',
|
||||
arguments: [uri, 'HEAD', '~']
|
||||
command: 'git.timeline.openDiff',
|
||||
arguments: [uri, this.id, item]
|
||||
};
|
||||
|
||||
items.push(item);
|
||||
@@ -166,22 +200,21 @@ export class GitTimelineProvider implements TimelineProvider {
|
||||
break;
|
||||
}
|
||||
|
||||
const item = new TimelineItem('Uncommited Changes', date.getTime());
|
||||
item.id = 'working';
|
||||
const item = new GitTimelineItem('', index ? '~' : 'HEAD', 'Uncommited Changes', date.getTime(), 'working', 'git:file:working');
|
||||
// TODO[ECA]: Replace with a better icon -- reflecting its status maybe?
|
||||
item.iconPath = new (ThemeIcon as any)('git-commit');
|
||||
item.description = `${dateFormatter.fromNow()} \u2022 You`;
|
||||
item.detail = `You \u2014 Working Tree\n${dateFormatter.fromNow()} (${dateFormatter.format('MMMM Do, YYYY h:mma')})\n${status}`;
|
||||
item.description = 'You';
|
||||
item.detail = `You \u2014 Working Tree\n${dateFormatter.format('MMMM Do, YYYY h:mma')}\n${status}`;
|
||||
item.command = {
|
||||
title: 'Open Comparison',
|
||||
command: 'git.openDiff',
|
||||
arguments: [uri, index ? '~' : 'HEAD', '']
|
||||
command: 'git.timeline.openDiff',
|
||||
arguments: [uri, this.id, item]
|
||||
};
|
||||
|
||||
items.push(item);
|
||||
}
|
||||
|
||||
return items;
|
||||
return { items: items };
|
||||
}
|
||||
|
||||
private onRepositoriesChanged(_repo: Repository) {
|
||||
@@ -208,6 +241,6 @@ export class GitTimelineProvider implements TimelineProvider {
|
||||
|
||||
@debounce(500)
|
||||
private fireChanged() {
|
||||
this._onDidChange.fire();
|
||||
this._onDidChange.fire({});
|
||||
}
|
||||
}
|
||||
|
||||
+14
-19
@@ -382,7 +382,7 @@ har-schema@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
|
||||
integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=
|
||||
|
||||
har-validator@~5.1.0:
|
||||
har-validator@~5.1.3:
|
||||
version "5.1.3"
|
||||
resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080"
|
||||
integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==
|
||||
@@ -697,17 +697,12 @@ performance-now@^2.1.0:
|
||||
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
|
||||
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
|
||||
|
||||
psl@^1.1.24:
|
||||
psl@^1.1.28:
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/psl/-/psl-1.7.0.tgz#f1c4c47a8ef97167dea5d6bbf4816d736e884a3c"
|
||||
integrity sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ==
|
||||
|
||||
punycode@^1.4.1:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
|
||||
integrity sha1-wNWmOycYgArY4esPpSachN1BhF4=
|
||||
|
||||
punycode@^2.1.0:
|
||||
punycode@^2.1.0, punycode@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
|
||||
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
|
||||
@@ -723,9 +718,9 @@ querystringify@^2.1.1:
|
||||
integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==
|
||||
|
||||
request@^2.88.0:
|
||||
version "2.88.0"
|
||||
resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef"
|
||||
integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==
|
||||
version "2.88.2"
|
||||
resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3"
|
||||
integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==
|
||||
dependencies:
|
||||
aws-sign2 "~0.7.0"
|
||||
aws4 "^1.8.0"
|
||||
@@ -734,7 +729,7 @@ request@^2.88.0:
|
||||
extend "~3.0.2"
|
||||
forever-agent "~0.6.1"
|
||||
form-data "~2.3.2"
|
||||
har-validator "~5.1.0"
|
||||
har-validator "~5.1.3"
|
||||
http-signature "~1.2.0"
|
||||
is-typedarray "~1.0.0"
|
||||
isstream "~0.1.2"
|
||||
@@ -744,7 +739,7 @@ request@^2.88.0:
|
||||
performance-now "^2.1.0"
|
||||
qs "~6.5.2"
|
||||
safe-buffer "^5.1.2"
|
||||
tough-cookie "~2.4.3"
|
||||
tough-cookie "~2.5.0"
|
||||
tunnel-agent "^0.6.0"
|
||||
uuid "^3.3.2"
|
||||
|
||||
@@ -822,13 +817,13 @@ supports-color@5.4.0:
|
||||
dependencies:
|
||||
has-flag "^3.0.0"
|
||||
|
||||
tough-cookie@~2.4.3:
|
||||
version "2.4.3"
|
||||
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781"
|
||||
integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==
|
||||
tough-cookie@~2.5.0:
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
|
||||
integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==
|
||||
dependencies:
|
||||
psl "^1.1.24"
|
||||
punycode "^1.4.1"
|
||||
psl "^1.1.28"
|
||||
punycode "^2.1.1"
|
||||
|
||||
tunnel-agent@^0.6.0:
|
||||
version "0.6.0"
|
||||
|
||||
@@ -295,7 +295,7 @@ class TaskDetector {
|
||||
private updateProvider(): void {
|
||||
if (!this.taskProvider && this.detectors.size > 0) {
|
||||
const thisCapture = this;
|
||||
this.taskProvider = vscode.workspace.registerTaskProvider('grunt', {
|
||||
this.taskProvider = vscode.tasks.registerTaskProvider('grunt', {
|
||||
provideTasks: (): Promise<vscode.Task[]> => {
|
||||
return thisCapture.getTasks();
|
||||
},
|
||||
|
||||
@@ -277,7 +277,7 @@ class TaskDetector {
|
||||
private updateProvider(): void {
|
||||
if (!this.taskProvider && this.detectors.size > 0) {
|
||||
const thisCapture = this;
|
||||
this.taskProvider = vscode.workspace.registerTaskProvider('gulp', {
|
||||
this.taskProvider = vscode.tasks.registerTaskProvider('gulp', {
|
||||
provideTasks(): Promise<vscode.Task[]> {
|
||||
return thisCapture.getTasks();
|
||||
},
|
||||
|
||||
@@ -515,22 +515,6 @@ connection.onRequest(MatchingTagPositionRequest.type, (params, token) => {
|
||||
}, null, `Error while computing matching tag position for ${params.textDocument.uri}`, token);
|
||||
});
|
||||
|
||||
connection.onRequest(MatchingTagPositionRequest.type, (params, token) => {
|
||||
return runSafe(() => {
|
||||
const document = documents.get(params.textDocument.uri);
|
||||
if (document) {
|
||||
const pos = params.position;
|
||||
if (pos.character > 0) {
|
||||
const mode = languageModes.getModeAtPosition(document, Position.create(pos.line, pos.character - 1));
|
||||
if (mode && mode.findMatchingTagPosition) {
|
||||
return mode.findMatchingTagPosition(document, pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}, null, `Error while computing matching tag position for ${params.textDocument.uri}`, token);
|
||||
});
|
||||
|
||||
let semanticTokensProvider: SemanticTokenProvider | undefined;
|
||||
function getSemanticTokenProvider() {
|
||||
if (!semanticTokensProvider) {
|
||||
|
||||
@@ -269,7 +269,7 @@ class TaskDetector {
|
||||
private updateProvider(): void {
|
||||
if (!this.taskProvider && this.detectors.size > 0) {
|
||||
const thisCapture = this;
|
||||
this.taskProvider = vscode.workspace.registerTaskProvider('jake', {
|
||||
this.taskProvider = vscode.tasks.registerTaskProvider('jake', {
|
||||
provideTasks(): Promise<vscode.Task[]> {
|
||||
return thisCapture.getTasks();
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "vscode-json-languageserver",
|
||||
"description": "JSON language server",
|
||||
"version": "1.2.2",
|
||||
"version": "1.2.3",
|
||||
"author": "Microsoft Corporation",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
|
||||
@@ -70,7 +70,7 @@ function registerTaskProvider(context: vscode.ExtensionContext): vscode.Disposab
|
||||
context.subscriptions.push(workspaceWatcher);
|
||||
|
||||
let provider: vscode.TaskProvider = new NpmTaskProvider();
|
||||
let disposable = vscode.workspace.registerTaskProvider('npm', provider);
|
||||
let disposable = vscode.tasks.registerTaskProvider('npm', provider);
|
||||
context.subscriptions.push(disposable);
|
||||
return disposable;
|
||||
}
|
||||
|
||||
@@ -247,7 +247,7 @@ export default class PHPValidationProvider {
|
||||
}
|
||||
};
|
||||
|
||||
let options = vscode.workspace.rootPath ? { cwd: vscode.workspace.rootPath } : undefined;
|
||||
let options = (vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders[0]) ? { cwd: vscode.workspace.workspaceFolders[0].uri.fsPath } : undefined;
|
||||
let args: string[];
|
||||
if (this.trigger === RunTrigger.onSave) {
|
||||
args = PHPValidationProvider.FileArgs.slice(0);
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
// @ts-check
|
||||
// todo@jackson
|
||||
/* eslint code-no-unexternalized-strings: 0 */
|
||||
|
||||
const mappings = [
|
||||
['bat', 'source.batchfile'],
|
||||
@@ -40,6 +38,7 @@ const mappings = [
|
||||
['perl', 'source.perl'],
|
||||
['php', 'source.php'],
|
||||
['pl', 'source.perl'],
|
||||
['pm', 'source.perl'],
|
||||
['ps1', 'source.powershell'],
|
||||
['pug', 'text.pug'],
|
||||
['py', 'source.python'],
|
||||
@@ -104,43 +103,43 @@ mappings.forEach(([ext, scope, regexp]) =>
|
||||
repository[ext] = {
|
||||
name: scopes.resultBlock.meta,
|
||||
begin: `^(?!\\s)(.*?)([^\\\\\\/\\n]*${regexp || `\\.${ext}`})(:)$`,
|
||||
end: "^(?!\\s)",
|
||||
end: '^(?!\\s)',
|
||||
beginCaptures: {
|
||||
"0": { name: scopes.resultBlock.path.meta },
|
||||
"1": { name: scopes.resultBlock.path.dirname },
|
||||
"2": { name: scopes.resultBlock.path.basename },
|
||||
"3": { name: scopes.resultBlock.path.colon },
|
||||
'0': { name: scopes.resultBlock.path.meta },
|
||||
'1': { name: scopes.resultBlock.path.dirname },
|
||||
'2': { name: scopes.resultBlock.path.basename },
|
||||
'3': { name: scopes.resultBlock.path.colon },
|
||||
},
|
||||
patterns: [
|
||||
{
|
||||
name: [scopes.resultBlock.result.meta, scopes.resultBlock.result.metaMultiLine].join(' '),
|
||||
begin: "^ ((\\d+) )",
|
||||
while: "^ (?:((\\d+)(:))|((\\d+) ))",
|
||||
begin: '^ ((\\d+) )',
|
||||
while: '^ (?:((\\d+)(:))|((\\d+) ))',
|
||||
beginCaptures: {
|
||||
"0": { name: scopes.resultBlock.result.prefix.meta },
|
||||
"1": { name: scopes.resultBlock.result.prefix.metaContext },
|
||||
"2": { name: scopes.resultBlock.result.prefix.lineNumber },
|
||||
'0': { name: scopes.resultBlock.result.prefix.meta },
|
||||
'1': { name: scopes.resultBlock.result.prefix.metaContext },
|
||||
'2': { name: scopes.resultBlock.result.prefix.lineNumber },
|
||||
},
|
||||
whileCaptures: {
|
||||
"0": { name: scopes.resultBlock.result.prefix.meta },
|
||||
"1": { name: scopes.resultBlock.result.prefix.metaMatch },
|
||||
"2": { name: scopes.resultBlock.result.prefix.lineNumber },
|
||||
"3": { name: scopes.resultBlock.result.prefix.colon },
|
||||
'0': { name: scopes.resultBlock.result.prefix.meta },
|
||||
'1': { name: scopes.resultBlock.result.prefix.metaMatch },
|
||||
'2': { name: scopes.resultBlock.result.prefix.lineNumber },
|
||||
'3': { name: scopes.resultBlock.result.prefix.colon },
|
||||
|
||||
"4": { name: scopes.resultBlock.result.prefix.metaContext },
|
||||
"5": { name: scopes.resultBlock.result.prefix.lineNumber },
|
||||
'4': { name: scopes.resultBlock.result.prefix.metaContext },
|
||||
'5': { name: scopes.resultBlock.result.prefix.lineNumber },
|
||||
},
|
||||
patterns: [{ include: scope }]
|
||||
},
|
||||
{
|
||||
begin: "^ ((\\d+)(:))",
|
||||
while: "(?=not)possible",
|
||||
begin: '^ ((\\d+)(:))',
|
||||
while: '(?=not)possible',
|
||||
name: [scopes.resultBlock.result.meta, scopes.resultBlock.result.metaSingleLine].join(' '),
|
||||
beginCaptures: {
|
||||
"0": { name: scopes.resultBlock.result.prefix.meta },
|
||||
"1": { name: scopes.resultBlock.result.prefix.metaMatch },
|
||||
"2": { name: scopes.resultBlock.result.prefix.lineNumber },
|
||||
"3": { name: scopes.resultBlock.result.prefix.colon },
|
||||
'0': { name: scopes.resultBlock.result.prefix.meta },
|
||||
'1': { name: scopes.resultBlock.result.prefix.metaMatch },
|
||||
'2': { name: scopes.resultBlock.result.prefix.lineNumber },
|
||||
'3': { name: scopes.resultBlock.result.prefix.colon },
|
||||
},
|
||||
patterns: [{ include: scope }]
|
||||
}
|
||||
@@ -149,10 +148,10 @@ mappings.forEach(([ext, scope, regexp]) =>
|
||||
|
||||
const header = [
|
||||
{
|
||||
begin: "^(# Query): ",
|
||||
end: "\n",
|
||||
begin: '^(# Query): ',
|
||||
end: '\n',
|
||||
name: scopes.header.meta,
|
||||
beginCaptures: { "1": { name: scopes.header.key }, },
|
||||
beginCaptures: { '1': { name: scopes.header.key }, },
|
||||
patterns: [
|
||||
{
|
||||
match: '(\\\\n)|(\\\\\\\\)',
|
||||
@@ -169,10 +168,10 @@ const header = [
|
||||
]
|
||||
},
|
||||
{
|
||||
begin: "^(# Flags): ",
|
||||
end: "\n",
|
||||
begin: '^(# Flags): ',
|
||||
end: '\n',
|
||||
name: scopes.header.meta,
|
||||
beginCaptures: { "1": { name: scopes.header.key }, },
|
||||
beginCaptures: { '1': { name: scopes.header.key }, },
|
||||
patterns: [
|
||||
{
|
||||
match: '(RegExp|CaseSensitive|IgnoreExcludeSettings|WordMatch)',
|
||||
@@ -182,10 +181,10 @@ const header = [
|
||||
]
|
||||
},
|
||||
{
|
||||
begin: "^(# ContextLines): ",
|
||||
end: "\n",
|
||||
begin: '^(# ContextLines): ',
|
||||
end: '\n',
|
||||
name: scopes.header.meta,
|
||||
beginCaptures: { "1": { name: scopes.header.key }, },
|
||||
beginCaptures: { '1': { name: scopes.header.key }, },
|
||||
patterns: [
|
||||
{
|
||||
match: '\\d',
|
||||
@@ -195,42 +194,42 @@ const header = [
|
||||
]
|
||||
},
|
||||
{
|
||||
match: "^(# (?:Including|Excluding)): (.*)$",
|
||||
match: '^(# (?:Including|Excluding)): (.*)$',
|
||||
name: scopes.header.meta,
|
||||
captures: {
|
||||
"1": { name: scopes.header.key },
|
||||
"2": { name: scopes.header.value }
|
||||
'1': { name: scopes.header.key },
|
||||
'2': { name: scopes.header.value }
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
const plainText = [
|
||||
{
|
||||
match: "^(?!\\s)(.*?)([^\\\\\\/\\n]*)(:)$",
|
||||
match: '^(?!\\s)(.*?)([^\\\\\\/\\n]*)(:)$',
|
||||
name: [scopes.resultBlock.meta, scopes.resultBlock.path.meta].join(' '),
|
||||
captures: {
|
||||
"1": { name: scopes.resultBlock.path.dirname },
|
||||
"2": { name: scopes.resultBlock.path.basename },
|
||||
"3": { name: scopes.resultBlock.path.colon }
|
||||
'1': { name: scopes.resultBlock.path.dirname },
|
||||
'2': { name: scopes.resultBlock.path.basename },
|
||||
'3': { name: scopes.resultBlock.path.colon }
|
||||
}
|
||||
},
|
||||
{
|
||||
match: "^ (?:((\\d+)(:))|((\\d+)( ))(.*))",
|
||||
match: '^ (?:((\\d+)(:))|((\\d+)( ))(.*))',
|
||||
name: [scopes.resultBlock.meta, scopes.resultBlock.result.meta].join(' '),
|
||||
captures: {
|
||||
"1": { name: [scopes.resultBlock.result.prefix.meta, scopes.resultBlock.result.prefix.metaMatch].join(' ') },
|
||||
"2": { name: scopes.resultBlock.result.prefix.lineNumber },
|
||||
"3": { name: scopes.resultBlock.result.prefix.colon },
|
||||
'1': { name: [scopes.resultBlock.result.prefix.meta, scopes.resultBlock.result.prefix.metaMatch].join(' ') },
|
||||
'2': { name: scopes.resultBlock.result.prefix.lineNumber },
|
||||
'3': { name: scopes.resultBlock.result.prefix.colon },
|
||||
|
||||
"4": { name: [scopes.resultBlock.result.prefix.meta, scopes.resultBlock.result.prefix.metaContext].join(' ') },
|
||||
"5": { name: scopes.resultBlock.result.prefix.lineNumber },
|
||||
'4': { name: [scopes.resultBlock.result.prefix.meta, scopes.resultBlock.result.prefix.metaContext].join(' ') },
|
||||
'5': { name: scopes.resultBlock.result.prefix.lineNumber },
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
const tmLanguage = {
|
||||
"information_for_contributors": "This file is generated from ./generateTMLanguage.js.",
|
||||
name: "Search Results",
|
||||
'information_for_contributors': 'This file is generated from ./generateTMLanguage.js.',
|
||||
name: 'Search Results',
|
||||
scopeName: scopes.root,
|
||||
patterns: [
|
||||
...header,
|
||||
|
||||
@@ -189,6 +189,9 @@
|
||||
{
|
||||
"include": "#pl"
|
||||
},
|
||||
{
|
||||
"include": "#pm"
|
||||
},
|
||||
{
|
||||
"include": "#ps1"
|
||||
},
|
||||
@@ -3457,6 +3460,92 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"pm": {
|
||||
"name": "meta.resultBlock.search",
|
||||
"begin": "^(?!\\s)(.*?)([^\\\\\\/\\n]*\\.pm)(:)$",
|
||||
"end": "^(?!\\s)",
|
||||
"beginCaptures": {
|
||||
"0": {
|
||||
"name": "string meta.path.search"
|
||||
},
|
||||
"1": {
|
||||
"name": "meta.path.dirname.search"
|
||||
},
|
||||
"2": {
|
||||
"name": "meta.path.basename.search"
|
||||
},
|
||||
"3": {
|
||||
"name": "punctuation.separator"
|
||||
}
|
||||
},
|
||||
"patterns": [
|
||||
{
|
||||
"name": "meta.resultLine.search meta.resultLine.multiLine.search",
|
||||
"begin": "^ ((\\d+) )",
|
||||
"while": "^ (?:((\\d+)(:))|((\\d+) ))",
|
||||
"beginCaptures": {
|
||||
"0": {
|
||||
"name": "constant.numeric.integer meta.resultLinePrefix.search"
|
||||
},
|
||||
"1": {
|
||||
"name": "meta.resultLinePrefix.contextLinePrefix.search"
|
||||
},
|
||||
"2": {
|
||||
"name": "meta.resultLinePrefix.lineNumber.search"
|
||||
}
|
||||
},
|
||||
"whileCaptures": {
|
||||
"0": {
|
||||
"name": "constant.numeric.integer meta.resultLinePrefix.search"
|
||||
},
|
||||
"1": {
|
||||
"name": "meta.resultLinePrefix.matchLinePrefix.search"
|
||||
},
|
||||
"2": {
|
||||
"name": "meta.resultLinePrefix.lineNumber.search"
|
||||
},
|
||||
"3": {
|
||||
"name": "punctuation.separator"
|
||||
},
|
||||
"4": {
|
||||
"name": "meta.resultLinePrefix.contextLinePrefix.search"
|
||||
},
|
||||
"5": {
|
||||
"name": "meta.resultLinePrefix.lineNumber.search"
|
||||
}
|
||||
},
|
||||
"patterns": [
|
||||
{
|
||||
"include": "source.perl"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"begin": "^ ((\\d+)(:))",
|
||||
"while": "(?=not)possible",
|
||||
"name": "meta.resultLine.search meta.resultLine.singleLine.search",
|
||||
"beginCaptures": {
|
||||
"0": {
|
||||
"name": "constant.numeric.integer meta.resultLinePrefix.search"
|
||||
},
|
||||
"1": {
|
||||
"name": "meta.resultLinePrefix.matchLinePrefix.search"
|
||||
},
|
||||
"2": {
|
||||
"name": "meta.resultLinePrefix.lineNumber.search"
|
||||
},
|
||||
"3": {
|
||||
"name": "punctuation.separator"
|
||||
}
|
||||
},
|
||||
"patterns": [
|
||||
{
|
||||
"include": "source.perl"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"ps1": {
|
||||
"name": "meta.resultBlock.search",
|
||||
"begin": "^(?!\\s)(.*?)([^\\\\\\/\\n]*\\.ps1)(:)$",
|
||||
|
||||
@@ -38,7 +38,7 @@ export function activate(
|
||||
});
|
||||
|
||||
registerCommands(commandManager, lazyClientHost, pluginManager);
|
||||
context.subscriptions.push(vscode.workspace.registerTaskProvider('typescript', new TscTaskProvider(lazyClientHost.map(x => x.serviceClient))));
|
||||
context.subscriptions.push(vscode.tasks.registerTaskProvider('typescript', new TscTaskProvider(lazyClientHost.map(x => x.serviceClient))));
|
||||
context.subscriptions.push(new LanguageConfigurationManager());
|
||||
|
||||
import('./features/tsconfig').then(module => {
|
||||
|
||||
@@ -32,6 +32,7 @@ const getSymbolKind = (kind: string): vscode.SymbolKind => {
|
||||
};
|
||||
|
||||
class TypeScriptDocumentSymbolProvider implements vscode.DocumentSymbolProvider {
|
||||
|
||||
public constructor(
|
||||
private readonly client: ITypeScriptServiceClient,
|
||||
private cachedResponse: CachedResponse<Proto.NavTreeResponse>,
|
||||
@@ -45,23 +46,27 @@ class TypeScriptDocumentSymbolProvider implements vscode.DocumentSymbolProvider
|
||||
|
||||
const args: Proto.FileRequestArgs = { file };
|
||||
const response = await this.cachedResponse.execute(document, () => this.client.execute('navtree', args, token));
|
||||
if (response.type !== 'response' || !response.body) {
|
||||
if (response.type !== 'response' || !response.body?.childItems) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let tree = response.body;
|
||||
if (tree && tree.childItems) {
|
||||
// The root represents the file. Ignore this when showing in the UI
|
||||
const result: vscode.DocumentSymbol[] = [];
|
||||
tree.childItems.forEach(item => TypeScriptDocumentSymbolProvider.convertNavTree(document.uri, result, item));
|
||||
return result;
|
||||
// The root represents the file. Ignore this when showing in the UI
|
||||
const result: vscode.DocumentSymbol[] = [];
|
||||
for (const item of response.body.childItems) {
|
||||
TypeScriptDocumentSymbolProvider.convertNavTree(document.uri, result, item);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
return result;
|
||||
}
|
||||
|
||||
private static convertNavTree(resource: vscode.Uri, bucket: vscode.DocumentSymbol[], item: Proto.NavigationTree): boolean {
|
||||
private static convertNavTree(
|
||||
resource: vscode.Uri,
|
||||
output: vscode.DocumentSymbol[],
|
||||
item: Proto.NavigationTree,
|
||||
): boolean {
|
||||
let shouldInclude = TypeScriptDocumentSymbolProvider.shouldInclueEntry(item);
|
||||
if (!shouldInclude && !item.childItems?.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const children = new Set(item.childItems || []);
|
||||
for (const span of item.spans) {
|
||||
@@ -83,7 +88,7 @@ class TypeScriptDocumentSymbolProvider implements vscode.DocumentSymbolProvider
|
||||
}
|
||||
|
||||
if (shouldInclude) {
|
||||
bucket.push(symbolInfo);
|
||||
output.push(symbolInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +103,6 @@ class TypeScriptDocumentSymbolProvider implements vscode.DocumentSymbolProvider
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function register(
|
||||
selector: vscode.DocumentSelector,
|
||||
client: ITypeScriptServiceClient,
|
||||
|
||||
@@ -99,6 +99,14 @@ export class TypeScriptReferencesCodeLensProvider extends TypeScriptBaseCodeLens
|
||||
case PConst.Kind.memberSetAccessor:
|
||||
case PConst.Kind.constructorImplementation:
|
||||
case PConst.Kind.memberVariable:
|
||||
// Don't show if child and parent have same start
|
||||
// For https://github.com/microsoft/vscode/issues/90396
|
||||
if (parent &&
|
||||
typeConverters.Position.fromLocation(parent.spans[0].start).isEqual(typeConverters.Position.fromLocation(item.spans[0].start))
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Only show if parent is a class type object (not a literal)
|
||||
switch (parent?.kind) {
|
||||
case PConst.Kind.class:
|
||||
|
||||
@@ -91,6 +91,19 @@ suite('TypeScript References', () => {
|
||||
const codeLenses = await getCodeLenses(testDocumentUri);
|
||||
assert.strictEqual(codeLenses?.length, 0);
|
||||
});
|
||||
|
||||
test('Should not show duplicate references on ES5 class (https://github.com/microsoft/vscode/issues/90396)', async () => {
|
||||
const testDocumentUri = vscode.Uri.parse('untitled:test3.js');
|
||||
await createTestEditor(testDocumentUri,
|
||||
`function A() {`,
|
||||
` console.log("hi");`,
|
||||
`}`,
|
||||
`A.x = {};`,
|
||||
);
|
||||
|
||||
const codeLenses = await getCodeLenses(testDocumentUri);
|
||||
assert.strictEqual(codeLenses?.length, 1);
|
||||
});
|
||||
});
|
||||
|
||||
function getCodeLenses(document: vscode.Uri): Thenable<readonly vscode.CodeLens[] | undefined> {
|
||||
|
||||
@@ -3,11 +3,12 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'mocha';
|
||||
import * as assert from 'assert';
|
||||
import * as vscode from 'vscode';
|
||||
import 'mocha';
|
||||
import * as os from 'os';
|
||||
import { join } from 'path';
|
||||
import { closeAllEditors, disposeAll, conditionalTest } from '../utils';
|
||||
import * as vscode from 'vscode';
|
||||
import { closeAllEditors, conditionalTest, delay, disposeAll } from '../utils';
|
||||
|
||||
const webviewId = 'myWebview';
|
||||
|
||||
@@ -332,8 +333,30 @@ suite('Webview tests', () => {
|
||||
webview.webview.postMessage({ value: 1 });
|
||||
await firstResponse;
|
||||
assert.strictEqual(webview.viewColumn, vscode.ViewColumn.One);
|
||||
|
||||
});
|
||||
|
||||
if (os.platform() === 'darwin') {
|
||||
conditionalTest('webview can copy text from webview', async () => {
|
||||
const expectedText = `webview text from: ${Date.now()}!`;
|
||||
|
||||
const webview = _register(vscode.window.createWebviewPanel(webviewId, 'title', { viewColumn: vscode.ViewColumn.One }, { enableScripts: true, retainContextWhenHidden: true }));
|
||||
const ready = getMesssage(webview);
|
||||
|
||||
|
||||
webview.webview.html = createHtmlDocumentWithBody(/*html*/`
|
||||
<b>${expectedText}</b>
|
||||
<script>
|
||||
const vscode = acquireVsCodeApi();
|
||||
document.execCommand('selectAll');
|
||||
vscode.postMessage({ type: 'ready' });
|
||||
</script>`);
|
||||
await ready;
|
||||
|
||||
await vscode.commands.executeCommand('editor.action.webvieweditor.copy');
|
||||
await delay(200); // Make sure copy has time to reach webview
|
||||
assert.strictEqual(await vscode.env.clipboard.readText(), expectedText);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function createHtmlDocumentWithBody(body: string): string {
|
||||
|
||||
@@ -145,14 +145,7 @@ suite('window namespace tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
// TODO this randomly fails when running against web and visually
|
||||
// what seems to happen is that the second editor opens and both
|
||||
// left and right editor show a blinking cursor. Since active editor
|
||||
// tracking relies on editor focus to function properly, this
|
||||
// seems to be the root cause of the failure.
|
||||
// https://github.com/microsoft/vscode/issues/90470
|
||||
test.skip('active editor not always correct... #49125', async function () {
|
||||
|
||||
test('active editor not always correct... #49125', async function () {
|
||||
const randomFile1 = await createRandomFile();
|
||||
const randomFile2 = await createRandomFile();
|
||||
|
||||
|
||||
@@ -214,104 +214,94 @@ suite('workspace-namespace', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('eol, change via onWillSave', function () {
|
||||
if (vscode.env.uiKind === vscode.UIKind.Web) {
|
||||
// TODO@Jo Test seems to fail when running in web due to
|
||||
// onWillSaveTextDocument not getting called
|
||||
return this.skip();
|
||||
}
|
||||
|
||||
test('eol, change via onWillSave', async function () {
|
||||
let called = false;
|
||||
let sub = vscode.workspace.onWillSaveTextDocument(e => {
|
||||
called = true;
|
||||
e.waitUntil(Promise.resolve([vscode.TextEdit.setEndOfLine(vscode.EndOfLine.LF)]));
|
||||
});
|
||||
|
||||
return createRandomFile('foo\r\nbar\r\nbar').then(file => {
|
||||
return vscode.workspace.openTextDocument(file).then(doc => {
|
||||
assert.equal(doc.eol, vscode.EndOfLine.CRLF);
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.set(file, [vscode.TextEdit.insert(new vscode.Position(0, 0), '-changes-')]);
|
||||
const file = await createRandomFile('foo\r\nbar\r\nbar');
|
||||
const doc = await vscode.workspace.openTextDocument(file);
|
||||
assert.equal(doc.eol, vscode.EndOfLine.CRLF);
|
||||
|
||||
return vscode.workspace.applyEdit(edit).then(success => {
|
||||
assert.ok(success);
|
||||
return doc.save();
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.set(file, [vscode.TextEdit.insert(new vscode.Position(0, 0), '-changes-')]);
|
||||
const successEdit = await vscode.workspace.applyEdit(edit);
|
||||
assert.ok(successEdit);
|
||||
|
||||
}).then(success => {
|
||||
assert.ok(success);
|
||||
assert.ok(called);
|
||||
assert.ok(!doc.isDirty);
|
||||
assert.equal(doc.eol, vscode.EndOfLine.LF);
|
||||
sub.dispose();
|
||||
});
|
||||
});
|
||||
});
|
||||
const successSave = await doc.save();
|
||||
assert.ok(successSave);
|
||||
assert.ok(called);
|
||||
assert.ok(!doc.isDirty);
|
||||
assert.equal(doc.eol, vscode.EndOfLine.LF);
|
||||
sub.dispose();
|
||||
});
|
||||
|
||||
test('events: onDidOpenTextDocument, onDidChangeTextDocument, onDidSaveTextDocument', () => {
|
||||
return createRandomFile().then(file => {
|
||||
let disposables: vscode.Disposable[] = [];
|
||||
function assertEqualPath(a: string, b: string): void {
|
||||
assert.ok(pathEquals(a, b), `${a} <-> ${b}`);
|
||||
}
|
||||
|
||||
let onDidOpenTextDocument = false;
|
||||
disposables.push(vscode.workspace.onDidOpenTextDocument(e => {
|
||||
assert.ok(pathEquals(e.uri.fsPath, file.fsPath));
|
||||
onDidOpenTextDocument = true;
|
||||
}));
|
||||
test('events: onDidOpenTextDocument, onDidChangeTextDocument, onDidSaveTextDocument', async () => {
|
||||
const file = await createRandomFile();
|
||||
let disposables: vscode.Disposable[] = [];
|
||||
|
||||
let onDidChangeTextDocument = false;
|
||||
disposables.push(vscode.workspace.onDidChangeTextDocument(e => {
|
||||
assert.ok(pathEquals(e.document.uri.fsPath, file.fsPath));
|
||||
onDidChangeTextDocument = true;
|
||||
}));
|
||||
await vscode.workspace.saveAll();
|
||||
|
||||
let onDidSaveTextDocument = false;
|
||||
disposables.push(vscode.workspace.onDidSaveTextDocument(e => {
|
||||
assert.ok(pathEquals(e.uri.fsPath, file.fsPath));
|
||||
onDidSaveTextDocument = true;
|
||||
}));
|
||||
let pendingAsserts: Function[] = [];
|
||||
let onDidOpenTextDocument = false;
|
||||
disposables.push(vscode.workspace.onDidOpenTextDocument(e => {
|
||||
pendingAsserts.push(() => assertEqualPath(e.uri.fsPath, file.fsPath));
|
||||
onDidOpenTextDocument = true;
|
||||
}));
|
||||
|
||||
return vscode.workspace.openTextDocument(file).then(doc => {
|
||||
return vscode.window.showTextDocument(doc).then((editor) => {
|
||||
return editor.edit((builder) => {
|
||||
builder.insert(new vscode.Position(0, 0), 'Hello World');
|
||||
}).then(_applied => {
|
||||
return doc.save().then(_saved => {
|
||||
assert.ok(onDidOpenTextDocument);
|
||||
assert.ok(onDidChangeTextDocument);
|
||||
assert.ok(onDidSaveTextDocument);
|
||||
let onDidChangeTextDocument = false;
|
||||
disposables.push(vscode.workspace.onDidChangeTextDocument(e => {
|
||||
pendingAsserts.push(() => assertEqualPath(e.document.uri.fsPath, file.fsPath));
|
||||
onDidChangeTextDocument = true;
|
||||
}));
|
||||
|
||||
disposeAll(disposables);
|
||||
let onDidSaveTextDocument = false;
|
||||
disposables.push(vscode.workspace.onDidSaveTextDocument(e => {
|
||||
pendingAsserts.push(() => assertEqualPath(e.uri.fsPath, file.fsPath));
|
||||
onDidSaveTextDocument = true;
|
||||
}));
|
||||
|
||||
return deleteFile(file);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
const doc = await vscode.workspace.openTextDocument(file);
|
||||
const editor = await vscode.window.showTextDocument(doc);
|
||||
|
||||
await editor.edit((builder) => {
|
||||
builder.insert(new vscode.Position(0, 0), 'Hello World');
|
||||
});
|
||||
await doc.save();
|
||||
|
||||
assert.ok(onDidOpenTextDocument);
|
||||
assert.ok(onDidChangeTextDocument);
|
||||
assert.ok(onDidSaveTextDocument);
|
||||
pendingAsserts.forEach(assert => assert());
|
||||
disposeAll(disposables);
|
||||
return deleteFile(file);
|
||||
});
|
||||
|
||||
test('events: onDidSaveTextDocument fires even for non dirty file when saved', () => {
|
||||
return createRandomFile().then(file => {
|
||||
let disposables: vscode.Disposable[] = [];
|
||||
test('events: onDidSaveTextDocument fires even for non dirty file when saved', async () => {
|
||||
const file = await createRandomFile();
|
||||
let disposables: vscode.Disposable[] = [];
|
||||
let pendingAsserts: Function[] = [];
|
||||
|
||||
let onDidSaveTextDocument = false;
|
||||
disposables.push(vscode.workspace.onDidSaveTextDocument(e => {
|
||||
assert.ok(pathEquals(e.uri.fsPath, file.fsPath));
|
||||
onDidSaveTextDocument = true;
|
||||
}));
|
||||
let onDidSaveTextDocument = false;
|
||||
disposables.push(vscode.workspace.onDidSaveTextDocument(e => {
|
||||
pendingAsserts.push(() => assertEqualPath(e.uri.fsPath, file.fsPath));
|
||||
onDidSaveTextDocument = true;
|
||||
}));
|
||||
|
||||
return vscode.workspace.openTextDocument(file).then(doc => {
|
||||
return vscode.window.showTextDocument(doc).then(() => {
|
||||
return vscode.commands.executeCommand('workbench.action.files.save').then(() => {
|
||||
assert.ok(onDidSaveTextDocument);
|
||||
const doc = await vscode.workspace.openTextDocument(file);
|
||||
await vscode.window.showTextDocument(doc);
|
||||
await vscode.commands.executeCommand('workbench.action.files.save');
|
||||
|
||||
disposeAll(disposables);
|
||||
|
||||
return deleteFile(file);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
assert.ok(onDidSaveTextDocument);
|
||||
pendingAsserts.forEach(fn => fn());
|
||||
disposeAll(disposables);
|
||||
return deleteFile(file);
|
||||
});
|
||||
|
||||
test('openTextDocument, with selection', function () {
|
||||
|
||||
Reference in New Issue
Block a user