Merge remote-tracking branch 'origin/main' into tyriar/terminal_layout
This commit is contained in:
commit
ae66110c90
|
@ -6,6 +6,9 @@ trigger:
|
|||
|
||||
pr: none
|
||||
|
||||
pool:
|
||||
vmImage: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- task: NodeTool@0
|
||||
inputs:
|
||||
|
@ -17,7 +20,7 @@ steps:
|
|||
|
||||
- bash: |
|
||||
TAG_VERSION=$(git describe --tags `git rev-list --tags --max-count=1`)
|
||||
CHANNEL="G1C14HJ2F"
|
||||
CHANNEL="C1C14HJ2F"
|
||||
|
||||
if [ "$TAG_VERSION" == "1.999.0" ]; then
|
||||
MESSAGE="<!here>. Someone pushed 1.999.0 tag. Please delete it ASAP from remote and local."
|
||||
|
@ -59,11 +62,11 @@ steps:
|
|||
|
||||
- bash: |
|
||||
TAG_VERSION=$(git describe --tags `git rev-list --tags --max-count=1`)
|
||||
CHANNEL="G1C14HJ2F"
|
||||
CHANNEL="C1C14HJ2F"
|
||||
|
||||
MESSAGE="DefinitelyTyped/DefinitelyTyped#vscode-types-$TAG_VERSION created. Endgame champion, please open this link, examine changes and create a PR:"
|
||||
LINK="https://github.com/DefinitelyTyped/DefinitelyTyped/compare/vscode-types-$TAG_VERSION?quick_pull=1&body=Updating%20VS%20Code%20Extension%20API.%20See%20https%3A%2F%2Fgithub.com%2Fmicrosoft%2Fvscode%2Fissues%2F70175%20for%20details."
|
||||
MESSAGE2="[@eamodio, @jrieken, @kmaetzel, @egamma]. Please review and merge PR to publish @types/vscode."
|
||||
MESSAGE2="[@jrieken, @kmaetzel, @egamma]. Please review and merge PR to publish @types/vscode."
|
||||
|
||||
curl -X POST -H "Authorization: Bearer $(SLACK_TOKEN)" \
|
||||
-H 'Content-type: application/json; charset=utf-8' \
|
||||
|
|
|
@ -1927,8 +1927,9 @@ export class Repository implements Disposable {
|
|||
if (HEAD !== undefined) {
|
||||
const config = workspace.getConfiguration('git', Uri.file(this.repository.root));
|
||||
const showActionButton = config.get<string>('showUnpublishedCommitsButton', 'whenEmpty');
|
||||
const postCommitCommand = config.get<string>('postCommitCommand');
|
||||
|
||||
if (showActionButton === 'always' || (showActionButton === 'whenEmpty' && workingTree.length === 0 && index.length === 0 && untracked.length === 0 && merge.length === 0)) {
|
||||
if (showActionButton === 'always' || (showActionButton === 'whenEmpty' && workingTree.length === 0 && index.length === 0 && untracked.length === 0 && merge.length === 0 && postCommitCommand !== 'sync' && postCommitCommand !== 'push')) {
|
||||
if (HEAD.name && HEAD.commit) {
|
||||
if (HEAD.upstream) {
|
||||
if (HEAD.ahead) {
|
||||
|
|
|
@ -179,7 +179,7 @@ class FolderDetector {
|
|||
for (const filename of await fs.promises.readdir(root)) {
|
||||
|
||||
const ext = path.extname(filename);
|
||||
if (ext !== '.js' && ext !== '.mjs' && ext !== '.cjs') {
|
||||
if (ext !== '.js' && ext !== '.mjs' && ext !== '.cjs' && ext !== '.ts') {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -331,7 +331,7 @@
|
|||
"customEditors": [
|
||||
{
|
||||
"viewType": "vscode.markdown.preview.editor",
|
||||
"displayName": "Markdown Preview (Experimental)",
|
||||
"displayName": "Markdown Preview",
|
||||
"priority": "option",
|
||||
"selector": [
|
||||
{
|
||||
|
|
|
@ -120,7 +120,6 @@ window.addEventListener('message', async event => {
|
|||
|
||||
case 'updateView':
|
||||
if (event.data.source === documentResource) {
|
||||
console.log('updateView', event.data.line);
|
||||
onUpdateView(event.data.line);
|
||||
}
|
||||
return;
|
||||
|
@ -155,7 +154,6 @@ window.addEventListener('message', async event => {
|
|||
// Move styles to head
|
||||
// This prevents an ugly flash of unstyled content
|
||||
const styles = newRoot.querySelectorAll('link');
|
||||
|
||||
for (const style of styles) {
|
||||
style.remove();
|
||||
}
|
||||
|
@ -165,7 +163,22 @@ window.addEventListener('message', async event => {
|
|||
childrenOnly: true,
|
||||
onBeforeElUpdated: (fromEl, toEl) => {
|
||||
if (areEqual(fromEl, toEl)) {
|
||||
fromEl.setAttribute('data-line', toEl.getAttribute('data-line')!);
|
||||
// areEqual doesn't look at `data-line` so copy those over
|
||||
|
||||
const fromLines = fromEl.querySelectorAll('[data-line]');
|
||||
const toLines = fromEl.querySelectorAll('[data-line]');
|
||||
if (fromLines.length !== toLines.length) {
|
||||
console.log('unexpected line number change');
|
||||
}
|
||||
|
||||
for (let i = 0; i < fromLines.length; ++i) {
|
||||
const fromChild = fromLines[i];
|
||||
const toChild = toLines[i];
|
||||
if (toChild) {
|
||||
fromChild.setAttribute('data-line', toChild.getAttribute('data-line')!);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -241,7 +254,7 @@ document.addEventListener('click', event => {
|
|||
|
||||
window.addEventListener('scroll', throttle(() => {
|
||||
updateScrollProgress();
|
||||
console.log('scroll');
|
||||
|
||||
if (scrollDisabledCount > 0) {
|
||||
scrollDisabledCount -= 1;
|
||||
} else {
|
||||
|
|
|
@ -58,7 +58,7 @@ export function activate(
|
|||
new TypeScriptVersion(
|
||||
TypeScriptVersionSource.Bundled,
|
||||
vscode.Uri.joinPath(context.extensionUri, 'dist/browser/typescript/tsserver.web.js').toString(),
|
||||
API.fromSimpleString('4.4.1')));
|
||||
API.fromSimpleString('4.5.0')));
|
||||
|
||||
const lazyClientHost = createLazyClientHost(context, false, {
|
||||
pluginManager,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "code-oss-dev",
|
||||
"version": "1.62.0",
|
||||
"version": "1.63.0",
|
||||
"distro": "68b7698bb44bb140dfd35df9825ea6825edf87af",
|
||||
"author": {
|
||||
"name": "Microsoft Corporation"
|
||||
|
@ -205,7 +205,7 @@
|
|||
"vinyl-fs": "^3.0.0",
|
||||
"vscode-debugprotocol": "1.50.0",
|
||||
"vscode-nls-dev": "^3.3.1",
|
||||
"vscode-telemetry-extractor": "^1.8.0",
|
||||
"vscode-telemetry-extractor": "^1.9.3",
|
||||
"webpack": "^5.42.0",
|
||||
"webpack-cli": "^4.7.2",
|
||||
"webpack-stream": "^6.1.2",
|
||||
|
|
|
@ -1182,7 +1182,7 @@ export function computeScreenAwareSize(cssPx: number): number {
|
|||
/**
|
||||
* Open safely a new window. This is the best way to do so, but you cannot tell
|
||||
* if the window was opened or if it was blocked by the browser's popup blocker.
|
||||
* If you want to tell if the browser blocked the new window, use `windowOpenNoOpenerWithSuccess`.
|
||||
* If you want to tell if the browser blocked the new window, use {@link windowOpenWithSuccess}.
|
||||
*
|
||||
* See https://github.com/microsoft/monaco-editor/issues/601
|
||||
* To protect against malicious code in the linked site, particularly phishing attempts,
|
||||
|
@ -1201,19 +1201,49 @@ export function windowOpenNoOpener(url: string): void {
|
|||
}
|
||||
|
||||
/**
|
||||
* Open safely a new window. This technique is not appropriate in certain contexts,
|
||||
* like for example when the JS context is executing inside a sandboxed iframe.
|
||||
* If it is not necessary to know if the browser blocked the new window, use
|
||||
* `windowOpenNoOpener`.
|
||||
* Open a new window in a popup. This is the best way to do so, but you cannot tell
|
||||
* if the window was opened or if it was blocked by the browser's popup blocker.
|
||||
* If you want to tell if the browser blocked the new window, use {@link windowOpenWithSuccess}.
|
||||
*
|
||||
* Note: this does not set {@link window.opener} to null. This is to allow the opened popup to
|
||||
* be able to use {@link window.close} to close itself. Because of this, you should only use
|
||||
* this function on urls that you trust.
|
||||
*
|
||||
* In otherwords, you should almost always use {@link windowOpenNoOpener} instead of this function.
|
||||
*/
|
||||
const popupWidth = 780, popupHeight = 640;
|
||||
export function windowOpenPopup(url: string): void {
|
||||
const left = Math.floor(window.screenLeft + window.innerWidth / 2 - popupWidth / 2);
|
||||
const top = Math.floor(window.screenTop + window.innerHeight / 2 - popupHeight / 2);
|
||||
window.open(
|
||||
url,
|
||||
'_blank',
|
||||
`width=${popupWidth},height=${popupHeight},top=${top},left=${left}`
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to open a window and returns whether it succeeded. This technique is
|
||||
* not appropriate in certain contexts, like for example when the JS context is
|
||||
* executing inside a sandboxed iframe. If it is not necessary to know if the
|
||||
* browser blocked the new window, use {@link windowOpenNoOpener}.
|
||||
*
|
||||
* See https://github.com/microsoft/monaco-editor/issues/601
|
||||
* See https://github.com/microsoft/monaco-editor/issues/2474
|
||||
* See https://mathiasbynens.github.io/rel-noopener/
|
||||
*
|
||||
* @param url the url to open
|
||||
* @param noOpener whether or not to set the {@link window.opener} to null. You should leave the default
|
||||
* (true) unless you trust the url that is being opened.
|
||||
* @returns boolean indicating if the {@link window.open} call succeeded
|
||||
*/
|
||||
export function windowOpenNoOpenerWithSuccess(url: string): boolean {
|
||||
export function windowOpenWithSuccess(url: string, noOpener = true): boolean {
|
||||
const newTab = window.open();
|
||||
if (newTab) {
|
||||
(newTab as any).opener = null;
|
||||
if (noOpener) {
|
||||
// see `windowOpenNoOpener` for details on why this is important
|
||||
(newTab as any).opener = null;
|
||||
}
|
||||
newTab.location.href = url;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -86,6 +86,7 @@ export namespace CSSIcon {
|
|||
export const iconNameSegment = '[A-Za-z0-9]+';
|
||||
export const iconNameExpression = '[A-Za-z0-9\\-]+';
|
||||
export const iconModifierExpression = '~[A-Za-z]+';
|
||||
export const iconNameCharacter = '[A-Za-z0-9\\-~]';
|
||||
|
||||
const cssIconIdRegex = new RegExp(`^(${iconNameExpression})(${iconModifierExpression})?$`);
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import { ltrim } from 'vs/base/common/strings';
|
|||
export const iconStartMarker = '$(';
|
||||
|
||||
const iconsRegex = new RegExp(`\\$\\(${CSSIcon.iconNameExpression}(?:${CSSIcon.iconModifierExpression})?\\)`, 'g'); // no capturing groups
|
||||
const iconNameCharacterRegexp = new RegExp(CSSIcon.iconNameCharacter);
|
||||
|
||||
const escapeIconsRegex = new RegExp(`(\\\\)?${iconsRegex.source}`, 'g');
|
||||
export function escapeIcons(text: string): string {
|
||||
|
@ -103,7 +104,7 @@ function doParseLabelWithIcons(text: string, firstIconIndex: number): IParsedLab
|
|||
// within icon
|
||||
else if (currentIconStart !== -1) {
|
||||
// Make sure this is a real icon name
|
||||
if (/^[a-z0-9\-]$/i.test(char)) {
|
||||
if (iconNameCharacterRegexp.test(char)) {
|
||||
currentIconValue += char;
|
||||
} else {
|
||||
// This is not a real icon, treat it as text
|
||||
|
|
|
@ -63,6 +63,11 @@ suite('Icon Labels', () => {
|
|||
filterOk(matchesFuzzyIconAware, 'unt', parseLabelWithIcons('$(primitive-dot) $(file-text) Untitled-1'), [
|
||||
{ start: 30, end: 33 },
|
||||
]);
|
||||
|
||||
// Testing #136172
|
||||
filterOk(matchesFuzzyIconAware, 's', parseLabelWithIcons('$(loading~spin) start'), [
|
||||
{ start: 16, end: 17 },
|
||||
]);
|
||||
});
|
||||
|
||||
test('stripIcons', () => {
|
||||
|
|
|
@ -268,7 +268,7 @@ class SharedProcessMain extends Disposable {
|
|||
this._register(toDisposable(() => collectorAppender.flush())); // Ensure the AI appender is disposed so that it flushes remaining data
|
||||
appenders.push(collectorAppender);
|
||||
}
|
||||
const appInsightsAppender = new AppInsightsAppender('monacoworkbench', null, productService.aiConfig.asimovKey, insiders ? false : testCollector);
|
||||
const appInsightsAppender = new AppInsightsAppender('monacoworkbench', null, productService.aiConfig.asimovKey, insiders ? false : testCollector, testCollector && insiders);
|
||||
this._register(toDisposable(() => appInsightsAppender.flush())); // Ensure the AI appender is disposed so that it flushes remaining data
|
||||
appenders.push(appInsightsAppender);
|
||||
}
|
||||
|
|
|
@ -72,8 +72,11 @@ export class BracketPairs extends Disposable implements IBracketPairs {
|
|||
this.onDidChangeEmitter.fire();
|
||||
}
|
||||
} else {
|
||||
this.bracketPairsTree.clear();
|
||||
this.onDidChangeEmitter.fire();
|
||||
if (this.bracketPairsTree.value) {
|
||||
this.bracketPairsTree.clear();
|
||||
// Important: Don't call fire if there was no change!
|
||||
this.onDidChangeEmitter.fire();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -71,6 +71,16 @@ export interface IFindStartOptions {
|
|||
loop: boolean;
|
||||
}
|
||||
|
||||
export interface IFindStartArguments {
|
||||
searchString?: string;
|
||||
replaceString?: string;
|
||||
isRegex?: boolean;
|
||||
matchWholeWord?: boolean;
|
||||
isCaseSensitive?: boolean;
|
||||
preserveCase?: boolean;
|
||||
findInSelection?: boolean;
|
||||
}
|
||||
|
||||
export class CommonFindController extends Disposable implements IEditorContribution {
|
||||
|
||||
public static readonly ID = 'editor.contrib.findController';
|
||||
|
@ -273,7 +283,7 @@ export class CommonFindController extends Disposable implements IEditorContribut
|
|||
// overwritten in subclass
|
||||
}
|
||||
|
||||
protected async _start(opts: IFindStartOptions): Promise<void> {
|
||||
protected async _start(opts: IFindStartOptions, newState?: INewFindReplaceState): Promise<void> {
|
||||
this.disposeModel();
|
||||
|
||||
if (!this._editor.hasModel()) {
|
||||
|
@ -282,6 +292,7 @@ export class CommonFindController extends Disposable implements IEditorContribut
|
|||
}
|
||||
|
||||
let stateChanges: INewFindReplaceState = {
|
||||
...newState,
|
||||
isRevealed: true
|
||||
};
|
||||
|
||||
|
@ -315,7 +326,7 @@ export class CommonFindController extends Disposable implements IEditorContribut
|
|||
}
|
||||
|
||||
// Overwrite isReplaceRevealed
|
||||
if (opts.forceRevealReplace) {
|
||||
if (opts.forceRevealReplace || stateChanges.isReplaceRevealed) {
|
||||
stateChanges.isReplaceRevealed = true;
|
||||
} else if (!this._findWidgetVisible.get()) {
|
||||
stateChanges.isReplaceRevealed = false;
|
||||
|
@ -337,8 +348,8 @@ export class CommonFindController extends Disposable implements IEditorContribut
|
|||
}
|
||||
}
|
||||
|
||||
public start(opts: IFindStartOptions): Promise<void> {
|
||||
return this._start(opts);
|
||||
public start(opts: IFindStartOptions, newState?: INewFindReplaceState): Promise<void> {
|
||||
return this._start(opts, newState);
|
||||
}
|
||||
|
||||
public moveToNextMatch(): boolean {
|
||||
|
@ -423,7 +434,7 @@ export class FindController extends CommonFindController implements IFindControl
|
|||
this._findOptionsWidget = null;
|
||||
}
|
||||
|
||||
protected override async _start(opts: IFindStartOptions): Promise<void> {
|
||||
protected override async _start(opts: IFindStartOptions, newState?: INewFindReplaceState): Promise<void> {
|
||||
if (!this._widget) {
|
||||
this._createFindWidget();
|
||||
}
|
||||
|
@ -447,9 +458,9 @@ export class FindController extends CommonFindController implements IFindControl
|
|||
break;
|
||||
}
|
||||
|
||||
opts.updateSearchScope = updateSearchScope;
|
||||
opts.updateSearchScope = opts.updateSearchScope || updateSearchScope;
|
||||
|
||||
await super._start(opts);
|
||||
await super._start(opts, newState);
|
||||
|
||||
if (this._widget) {
|
||||
if (opts.shouldFocus === FindStartFocusAction.FocusReplaceInput) {
|
||||
|
@ -520,6 +531,90 @@ StartFindAction.addImplementation(0, (accessor: ServicesAccessor, editor: ICodeE
|
|||
});
|
||||
});
|
||||
|
||||
const findArgDescription = {
|
||||
description: 'Open a new In-Editor Find Widget.',
|
||||
args: [{
|
||||
name: 'Open a new In-Editor Find Widget args',
|
||||
schema: {
|
||||
properties: {
|
||||
searchString: { type: 'string' },
|
||||
replaceString: { type: 'string' },
|
||||
regex: { type: 'boolean' },
|
||||
regexOverride: {
|
||||
type: 'number',
|
||||
description: nls.localize('actions.find.isRegexOverride', 'Overrides "Use Regular Expression" flag.\nThe flag will not be saved for the future.\n0: Do Nothing\n1: True\n2: False')
|
||||
},
|
||||
wholeWord: { type: 'boolean' },
|
||||
wholeWordOverride: {
|
||||
type: 'number',
|
||||
description: nls.localize('actions.find.wholeWordOverride', 'Overrides "Match Whole Word" flag.\nThe flag will not be saved for the future.\n0: Do Nothing\n1: True\n2: False')
|
||||
},
|
||||
matchCase: { type: 'boolean' },
|
||||
matchCaseOverride: {
|
||||
type: 'number',
|
||||
description: nls.localize('actions.find.matchCaseOverride', 'Overrides "Math Case" flag.\nThe flag will not be saved for the future.\n0: Do Nothing\n1: True\n2: False')
|
||||
},
|
||||
preserveCase: { type: 'boolean' },
|
||||
preserveCaseOverride: {
|
||||
type: 'number',
|
||||
description: nls.localize('actions.find.preserveCaseOverride', 'Overrides "Preserve Case" flag.\nThe flag will not be saved for the future.\n0: Do Nothing\n1: True\n2: False')
|
||||
},
|
||||
findInSelection: { type: 'boolean' },
|
||||
}
|
||||
}
|
||||
}]
|
||||
} as const;
|
||||
|
||||
export class StartFindWithArgsAction extends EditorAction {
|
||||
|
||||
constructor() {
|
||||
super({
|
||||
id: FIND_IDS.StartFindWithArgs,
|
||||
label: nls.localize('startFindWithArgsAction', "Find With Arguments"),
|
||||
alias: 'Find With Arguments',
|
||||
precondition: undefined,
|
||||
kbOpts: {
|
||||
kbExpr: null,
|
||||
primary: 0,
|
||||
weight: KeybindingWeight.EditorContrib
|
||||
},
|
||||
description: findArgDescription
|
||||
});
|
||||
}
|
||||
|
||||
public async run(accessor: ServicesAccessor | null, editor: ICodeEditor, args?: IFindStartArguments): Promise<void> {
|
||||
let controller = CommonFindController.get(editor);
|
||||
if (controller) {
|
||||
const newState: INewFindReplaceState = args ? {
|
||||
searchString: args.searchString,
|
||||
replaceString: args.replaceString,
|
||||
isReplaceRevealed: args.replaceString !== undefined,
|
||||
isRegex: args.isRegex,
|
||||
// isRegexOverride: args.regexOverride,
|
||||
wholeWord: args.matchWholeWord,
|
||||
// wholeWordOverride: args.wholeWordOverride,
|
||||
matchCase: args.isCaseSensitive,
|
||||
// matchCaseOverride: args.matchCaseOverride,
|
||||
preserveCase: args.preserveCase,
|
||||
// preserveCaseOverride: args.preserveCaseOverride,
|
||||
} : {};
|
||||
|
||||
await controller.start({
|
||||
forceRevealReplace: false,
|
||||
seedSearchStringFromSelection: (controller.getState().searchString.length === 0) && editor.getOption(EditorOption.find).seedSearchStringFromSelection !== 'never' ? 'single' : 'none',
|
||||
seedSearchStringFromNonEmptySelection: editor.getOption(EditorOption.find).seedSearchStringFromSelection === 'selection',
|
||||
seedSearchStringFromGlobalClipboard: true,
|
||||
shouldFocus: FindStartFocusAction.FocusFindInput,
|
||||
shouldAnimate: true,
|
||||
updateSearchScope: args?.findInSelection || false,
|
||||
loop: editor.getOption(EditorOption.find).loop
|
||||
}, newState);
|
||||
|
||||
controller.setGlobalBufferTerm(controller.getState().searchString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class StartFindWithSelectionAction extends EditorAction {
|
||||
|
||||
constructor() {
|
||||
|
@ -772,6 +867,7 @@ StartFindReplaceAction.addImplementation(0, (accessor: ServicesAccessor, editor:
|
|||
|
||||
registerEditorContribution(CommonFindController.ID, FindController);
|
||||
|
||||
registerEditorAction(StartFindWithArgsAction);
|
||||
registerEditorAction(StartFindWithSelectionAction);
|
||||
registerEditorAction(NextMatchFindAction);
|
||||
registerEditorAction(PreviousMatchFindAction);
|
||||
|
|
|
@ -55,6 +55,7 @@ export const TogglePreserveCaseKeybinding: IKeybindings = {
|
|||
export const FIND_IDS = {
|
||||
StartFindAction: 'actions.find',
|
||||
StartFindWithSelection: 'actions.findWithSelection',
|
||||
StartFindWithArgs: 'editor.actions.findWithArgs',
|
||||
NextMatchFindAction: 'editor.action.nextMatchFindAction',
|
||||
PreviousMatchFindAction: 'editor.action.previousMatchFindAction',
|
||||
NextSelectionMatchFindAction: 'editor.action.nextSelectionMatchFindAction',
|
||||
|
|
|
@ -176,7 +176,7 @@ export class InlayHintsController implements IEditorContribution {
|
|||
|
||||
// update inline hints when content or scroll position changes
|
||||
this._sessionDisposables.add(this._editor.onDidChangeModelContent(() => scheduler.schedule()));
|
||||
this._disposables.add(this._editor.onDidScrollChange(() => scheduler.schedule()));
|
||||
this._sessionDisposables.add(this._editor.onDidScrollChange(() => scheduler.schedule()));
|
||||
scheduler.schedule();
|
||||
|
||||
// update inline hints when any any provider fires an event
|
||||
|
|
|
@ -264,7 +264,7 @@
|
|||
|
||||
/** Do NOT display ReadMore when docs is side/below **/
|
||||
|
||||
.monaco-editor .suggest-widget.docs-side .monaco-list .monaco-list-row>.contents>.main>.right>.readMore, .monaco-editor .suggest-widget.docs-below .monaco-list .monaco-list-row>.contents>.main>.right>.readMore {
|
||||
.monaco-editor .suggest-widget.docs-side .monaco-list .monaco-list-row>.contents>.main>.right>.readMore {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
|
@ -280,11 +280,6 @@
|
|||
display: inline-block;
|
||||
}
|
||||
|
||||
.monaco-editor .suggest-widget.docs-side .monaco-list .monaco-list-row>.contents>.main>.right>.readMore,
|
||||
.monaco-editor .suggest-widget.docs-below .monaco-list .monaco-list-row>.contents>.main>.right>.readMore {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.monaco-editor .suggest-widget .monaco-list .monaco-list-row:hover>.contents>.main>.right>.readMore {
|
||||
visibility: visible;
|
||||
}
|
||||
|
@ -394,7 +389,6 @@
|
|||
word-break: break-all;
|
||||
}
|
||||
|
||||
|
||||
.monaco-editor .suggest-details>.monaco-scrollable-element>.body>.docs {
|
||||
margin: 0;
|
||||
padding: 4px 5px;
|
||||
|
|
|
@ -825,7 +825,7 @@ export class SuggestWidget implements IDisposable {
|
|||
|
||||
private _positionDetails(): void {
|
||||
if (this._isDetailsVisible()) {
|
||||
this._details.placeAtAnchor(this.element.domNode);
|
||||
this._details.placeAtAnchor(this.element.domNode, this._contentWidget.getPosition()?.preference[0] === ContentWidgetPositionPreference.BELOW);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -262,6 +262,7 @@ export class SuggestDetailsOverlay implements IOverlayWidget {
|
|||
|
||||
private _added: boolean = false;
|
||||
private _anchorBox?: dom.IDomNodePagePosition;
|
||||
private _preferAlignAtTop: boolean = true;
|
||||
private _userSize?: dom.Dimension;
|
||||
private _topLeft?: TopLeftPosition;
|
||||
|
||||
|
@ -315,7 +316,7 @@ export class SuggestDetailsOverlay implements IOverlayWidget {
|
|||
|
||||
this._disposables.add(this.widget.onDidChangeContents(() => {
|
||||
if (this._anchorBox) {
|
||||
this._placeAtAnchor(this._anchorBox, this._userSize ?? this.widget.size);
|
||||
this._placeAtAnchor(this._anchorBox, this._userSize ?? this.widget.size, this._preferAlignAtTop);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
@ -361,13 +362,14 @@ export class SuggestDetailsOverlay implements IOverlayWidget {
|
|||
}
|
||||
}
|
||||
|
||||
placeAtAnchor(anchor: HTMLElement) {
|
||||
placeAtAnchor(anchor: HTMLElement, preferAlignAtTop: boolean) {
|
||||
const anchorBox = dom.getDomNodePagePosition(anchor);
|
||||
this._anchorBox = anchorBox;
|
||||
this._placeAtAnchor(this._anchorBox, this._userSize ?? this.widget.size);
|
||||
this._preferAlignAtTop = preferAlignAtTop;
|
||||
this._placeAtAnchor(this._anchorBox, this._userSize ?? this.widget.size, preferAlignAtTop);
|
||||
}
|
||||
|
||||
_placeAtAnchor(anchorBox: dom.IDomNodePagePosition, size: dom.Dimension) {
|
||||
_placeAtAnchor(anchorBox: dom.IDomNodePagePosition, size: dom.Dimension, preferAlignAtTop: boolean) {
|
||||
const bodyBox = dom.getClientArea(document.body);
|
||||
|
||||
const info = this.widget.getLayoutInfo();
|
||||
|
@ -416,12 +418,22 @@ export class SuggestDetailsOverlay implements IOverlayWidget {
|
|||
height = maxHeight;
|
||||
}
|
||||
let maxSize: dom.Dimension;
|
||||
if (height <= placement.maxSizeTop.height) {
|
||||
alignAtTop = true;
|
||||
maxSize = placement.maxSizeTop;
|
||||
if (preferAlignAtTop) {
|
||||
if (height <= placement.maxSizeTop.height) {
|
||||
alignAtTop = true;
|
||||
maxSize = placement.maxSizeTop;
|
||||
} else {
|
||||
alignAtTop = false;
|
||||
maxSize = placement.maxSizeBottom;
|
||||
}
|
||||
} else {
|
||||
alignAtTop = false;
|
||||
maxSize = placement.maxSizeBottom;
|
||||
if (height <= placement.maxSizeBottom.height) {
|
||||
alignAtTop = false;
|
||||
maxSize = placement.maxSizeBottom;
|
||||
} else {
|
||||
alignAtTop = true;
|
||||
maxSize = placement.maxSizeTop;
|
||||
}
|
||||
}
|
||||
|
||||
this._applyTopLeft({ left: placement.left, top: alignAtTop ? placement.top : bottom - height });
|
||||
|
|
|
@ -62,7 +62,6 @@ export interface IConstructorSignature8<A1, A2, A3, A4, A5, A6, A7, A8, T> {
|
|||
|
||||
export interface ServicesAccessor {
|
||||
get<T>(id: ServiceIdentifier<T>): T;
|
||||
get<T>(id: ServiceIdentifier<T>, isOptional: typeof optional): T | undefined;
|
||||
}
|
||||
|
||||
export const IInstantiationService = createDecorator<IInstantiationService>('instantiationService');
|
||||
|
@ -158,17 +157,3 @@ export function createDecorator<T>(serviceId: string): ServiceIdentifier<T> {
|
|||
export function refineServiceDecorator<T1, T extends T1>(serviceIdentifier: ServiceIdentifier<T1>): ServiceIdentifier<T> {
|
||||
return <ServiceIdentifier<T>>serviceIdentifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark a service dependency as optional.
|
||||
* @deprecated Avoid, see https://github.com/microsoft/vscode/issues/119440
|
||||
*/
|
||||
export function optional<T>(serviceIdentifier: ServiceIdentifier<T>) {
|
||||
|
||||
return function (target: Function, key: string, index: number) {
|
||||
if (arguments.length !== 3) {
|
||||
throw new Error('@optional-decorator can only be used to decorate a parameter');
|
||||
}
|
||||
storeServiceDependency(serviceIdentifier, target, index, true);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ import { IdleValue } from 'vs/base/common/async';
|
|||
import { illegalState } from 'vs/base/common/errors';
|
||||
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
|
||||
import { Graph } from 'vs/platform/instantiation/common/graph';
|
||||
import { IInstantiationService, optional, ServiceIdentifier, ServicesAccessor, _util } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IInstantiationService, ServiceIdentifier, ServicesAccessor, _util } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
|
||||
|
||||
// TRACING
|
||||
|
@ -45,14 +45,14 @@ export class InstantiationService implements IInstantiationService {
|
|||
let _done = false;
|
||||
try {
|
||||
const accessor: ServicesAccessor = {
|
||||
get: <T>(id: ServiceIdentifier<T>, isOptional?: typeof optional) => {
|
||||
get: <T>(id: ServiceIdentifier<T>) => {
|
||||
|
||||
if (_done) {
|
||||
throw illegalState('service accessor is only valid during the invocation of its target method');
|
||||
}
|
||||
|
||||
const result = this._getOrCreateServiceInstance(id, _trace);
|
||||
if (!result && isOptional !== optional) {
|
||||
if (!result) {
|
||||
throw new Error(`[invokeFunction] unknown service '${id}'`);
|
||||
}
|
||||
return result;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
import * as assert from 'assert';
|
||||
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
|
||||
import { createDecorator, IInstantiationService, optional, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { createDecorator, IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
|
||||
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
|
||||
|
||||
|
@ -85,18 +85,7 @@ class TargetWithStaticParam {
|
|||
}
|
||||
}
|
||||
|
||||
class TargetNotOptional {
|
||||
constructor(@IService1 service1: IService1, @IService2 service2: IService2) {
|
||||
|
||||
}
|
||||
}
|
||||
class TargetOptional {
|
||||
constructor(@IService1 service1: IService1, @optional(IService2) service2: IService2) {
|
||||
assert.ok(service1);
|
||||
assert.strictEqual(service1.c, 1);
|
||||
assert.ok(service2 === undefined);
|
||||
}
|
||||
}
|
||||
|
||||
class DependentServiceTarget {
|
||||
constructor(@IDependentService d: IDependentService) {
|
||||
|
@ -181,13 +170,6 @@ suite('Instantiation Service', () => {
|
|||
let service = new InstantiationService(collection);
|
||||
service.createInstance(Service1Consumer);
|
||||
|
||||
// no IService2
|
||||
assert.throws(() => service.createInstance(Target2Dep));
|
||||
service.invokeFunction(function (a) {
|
||||
assert.ok(a.get(IService1));
|
||||
assert.ok(!a.get(IService2, optional));
|
||||
});
|
||||
|
||||
collection.set(IService2, new Service2());
|
||||
|
||||
service.createInstance(Target2Dep);
|
||||
|
@ -197,18 +179,6 @@ suite('Instantiation Service', () => {
|
|||
});
|
||||
});
|
||||
|
||||
test('@Param - optional', function () {
|
||||
let collection = new ServiceCollection([IService1, new Service1()]);
|
||||
let service = new InstantiationService(collection, true);
|
||||
|
||||
service.createInstance(TargetOptional);
|
||||
assert.throws(() => service.createInstance(TargetNotOptional));
|
||||
|
||||
service = new InstantiationService(collection, false);
|
||||
service.createInstance(TargetOptional);
|
||||
service.createInstance(TargetNotOptional);
|
||||
});
|
||||
|
||||
// we made this a warning
|
||||
// test('@Param - too many args', function () {
|
||||
// let service = instantiationService.create(Object.create(null));
|
||||
|
@ -320,7 +290,6 @@ suite('Instantiation Service', () => {
|
|||
function test(accessor: ServicesAccessor) {
|
||||
assert.ok(accessor.get(IService1) instanceof Service1);
|
||||
assert.throws(() => accessor.get(IService2));
|
||||
assert.strictEqual(accessor.get(IService2, optional), undefined);
|
||||
return true;
|
||||
}
|
||||
assert.strictEqual(service.invokeFunction(test), true);
|
||||
|
|
|
@ -29,7 +29,7 @@ async function getClient(aiKey: string, testCollector: boolean): Promise<Telemet
|
|||
}
|
||||
|
||||
if (aiKey.indexOf('AIF-') === 0) {
|
||||
client.config.endpointUrl = testCollector ? 'https://mobile.events.data.microsoft.com/OneCollector/1.0' : 'https://vortex.data.microsoft.com/collect/v1';
|
||||
client.config.endpointUrl = testCollector ? 'https://mobile.events.data.microsoft.com/collect/v1' : 'https://vortex.data.microsoft.com/collect/v1';
|
||||
}
|
||||
return client;
|
||||
}
|
||||
|
|
|
@ -142,6 +142,9 @@ export class PtyService extends Disposable implements IPtyService {
|
|||
{
|
||||
...state.shellLaunchConfig,
|
||||
cwd: state.processDetails.cwd,
|
||||
color: state.processDetails.color,
|
||||
icon: state.processDetails.icon,
|
||||
name: state.processDetails.title,
|
||||
initialText: state.replayEvent.events[0].data + '\x1b[0m\n\n\r\x1b[1;48;5;252;38;5;234m ' + restoreMessage + ' \x1b[K\x1b[0m\n\r'
|
||||
},
|
||||
state.processDetails.cwd,
|
||||
|
@ -190,7 +193,7 @@ export class PtyService extends Disposable implements IPtyService {
|
|||
executableEnv,
|
||||
windowsEnableConpty
|
||||
};
|
||||
const persistentProcess = new PersistentTerminalProcess(id, process, workspaceId, workspaceName, shouldPersist, cols, rows, processLaunchOptions, unicodeVersion, this._reconnectConstants, this._logService, isReviving ? shellLaunchConfig.initialText : undefined, shellLaunchConfig.icon, shellLaunchConfig.color, shellLaunchConfig.fixedDimensions);
|
||||
const persistentProcess = new PersistentTerminalProcess(id, process, workspaceId, workspaceName, shouldPersist, cols, rows, processLaunchOptions, unicodeVersion, this._reconnectConstants, this._logService, isReviving ? shellLaunchConfig.initialText : undefined, shellLaunchConfig.icon, shellLaunchConfig.color, shellLaunchConfig.name, shellLaunchConfig.fixedDimensions);
|
||||
process.onDidChangeProperty(property => this._onDidChangeProperty.fire({ id, property }));
|
||||
process.onProcessExit(event => {
|
||||
persistentProcess.dispose();
|
||||
|
@ -461,9 +464,13 @@ export class PersistentTerminalProcess extends Disposable {
|
|||
reviveBuffer: string | undefined,
|
||||
private _icon?: TerminalIcon,
|
||||
private _color?: string,
|
||||
name?: string,
|
||||
fixedDimensions?: IFixedTerminalDimensions
|
||||
) {
|
||||
super();
|
||||
if (name) {
|
||||
this.setTitle(name, TitleEventSource.Api);
|
||||
}
|
||||
this._logService.trace('persistentTerminalProcess#ctor', _persistentProcessId, arguments);
|
||||
this._wasRevived = reviveBuffer !== undefined;
|
||||
this._serializer = new XtermSerializer(
|
||||
|
|
|
@ -9,6 +9,7 @@ import { URI, UriComponents } from 'vs/base/common/uri';
|
|||
import { ISandboxConfiguration } from 'vs/base/parts/sandbox/common/sandboxTypes';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { NativeParsedArgs } from 'vs/platform/environment/common/argv';
|
||||
import { FileType } from 'vs/platform/files/common/files';
|
||||
import { LogLevel } from 'vs/platform/log/common/log';
|
||||
import { ISingleFolderWorkspaceIdentifier, IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
|
||||
|
||||
|
@ -187,13 +188,19 @@ export interface IPathData {
|
|||
|
||||
// a hint that the file exists. if true, the
|
||||
// file exists, if false it does not. with
|
||||
// undefined the state is unknown.
|
||||
// `undefined` the state is unknown.
|
||||
readonly exists?: boolean;
|
||||
|
||||
// Specifies if the file should be only be opened if it exists
|
||||
// a hint about the file type of this path.
|
||||
// with `undefined` the type is unknown.
|
||||
readonly type?: FileType;
|
||||
|
||||
// Specifies if the file should be only be opened
|
||||
// if it exists
|
||||
readonly openOnlyIfExists?: boolean;
|
||||
|
||||
// Specifies an optional id to override the editor used to edit the resource, e.g. custom editor.
|
||||
// Specifies an optional id to override the editor
|
||||
// used to edit the resource, e.g. custom editor.
|
||||
readonly editorOverrideId?: string;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
|
|||
import { IDialogMainService } from 'vs/platform/dialogs/electron-main/dialogMainService';
|
||||
import { NativeParsedArgs } from 'vs/platform/environment/common/argv';
|
||||
import { IEnvironmentMainService } from 'vs/platform/environment/electron-main/environmentMainService';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { FileType, IFileService } from 'vs/platform/files/common/files';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ILifecycleMainService } from 'vs/platform/lifecycle/electron-main/lifecycleMainService';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
|
@ -988,14 +988,21 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
|
|||
return undefined;
|
||||
}
|
||||
|
||||
return { workspace: { id: workspace.id, configPath: workspace.configPath }, remoteAuthority: workspace.remoteAuthority, exists: true, transient: workspace.transient };
|
||||
return {
|
||||
workspace: { id: workspace.id, configPath: workspace.configPath },
|
||||
type: FileType.File,
|
||||
exists: true,
|
||||
remoteAuthority: workspace.remoteAuthority,
|
||||
transient: workspace.transient
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
fileUri: URI.file(path),
|
||||
selection: lineNumber ? { startLineNumber: lineNumber, startColumn: columnNumber || 1 } : undefined,
|
||||
exists: true
|
||||
type: FileType.File,
|
||||
exists: true,
|
||||
selection: lineNumber ? { startLineNumber: lineNumber, startColumn: columnNumber || 1 } : undefined
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1003,6 +1010,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
|
|||
else if (pathStat.isDirectory()) {
|
||||
return {
|
||||
workspace: getSingleFolderWorkspaceIdentifier(URI.file(path), pathStat),
|
||||
type: FileType.Directory,
|
||||
exists: true
|
||||
};
|
||||
}
|
||||
|
@ -1014,6 +1022,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
|
|||
else if (!isWindows && path === '/dev/null') {
|
||||
return {
|
||||
fileUri: URI.file(path),
|
||||
type: FileType.File,
|
||||
exists: true
|
||||
};
|
||||
}
|
||||
|
@ -1027,6 +1036,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
|
|||
if (options.ignoreFileNotFound) {
|
||||
return {
|
||||
fileUri,
|
||||
type: FileType.File,
|
||||
exists: false
|
||||
};
|
||||
}
|
||||
|
|
12
src/vs/vscode.d.ts
vendored
12
src/vs/vscode.d.ts
vendored
|
@ -541,7 +541,7 @@ declare module 'vscode' {
|
|||
* The {@link TextEditorSelectionChangeKind change kind} which has triggered this
|
||||
* event. Can be `undefined`.
|
||||
*/
|
||||
readonly kind: TextEditorSelectionChangeKind | undefined
|
||||
readonly kind: TextEditorSelectionChangeKind | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -8137,14 +8137,14 @@ declare module 'vscode' {
|
|||
* If this is provided, your extension should restore the editor from the backup instead of reading the file
|
||||
* from the user's workspace.
|
||||
*/
|
||||
readonly backupId: string | undefined
|
||||
readonly backupId: string | undefined;
|
||||
|
||||
/**
|
||||
* If the URI is an untitled file, this will be populated with the byte data of that file
|
||||
*
|
||||
* If this is provided, your extension should utilize this byte data rather than executing fs APIs on the URI passed in
|
||||
*/
|
||||
readonly untitledDocumentData: Uint8Array | undefined
|
||||
readonly untitledDocumentData: Uint8Array | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -12926,7 +12926,7 @@ declare module 'vscode' {
|
|||
/**
|
||||
* Event specific information.
|
||||
*/
|
||||
readonly body: any | undefined;
|
||||
readonly body: any;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -13917,12 +13917,12 @@ declare module 'vscode' {
|
|||
/**
|
||||
* The {@link AuthenticationSession AuthenticationSessions} of the {@link AuthenticationProvider} that have been added.
|
||||
*/
|
||||
readonly added: readonly AuthenticationSession[] | undefined
|
||||
readonly added: readonly AuthenticationSession[] | undefined;
|
||||
|
||||
/**
|
||||
* The {@link AuthenticationSession AuthenticationSessions} of the {@link AuthenticationProvider} that have been removed.
|
||||
*/
|
||||
readonly removed: readonly AuthenticationSession[] | undefined
|
||||
readonly removed: readonly AuthenticationSession[] | undefined;
|
||||
|
||||
/**
|
||||
* The {@link AuthenticationSession AuthenticationSessions} of the {@link AuthenticationProvider} that have been changed.
|
||||
|
|
|
@ -11,7 +11,7 @@ import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService
|
|||
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
||||
import { reviveWebviewContentOptions } from 'vs/workbench/api/browser/mainThreadWebviews';
|
||||
import { ExtHostContext, ExtHostEditorInsetsShape, IExtHostContext, IWebviewOptions, MainContext, MainThreadEditorInsetsShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { IWebviewService, WebviewElement } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { IWebviewService, IWebviewElement } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { extHostNamedCustomer } from '../common/extHostCustomers';
|
||||
|
||||
// todo@jrieken move these things back into something like contrib/insets
|
||||
|
@ -34,7 +34,7 @@ class EditorWebviewZone implements IViewZone {
|
|||
readonly editor: IActiveCodeEditor,
|
||||
readonly line: number,
|
||||
readonly height: number,
|
||||
readonly webview: WebviewElement,
|
||||
readonly webview: IWebviewElement,
|
||||
) {
|
||||
this.domNode = document.createElement('div');
|
||||
this.domNode.style.zIndex = '10'; // without this, the webview is not interactive
|
||||
|
|
|
@ -37,12 +37,14 @@ export class MainThreadDiagnostics implements MainThreadDiagnosticsShape {
|
|||
private _forwardMarkers(resources: readonly URI[]): void {
|
||||
const data: [UriComponents, IMarkerData[]][] = [];
|
||||
for (const resource of resources) {
|
||||
data.push([
|
||||
resource,
|
||||
this._markerService.read({ resource }).filter(marker => !this._activeOwners.has(marker.owner))
|
||||
]);
|
||||
const markerData = this._markerService.read({ resource }).filter(marker => !this._activeOwners.has(marker.owner));
|
||||
if (markerData.length > 0) {
|
||||
data.push([resource, markerData]);
|
||||
}
|
||||
}
|
||||
if (data.length > 0) {
|
||||
this._proxy.$acceptMarkersChange(data);
|
||||
}
|
||||
this._proxy.$acceptMarkersChange(data);
|
||||
}
|
||||
|
||||
$changeMany(owner: string, entries: [UriComponents, IMarkerData[]][]): void {
|
||||
|
|
|
@ -15,7 +15,7 @@ import { IOpenerService } from 'vs/platform/opener/common/opener';
|
|||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import * as extHostProtocol from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { serializeWebviewMessage, deserializeWebviewMessage } from 'vs/workbench/api/common/extHostWebviewMessaging';
|
||||
import { Webview, WebviewContentOptions, WebviewExtensionDescription, WebviewOverlay } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { IWebview, WebviewContentOptions, WebviewExtensionDescription, IOverlayWebview } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
|
||||
export class MainThreadWebviews extends Disposable implements extHostProtocol.MainThreadWebviewsShape {
|
||||
|
||||
|
@ -29,7 +29,7 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
|
|||
|
||||
private readonly _proxy: extHostProtocol.ExtHostWebviewsShape;
|
||||
|
||||
private readonly _webviews = new Map<string, Webview>();
|
||||
private readonly _webviews = new Map<string, IWebview>();
|
||||
|
||||
constructor(
|
||||
context: extHostProtocol.IExtHostContext,
|
||||
|
@ -41,7 +41,7 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
|
|||
this._proxy = context.getProxy(extHostProtocol.ExtHostContext.ExtHostWebviews);
|
||||
}
|
||||
|
||||
public addWebview(handle: extHostProtocol.WebviewHandle, webview: WebviewOverlay, options: { serializeBuffersForPostMessage: boolean }): void {
|
||||
public addWebview(handle: extHostProtocol.WebviewHandle, webview: IOverlayWebview, options: { serializeBuffersForPostMessage: boolean }): void {
|
||||
if (this._webviews.has(handle)) {
|
||||
throw new Error('Webview already registered');
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
|
|||
return true;
|
||||
}
|
||||
|
||||
private hookupWebviewEventDelegate(handle: extHostProtocol.WebviewHandle, webview: WebviewOverlay, options: { serializeBuffersForPostMessage: boolean }) {
|
||||
private hookupWebviewEventDelegate(handle: extHostProtocol.WebviewHandle, webview: IOverlayWebview, options: { serializeBuffersForPostMessage: boolean }) {
|
||||
const disposables = new DisposableStore();
|
||||
|
||||
disposables.add(webview.onDidClickLink((uri) => this.onDidClickLink(handle, uri)));
|
||||
|
@ -92,7 +92,7 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
|
|||
}
|
||||
}
|
||||
|
||||
private isSupportedLink(webview: Webview, link: URI): boolean {
|
||||
private isSupportedLink(webview: IWebview, link: URI): boolean {
|
||||
if (MainThreadWebviews.standardSupportedLinkSchemes.has(link.scheme)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
|
|||
return !!webview.contentOptions.enableCommandUris && link.scheme === Schemas.command;
|
||||
}
|
||||
|
||||
private getWebview(handle: extHostProtocol.WebviewHandle): Webview {
|
||||
private getWebview(handle: extHostProtocol.WebviewHandle): IWebview {
|
||||
const webview = this._webviews.get(handle);
|
||||
if (!webview) {
|
||||
throw new Error(`Unknown webview handle:${handle}`);
|
||||
|
|
|
@ -207,7 +207,7 @@ class ToggleScreencastModeAction extends Action2 {
|
|||
const event = new StandardKeyboardEvent(e);
|
||||
const shortcut = keybindingService.softDispatch(event, event.target);
|
||||
|
||||
if (shortcut || !configurationService.getValue('screencastMode.onlyKeyboardShortcuts')) {
|
||||
if (shortcut?.commandId || !configurationService.getValue('screencastMode.onlyKeyboardShortcuts')) {
|
||||
if (
|
||||
event.ctrlKey || event.altKey || event.metaKey || event.shiftKey
|
||||
|| length > 20
|
||||
|
@ -243,7 +243,7 @@ class ToggleScreencastModeAction extends Action2 {
|
|||
append(keyboardMarker, $('span.title', {}, `${titleLabel} `));
|
||||
}
|
||||
|
||||
if (format === 'keys' || format === 'commandAndKeys' || format === 'commandWithGroupAndKeys') {
|
||||
if (!configurationService.getValue('screencastMode.onlyKeyboardShortcuts') || !titleLabel || shortcut?.commandId && (format === 'keys' || format === 'commandAndKeys' || format === 'commandWithGroupAndKeys')) {
|
||||
append(keyboardMarker, $('span.key', {}, keyLabel || ''));
|
||||
}
|
||||
|
||||
|
|
|
@ -586,9 +586,23 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
|
|||
return;
|
||||
}
|
||||
|
||||
const selection = widget.getSelection();
|
||||
const focus = widget.getFocus()[0];
|
||||
const fakeKeyboardEvent = new KeyboardEvent('keydown');
|
||||
widget.setSelection([], fakeKeyboardEvent);
|
||||
widget.setFocus([], fakeKeyboardEvent);
|
||||
|
||||
if (selection.length > 1) {
|
||||
if (focus) {
|
||||
widget.setSelection([focus], fakeKeyboardEvent);
|
||||
} else {
|
||||
widget.setSelection(selection[0], fakeKeyboardEvent);
|
||||
}
|
||||
} else if (selection.length === 1 && selection[0] !== focus) {
|
||||
widget.setSelection([focus], fakeKeyboardEvent);
|
||||
} else {
|
||||
widget.setSelection([], fakeKeyboardEvent);
|
||||
widget.setFocus([], fakeKeyboardEvent);
|
||||
}
|
||||
|
||||
widget.setAnchor(undefined);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { isSafari, setFullscreen } from 'vs/base/browser/browser';
|
||||
import { addDisposableListener, addDisposableThrottledListener, detectFullscreen, EventHelper, EventType, windowOpenNoOpenerWithSuccess, windowOpenNoOpener } from 'vs/base/browser/dom';
|
||||
import { addDisposableListener, addDisposableThrottledListener, detectFullscreen, EventHelper, EventType, windowOpenNoOpener, windowOpenPopup, windowOpenWithSuccess } from 'vs/base/browser/dom';
|
||||
import { DomEmitter } from 'vs/base/browser/event';
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
|
@ -141,10 +141,20 @@ export class BrowserWindow extends Disposable {
|
|||
}
|
||||
}
|
||||
|
||||
let isAllowedOpener = false;
|
||||
if (this.environmentService.options?.openerAllowedExternalUrlPrefixes) {
|
||||
for (const trustedPopupPrefix of this.environmentService.options.openerAllowedExternalUrlPrefixes) {
|
||||
if (href.startsWith(trustedPopupPrefix)) {
|
||||
isAllowedOpener = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// HTTP(s): open in new window and deal with potential popup blockers
|
||||
if (matchesScheme(href, Schemas.http) || matchesScheme(href, Schemas.https)) {
|
||||
if (isSafari) {
|
||||
const opened = windowOpenNoOpenerWithSuccess(href);
|
||||
const opened = windowOpenWithSuccess(href, !isAllowedOpener);
|
||||
if (!opened) {
|
||||
const showResult = await this.dialogService.show(
|
||||
Severity.Warning,
|
||||
|
@ -161,7 +171,9 @@ export class BrowserWindow extends Disposable {
|
|||
);
|
||||
|
||||
if (showResult.choice === 0) {
|
||||
windowOpenNoOpener(href);
|
||||
isAllowedOpener
|
||||
? windowOpenPopup(href)
|
||||
: windowOpenNoOpener(href);
|
||||
}
|
||||
|
||||
if (showResult.choice === 1) {
|
||||
|
|
|
@ -17,7 +17,7 @@ import { Registry } from 'vs/platform/registry/common/platform';
|
|||
import { IEncodingSupport, IModeSupport } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { ICompositeControl, IComposite } from 'vs/workbench/common/composite';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { FileType, IFileService } from 'vs/platform/files/common/files';
|
||||
import { IPathData } from 'vs/platform/windows/common/windows';
|
||||
import { coalesce } from 'vs/base/common/arrays';
|
||||
import { IExtUri } from 'vs/base/common/resources';
|
||||
|
@ -1138,11 +1138,25 @@ export async function pathsToEditors(paths: IPathData[] | undefined, fileService
|
|||
return;
|
||||
}
|
||||
|
||||
const exists = (typeof path.exists === 'boolean') ? path.exists : await fileService.exists(resource);
|
||||
let exists = path.exists;
|
||||
let type = path.type;
|
||||
if (typeof exists !== 'boolean' || typeof type !== 'number') {
|
||||
try {
|
||||
type = (await fileService.resolve(resource)).isFile ? FileType.File : FileType.Unknown;
|
||||
exists = true;
|
||||
} catch {
|
||||
exists = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!exists && path.openOnlyIfExists) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (type !== FileType.File) {
|
||||
return;
|
||||
}
|
||||
|
||||
const options: ITextEditorOptions = {
|
||||
selection: exists ? path.selection : undefined,
|
||||
pinned: true,
|
||||
|
|
|
@ -20,7 +20,7 @@ import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo';
|
|||
import { DEFAULT_EDITOR_ASSOCIATION, EditorInputCapabilities, GroupIdentifier, IRevertOptions, ISaveOptions, isEditorInputWithOptionsAndGroup, IUntypedEditorInput, Verbosity } from 'vs/workbench/common/editor';
|
||||
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
|
||||
import { ICustomEditorModel, ICustomEditorService } from 'vs/workbench/contrib/customEditor/common/customEditor';
|
||||
import { IWebviewService, WebviewOverlay } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { IWebviewService, IOverlayWebview } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { IWebviewWorkbenchService, LazilyResolvedWebviewEditorInput } from 'vs/workbench/contrib/webviewPanel/browser/webviewWorkbenchService';
|
||||
import { IEditorResolverService } from 'vs/workbench/services/editor/common/editorResolverService';
|
||||
import { IUntitledTextEditorService } from 'vs/workbench/services/untitled/common/untitledTextEditorService';
|
||||
|
@ -66,7 +66,7 @@ export class CustomEditorInput extends LazilyResolvedWebviewEditorInput {
|
|||
resource: URI,
|
||||
viewType: string,
|
||||
id: string,
|
||||
webview: WebviewOverlay,
|
||||
webview: IOverlayWebview,
|
||||
options: { startsDirty?: boolean, backupId?: string, untitledDocumentData?: VSBuffer, readonly oldResource?: URI },
|
||||
@IWebviewWorkbenchService webviewWorkbenchService: IWebviewWorkbenchService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
|
|
|
@ -22,13 +22,14 @@ import { Extensions as JSONExtensions, IJSONContributionRegistry } from 'vs/plat
|
|||
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import { CONTEXT_DEBUGGERS_AVAILABLE, IAdapterDescriptor, IAdapterManager, IConfig, IDebugAdapter, IDebugAdapterDescriptorFactory, IDebugAdapterFactory, IDebugConfiguration, IDebugSession, INTERNAL_CONSOLE_OPTIONS_SCHEMA } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { CONTEXT_DEBUGGERS_AVAILABLE, CONTEXT_DEBUG_EXTENSION_AVAILABLE, IAdapterDescriptor, IAdapterManager, IConfig, IDebugAdapter, IDebugAdapterDescriptorFactory, IDebugAdapterFactory, IDebugConfiguration, IDebugSession, INTERNAL_CONSOLE_OPTIONS_SCHEMA } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { Debugger } from 'vs/workbench/contrib/debug/common/debugger';
|
||||
import { breakpointsExtPoint, debuggersExtPoint, launchSchema, presentationSchema } from 'vs/workbench/contrib/debug/common/debugSchemas';
|
||||
import { TaskDefinitionRegistry } from 'vs/workbench/contrib/tasks/common/taskDefinitionRegistry';
|
||||
import { launchSchemaId } from 'vs/workbench/services/configuration/common/configuration';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { ILifecycleService, LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
|
||||
|
||||
const jsonRegistry = Registry.as<IJSONContributionRegistry>(JSONExtensions.JSONContribution);
|
||||
|
||||
|
@ -38,6 +39,7 @@ export class AdapterManager extends Disposable implements IAdapterManager {
|
|||
private adapterDescriptorFactories: IDebugAdapterDescriptorFactory[];
|
||||
private debugAdapterFactories = new Map<string, IDebugAdapterFactory>();
|
||||
private debuggersAvailable: IContextKey<boolean>;
|
||||
private debugExtensionsAvailable: IContextKey<boolean>;
|
||||
private readonly _onDidRegisterDebugger = new Emitter<void>();
|
||||
private readonly _onDidDebuggersExtPointRead = new Emitter<void>();
|
||||
private breakpointModeIdsSet = new Set<string>();
|
||||
|
@ -53,6 +55,7 @@ export class AdapterManager extends Disposable implements IAdapterManager {
|
|||
@IContextKeyService private readonly contextKeyService: IContextKeyService,
|
||||
@IModeService private readonly modeService: IModeService,
|
||||
@IDialogService private readonly dialogService: IDialogService,
|
||||
@ILifecycleService private readonly lifecycleService: ILifecycleService,
|
||||
) {
|
||||
super();
|
||||
this.adapterDescriptorFactories = [];
|
||||
|
@ -64,6 +67,13 @@ export class AdapterManager extends Disposable implements IAdapterManager {
|
|||
this.debuggersAvailable.set(this.hasEnabledDebuggers());
|
||||
}
|
||||
}));
|
||||
this.debugExtensionsAvailable = CONTEXT_DEBUG_EXTENSION_AVAILABLE.bindTo(contextKeyService);
|
||||
this.debugExtensionsAvailable.set(true); // Avoid a flash of the default message before extensions load.
|
||||
this._register(this.onDidDebuggersExtPointRead(() => {
|
||||
this.debugExtensionsAvailable.set(this.debuggers.length > 0);
|
||||
}));
|
||||
this.lifecycleService.when(LifecyclePhase.Eventually)
|
||||
.then(() => this.debugExtensionsAvailable.set(this.debuggers.length > 0)); // If no extensions with a debugger contribution are loaded
|
||||
}
|
||||
|
||||
private registerListeners(): void {
|
||||
|
|
|
@ -10,7 +10,7 @@ import { IContextMenuService } from 'vs/platform/contextview/browser/contextView
|
|||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IContextKeyService, RawContextKey, IContextKey, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { localize } from 'vs/nls';
|
||||
import { IDebugService, CONTEXT_DEBUGGERS_AVAILABLE } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { IDebugService, CONTEXT_DEBUGGERS_AVAILABLE, CONTEXT_DEBUG_EXTENSION_AVAILABLE } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { ViewPane } from 'vs/workbench/browser/parts/views/viewPane';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
@ -142,3 +142,9 @@ viewsRegistry.registerViewWelcomeContent(WelcomeView.ID, {
|
|||
when: ContextKeyExpr.and(CONTEXT_DEBUGGERS_AVAILABLE, WorkbenchStateContext.isEqualTo('empty')),
|
||||
group: ViewContentGroups.Debug
|
||||
});
|
||||
|
||||
viewsRegistry.registerViewWelcomeContent(WelcomeView.ID, {
|
||||
content: localize('allDebuggersDisabled', "All debug extensions are disabled. Enable a debug extension or install a new one from the Marketplace."),
|
||||
when: CONTEXT_DEBUG_EXTENSION_AVAILABLE.toNegated(),
|
||||
group: ViewContentGroups.Debug
|
||||
});
|
||||
|
|
|
@ -71,6 +71,7 @@ export const CONTEXT_JUMP_TO_CURSOR_SUPPORTED = new RawContextKey<boolean>('jump
|
|||
export const CONTEXT_STEP_INTO_TARGETS_SUPPORTED = new RawContextKey<boolean>('stepIntoTargetsSupported', false, { type: 'boolean', description: nls.localize('stepIntoTargetsSupported', "True when the focused session supports 'stepIntoTargets' request.") });
|
||||
export const CONTEXT_BREAKPOINTS_EXIST = new RawContextKey<boolean>('breakpointsExist', false, { type: 'boolean', description: nls.localize('breakpointsExist', "True when at least one breakpoint exists.") });
|
||||
export const CONTEXT_DEBUGGERS_AVAILABLE = new RawContextKey<boolean>('debuggersAvailable', false, { type: 'boolean', description: nls.localize('debuggersAvailable', "True when there is at least one debug extensions active.") });
|
||||
export const CONTEXT_DEBUG_EXTENSION_AVAILABLE = new RawContextKey<boolean>('debugExtensionAvailable', false, { type: 'boolean', description: nls.localize('debugExtensionsAvailable', "True when there is at least one debug extension installed and enabled.") });
|
||||
export const CONTEXT_DEBUG_PROTOCOL_VARIABLE_MENU_CONTEXT = new RawContextKey<string>('debugProtocolVariableMenuContext', undefined, { type: 'string', description: nls.localize('debugProtocolVariableMenuContext', "Represents the context the debug adapter sets on the focused variable in the VARIABLES view.") });
|
||||
export const CONTEXT_SET_VARIABLE_SUPPORTED = new RawContextKey<boolean>('debugSetVariableSupported', false, { type: 'boolean', description: nls.localize('debugSetVariableSupported', "True when the focused session supports 'setVariable' request.") });
|
||||
export const CONTEXT_SET_EXPRESSION_SUPPORTED = new RawContextKey<boolean>('debugSetExpressionSupported', false, { type: 'boolean', description: nls.localize('debugSetExpressionSupported', "True when the focused session supports 'setExpression' request.") });
|
||||
|
|
|
@ -50,7 +50,7 @@ import { IExtensionService } from 'vs/workbench/services/extensions/common/exten
|
|||
import { getDefaultValue } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { isUndefined } from 'vs/base/common/types';
|
||||
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
|
||||
import { IWebviewService, Webview, KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_FOCUSED } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { IWebviewService, IWebview, KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_FOCUSED } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import { platform } from 'vs/base/common/process';
|
||||
|
@ -554,11 +554,11 @@ export class ExtensionEditor extends EditorPane {
|
|||
this.activeWebview?.runFindAction(previous);
|
||||
}
|
||||
|
||||
public get activeWebview(): Webview | undefined {
|
||||
if (!this.activeElement || !(this.activeElement as Webview).runFindAction) {
|
||||
public get activeWebview(): IWebview | undefined {
|
||||
if (!this.activeElement || !(this.activeElement as IWebview).runFindAction) {
|
||||
return undefined;
|
||||
}
|
||||
return this.activeElement as Webview;
|
||||
return this.activeElement as IWebview;
|
||||
}
|
||||
|
||||
private onNavbarChange(extension: IExtension, { id, focus }: { id: string | null, focus: boolean }, template: IExtensionEditorTemplate): void {
|
||||
|
|
|
@ -44,7 +44,7 @@ import { CONTEXT_SYNC_ENABLEMENT } from 'vs/workbench/services/userDataSync/comm
|
|||
import { CopyAction, CutAction, PasteAction } from 'vs/editor/contrib/clipboard/clipboard';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { MultiCommand } from 'vs/editor/browser/editorExtensions';
|
||||
import { Webview } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { IWebview } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { ExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/browser/extensionsWorkbenchService';
|
||||
import { WorkbenchStateContext } from 'vs/workbench/browser/contextkeys';
|
||||
import { CATEGORIES } from 'vs/workbench/common/actions';
|
||||
|
@ -366,7 +366,7 @@ CommandsRegistry.registerCommand({
|
|||
}
|
||||
});
|
||||
|
||||
function overrideActionForActiveExtensionEditorWebview(command: MultiCommand | undefined, f: (webview: Webview) => void) {
|
||||
function overrideActionForActiveExtensionEditorWebview(command: MultiCommand | undefined, f: (webview: IWebview) => void) {
|
||||
command?.addImplementation(105, 'extensions-editor', (accessor) => {
|
||||
const editorService = accessor.get(IEditorService);
|
||||
const editor = editorService.activeEditorPane;
|
||||
|
|
|
@ -7,7 +7,7 @@ import { localize } from 'vs/nls';
|
|||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { parse } from 'vs/base/common/marshalling';
|
||||
import { assertType } from 'vs/base/common/types';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
|
@ -52,6 +52,9 @@ import { peekViewBorder /*, peekViewEditorBackground, peekViewResultsBackground
|
|||
import * as icons from 'vs/workbench/contrib/notebook/browser/notebookIcons';
|
||||
import { isFalsyOrWhitespace } from 'vs/base/common/strings';
|
||||
import { EditOperation } from 'vs/editor/common/core/editOperation';
|
||||
import { ITextModelContentProvider, ITextModelService } from 'vs/editor/common/services/resolverService';
|
||||
import { ITextModel } from 'vs/editor/common/model';
|
||||
import { IModelService } from 'vs/editor/common/services/modelService';
|
||||
|
||||
|
||||
Registry.as<IEditorPaneRegistry>(EditorExtensions.EditorPane).registerEditorPane(
|
||||
|
@ -218,8 +221,35 @@ export class InteractiveDocumentContribution extends Disposable implements IWork
|
|||
}
|
||||
}
|
||||
|
||||
class InteractiveInputContentProvider implements ITextModelContentProvider {
|
||||
|
||||
private readonly _registration: IDisposable;
|
||||
|
||||
constructor(
|
||||
@ITextModelService textModelService: ITextModelService,
|
||||
@IModelService private readonly _modelService: IModelService,
|
||||
) {
|
||||
this._registration = textModelService.registerTextModelContentProvider(Schemas.vscodeInteractiveInput, this);
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this._registration.dispose();
|
||||
}
|
||||
|
||||
async provideTextContent(resource: URI): Promise<ITextModel | null> {
|
||||
const existing = this._modelService.getModel(resource);
|
||||
if (existing) {
|
||||
return existing;
|
||||
}
|
||||
let result: ITextModel | null = this._modelService.createModel('', null, resource, false);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const workbenchContributionsRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench);
|
||||
workbenchContributionsRegistry.registerWorkbenchContribution(InteractiveDocumentContribution, LifecyclePhase.Starting);
|
||||
workbenchContributionsRegistry.registerWorkbenchContribution(InteractiveInputContentProvider, LifecyclePhase.Starting);
|
||||
|
||||
export class InteractiveEditorSerializer implements IEditorSerializer {
|
||||
canSerialize(): boolean {
|
||||
|
|
|
@ -330,7 +330,7 @@ export class InteractiveEditor extends EditorPane {
|
|||
}
|
||||
}));
|
||||
|
||||
const editorModel = input.resolveInput(this.#notebookWidget.value?.activeKernel?.supportedLanguages[0] ?? 'plaintext');
|
||||
const editorModel = await input.resolveInput(this.#notebookWidget.value?.activeKernel?.supportedLanguages[0] ?? 'plaintext');
|
||||
this.#codeEditorWidget.setModel(editorModel);
|
||||
this.#widgetDisposableStore.add(this.#codeEditorWidget.onDidFocusEditorWidget(() => this.#onDidFocusWidget.fire()));
|
||||
this.#widgetDisposableStore.add(this.#codeEditorWidget.onDidContentSizeChange(e => {
|
||||
|
|
|
@ -4,11 +4,12 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { IReference } from 'vs/base/common/lifecycle';
|
||||
import * as paths from 'vs/base/common/path';
|
||||
import { isEqual } from 'vs/base/common/resources';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ITextModel } from 'vs/editor/common/model';
|
||||
import { IModelService } from 'vs/editor/common/services/modelService';
|
||||
import { IResolvedTextEditorModel, ITextModelService } from 'vs/editor/common/services/resolverService';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IUntypedEditorInput } from 'vs/workbench/common/editor';
|
||||
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
|
||||
|
@ -54,16 +55,12 @@ export class InteractiveEditorInput extends EditorInput implements ICompositeNot
|
|||
private _inputResolver: Promise<IResolvedNotebookEditorModel | null> | null;
|
||||
private _editorModelReference: IResolvedNotebookEditorModel | null;
|
||||
|
||||
private _inputModel: ITextModel | null;
|
||||
|
||||
get inputModel() {
|
||||
return this._inputModel;
|
||||
}
|
||||
private _inputModelRef: IReference<IResolvedTextEditorModel> | null;
|
||||
|
||||
get primary(): EditorInput {
|
||||
return this._notebookEditorInput;
|
||||
}
|
||||
private _modelService: IModelService;
|
||||
private _textModelService: ITextModelService;
|
||||
private _interactiveDocumentService: IInteractiveDocumentService;
|
||||
|
||||
|
||||
|
@ -73,6 +70,8 @@ export class InteractiveEditorInput extends EditorInput implements ICompositeNot
|
|||
title: string | undefined,
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@IModelService modelService: IModelService,
|
||||
@ITextModelService textModelService: ITextModelService,
|
||||
|
||||
@IInteractiveDocumentService interactiveDocumentService: IInteractiveDocumentService
|
||||
) {
|
||||
const input = NotebookEditorInput.create(instantiationService, resource, 'interactive', {});
|
||||
|
@ -83,8 +82,8 @@ export class InteractiveEditorInput extends EditorInput implements ICompositeNot
|
|||
this._inputResource = inputResource;
|
||||
this._inputResolver = null;
|
||||
this._editorModelReference = null;
|
||||
this._inputModel = null;
|
||||
this._modelService = modelService;
|
||||
this._inputModelRef = null;
|
||||
this._textModelService = textModelService;
|
||||
this._interactiveDocumentService = interactiveDocumentService;
|
||||
|
||||
this._registerListeners();
|
||||
|
@ -131,14 +130,15 @@ export class InteractiveEditorInput extends EditorInput implements ICompositeNot
|
|||
return this._inputResolver;
|
||||
}
|
||||
|
||||
resolveInput(language: string) {
|
||||
if (this._inputModel) {
|
||||
return this._inputModel;
|
||||
async resolveInput(language: string) {
|
||||
if (this._inputModelRef) {
|
||||
return this._inputModelRef.object.textEditorModel;
|
||||
}
|
||||
|
||||
this._interactiveDocumentService.willCreateInteractiveDocument(this.resource!, this.inputResource, language);
|
||||
this._inputModel = this._modelService.createModel('', null, this.inputResource, false);
|
||||
return this._inputModel;
|
||||
this._inputModelRef = await this._textModelService.createModelReference(this.inputResource);
|
||||
|
||||
return this._inputModelRef.object.textEditorModel;
|
||||
}
|
||||
|
||||
override matches(otherInput: EditorInput | IUntypedEditorInput): boolean {
|
||||
|
@ -170,8 +170,8 @@ export class InteractiveEditorInput extends EditorInput implements ICompositeNot
|
|||
this._editorModelReference?.dispose();
|
||||
this._editorModelReference = null;
|
||||
this._interactiveDocumentService.willRemoveInteractiveDocument(this.resource!, this.inputResource);
|
||||
this._inputModel?.dispose();
|
||||
this._inputModel = null;
|
||||
this._inputModelRef?.dispose();
|
||||
this._inputModelRef = null;
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ import { InputFocusedContextKey } from 'vs/platform/contextkey/common/contextkey
|
|||
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { RedoCommand, UndoCommand } from 'vs/editor/browser/editorExtensions';
|
||||
import { Webview } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { IWebview } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { CATEGORIES } from 'vs/workbench/common/actions';
|
||||
import { IOutputService } from 'vs/workbench/contrib/output/common/output';
|
||||
import { rendererLogChannelId } from 'vs/workbench/contrib/logs/common/logConstants';
|
||||
|
@ -41,7 +41,7 @@ function _log(loggerService: ILogService, str: string) {
|
|||
}
|
||||
}
|
||||
|
||||
function getFocusedWebviewDelegate(accessor: ServicesAccessor): Webview | undefined {
|
||||
function getFocusedWebviewDelegate(accessor: ServicesAccessor): IWebview | undefined {
|
||||
const loggerService = accessor.get(ILogService);
|
||||
const editorService = accessor.get(IEditorService);
|
||||
const editor = getNotebookEditorFromEditorPane(editorService.activeEditorPane);
|
||||
|
@ -65,7 +65,7 @@ function getFocusedWebviewDelegate(accessor: ServicesAccessor): Webview | undefi
|
|||
return webview;
|
||||
}
|
||||
|
||||
function withWebview(accessor: ServicesAccessor, f: (webviewe: Webview) => void) {
|
||||
function withWebview(accessor: ServicesAccessor, f: (webviewe: IWebview) => void) {
|
||||
const webview = getFocusedWebviewDelegate(accessor);
|
||||
if (webview) {
|
||||
f(webview);
|
||||
|
|
|
@ -16,7 +16,7 @@ import { CellViewModel, IModelDecorationsChangeAccessor, INotebookEditorViewStat
|
|||
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
|
||||
import { CellKind, NotebookCellMetadata, IOrderedMimeType, INotebookRendererInfo, ICellOutput, INotebookCellStatusBarItem, NotebookCellInternalMetadata, NotebookDocumentMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { ICellRange, cellRangesToIndexes, reduceCellRanges } from 'vs/workbench/contrib/notebook/common/notebookRange';
|
||||
import { Webview } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { IWebview } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
|
||||
import { MenuId } from 'vs/platform/actions/common/actions';
|
||||
import { IEditorPane } from 'vs/workbench/common/editor';
|
||||
|
@ -430,7 +430,7 @@ export interface INotebookEditor {
|
|||
hasModel(): this is IActiveNotebookEditor;
|
||||
dispose(): void;
|
||||
getDomNode(): HTMLElement;
|
||||
getInnerWebview(): Webview | undefined;
|
||||
getInnerWebview(): IWebview | undefined;
|
||||
getSelectionViewModels(): ICellViewModel[];
|
||||
|
||||
/**
|
||||
|
|
|
@ -58,7 +58,7 @@ import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/no
|
|||
import { CellKind, SelectionStateType } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange';
|
||||
import { editorGutterModifiedBackground } from 'vs/workbench/contrib/scm/browser/dirtydiffDecorator';
|
||||
import { Webview } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { IWebview } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { mark } from 'vs/workbench/contrib/notebook/common/notebookPerformance';
|
||||
import { readFontInfo } from 'vs/editor/browser/config/configuration';
|
||||
import { INotebookKernelService } from 'vs/workbench/contrib/notebook/common/notebookKernelService';
|
||||
|
@ -1055,7 +1055,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD
|
|||
return this._overflowContainer;
|
||||
}
|
||||
|
||||
getInnerWebview(): Webview | undefined {
|
||||
getInnerWebview(): IWebview | undefined {
|
||||
return this._webview?.webview;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ import { INotebookEditorOptions } from 'vs/workbench/contrib/notebook/browser/no
|
|||
import { NotebookDiffEditorInput } from 'vs/workbench/contrib/notebook/browser/notebookDiffEditorInput';
|
||||
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
|
||||
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
|
||||
import { ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, BUILTIN_RENDERER_ID, CellUri, DisplayOrderKey, INotebookContributionData, INotebookExclusiveDocumentFilter, INotebookRendererInfo, INotebookTextModel, IOrderedMimeType, IOutputDto, MimeTypeDisplayOrder, mimeTypeIsAlwaysSecure, mimeTypeSupportedByCore, NotebookData, NotebookEditorPriority, NotebookRendererMatch, NotebookTextDiffEditorPreview, NOTEBOOK_DISPLAY_ORDER, RENDERER_NOT_AVAILABLE, TransientOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, BUILTIN_RENDERER_ID, CellUri, DisplayOrderKey, INotebookContributionData, INotebookExclusiveDocumentFilter, INotebookRendererInfo, INotebookTextModel, IOrderedMimeType, IOutputDto, MimeTypeDisplayOrder, mimeTypeIsAlwaysSecure, mimeTypeSupportedByCore, NotebookData, NotebookEditorPriority, NotebookRendererMatch, NotebookTextDiffEditorPreview, NOTEBOOK_DISPLAY_ORDER, RENDERER_EQUIVALENT_EXTENSIONS, RENDERER_NOT_AVAILABLE, TransientOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { NotebookEditorInput } from 'vs/workbench/contrib/notebook/common/notebookEditorInput';
|
||||
import { INotebookEditorModelResolverService } from 'vs/workbench/contrib/notebook/common/notebookEditorModelResolverService';
|
||||
import { updateEditorTopPadding } from 'vs/workbench/contrib/notebook/common/notebookOptions';
|
||||
|
@ -314,11 +314,12 @@ export class NotebookOutputRendererInfoStore {
|
|||
const enum ReuseOrder {
|
||||
PreviouslySelected = 1 << 8,
|
||||
SameExtensionAsNotebook = 2 << 8,
|
||||
OtherRenderer = 3 << 8,
|
||||
BuiltIn = 4 << 8,
|
||||
BuiltIn = 3 << 8,
|
||||
OtherRenderer = 4 << 8,
|
||||
}
|
||||
|
||||
const preferred = notebookProviderInfo && this.preferredMimetype.getValue()[notebookProviderInfo.id]?.[mimeType];
|
||||
const notebookExtId = notebookProviderInfo?.extension?.value;
|
||||
const renderers: { ordered: IOrderedMimeType, score: number }[] = Array.from(this.contributedRenderers.values())
|
||||
.map(renderer => {
|
||||
const ownScore = kernelProvides === undefined
|
||||
|
@ -329,9 +330,10 @@ export class NotebookOutputRendererInfoStore {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
const rendererExtId = renderer.extensionId.value;
|
||||
const reuseScore = preferred === renderer.id
|
||||
? ReuseOrder.PreviouslySelected
|
||||
: renderer.extensionId.value === notebookProviderInfo?.extension?.value
|
||||
: rendererExtId === notebookExtId || RENDERER_EQUIVALENT_EXTENSIONS.get(rendererExtId)?.has(notebookExtId!)
|
||||
? ReuseOrder.SameExtensionAsNotebook
|
||||
: renderer.isBuiltin ? ReuseOrder.BuiltIn : ReuseOrder.OtherRenderer;
|
||||
return {
|
||||
|
|
|
@ -36,7 +36,7 @@ import { INotebookRendererInfo, RendererMessagingSpec } from 'vs/workbench/contr
|
|||
import { INotebookKernel } from 'vs/workbench/contrib/notebook/common/notebookKernelService';
|
||||
import { IScopedRendererMessaging } from 'vs/workbench/contrib/notebook/common/notebookRendererMessagingService';
|
||||
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
|
||||
import { IWebviewService, WebviewContentPurpose, WebviewElement } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { IWebviewService, WebviewContentPurpose, IWebviewElement } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { FromWebviewMessage, IAckOutputHeight, IClickedDataUrlMessage, IContentWidgetTopRequest, IControllerPreload, ICreationRequestMessage, IMarkupCellInitialization, ToWebviewMessage } from './webviewMessages';
|
||||
|
||||
|
@ -60,7 +60,7 @@ export interface INotebookWebviewMessage {
|
|||
}
|
||||
|
||||
export interface IResolvedBackLayerWebview {
|
||||
webview: WebviewElement;
|
||||
webview: IWebviewElement;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -87,7 +87,7 @@ export interface INotebookDelegateForWebview {
|
|||
|
||||
export class BackLayerWebView<T extends ICommonCellInfo> extends Disposable {
|
||||
element: HTMLElement;
|
||||
webview: WebviewElement | undefined = undefined;
|
||||
webview: IWebviewElement | undefined = undefined;
|
||||
insetMapping: Map<IDisplayOutputViewModel, ICachedInset<T>> = new Map();
|
||||
readonly markupPreviewMapping = new Map<string, IMarkupCellInitialization>();
|
||||
private hiddenInsetMapping: Set<IDisplayOutputViewModel> = new Set();
|
||||
|
|
|
@ -56,6 +56,17 @@ export const ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER: readonly string[] = [
|
|||
'image/jpeg',
|
||||
];
|
||||
|
||||
/**
|
||||
* A mapping of extension IDs who contain renderers, to extensions who they
|
||||
* should be treated as the same in the renderer selection logic. This is used
|
||||
* to prefer the 1st party Jupyter renderers even though they're in a separate
|
||||
* extension, for instance. See #136247.
|
||||
*/
|
||||
export const RENDERER_EQUIVALENT_EXTENSIONS: ReadonlyMap<string, ReadonlySet<string>> = new Map([
|
||||
['ms-toolsai.jupyter', new Set(['vscode.ipynb'])],
|
||||
['ms-toolsai.jupyter-renderers', new Set(['vscode.ipynb'])],
|
||||
]);
|
||||
|
||||
export const BUILTIN_RENDERER_ID = '_builtin';
|
||||
export const RENDERER_NOT_AVAILABLE = '_notAvailable';
|
||||
|
||||
|
|
|
@ -16,9 +16,10 @@ import { ITextModelService, ITextModelContentProvider } from 'vs/editor/common/s
|
|||
import { ITextModel } from 'vs/editor/common/model';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { ILifecycleService } from 'vs/workbench/services/lifecycle/common/lifecycle';
|
||||
import { IOutputChannelModel, IOutputChannelModelService } from 'vs/workbench/contrib/output/common/outputChannelModel';
|
||||
import { IOutputChannelModel } from 'vs/workbench/contrib/output/common/outputChannelModel';
|
||||
import { IViewsService } from 'vs/workbench/common/views';
|
||||
import { OutputViewPane } from 'vs/workbench/contrib/output/browser/outputView';
|
||||
import { IOutputChannelModelService } from 'vs/workbench/contrib/output/common/outputChannelModelService';
|
||||
|
||||
const OUTPUT_ACTIVE_CHANNEL_KEY = 'output.activechannel';
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { createDecorator, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import * as resources from 'vs/base/common/resources';
|
||||
import { ITextModel } from 'vs/editor/common/model';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
|
@ -28,39 +28,6 @@ export interface IOutputChannelModel extends IDisposable {
|
|||
clear(till?: number): void;
|
||||
}
|
||||
|
||||
export const IOutputChannelModelService = createDecorator<IOutputChannelModelService>('outputChannelModelService');
|
||||
|
||||
export interface IOutputChannelModelService {
|
||||
readonly _serviceBrand: undefined;
|
||||
|
||||
createOutputChannelModel(id: string, modelUri: URI, mimeType: string, file?: URI): IOutputChannelModel;
|
||||
|
||||
}
|
||||
|
||||
export abstract class AbstractOutputChannelModelService {
|
||||
|
||||
declare readonly _serviceBrand: undefined;
|
||||
|
||||
constructor(
|
||||
private readonly outputLocation: URI,
|
||||
@IFileService protected readonly fileService: IFileService,
|
||||
@IInstantiationService protected readonly instantiationService: IInstantiationService
|
||||
) { }
|
||||
|
||||
createOutputChannelModel(id: string, modelUri: URI, mimeType: string, file?: URI): IOutputChannelModel {
|
||||
return file ? this.instantiationService.createInstance(FileOutputChannelModel, modelUri, mimeType, file) : this.instantiationService.createInstance(DelegatedOutputChannelModel, id, modelUri, mimeType, this.outputDir);
|
||||
}
|
||||
|
||||
private _outputDir: Promise<URI> | null = null;
|
||||
private get outputDir(): Promise<URI> {
|
||||
if (!this._outputDir) {
|
||||
this._outputDir = this.fileService.createFolder(this.outputLocation).then(() => this.outputLocation);
|
||||
}
|
||||
return this._outputDir;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export abstract class AbstractFileOutputChannelModel extends Disposable implements IOutputChannelModel {
|
||||
|
||||
protected readonly _onDidAppendedContent = this._register(new Emitter<void>());
|
||||
|
@ -117,7 +84,7 @@ export abstract class AbstractFileOutputChannelModel extends Disposable implemen
|
|||
return this.model;
|
||||
}
|
||||
|
||||
appendToModel(content: string): void {
|
||||
protected appendToModel(content: string): void {
|
||||
if (this.model && content) {
|
||||
const lastLine = this.model.getLineCount();
|
||||
const lastLineMaxColumn = this.model.getLineMaxColumn(lastLine);
|
||||
|
@ -197,7 +164,7 @@ class OutputFileListener extends Disposable {
|
|||
/**
|
||||
* An output channel driven by a file and does not support appending messages.
|
||||
*/
|
||||
class FileOutputChannelModel extends AbstractFileOutputChannelModel implements IOutputChannelModel {
|
||||
export class FileOutputChannelModel extends AbstractFileOutputChannelModel implements IOutputChannelModel {
|
||||
|
||||
private readonly fileHandler: OutputFileListener;
|
||||
|
||||
|
@ -359,44 +326,38 @@ class OutputChannelBackedByFile extends AbstractFileOutputChannelModel implement
|
|||
this.appendedMessage = '';
|
||||
}
|
||||
|
||||
loadModel(): Promise<ITextModel> {
|
||||
async loadModel(): Promise<ITextModel> {
|
||||
this.loadingFromFileInProgress = true;
|
||||
if (this.modelUpdater.isScheduled()) {
|
||||
this.modelUpdater.cancel();
|
||||
}
|
||||
this.appendedMessage = '';
|
||||
return this.loadFile()
|
||||
.then(content => {
|
||||
if (this.endOffset !== this.startOffset + VSBuffer.fromString(content).byteLength) {
|
||||
// Queue content is not written into the file
|
||||
// Flush it and load file again
|
||||
this.flush();
|
||||
return this.loadFile();
|
||||
}
|
||||
return content;
|
||||
})
|
||||
.then(content => {
|
||||
if (this.appendedMessage) {
|
||||
this.write(this.appendedMessage);
|
||||
this.appendedMessage = '';
|
||||
}
|
||||
this.loadingFromFileInProgress = false;
|
||||
return this.createModel(content);
|
||||
});
|
||||
let content = await this.loadFile();
|
||||
if (this.endOffset !== this.startOffset + VSBuffer.fromString(content).byteLength) {
|
||||
// Queue content is not written into the file
|
||||
// Flush it and load file again
|
||||
this.flush();
|
||||
content = await this.loadFile();
|
||||
}
|
||||
if (this.appendedMessage) {
|
||||
this.write(this.appendedMessage);
|
||||
this.appendedMessage = '';
|
||||
}
|
||||
this.loadingFromFileInProgress = false;
|
||||
return this.createModel(content);
|
||||
}
|
||||
|
||||
private resetModel(): Promise<void> {
|
||||
private async resetModel(): Promise<void> {
|
||||
this.startOffset = 0;
|
||||
this.endOffset = 0;
|
||||
if (this.model) {
|
||||
return this.loadModel().then(() => undefined);
|
||||
await this.loadModel();
|
||||
}
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
private loadFile(): Promise<string> {
|
||||
return this.fileService.readFile(this.file, { position: this.startOffset })
|
||||
.then(content => this.appendedMessage ? content.value + this.appendedMessage : content.value.toString());
|
||||
private async loadFile(): Promise<string> {
|
||||
const content = await this.fileService.readFile(this.file, { position: this.startOffset });
|
||||
return this.appendedMessage ? content.value + this.appendedMessage : content.value.toString();
|
||||
}
|
||||
|
||||
protected override updateModel(): void {
|
||||
|
@ -415,7 +376,7 @@ class OutputChannelBackedByFile extends AbstractFileOutputChannelModel implement
|
|||
}
|
||||
}
|
||||
|
||||
class DelegatedOutputChannelModel extends Disposable implements IOutputChannelModel {
|
||||
export class DelegatedOutputChannelModel extends Disposable implements IOutputChannelModel {
|
||||
|
||||
private readonly _onDidAppendedContent: Emitter<void> = this._register(new Emitter<void>());
|
||||
readonly onDidAppendedContent: Event<void> = this._onDidAppendedContent.event;
|
||||
|
|
|
@ -3,13 +3,47 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IOutputChannelModelService, AbstractOutputChannelModelService } from 'vs/workbench/contrib/output/common/outputChannelModel';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { createDecorator, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { toLocalISOString } from 'vs/base/common/date';
|
||||
import { dirname, joinPath } from 'vs/base/common/resources';
|
||||
import { DelegatedOutputChannelModel, FileOutputChannelModel, IOutputChannelModel } from 'vs/workbench/contrib/output/common/outputChannelModel';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
|
||||
export const IOutputChannelModelService = createDecorator<IOutputChannelModelService>('outputChannelModelService');
|
||||
|
||||
export interface IOutputChannelModelService {
|
||||
readonly _serviceBrand: undefined;
|
||||
|
||||
createOutputChannelModel(id: string, modelUri: URI, mimeType: string, file?: URI): IOutputChannelModel;
|
||||
|
||||
}
|
||||
|
||||
export abstract class AbstractOutputChannelModelService {
|
||||
|
||||
declare readonly _serviceBrand: undefined;
|
||||
|
||||
constructor(
|
||||
private readonly outputLocation: URI,
|
||||
@IFileService protected readonly fileService: IFileService,
|
||||
@IInstantiationService protected readonly instantiationService: IInstantiationService
|
||||
) { }
|
||||
|
||||
createOutputChannelModel(id: string, modelUri: URI, mimeType: string, file?: URI): IOutputChannelModel {
|
||||
return file ? this.instantiationService.createInstance(FileOutputChannelModel, modelUri, mimeType, file) : this.instantiationService.createInstance(DelegatedOutputChannelModel, id, modelUri, mimeType, this.outputDir);
|
||||
}
|
||||
|
||||
private _outputDir: Promise<URI> | null = null;
|
||||
private get outputDir(): Promise<URI> {
|
||||
if (!this._outputDir) {
|
||||
this._outputDir = this.fileService.createFolder(this.outputLocation).then(() => this.outputLocation);
|
||||
}
|
||||
return this._outputDir;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class OutputChannelModelService extends AbstractOutputChannelModelService implements IOutputChannelModelService {
|
||||
|
||||
|
|
|
@ -7,11 +7,11 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
|
|||
import { join } from 'vs/base/common/path';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { IOutputChannelModelService, AbstractOutputChannelModelService } from 'vs/workbench/contrib/output/common/outputChannelModel';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { toLocalISOString } from 'vs/base/common/date';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { INativeHostService } from 'vs/platform/native/electron-sandbox/native';
|
||||
import { AbstractOutputChannelModelService, IOutputChannelModelService } from 'vs/workbench/contrib/output/common/outputChannelModelService';
|
||||
|
||||
export class OutputChannelModelService extends AbstractOutputChannelModelService implements IOutputChannelModelService {
|
||||
|
||||
|
|
|
@ -137,6 +137,8 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
|||
private _containerReadyBarrier: AutoOpenBarrier;
|
||||
private _attachBarrier: AutoOpenBarrier;
|
||||
|
||||
private _icon: TerminalIcon | undefined;
|
||||
|
||||
private _messageTitleDisposable: IDisposable | undefined;
|
||||
|
||||
private _widgetManager: TerminalWidgetManager = this._instantiationService.createInstance(TerminalWidgetManager);
|
||||
|
@ -316,6 +318,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
|||
|
||||
this._fixedRows = _shellLaunchConfig.attachPersistentProcess?.fixedDimensions?.rows;
|
||||
this._fixedCols = _shellLaunchConfig.attachPersistentProcess?.fixedDimensions?.cols;
|
||||
this._icon = _shellLaunchConfig.attachPersistentProcess?.icon || _shellLaunchConfig.icon;
|
||||
|
||||
// the resource is already set when it's been moved from another window
|
||||
this._resource = resource || getTerminalUri(this._workspaceContextService.getWorkspace().id, this.instanceId, this.title);
|
||||
|
@ -411,11 +414,10 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
|||
}
|
||||
|
||||
private _getIcon(): TerminalIcon | undefined {
|
||||
const icon = this._shellLaunchConfig.icon || this._shellLaunchConfig.attachPersistentProcess?.icon;
|
||||
if (!icon) {
|
||||
return this._processManager.processState >= ProcessState.Launching ? Codicon.terminal : undefined;
|
||||
if (!this._icon) {
|
||||
this._icon = this._processManager.processState >= ProcessState.Launching ? Codicon.terminal : undefined;
|
||||
}
|
||||
return icon;
|
||||
return this._icon;
|
||||
}
|
||||
|
||||
private _getColor(): string | undefined {
|
||||
|
@ -1850,7 +1852,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
|||
matchOnDescription: true
|
||||
});
|
||||
if (result && result.description) {
|
||||
this.shellLaunchConfig.icon = iconRegistry.get(result.description);
|
||||
this._icon = iconRegistry.get(result.description);
|
||||
this._onIconChanged.fire(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -886,6 +886,7 @@ class ScrollableMarkdownMessage extends Disposable {
|
|||
|
||||
const rendered = this._register(markdown.render(message, {}));
|
||||
rendered.element.style.height = '100%';
|
||||
rendered.element.style.userSelect = 'text';
|
||||
container.appendChild(rendered.element);
|
||||
|
||||
this.scrollable = this._register(new DomScrollableElement(rendered.element, {
|
||||
|
|
|
@ -11,18 +11,18 @@ import { URI } from 'vs/base/common/uri';
|
|||
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
||||
import { ILayoutService } from 'vs/platform/layout/browser/layoutService';
|
||||
import { IWebviewService, KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_ENABLED, KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_VISIBLE, Webview, WebviewContentOptions, WebviewElement, WebviewExtensionDescription, WebviewMessageReceivedEvent, WebviewOptions, WebviewOverlay } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { IWebviewService, KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_ENABLED, KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_VISIBLE, IWebview, WebviewContentOptions, IWebviewElement, WebviewExtensionDescription, WebviewMessageReceivedEvent, WebviewOptions, IOverlayWebview } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
|
||||
/**
|
||||
* Webview editor overlay that creates and destroys the underlying webview as needed.
|
||||
* Webview that is absolutely positioned over another element and that can creates and destroys an underlying webview as needed.
|
||||
*/
|
||||
export class DynamicWebviewEditorOverlay extends Disposable implements WebviewOverlay {
|
||||
export class OverlayWebview extends Disposable implements IOverlayWebview {
|
||||
|
||||
private readonly _onDidWheel = this._register(new Emitter<IMouseWheelEvent>());
|
||||
public readonly onDidWheel = this._onDidWheel.event;
|
||||
|
||||
private readonly _pendingMessages = new Set<{ readonly message: any, readonly transfer?: readonly ArrayBuffer[] }>();
|
||||
private readonly _webview = this._register(new MutableDisposable<WebviewElement>());
|
||||
private readonly _webview = this._register(new MutableDisposable<IWebviewElement>());
|
||||
private readonly _webviewEvents = this._register(new DisposableStore());
|
||||
|
||||
private _html: string = '';
|
||||
|
@ -299,7 +299,7 @@ export class DynamicWebviewEditorOverlay extends Disposable implements WebviewOv
|
|||
|
||||
runFindAction(previous: boolean): void { this._webview.value?.runFindAction(previous); }
|
||||
|
||||
private withWebview(f: (webview: Webview) => void): void {
|
||||
private withWebview(f: (webview: IWebview) => void): void {
|
||||
if (this._webview.value) {
|
||||
f(this._webview.value);
|
||||
}
|
|
@ -980,6 +980,36 @@ onDomReady(() => {
|
|||
assertIsDefined(target.contentDocument).execCommand(data);
|
||||
});
|
||||
|
||||
hostMessaging.onMessage('find', (_event, data) => {
|
||||
const target = getActiveFrame();
|
||||
if (!target) {
|
||||
return;
|
||||
}
|
||||
const didFind = (/** @type {any} */ (target.contentWindow)).find(
|
||||
data.value,
|
||||
false,
|
||||
/* backwards*/ data.previous,
|
||||
/* wrapAround*/ true,
|
||||
false,
|
||||
/*aSearchInFrames*/ true,
|
||||
false);
|
||||
hostMessaging.postMessage('did-find', didFind);
|
||||
});
|
||||
|
||||
hostMessaging.onMessage('find-stop', (_event, data) => {
|
||||
const target = getActiveFrame();
|
||||
if (!target) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!data.clearSelection) {
|
||||
const selection = target.contentWindow.getSelection();
|
||||
for (let i = 0; i < selection.rangeCount; i++) {
|
||||
selection.removeRange(selection.getRangeAt(i));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
trackFocus({
|
||||
onFocus: () => hostMessaging.postMessage('did-focus'),
|
||||
onBlur: () => hostMessaging.postMessage('did-blur')
|
||||
|
|
|
@ -7,14 +7,14 @@ import { MultiCommand, RedoCommand, SelectAllCommand, UndoCommand } from 'vs/edi
|
|||
import { CopyAction, CutAction, PasteAction } from 'vs/editor/contrib/clipboard/clipboard';
|
||||
import * as nls from 'vs/nls';
|
||||
import { MenuId, MenuRegistry } from 'vs/platform/actions/common/actions';
|
||||
import { IWebviewService, Webview } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { IWebviewService, IWebview } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { WebviewInput } from 'vs/workbench/contrib/webviewPanel/browser/webviewEditorInput';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
|
||||
|
||||
const PRIORITY = 100;
|
||||
|
||||
function overrideCommandForWebview(command: MultiCommand | undefined, f: (webview: Webview) => void) {
|
||||
function overrideCommandForWebview(command: MultiCommand | undefined, f: (webview: IWebview) => void) {
|
||||
command?.addImplementation(PRIORITY, 'webview', accessor => {
|
||||
const webviewService = accessor.get(IWebviewService);
|
||||
const webview = webviewService.activeWebview;
|
||||
|
|
|
@ -30,17 +30,17 @@ export interface IWebviewService {
|
|||
/**
|
||||
* The currently focused webview.
|
||||
*/
|
||||
readonly activeWebview: Webview | undefined;
|
||||
readonly activeWebview: IWebview | undefined;
|
||||
|
||||
/**
|
||||
* All webviews.
|
||||
*/
|
||||
readonly webviews: Iterable<Webview>;
|
||||
readonly webviews: Iterable<IWebview>;
|
||||
|
||||
/**
|
||||
* Fired when the currently focused webview changes.
|
||||
*/
|
||||
readonly onDidChangeActiveWebview: Event<Webview | undefined>;
|
||||
readonly onDidChangeActiveWebview: Event<IWebview | undefined>;
|
||||
|
||||
/**
|
||||
* Create a basic webview dom element.
|
||||
|
@ -50,7 +50,7 @@ export interface IWebviewService {
|
|||
options: WebviewOptions,
|
||||
contentOptions: WebviewContentOptions,
|
||||
extension: WebviewExtensionDescription | undefined,
|
||||
): WebviewElement;
|
||||
): IWebviewElement;
|
||||
|
||||
/**
|
||||
* Create a lazily created webview element that is overlaid on top of another element.
|
||||
|
@ -63,7 +63,7 @@ export interface IWebviewService {
|
|||
options: WebviewOptions,
|
||||
contentOptions: WebviewContentOptions,
|
||||
extension: WebviewExtensionDescription | undefined,
|
||||
): WebviewOverlay;
|
||||
): IOverlayWebview;
|
||||
}
|
||||
|
||||
export const enum WebviewContentPurpose {
|
||||
|
@ -119,7 +119,7 @@ export interface WebviewMessageReceivedEvent {
|
|||
readonly transfer?: readonly ArrayBuffer[];
|
||||
}
|
||||
|
||||
export interface Webview extends IDisposable {
|
||||
export interface IWebview extends IDisposable {
|
||||
|
||||
readonly id: string;
|
||||
|
||||
|
@ -169,12 +169,12 @@ export interface Webview extends IDisposable {
|
|||
/**
|
||||
* Basic webview rendered directly in the dom
|
||||
*/
|
||||
export interface WebviewElement extends Webview {
|
||||
export interface IWebviewElement extends IWebview {
|
||||
/**
|
||||
* Append the webview to a HTML element.
|
||||
*
|
||||
* Note that the webview content will be destroyed if any part of the parent hierarchy
|
||||
* changes. You can avoid this by using a {@link WebviewOverlay} instead.
|
||||
* changes. You can avoid this by using a {@link IOverlayWebview} instead.
|
||||
*
|
||||
* @param parent Element to append the webview to.
|
||||
*/
|
||||
|
@ -182,15 +182,15 @@ export interface WebviewElement extends Webview {
|
|||
}
|
||||
|
||||
/**
|
||||
* Lazily created {@link Webview} that is absolutely positioned over another element.
|
||||
* Lazily created {@link IWebview} that is absolutely positioned over another element.
|
||||
*
|
||||
* Absolute positioning lets us avoid having the webview be re-parented, which would destroy the
|
||||
* webview's content.
|
||||
*
|
||||
* Note that the underlying webview owned by a `WebviewOverlay` can be dynamically created
|
||||
* and destroyed depending on who has {@link WebviewOverlay.claim claimed} or {@link WebviewOverlay.release released} it.
|
||||
* and destroyed depending on who has {@link IOverlayWebview.claim claimed} or {@link IOverlayWebview.release released} it.
|
||||
*/
|
||||
export interface WebviewOverlay extends Webview {
|
||||
export interface IOverlayWebview extends IWebview {
|
||||
/**
|
||||
* The HTML element that holds the webview.
|
||||
*/
|
||||
|
@ -204,7 +204,7 @@ export interface WebviewOverlay extends Webview {
|
|||
* This will create the underlying webview element.
|
||||
*
|
||||
* @param claimant Identifier for the object claiming the webview.
|
||||
* This must match the `claimant` passed to {@link WebviewOverlay.release}.
|
||||
* This must match the `claimant` passed to {@link IOverlayWebview.release}.
|
||||
*/
|
||||
claim(claimant: any, scopedContextKeyService: IContextKeyService | undefined): void;
|
||||
|
||||
|
@ -215,7 +215,7 @@ export interface WebviewOverlay extends Webview {
|
|||
* cause the underlying webview element to be destoryed.
|
||||
*
|
||||
* @param claimant Identifier for the object releasing its claim on the webview.
|
||||
* This must match the `claimant` passed to {@link WebviewOverlay.claim}.
|
||||
* This must match the `claimant` passed to {@link IOverlayWebview.claim}.
|
||||
*/
|
||||
release(claimant: any): void;
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ import { IAction } from 'vs/base/common/actions';
|
|||
import { ThrottledDelayer } from 'vs/base/common/async';
|
||||
import { streamToBuffer } from 'vs/base/common/buffer';
|
||||
import { CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
|
@ -22,6 +22,7 @@ import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
|||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { IRemoteAuthorityResolverService } from 'vs/platform/remote/common/remoteAuthorityResolver';
|
||||
|
@ -31,7 +32,8 @@ import { WebviewPortMappingManager } from 'vs/platform/webview/common/webviewPor
|
|||
import { asWebviewUri, decodeAuthority, webviewGenericCspSource, webviewRootResourceAuthority } from 'vs/workbench/api/common/shared/webview';
|
||||
import { loadLocalResource, WebviewResourceResponse } from 'vs/workbench/contrib/webview/browser/resourceLoading';
|
||||
import { WebviewThemeDataProvider } from 'vs/workbench/contrib/webview/browser/themeing';
|
||||
import { areWebviewContentOptionsEqual, Webview, WebviewContentOptions, WebviewExtensionDescription, WebviewMessageReceivedEvent, WebviewOptions } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { areWebviewContentOptionsEqual, IWebview, WebviewContentOptions, WebviewExtensionDescription, WebviewMessageReceivedEvent, WebviewOptions } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { WebviewFindDelegate, WebviewFindWidget } from 'vs/workbench/contrib/webview/browser/webviewFindWidget';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
|
||||
export const enum WebviewMessageChannels {
|
||||
|
@ -41,6 +43,7 @@ export const enum WebviewMessageChannels {
|
|||
didFocus = 'did-focus',
|
||||
didBlur = 'did-blur',
|
||||
didLoad = 'did-load',
|
||||
didFind = 'did-find',
|
||||
doUpdateState = 'do-update-state',
|
||||
doReload = 'do-reload',
|
||||
setConfirmBeforeClose = 'set-confirm-before-close',
|
||||
|
@ -88,7 +91,7 @@ namespace WebviewState {
|
|||
export type State = typeof Ready | Initializing;
|
||||
}
|
||||
|
||||
export class IFrameWebview extends Disposable implements Webview {
|
||||
export class WebviewElement extends Disposable implements IWebview, WebviewFindDelegate {
|
||||
|
||||
protected get platform(): string { return 'browser'; }
|
||||
|
||||
|
@ -129,6 +132,9 @@ export class IFrameWebview extends Disposable implements Webview {
|
|||
|
||||
private readonly _messageHandlers = new Map<string, Set<(data: any) => void>>();
|
||||
|
||||
protected readonly _webviewFindWidget: WebviewFindWidget | undefined;
|
||||
public readonly checkImeCompletionState = true;
|
||||
|
||||
constructor(
|
||||
public readonly id: string,
|
||||
private readonly options: WebviewOptions,
|
||||
|
@ -145,6 +151,7 @@ export class IFrameWebview extends Disposable implements Webview {
|
|||
@IRemoteAuthorityResolverService private readonly _remoteAuthorityResolverService: IRemoteAuthorityResolverService,
|
||||
@ITelemetryService private readonly _telemetryService: ITelemetryService,
|
||||
@ITunnelService private readonly _tunnelService: ITunnelService,
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
) {
|
||||
super();
|
||||
|
||||
|
@ -215,6 +222,10 @@ export class IFrameWebview extends Disposable implements Webview {
|
|||
this.handleFocusChange(false);
|
||||
}));
|
||||
|
||||
this._register(this.on(WebviewMessageChannels.didFind, (didFind: boolean) => {
|
||||
this._hasFindResult.fire(didFind);
|
||||
}));
|
||||
|
||||
this._register(this.on<{ message: string }>(WebviewMessageChannels.fatalError, (e) => {
|
||||
notificationService.error(localize('fatalErrorMessage', "Error loading webview: {0}", e.message));
|
||||
}));
|
||||
|
@ -312,13 +323,16 @@ export class IFrameWebview extends Disposable implements Webview {
|
|||
}
|
||||
}));
|
||||
|
||||
if (options.enableFindWidget) {
|
||||
this._webviewFindWidget = this._register(instantiationService.createInstance(WebviewFindWidget, this));
|
||||
this.styledFindWidget();
|
||||
}
|
||||
|
||||
this.initElement(extension, options);
|
||||
}
|
||||
|
||||
override dispose(): void {
|
||||
if (this.element) {
|
||||
this.element.remove();
|
||||
}
|
||||
this.element?.remove();
|
||||
this._element = undefined;
|
||||
|
||||
this._onDidDispose.fire();
|
||||
|
@ -418,9 +432,14 @@ export class IFrameWebview extends Disposable implements Webview {
|
|||
}
|
||||
|
||||
public mountTo(parent: HTMLElement) {
|
||||
if (this.element) {
|
||||
parent.appendChild(this.element);
|
||||
if (!this.element) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._webviewFindWidget) {
|
||||
parent.appendChild(this._webviewFindWidget.getDomNode()!);
|
||||
}
|
||||
parent.appendChild(this.element);
|
||||
}
|
||||
|
||||
protected get webviewContentEndpoint(): string {
|
||||
|
@ -467,7 +486,7 @@ export class IFrameWebview extends Disposable implements Webview {
|
|||
}
|
||||
this._hasAlertedAboutMissingCsp = true;
|
||||
|
||||
if (this.extension && this.extension.id) {
|
||||
if (this.extension?.id) {
|
||||
if (this._environmentService.isExtensionDevelopment) {
|
||||
this._onMissingCsp.fire(this.extension.id);
|
||||
}
|
||||
|
@ -586,6 +605,12 @@ export class IFrameWebview extends Disposable implements Webview {
|
|||
}
|
||||
|
||||
this._send('styles', { styles, activeTheme, themeName: themeLabel });
|
||||
|
||||
this.styledFindWidget();
|
||||
}
|
||||
|
||||
private styledFindWidget() {
|
||||
this._webviewFindWidget?.updateTheme(this.webviewThemeDataProvider.getTheme());
|
||||
}
|
||||
|
||||
private handleFocusChange(isFocused: boolean): void {
|
||||
|
@ -757,15 +782,51 @@ export class IFrameWebview extends Disposable implements Webview {
|
|||
});
|
||||
}
|
||||
|
||||
public showFind(): void {
|
||||
// noop
|
||||
protected readonly _hasFindResult = this._register(new Emitter<boolean>());
|
||||
public readonly hasFindResult: Event<boolean> = this._hasFindResult.event;
|
||||
|
||||
protected readonly _onDidStopFind = this._register(new Emitter<void>());
|
||||
public readonly onDidStopFind: Event<void> = this._onDidStopFind.event;
|
||||
|
||||
/**
|
||||
* Webviews expose a stateful find API.
|
||||
* Successive calls to find will move forward or backward through onFindResults
|
||||
* depending on the supplied options.
|
||||
*
|
||||
* @param value The string to search for. Empty strings are ignored.
|
||||
*/
|
||||
public find(value: string, previous: boolean): void {
|
||||
if (!this.element) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._send('find', { value, previous });
|
||||
}
|
||||
|
||||
public hideFind(): void {
|
||||
// noop
|
||||
public startFind(value: string) {
|
||||
if (!value || !this.element) {
|
||||
return;
|
||||
}
|
||||
this._send('find', { value });
|
||||
}
|
||||
|
||||
public runFindAction(previous: boolean): void {
|
||||
// noop
|
||||
public stopFind(keepSelection?: boolean): void {
|
||||
if (!this.element) {
|
||||
return;
|
||||
}
|
||||
this._send('find-stop', { keepSelection });
|
||||
this._onDidStopFind.fire();
|
||||
}
|
||||
|
||||
public showFind() {
|
||||
this._webviewFindWidget?.reveal();
|
||||
}
|
||||
|
||||
public hideFind() {
|
||||
this._webviewFindWidget?.hide();
|
||||
}
|
||||
|
||||
public runFindAction(previous: boolean) {
|
||||
this._webviewFindWidget?.find(previous);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,9 +7,9 @@ import { Emitter } from 'vs/base/common/event';
|
|||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { WebviewThemeDataProvider } from 'vs/workbench/contrib/webview/browser/themeing';
|
||||
import { IWebviewService, Webview, WebviewContentOptions, WebviewElement, WebviewExtensionDescription, WebviewOptions, WebviewOverlay } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { IFrameWebview } from 'vs/workbench/contrib/webview/browser/webviewElement';
|
||||
import { DynamicWebviewEditorOverlay } from './dynamicWebviewEditorOverlay';
|
||||
import { IWebviewService, IWebview, WebviewContentOptions, IWebviewElement, WebviewExtensionDescription, WebviewOptions, IOverlayWebview } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { WebviewElement } from 'vs/workbench/contrib/webview/browser/webviewElement';
|
||||
import { OverlayWebview } from './overlayWebview';
|
||||
|
||||
export class WebviewService extends Disposable implements IWebviewService {
|
||||
declare readonly _serviceBrand: undefined;
|
||||
|
@ -23,24 +23,24 @@ export class WebviewService extends Disposable implements IWebviewService {
|
|||
this._webviewThemeDataProvider = this._instantiationService.createInstance(WebviewThemeDataProvider);
|
||||
}
|
||||
|
||||
private _activeWebview?: Webview;
|
||||
private _activeWebview?: IWebview;
|
||||
|
||||
public get activeWebview() { return this._activeWebview; }
|
||||
|
||||
private updateActiveWebview(value: Webview | undefined) {
|
||||
private updateActiveWebview(value: IWebview | undefined) {
|
||||
if (value !== this._activeWebview) {
|
||||
this._activeWebview = value;
|
||||
this._onDidChangeActiveWebview.fire(value);
|
||||
}
|
||||
}
|
||||
|
||||
private _webviews = new Set<Webview>();
|
||||
private _webviews = new Set<IWebview>();
|
||||
|
||||
public get webviews(): Iterable<Webview> {
|
||||
public get webviews(): Iterable<IWebview> {
|
||||
return this._webviews.values();
|
||||
}
|
||||
|
||||
private readonly _onDidChangeActiveWebview = this._register(new Emitter<Webview | undefined>());
|
||||
private readonly _onDidChangeActiveWebview = this._register(new Emitter<IWebview | undefined>());
|
||||
public readonly onDidChangeActiveWebview = this._onDidChangeActiveWebview.event;
|
||||
|
||||
createWebviewElement(
|
||||
|
@ -48,8 +48,8 @@ export class WebviewService extends Disposable implements IWebviewService {
|
|||
options: WebviewOptions,
|
||||
contentOptions: WebviewContentOptions,
|
||||
extension: WebviewExtensionDescription | undefined,
|
||||
): WebviewElement {
|
||||
const webview = this._instantiationService.createInstance(IFrameWebview, id, options, contentOptions, extension, this._webviewThemeDataProvider);
|
||||
): IWebviewElement {
|
||||
const webview = this._instantiationService.createInstance(WebviewElement, id, options, contentOptions, extension, this._webviewThemeDataProvider);
|
||||
this.registerNewWebview(webview);
|
||||
return webview;
|
||||
}
|
||||
|
@ -59,13 +59,13 @@ export class WebviewService extends Disposable implements IWebviewService {
|
|||
options: WebviewOptions,
|
||||
contentOptions: WebviewContentOptions,
|
||||
extension: WebviewExtensionDescription | undefined,
|
||||
): WebviewOverlay {
|
||||
const webview = this._instantiationService.createInstance(DynamicWebviewEditorOverlay, id, options, contentOptions, extension);
|
||||
): IOverlayWebview {
|
||||
const webview = this._instantiationService.createInstance(OverlayWebview, id, options, contentOptions, extension);
|
||||
this.registerNewWebview(webview);
|
||||
return webview;
|
||||
}
|
||||
|
||||
protected registerNewWebview(webview: Webview) {
|
||||
protected registerNewWebview(webview: IWebview) {
|
||||
this._webviews.add(webview);
|
||||
|
||||
webview.onDidFocus(() => {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { Webview } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { IWebview } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
|
||||
/**
|
||||
* Allows webviews to monitor when an element in the VS Code editor is being dragged/dropped.
|
||||
|
@ -14,7 +14,7 @@ import { Webview } from 'vs/workbench/contrib/webview/browser/webview';
|
|||
* event so it can handle editor element drag drop.
|
||||
*/
|
||||
export class WebviewWindowDragMonitor extends Disposable {
|
||||
constructor(getWebview: () => Webview | undefined) {
|
||||
constructor(getWebview: () => IWebview | undefined) {
|
||||
super();
|
||||
|
||||
this._register(DOM.addDisposableListener(window, DOM.EventType.DRAG_START, () => {
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Delayer } from 'vs/base/common/async';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { ProxyChannel } from 'vs/base/parts/ipc/common/ipc';
|
||||
import { IMenuService } from 'vs/platform/actions/common/actions';
|
||||
|
@ -22,27 +21,23 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
|||
import { FindInFrameOptions, IWebviewManagerService } from 'vs/platform/webview/common/webviewManagerService';
|
||||
import { WebviewThemeDataProvider } from 'vs/workbench/contrib/webview/browser/themeing';
|
||||
import { WebviewContentOptions, WebviewExtensionDescription, WebviewOptions } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { IFrameWebview, WebviewMessageChannels } from 'vs/workbench/contrib/webview/browser/webviewElement';
|
||||
import { WebviewFindDelegate, WebviewFindWidget } from 'vs/workbench/contrib/webview/browser/webviewFindWidget';
|
||||
import { WebviewElement, WebviewMessageChannels } from 'vs/workbench/contrib/webview/browser/webviewElement';
|
||||
import { WindowIgnoreMenuShortcutsManager } from 'vs/workbench/contrib/webview/electron-sandbox/windowIgnoreMenuShortcutsManager';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
|
||||
/**
|
||||
* Webview backed by an iframe but that uses Electron APIs to power the webview.
|
||||
*/
|
||||
export class ElectronIframeWebview extends IFrameWebview implements WebviewFindDelegate {
|
||||
export class ElectronWebviewElement extends WebviewElement {
|
||||
|
||||
private readonly _webviewKeyboardHandler: WindowIgnoreMenuShortcutsManager;
|
||||
|
||||
private _webviewFindWidget: WebviewFindWidget | undefined;
|
||||
private _findStarted: boolean = false;
|
||||
private _cachedHtmlContent: string | undefined;
|
||||
|
||||
private readonly _webviewMainService: IWebviewManagerService;
|
||||
private readonly _iframeDelayer = this._register(new Delayer<void>(200));
|
||||
|
||||
public readonly checkImeCompletionState = true;
|
||||
|
||||
protected override get platform() { return 'electron'; }
|
||||
|
||||
constructor(
|
||||
|
@ -67,7 +62,7 @@ export class ElectronIframeWebview extends IFrameWebview implements WebviewFindD
|
|||
) {
|
||||
super(id, options, contentOptions, extension, webviewThemeDataProvider,
|
||||
configurationService, contextMenuService, menuService, notificationService, environmentService,
|
||||
fileService, logService, remoteAuthorityResolverService, telemetryService, tunnelService);
|
||||
fileService, logService, remoteAuthorityResolverService, telemetryService, tunnelService, instantiationService);
|
||||
|
||||
this._webviewKeyboardHandler = new WindowIgnoreMenuShortcutsManager(configurationService, mainProcessService, nativeHostService);
|
||||
|
||||
|
@ -82,8 +77,6 @@ export class ElectronIframeWebview extends IFrameWebview implements WebviewFindD
|
|||
}));
|
||||
|
||||
if (options.enableFindWidget) {
|
||||
this._webviewFindWidget = this._register(instantiationService.createInstance(WebviewFindWidget, this));
|
||||
|
||||
this._register(this.onDidHtmlChange((newContent) => {
|
||||
if (this._findStarted && this._cachedHtmlContent !== newContent) {
|
||||
this.stopFind(false);
|
||||
|
@ -94,42 +87,35 @@ export class ElectronIframeWebview extends IFrameWebview implements WebviewFindD
|
|||
this._register(this._webviewMainService.onFoundInFrame((result) => {
|
||||
this._hasFindResult.fire(result.matches > 0);
|
||||
}));
|
||||
|
||||
this.styledFindWidget();
|
||||
}
|
||||
}
|
||||
|
||||
public override mountTo(parent: HTMLElement) {
|
||||
if (!this.element) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._webviewFindWidget) {
|
||||
parent.appendChild(this._webviewFindWidget.getDomNode()!);
|
||||
}
|
||||
parent.appendChild(this.element);
|
||||
}
|
||||
|
||||
protected override get webviewContentEndpoint(): string {
|
||||
return `${Schemas.vscodeWebview}://${this.id}`;
|
||||
}
|
||||
|
||||
protected override style(): void {
|
||||
super.style();
|
||||
this.styledFindWidget();
|
||||
/**
|
||||
* Webviews expose a stateful find API.
|
||||
* Successive calls to find will move forward or backward through onFindResults
|
||||
* depending on the supplied options.
|
||||
*
|
||||
* @param value The string to search for. Empty strings are ignored.
|
||||
*/
|
||||
public override find(value: string, previous: boolean): void {
|
||||
if (!this.element) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this._findStarted) {
|
||||
this.startFind(value);
|
||||
} else {
|
||||
// continuing the find, so set findNext to false
|
||||
const options: FindInFrameOptions = { forward: !previous, findNext: false, matchCase: false };
|
||||
this._webviewMainService.findInFrame({ windowId: this.nativeHostService.windowId }, this.id, value, options);
|
||||
}
|
||||
}
|
||||
|
||||
private styledFindWidget() {
|
||||
this._webviewFindWidget?.updateTheme(this.webviewThemeDataProvider.getTheme());
|
||||
}
|
||||
|
||||
private readonly _hasFindResult = this._register(new Emitter<boolean>());
|
||||
public readonly hasFindResult: Event<boolean> = this._hasFindResult.event;
|
||||
|
||||
private readonly _onDidStopFind = this._register(new Emitter<void>());
|
||||
public readonly onDidStopFind: Event<void> = this._onDidStopFind.event;
|
||||
|
||||
public startFind(value: string) {
|
||||
public override startFind(value: string) {
|
||||
if (!value || !this.element) {
|
||||
return;
|
||||
}
|
||||
|
@ -147,28 +133,7 @@ export class ElectronIframeWebview extends IFrameWebview implements WebviewFindD
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Webviews expose a stateful find API.
|
||||
* Successive calls to find will move forward or backward through onFindResults
|
||||
* depending on the supplied options.
|
||||
*
|
||||
* @param value The string to search for. Empty strings are ignored.
|
||||
*/
|
||||
public find(value: string, previous: boolean): void {
|
||||
if (!this.element) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this._findStarted) {
|
||||
this.startFind(value);
|
||||
} else {
|
||||
// continuing the find, so set findNext to false
|
||||
const options: FindInFrameOptions = { forward: !previous, findNext: false, matchCase: false };
|
||||
this._webviewMainService.findInFrame({ windowId: this.nativeHostService.windowId }, this.id, value, options);
|
||||
}
|
||||
}
|
||||
|
||||
public stopFind(keepSelection?: boolean): void {
|
||||
public override stopFind(keepSelection?: boolean): void {
|
||||
if (!this.element) {
|
||||
return;
|
||||
}
|
||||
|
@ -179,16 +144,4 @@ export class ElectronIframeWebview extends IFrameWebview implements WebviewFindD
|
|||
});
|
||||
this._onDidStopFind.fire();
|
||||
}
|
||||
|
||||
public override showFind() {
|
||||
this._webviewFindWidget?.reveal();
|
||||
}
|
||||
|
||||
public override hideFind() {
|
||||
this._webviewFindWidget?.hide();
|
||||
}
|
||||
|
||||
public override runFindAction(previous: boolean) {
|
||||
this._webviewFindWidget?.find(previous);
|
||||
}
|
||||
}
|
|
@ -3,9 +3,9 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { WebviewContentOptions, WebviewElement, WebviewExtensionDescription, WebviewOptions } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { IWebviewElement, WebviewContentOptions, WebviewExtensionDescription, WebviewOptions } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { WebviewService } from 'vs/workbench/contrib/webview/browser/webviewService';
|
||||
import { ElectronIframeWebview } from 'vs/workbench/contrib/webview/electron-sandbox/iframeWebviewElement';
|
||||
import { ElectronWebviewElement } from 'vs/workbench/contrib/webview/electron-sandbox/webviewElement';
|
||||
|
||||
export class ElectronWebviewService extends WebviewService {
|
||||
|
||||
|
@ -14,8 +14,8 @@ export class ElectronWebviewService extends WebviewService {
|
|||
options: WebviewOptions,
|
||||
contentOptions: WebviewContentOptions,
|
||||
extension: WebviewExtensionDescription | undefined,
|
||||
): WebviewElement {
|
||||
const webview = this._instantiationService.createInstance(ElectronIframeWebview, id, options, contentOptions, extension, this._webviewThemeDataProvider);
|
||||
): IWebviewElement {
|
||||
const webview = this._instantiationService.createInstance(ElectronWebviewElement, id, options, contentOptions, extension, this._webviewThemeDataProvider);
|
||||
this.registerNewWebview(webview);
|
||||
return webview;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
|||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { CATEGORIES } from 'vs/workbench/common/actions';
|
||||
import { IWebviewService, KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_ENABLED, KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_FOCUSED, KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_VISIBLE, Webview } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { IWebviewService, KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_ENABLED, KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_FOCUSED, KEYBINDING_CONTEXT_WEBVIEW_FIND_WIDGET_VISIBLE, IWebview } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { WebviewEditor } from 'vs/workbench/contrib/webviewPanel/browser/webviewEditor';
|
||||
import { WebviewInput } from 'vs/workbench/contrib/webviewPanel/browser/webviewEditorInput';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
|
@ -125,7 +125,7 @@ export class ReloadWebviewAction extends Action2 {
|
|||
}
|
||||
}
|
||||
|
||||
export function getActiveWebviewEditor(accessor: ServicesAccessor): Webview | undefined {
|
||||
export function getActiveWebviewEditor(accessor: ServicesAccessor): IWebview | undefined {
|
||||
const editorService = accessor.get(IEditorService);
|
||||
const activeEditor = editorService.activeEditor;
|
||||
return activeEditor instanceof WebviewInput ? activeEditor.webview : undefined;
|
||||
|
|
|
@ -17,7 +17,7 @@ import { IThemeService } from 'vs/platform/theme/common/themeService';
|
|||
import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane';
|
||||
import { IEditorOpenContext } from 'vs/workbench/common/editor';
|
||||
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
|
||||
import { WebviewOverlay } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { IOverlayWebview } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { WebviewWindowDragMonitor } from 'vs/workbench/contrib/webview/browser/webviewWindowDragMonitor';
|
||||
import { WebviewInput } from 'vs/workbench/contrib/webviewPanel/browser/webviewEditorInput';
|
||||
import { IEditorDropService } from 'vs/workbench/services/editor/browser/editorDropService';
|
||||
|
@ -56,7 +56,7 @@ export class WebviewEditor extends EditorPane {
|
|||
super(WebviewEditor.ID, telemetryService, themeService, storageService);
|
||||
}
|
||||
|
||||
private get webview(): WebviewOverlay | undefined {
|
||||
private get webview(): IOverlayWebview | undefined {
|
||||
return this.input instanceof WebviewInput ? this.input.webview : undefined;
|
||||
}
|
||||
|
||||
|
@ -175,13 +175,13 @@ export class WebviewEditor extends EditorPane {
|
|||
this._webviewVisibleDisposables.add(this.trackFocus(input.webview));
|
||||
}
|
||||
|
||||
private synchronizeWebviewContainerDimensions(webview: WebviewOverlay, dimension?: DOM.Dimension) {
|
||||
private synchronizeWebviewContainerDimensions(webview: IOverlayWebview, dimension?: DOM.Dimension) {
|
||||
if (this._element) {
|
||||
webview.layoutWebviewOverElement(this._element.parentElement!, dimension);
|
||||
}
|
||||
}
|
||||
|
||||
private trackFocus(webview: WebviewOverlay): IDisposable {
|
||||
private trackFocus(webview: IOverlayWebview): IDisposable {
|
||||
const store = new DisposableStore();
|
||||
|
||||
// Track focus in webview content
|
||||
|
|
|
@ -7,7 +7,7 @@ import { Schemas } from 'vs/base/common/network';
|
|||
import { URI } from 'vs/base/common/uri';
|
||||
import { EditorInputCapabilities, GroupIdentifier, IUntypedEditorInput, Verbosity } from 'vs/workbench/common/editor';
|
||||
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
|
||||
import { WebviewOverlay } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { IOverlayWebview } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { WebviewIconManager, WebviewIcons } from 'vs/workbench/contrib/webviewPanel/browser/webviewIconManager';
|
||||
|
||||
export class WebviewInput extends EditorInput {
|
||||
|
@ -30,7 +30,7 @@ export class WebviewInput extends EditorInput {
|
|||
private _iconPath?: WebviewIcons;
|
||||
private _group?: GroupIdentifier;
|
||||
|
||||
private _webview: WebviewOverlay;
|
||||
private _webview: IOverlayWebview;
|
||||
|
||||
private _hasTransfered = false;
|
||||
|
||||
|
@ -45,7 +45,7 @@ export class WebviewInput extends EditorInput {
|
|||
public readonly id: string,
|
||||
public readonly viewType: string,
|
||||
name: string,
|
||||
webview: WebviewOverlay,
|
||||
webview: IOverlayWebview,
|
||||
private readonly _iconManager: WebviewIconManager,
|
||||
) {
|
||||
super();
|
||||
|
@ -79,7 +79,7 @@ export class WebviewInput extends EditorInput {
|
|||
this._onDidChangeLabel.fire();
|
||||
}
|
||||
|
||||
public get webview(): WebviewOverlay {
|
||||
public get webview(): IOverlayWebview {
|
||||
return this._webview;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ import { createDecorator, IInstantiationService } from 'vs/platform/instantiatio
|
|||
import { GroupIdentifier } from 'vs/workbench/common/editor';
|
||||
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
|
||||
import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
|
||||
import { IWebviewService, WebviewContentOptions, WebviewExtensionDescription, WebviewOptions, WebviewOverlay } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { IWebviewService, WebviewContentOptions, WebviewExtensionDescription, WebviewOptions, IOverlayWebview } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { WebviewIconManager, WebviewIcons } from 'vs/workbench/contrib/webviewPanel/browser/webviewIconManager';
|
||||
import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { ACTIVE_GROUP_TYPE, IEditorService, SIDE_GROUP_TYPE } from 'vs/workbench/services/editor/common/editorService';
|
||||
|
@ -102,7 +102,7 @@ export class LazilyResolvedWebviewEditorInput extends WebviewInput {
|
|||
id: string,
|
||||
viewType: string,
|
||||
name: string,
|
||||
webview: WebviewOverlay,
|
||||
webview: IOverlayWebview,
|
||||
@IWebviewWorkbenchService private readonly _webviewWorkbenchService: IWebviewWorkbenchService,
|
||||
) {
|
||||
super(id, viewType, name, webview, _webviewWorkbenchService.iconManager);
|
||||
|
|
|
@ -22,7 +22,7 @@ import { ViewPane } from 'vs/workbench/browser/parts/views/viewPane';
|
|||
import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet';
|
||||
import { Memento, MementoObject } from 'vs/workbench/common/memento';
|
||||
import { IViewDescriptorService, IViewsService } from 'vs/workbench/common/views';
|
||||
import { IWebviewService, WebviewContentPurpose, WebviewOverlay } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { IOverlayWebview, IWebviewService, WebviewContentPurpose } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { WebviewWindowDragMonitor } from 'vs/workbench/contrib/webview/browser/webviewWindowDragMonitor';
|
||||
import { IWebviewViewService, WebviewView } from 'vs/workbench/contrib/webviewView/browser/webviewViewService';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
|
@ -35,7 +35,7 @@ const storageKeys = {
|
|||
|
||||
export class WebviewViewPane extends ViewPane {
|
||||
|
||||
private readonly _webview = this._register(new MutableDisposable<WebviewOverlay>());
|
||||
private readonly _webview = this._register(new MutableDisposable<IOverlayWebview>());
|
||||
private readonly _webviewDisposables = this._register(new DisposableStore());
|
||||
private _activated = false;
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import { CancellationToken } from 'vs/base/common/cancellation';
|
|||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { WebviewOverlay } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { IOverlayWebview } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
|
||||
export const IWebviewViewService = createDecorator<IWebviewViewService>('webviewViewService');
|
||||
|
||||
|
@ -15,7 +15,7 @@ export interface WebviewView {
|
|||
title?: string;
|
||||
description?: string;
|
||||
|
||||
readonly webview: WebviewOverlay;
|
||||
readonly webview: IOverlayWebview;
|
||||
|
||||
readonly onDidChangeVisibility: Event<boolean>;
|
||||
readonly onDispose: Event<void>;
|
||||
|
|
|
@ -29,7 +29,7 @@ import { WORKSPACE_TRUST_BANNER, WORKSPACE_TRUST_EMPTY_WINDOW, WORKSPACE_TRUST_E
|
|||
import { IEditorSerializer, IEditorFactoryRegistry, EditorExtensions } from 'vs/workbench/common/editor';
|
||||
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
|
||||
import { IWorkspaceContextService, IWorkspaceFoldersWillChangeEvent, WorkbenchState } from 'vs/platform/workspace/common/workspace';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { isWeb } from 'vs/base/common/platform';
|
||||
import { IsWebContext } from 'vs/platform/contextkey/common/contextkeys';
|
||||
|
@ -279,10 +279,10 @@ export class WorkspaceTrustUXHandler extends Disposable implements IWorkbenchCon
|
|||
if (!this.workspaceTrustEnablementService.isWorkspaceTrustEnabled()) {
|
||||
return;
|
||||
}
|
||||
const trusted = this.workspaceTrustManagementService.isWorkspaceTrusted();
|
||||
|
||||
// eslint-disable-next-line no-async-promise-executor
|
||||
return e.join(new Promise(async resolve => {
|
||||
const addWorkspaceFolder = async (e: IWorkspaceFoldersWillChangeEvent): Promise<void> => {
|
||||
const trusted = this.workspaceTrustManagementService.isWorkspaceTrusted();
|
||||
|
||||
// Workspace is trusted and there are added/changed folders
|
||||
if (trusted && (e.changes.added.length || e.changes.changed.length)) {
|
||||
const addedFoldersTrustInfo = await Promise.all(e.changes.added.map(folder => this.workspaceTrustManagementService.getUriTrustInfo(folder.uri)));
|
||||
|
@ -305,13 +305,11 @@ export class WorkspaceTrustUXHandler extends Disposable implements IWorkbenchCon
|
|||
|
||||
// Mark added/changed folders as trusted
|
||||
await this.workspaceTrustManagementService.setUrisTrust(addedFoldersTrustInfo.map(i => i.uri), result.choice === 0);
|
||||
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
resolve();
|
||||
}));
|
||||
return e.join(addWorkspaceFolder(e));
|
||||
}));
|
||||
|
||||
this._register(this.workspaceTrustManagementService.onDidChangeTrust(trusted => {
|
||||
|
|
|
@ -263,7 +263,7 @@ export class DecorationsService implements IDecorationsService {
|
|||
}
|
||||
|
||||
registerDecorationsProvider(provider: IDecorationsProvider): IDisposable {
|
||||
const rm = this._provider.push(provider);
|
||||
const rm = this._provider.unshift(provider);
|
||||
|
||||
this._onDidChangeDecorations.fire({
|
||||
// everything might have changed
|
||||
|
|
|
@ -300,4 +300,31 @@ suite('DecorationsService', function () {
|
|||
emitter.fire([uri]);
|
||||
});
|
||||
});
|
||||
|
||||
test('FileDecorationProvider intermittently fails #133210', async function () {
|
||||
|
||||
const invokeOrder: string[] = [];
|
||||
|
||||
service.registerDecorationsProvider(new class {
|
||||
label = 'Provider-1';
|
||||
onDidChange = Event.None;
|
||||
provideDecorations() {
|
||||
invokeOrder.push(this.label);
|
||||
return undefined;
|
||||
}
|
||||
});
|
||||
|
||||
service.registerDecorationsProvider(new class {
|
||||
label = 'Provider-2';
|
||||
onDidChange = Event.None;
|
||||
provideDecorations() {
|
||||
invokeOrder.push(this.label);
|
||||
return undefined;
|
||||
}
|
||||
});
|
||||
|
||||
service.getDecoration(URI.parse('test://me/path'), false);
|
||||
|
||||
assert.deepStrictEqual(invokeOrder, ['Provider-2', 'Provider-1']);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -547,7 +547,8 @@ export class TunnelModel extends Disposable {
|
|||
remote: { host: tunnel.remoteHost, port: tunnel.remotePort },
|
||||
local: tunnel.localPort,
|
||||
name: tunnel.name,
|
||||
privacy: tunnel.privacy
|
||||
privacy: tunnel.privacy,
|
||||
elevateIfNeeded: true
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,11 +6,14 @@
|
|||
import * as assert from 'assert';
|
||||
import { MarkerService } from 'vs/platform/markers/common/markerService';
|
||||
import { MainThreadDiagnostics } from 'vs/workbench/api/browser/mainThreadDiagnostics';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { IExtHostContext } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { mock } from 'vs/workbench/test/common/workbenchTestServices';
|
||||
import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity';
|
||||
import { ExtensionHostKind } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { IMarkerData } from 'vs/platform/markers/common/markers';
|
||||
import { runWithFakedTimers } from 'vs/base/test/common/timeTravelScheduler';
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
|
||||
|
||||
suite('MainThreadDiagnostics', function () {
|
||||
|
@ -57,4 +60,54 @@ suite('MainThreadDiagnostics', function () {
|
|||
diag.dispose();
|
||||
assert.strictEqual(markerService.read().length, 0);
|
||||
});
|
||||
|
||||
test('OnDidChangeDiagnostics triggers twice on same diagnostics #136434', function () {
|
||||
|
||||
return runWithFakedTimers({}, async () => {
|
||||
|
||||
const changedData: [UriComponents, IMarkerData[]][][] = [];
|
||||
|
||||
let diag = new MainThreadDiagnostics(
|
||||
new class implements IExtHostContext {
|
||||
remoteAuthority = '';
|
||||
extensionHostKind = ExtensionHostKind.LocalProcess;
|
||||
assertRegistered() { }
|
||||
set(v: any): any { return null; }
|
||||
getProxy(): any {
|
||||
return {
|
||||
$acceptMarkersChange(data: [UriComponents, IMarkerData[]][]) {
|
||||
changedData.push(data);
|
||||
}
|
||||
};
|
||||
}
|
||||
drain(): any { return null; }
|
||||
},
|
||||
markerService,
|
||||
new class extends mock<IUriIdentityService>() {
|
||||
override asCanonicalUri(uri: URI) { return uri; }
|
||||
}
|
||||
);
|
||||
|
||||
const markerDataStub = {
|
||||
code: '666',
|
||||
startLineNumber: 1,
|
||||
startColumn: 1,
|
||||
endLineNumber: 1,
|
||||
endColumn: 1,
|
||||
severity: 1,
|
||||
source: 'me'
|
||||
};
|
||||
const target = URI.file('a');
|
||||
diag.$changeMany('foo', [[target, [{ ...markerDataStub, message: 'same_owner' }]]]);
|
||||
markerService.changeOne('bar', target, [{ ...markerDataStub, message: 'forgein_owner' }]);
|
||||
|
||||
// added one marker via the API and one via the ext host. the latter must not
|
||||
// trigger an event to the extension host
|
||||
|
||||
await timeout(0);
|
||||
assert.strictEqual(markerService.read().length, 2);
|
||||
assert.strictEqual(changedData.length, 1);
|
||||
assert.strictEqual(changedData[0][0][1][0].message, 'forgein_owner');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -448,6 +448,13 @@ interface IWorkbenchConstructionOptions {
|
|||
*/
|
||||
readonly additionalTrustedDomains?: string[];
|
||||
|
||||
/**
|
||||
* Urls that will be opened externally that are allowed access
|
||||
* to the opener window. This is primarily used to allow
|
||||
* `window.close()` to be called from the newly opened window.
|
||||
*/
|
||||
readonly openerAllowedExternalUrlPrefixes?: string[];
|
||||
|
||||
/**
|
||||
* Support for URL callbacks.
|
||||
*/
|
||||
|
|
82
yarn.lock
82
yarn.lock
|
@ -470,12 +470,12 @@
|
|||
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
|
||||
integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==
|
||||
|
||||
"@ts-morph/common@~0.10.0":
|
||||
version "0.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@ts-morph/common/-/common-0.10.0.tgz#d032ea6f6d4115b72fa50ad56009baebcc1e71b8"
|
||||
integrity sha512-6wC+CovwzxLP+bQZcqHJEbZ7ViaIfsid8VzsVjJRkdfCQ8C8K5mm1+9/wkgmn814BPATtgSgFuDmVJnIb8/leg==
|
||||
"@ts-morph/common@~0.11.1":
|
||||
version "0.11.1"
|
||||
resolved "https://registry.yarnpkg.com/@ts-morph/common/-/common-0.11.1.tgz#281af2a0642b19354d8aa07a0d50dfdb4aa8164e"
|
||||
integrity sha512-7hWZS0NRpEsNV8vWJzg7FEz6V8MaLNeJOmwmghqUXTpzk16V1LLZhdo+4QvE/+zv4cVci0OviuJFnqhEfoV3+g==
|
||||
dependencies:
|
||||
fast-glob "^3.2.5"
|
||||
fast-glob "^3.2.7"
|
||||
minimatch "^3.0.4"
|
||||
mkdirp "^1.0.4"
|
||||
path-browserify "^1.0.1"
|
||||
|
@ -1455,7 +1455,7 @@ arr-union@^3.1.0:
|
|||
resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4"
|
||||
integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=
|
||||
|
||||
array-back@^3.0.1:
|
||||
array-back@^3.0.1, array-back@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/array-back/-/array-back-3.1.0.tgz#b8859d7a508871c9a7b2cf42f99428f65e96bfb0"
|
||||
integrity sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==
|
||||
|
@ -2480,12 +2480,12 @@ combined-stream@^1.0.6, combined-stream@~1.0.6:
|
|||
dependencies:
|
||||
delayed-stream "~1.0.0"
|
||||
|
||||
command-line-args@^5.1.1:
|
||||
version "5.1.1"
|
||||
resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-5.1.1.tgz#88e793e5bb3ceb30754a86863f0401ac92fd369a"
|
||||
integrity sha512-hL/eG8lrll1Qy1ezvkant+trihbGnaKaeEjj6Scyr3DN+RC7iQ5Rz84IeLERfAWDGo0HBSNAakczwgCilDXnWg==
|
||||
command-line-args@^5.2.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-5.2.0.tgz#087b02748272169741f1fd7c785b295df079b9be"
|
||||
integrity sha512-4zqtU1hYsSJzcJBOcNZIbW5Fbk9BkjCp1pZVhQKoRaWL5J7N4XphDLwo8aWwdQpTugxwu+jf9u2ZhkXiqp5Z6A==
|
||||
dependencies:
|
||||
array-back "^3.0.1"
|
||||
array-back "^3.1.0"
|
||||
find-replace "^3.0.0"
|
||||
lodash.camelcase "^4.3.0"
|
||||
typical "^4.0.0"
|
||||
|
@ -3976,17 +3976,16 @@ fast-glob@^3.1.1, fast-glob@^3.2.4:
|
|||
micromatch "^4.0.2"
|
||||
picomatch "^2.2.1"
|
||||
|
||||
fast-glob@^3.2.5:
|
||||
version "3.2.5"
|
||||
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.5.tgz#7939af2a656de79a4f1901903ee8adcaa7cb9661"
|
||||
integrity sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==
|
||||
fast-glob@^3.2.7:
|
||||
version "3.2.7"
|
||||
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.7.tgz#fd6cb7a2d7e9aa7a7846111e85a196d6b2f766a1"
|
||||
integrity sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==
|
||||
dependencies:
|
||||
"@nodelib/fs.stat" "^2.0.2"
|
||||
"@nodelib/fs.walk" "^1.2.3"
|
||||
glob-parent "^5.1.0"
|
||||
glob-parent "^5.1.2"
|
||||
merge2 "^1.3.0"
|
||||
micromatch "^4.0.2"
|
||||
picomatch "^2.2.1"
|
||||
micromatch "^4.0.4"
|
||||
|
||||
fast-json-stable-stringify@^2.0.0:
|
||||
version "2.1.0"
|
||||
|
@ -4477,7 +4476,7 @@ glob-parent@^3.1.0:
|
|||
is-glob "^3.1.0"
|
||||
path-dirname "^1.0.0"
|
||||
|
||||
glob-parent@^5.0.0, glob-parent@^5.1.0, glob-parent@^5.1.1, glob-parent@~5.1.0:
|
||||
glob-parent@^5.0.0, glob-parent@^5.1.0, glob-parent@^5.1.1, glob-parent@^5.1.2, glob-parent@~5.1.0:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
|
||||
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
|
||||
|
@ -6517,6 +6516,14 @@ micromatch@^4.0.0, micromatch@^4.0.2:
|
|||
braces "^3.0.1"
|
||||
picomatch "^2.0.5"
|
||||
|
||||
micromatch@^4.0.4:
|
||||
version "4.0.4"
|
||||
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9"
|
||||
integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==
|
||||
dependencies:
|
||||
braces "^3.0.1"
|
||||
picomatch "^2.2.3"
|
||||
|
||||
miller-rabin@^4.0.0:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d"
|
||||
|
@ -7602,6 +7609,11 @@ picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1:
|
|||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad"
|
||||
integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==
|
||||
|
||||
picomatch@^2.2.3:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972"
|
||||
integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==
|
||||
|
||||
pidtree@^0.3.0:
|
||||
version "0.3.1"
|
||||
resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.3.1.tgz#ef09ac2cc0533df1f3250ccf2c4d366b0d12114a"
|
||||
|
@ -9911,12 +9923,12 @@ ts-loader@^9.2.3:
|
|||
micromatch "^4.0.0"
|
||||
semver "^7.3.4"
|
||||
|
||||
ts-morph@^11.0.0:
|
||||
version "11.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ts-morph/-/ts-morph-11.0.0.tgz#511b3caa194739fef0619367f8e65de9b475e1d4"
|
||||
integrity sha512-u5y0jaft5c0sRFnU0K8cZhhsvPUtXjZK5L31JLIhP17qcqo9MDjwsSYLg3UryQDzlktv8wyf/UtoqpFLDYHijg==
|
||||
ts-morph@^12.2.0:
|
||||
version "12.2.0"
|
||||
resolved "https://registry.yarnpkg.com/ts-morph/-/ts-morph-12.2.0.tgz#3332319cecd44aff0b7b410f1fe39637499b1a1b"
|
||||
integrity sha512-WHXLtFDcIRwoqaiu0elAoZ/AmI+SwwDafnPKjgJmdwJ2gRVO0jMKBt88rV2liT/c6MTsXyuWbGFiHe9MRddWJw==
|
||||
dependencies:
|
||||
"@ts-morph/common" "~0.10.0"
|
||||
"@ts-morph/common" "~0.11.1"
|
||||
code-block-writer "^10.1.1"
|
||||
|
||||
tsec@0.1.4:
|
||||
|
@ -10447,14 +10459,6 @@ vscode-regexpp@^3.1.0:
|
|||
resolved "https://registry.yarnpkg.com/vscode-regexpp/-/vscode-regexpp-3.1.0.tgz#42d059b6fffe99bd42939c0d013f632f0cad823f"
|
||||
integrity sha512-pqtN65VC1jRLawfluX4Y80MMG0DHJydWhe5ZwMHewZD6sys4LbU6lHwFAHxeuaVE6Y6+xZOtAw+9hvq7/0ejkg==
|
||||
|
||||
vscode-ripgrep@^1.11.3:
|
||||
version "1.11.3"
|
||||
resolved "https://registry.yarnpkg.com/vscode-ripgrep/-/vscode-ripgrep-1.11.3.tgz#a997f4f4535dfeb9d775f04053c1247454d7a37a"
|
||||
integrity sha512-fdD+BciXiEO1iWTrV/S3sAthlK/tHRBjHF+aJIZDxUMD/q9wpNq+YPFEiLCrW+8epahfR19241DeVHHgX/I4Ww==
|
||||
dependencies:
|
||||
https-proxy-agent "^4.0.0"
|
||||
proxy-from-env "^1.1.0"
|
||||
|
||||
vscode-ripgrep@^1.12.1:
|
||||
version "1.12.1"
|
||||
resolved "https://registry.yarnpkg.com/vscode-ripgrep/-/vscode-ripgrep-1.12.1.tgz#4a319809d4010ea230659ce605fddacd1e36a589"
|
||||
|
@ -10463,14 +10467,14 @@ vscode-ripgrep@^1.12.1:
|
|||
https-proxy-agent "^4.0.0"
|
||||
proxy-from-env "^1.1.0"
|
||||
|
||||
vscode-telemetry-extractor@^1.8.0:
|
||||
version "1.8.0"
|
||||
resolved "https://registry.yarnpkg.com/vscode-telemetry-extractor/-/vscode-telemetry-extractor-1.8.0.tgz#5562106fe2eebfce0593f336c91f5a5ddc154cee"
|
||||
integrity sha512-jWe+caeLyB/F3V0EqsdkCC98wXx9+XLbm6EoPngz0sC4GOM7lcDSnVhUXzrIhZD/TSRPSPGlxp5r4/CrvhbmMQ==
|
||||
vscode-telemetry-extractor@^1.9.3:
|
||||
version "1.9.3"
|
||||
resolved "https://registry.yarnpkg.com/vscode-telemetry-extractor/-/vscode-telemetry-extractor-1.9.3.tgz#239d89a13b49c5ffe49eb7b2a6f8c1021ff584c7"
|
||||
integrity sha512-NWmao/CzDj347Minf+xuP/eDxSL7T6+bEABs3z/YcwXV9sHpcorXBqOVL7cZj1n+p0DQmyZUYo9byh3iXsx72g==
|
||||
dependencies:
|
||||
command-line-args "^5.1.1"
|
||||
ts-morph "^11.0.0"
|
||||
vscode-ripgrep "^1.11.3"
|
||||
command-line-args "^5.2.0"
|
||||
ts-morph "^12.2.0"
|
||||
vscode-ripgrep "^1.12.1"
|
||||
|
||||
vscode-textmate@5.4.1:
|
||||
version "5.4.1"
|
||||
|
|
Loading…
Reference in a new issue