Merge from vscode a416c77e56ef0314ae00633faa04878151610de8 (#8600)

* Merge from vscode a416c77e56ef0314ae00633faa04878151610de8

* distro

* fix tests

* fix tests
This commit is contained in:
Anthony Dresser
2019-12-07 17:19:16 -08:00
committed by GitHub
parent a7ff238653
commit d614116b63
155 changed files with 1982 additions and 1599 deletions

View File

@@ -24,7 +24,7 @@ import { Range } from 'vs/editor/common/core/range';
import { IPosition } from 'vs/editor/common/core/position';
import { MenuId } from 'vs/platform/actions/common/actions';
const _ctxHasCompletionItemProvider = new RawContextKey<boolean>('editorHasCallHierarchyProvider', false);
const _ctxHasCallHierarchyProvider = new RawContextKey<boolean>('editorHasCallHierarchyProvider', false);
const _ctxCallHierarchyVisible = new RawContextKey<boolean>('callHierarchyVisible', false);
class CallHierarchyController implements IEditorContribution {
@@ -52,7 +52,7 @@ class CallHierarchyController implements IEditorContribution {
@IInstantiationService private readonly _instantiationService: IInstantiationService,
) {
this._ctxIsVisible = _ctxCallHierarchyVisible.bindTo(this._contextKeyService);
this._ctxHasProvider = _ctxHasCompletionItemProvider.bindTo(this._contextKeyService);
this._ctxHasProvider = _ctxHasCallHierarchyProvider.bindTo(this._contextKeyService);
this._dispoables.add(Event.any<any>(_editor.onDidChangeModel, _editor.onDidChangeModelLanguage, CallHierarchyProviderRegistry.onDidChange)(() => {
this._ctxHasProvider.set(_editor.hasModel() && CallHierarchyProviderRegistry.has(_editor.getModel()));
}));
@@ -172,8 +172,7 @@ registerEditorAction(class extends EditorAction {
primary: KeyMod.Shift + KeyMod.Alt + KeyCode.KEY_H
},
precondition: ContextKeyExpr.and(
_ctxCallHierarchyVisible.negate(),
_ctxHasCompletionItemProvider,
_ctxHasCallHierarchyProvider,
PeekContext.notInPeekEditor
)
});

View File

@@ -49,10 +49,10 @@ class ChangeHierarchyDirectionAction extends Action {
});
const update = () => {
if (getDirection() === CallHierarchyDirection.CallsFrom) {
this.label = localize('toggle.from', "Showing Calls");
this.label = localize('toggle.from', "Show Incoming Calls");
this.class = 'calls-from';
} else {
this.label = localize('toggle.to', "Showing Callers");
this.label = localize('toggle.to', "Showing Outgoing Calls");
this.class = 'calls-to';
}
};
@@ -325,7 +325,11 @@ export class CallHierarchyTreePeekWidget extends peekView.PeekViewWidget {
// set decorations for caller ranges (if in the same file)
let decorations: IModelDeltaDecoration[] = [];
let fullRange: IRange | undefined;
for (const loc of element.locations) {
let locations = element.locations;
if (!locations) {
locations = [{ uri: element.item.uri, range: element.item.selectionRange }];
}
for (const loc of locations) {
if (loc.uri.toString() === previewUri.toString()) {
decorations.push({ range: loc.range, options });
fullRange = !fullRange ? loc.range : Range.plusRange(loc.range, fullRange);
@@ -424,7 +428,7 @@ export class CallHierarchyTreePeekWidget extends peekView.PeekViewWidget {
}
protected _doLayoutBody(height: number, width: number): void {
if (this._dim.height !== height || this._dim.width === width) {
if (this._dim.height !== height || this._dim.width !== width) {
super._doLayoutBody(height, width);
this._dim = { height, width };
this._layoutInfo.height = this._viewZone ? this._viewZone.heightInLines : this._layoutInfo.height;

View File

@@ -17,7 +17,7 @@ import { Range } from 'vs/editor/common/core/range';
export class Call {
constructor(
readonly item: CallHierarchyItem,
readonly locations: Location[],
readonly locations: Location[] | undefined,
readonly model: CallHierarchyModel,
readonly parent: Call | undefined
) { }
@@ -43,7 +43,7 @@ export class DataSource implements IAsyncDataSource<CallHierarchyModel, Call> {
async getChildren(element: CallHierarchyModel | Call): Promise<Call[]> {
if (element instanceof CallHierarchyModel) {
return [new Call(element.root, [], element, undefined)];
return [new Call(element.root, undefined, element, undefined)];
}
const { model, item } = element;

View File

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.5469 9.32812C12.3542 9.25 12.1562 9.21094 11.9531 9.21094C11.7344 9.20573 11.5495 9.23958 11.3984 9.3125C11.2474 9.38542 11.1042 9.47135 10.9688 9.57031C10.8333 9.66927 10.7135 9.77865 10.6094 9.89844C10.5052 10.0182 10.4036 10.1276 10.3047 10.2266C10.2057 10.3255 10.1094 10.4089 10.0156 10.4766C9.92188 10.5443 9.82031 10.5781 9.71094 10.5781C9.5599 10.5781 9.42969 10.5234 9.32031 10.4141C9.24219 10.3411 9.13281 10.237 8.99219 10.1016C8.85156 9.96615 8.67969 9.80208 8.47656 9.60938C8.27344 9.41667 8.0625 9.21354 7.84375 9C7.625 8.78646 7.39844 8.5651 7.16406 8.33594C6.92969 8.10677 6.71094 7.88542 6.50781 7.67188C6.30469 7.45833 6.11979 7.25781 5.95312 7.07031C5.78646 6.88281 5.65625 6.72135 5.5625 6.58594C5.46875 6.45052 5.42188 6.35156 5.42188 6.28906C5.41667 6.17448 5.45052 6.07031 5.52344 5.97656C5.59635 5.88281 5.68229 5.78646 5.78125 5.6875C5.88021 5.58854 5.98958 5.48438 6.10938 5.375C6.22917 5.26562 6.33854 5.14844 6.4375 5.02344C6.53646 4.89844 6.61979 4.75521 6.6875 4.59375C6.75521 4.43229 6.78906 4.25 6.78906 4.04688C6.78906 3.84375 6.75 3.64583 6.67188 3.45312C6.59375 3.26042 6.48177 3.09115 6.33594 2.94531C6.16927 2.78385 5.99219 2.59115 5.80469 2.36719C5.61719 2.14323 5.41146 1.92969 5.1875 1.72656C4.96354 1.52344 4.73177 1.35156 4.49219 1.21094C4.2526 1.07031 4.0026 1 3.74219 1C3.53906 1 3.34115 1.03906 3.14844 1.11719C2.95573 1.19531 2.78646 1.30729 2.64062 1.45313C2.36979 1.72396 2.13281 1.96615 1.92969 2.17969C1.72656 2.39323 1.55469 2.61458 1.41406 2.84375C1.27344 3.07292 1.16927 3.32812 1.10156 3.60938C1.03385 3.89062 1 4.22917 1 4.625C1 5.17708 1.08854 5.75 1.26562 6.34375C1.44271 6.9375 1.68229 7.52865 1.98438 8.11719C2.28646 8.70573 2.65365 9.28385 3.08594 9.85156C3.51823 10.4193 3.98698 10.9583 4.49219 11.4688C4.9974 11.9792 5.53385 12.4505 6.10156 12.8828C6.66927 13.3151 7.25 13.6875 7.84375 14C8.4375 14.3125 9.03385 14.5573 9.63281 14.7344C10.2318 14.9115 10.8151 15 11.3828 15C11.7682 14.9948 12.1042 14.9583 12.3906 14.8906C12.6771 14.8229 12.9349 14.7188 13.1641 14.5781C13.3932 14.4375 13.6146 14.2656 13.8281 14.0625C14.0417 13.8594 14.2812 13.625 14.5469 13.3594C14.6927 13.2135 14.8047 13.0443 14.8828 12.8516C14.9609 12.6589 15 12.4609 15 12.2578C14.9896 12.0859 14.9557 11.9141 14.8984 11.7422C14.8411 11.5703 14.7552 11.4089 14.6406 11.2578C14.526 11.1068 14.4036 10.9583 14.2734 10.8125C14.1432 10.6667 14.0026 10.526 13.8516 10.3906C13.7005 10.2552 13.5573 10.1276 13.4219 10.0078C13.2865 9.88802 13.1641 9.77344 13.0547 9.66406C12.9089 9.51823 12.7396 9.40625 12.5469 9.32812ZM12.1797 13.9141C11.9661 13.9714 11.7005 14 11.3828 14C10.8984 13.9948 10.3932 13.9141 9.86719 13.7578C9.34115 13.6016 8.8125 13.3802 8.28125 13.0938C7.75 12.8073 7.22396 12.4688 6.70312 12.0781C6.18229 11.6875 5.69271 11.2604 5.23438 10.7969C4.77604 10.3333 4.34635 9.84635 3.94531 9.33594C3.54427 8.82552 3.20052 8.29948 2.91406 7.75781C2.6276 7.21615 2.40365 6.67969 2.24219 6.14844C2.08073 5.61719 2 5.10156 2 4.60156C2.00521 4.29427 2.03646 4.03125 2.09375 3.8125C2.15104 3.59375 2.23698 3.39844 2.35156 3.22656C2.46615 3.05469 2.60677 2.88802 2.77344 2.72656C2.9401 2.5651 3.13021 2.3776 3.34375 2.16406C3.45312 2.05469 3.58594 2 3.74219 2C3.80469 1.99479 3.90104 2.03646 4.03125 2.125C4.16146 2.21354 4.30208 2.32031 4.45312 2.44531C4.60417 2.57031 4.76042 2.71354 4.92188 2.875C5.08333 3.03646 5.22656 3.19271 5.35156 3.34375C5.47656 3.49479 5.58073 3.63281 5.66406 3.75781C5.7474 3.88281 5.78906 3.97917 5.78906 4.04688C5.79427 4.17188 5.76042 4.27604 5.6875 4.35938C5.61458 4.44271 5.52865 4.53906 5.42969 4.64844C5.33073 4.75781 5.22135 4.86198 5.10156 4.96094C4.98177 5.0599 4.8724 5.17708 4.77344 5.3125C4.67448 5.44792 4.59115 5.59375 4.52344 5.75C4.45573 5.90625 4.42188 6.08594 4.42188 6.28906C4.42708 6.5026 4.46875 6.70312 4.54688 6.89062C4.625 7.07812 4.73698 7.24479 4.88281 7.39062L8.60938 11.1172C8.76042 11.2682 8.92969 11.3828 9.11719 11.4609C9.30469 11.5391 9.5026 11.5781 9.71094 11.5781C9.91927 11.5833 10.1016 11.5495 10.2578 11.4766C10.4141 11.4036 10.5573 11.3177 10.6875 11.2188C10.8177 11.1198 10.9375 11.0104 11.0469 10.8906C11.1562 10.7708 11.2578 10.6615 11.3516 10.5625C11.4453 10.4635 11.5417 10.3802 11.6406 10.3125C11.7396 10.2448 11.8438 10.2109 11.9531 10.2109C12.026 10.2109 12.125 10.2526 12.25 10.3359C12.375 10.4193 12.513 10.526 12.6641 10.6562C12.8151 10.7865 12.9714 10.9297 13.1328 11.0859C13.2943 11.2422 13.4375 11.3984 13.5625 11.5547C13.6875 11.7109 13.7917 11.8516 13.875 11.9766C13.9583 12.1016 14 12.1979 14 12.2656C14 12.4167 13.9453 12.5469 13.8359 12.6562C13.612 12.875 13.4219 13.0651 13.2656 13.2266C13.1094 13.388 12.9427 13.5286 12.7656 13.6484C12.5885 13.7682 12.3932 13.8568 12.1797 13.9141ZM15 1.70312L10.3594 6.35156L13.6484 6.35156V7.35156L8.64844 7.35156L8.64844 2.35156L9.64844 2.35156V5.64062L14.2969 1L15 1.70312Z" fill="#C5C5C5"/>
</svg>

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.5469 9.32812C12.3542 9.25 12.1562 9.21094 11.9531 9.21094C11.7344 9.20573 11.5495 9.23958 11.3984 9.3125C11.2474 9.38542 11.1042 9.47135 10.9688 9.57031C10.8333 9.66927 10.7135 9.77865 10.6094 9.89844C10.5052 10.0182 10.4036 10.1276 10.3047 10.2266C10.2057 10.3255 10.1094 10.4089 10.0156 10.4766C9.92188 10.5443 9.82031 10.5781 9.71094 10.5781C9.5599 10.5781 9.42969 10.5234 9.32031 10.4141C9.24219 10.3411 9.13281 10.237 8.99219 10.1016C8.85156 9.96615 8.67969 9.80208 8.47656 9.60938C8.27344 9.41667 8.0625 9.21354 7.84375 9C7.625 8.78646 7.39844 8.5651 7.16406 8.33594C6.92969 8.10677 6.71094 7.88542 6.50781 7.67188C6.30469 7.45833 6.11979 7.25781 5.95312 7.07031C5.78646 6.88281 5.65625 6.72135 5.5625 6.58594C5.46875 6.45052 5.42188 6.35156 5.42188 6.28906C5.41667 6.17448 5.45052 6.07031 5.52344 5.97656C5.59635 5.88281 5.68229 5.78646 5.78125 5.6875C5.88021 5.58854 5.98958 5.48438 6.10938 5.375C6.22917 5.26562 6.33854 5.14844 6.4375 5.02344C6.53646 4.89844 6.61979 4.75521 6.6875 4.59375C6.75521 4.43229 6.78906 4.25 6.78906 4.04688C6.78906 3.84375 6.75 3.64583 6.67188 3.45312C6.59375 3.26042 6.48177 3.09115 6.33594 2.94531C6.16927 2.78385 5.99219 2.59115 5.80469 2.36719C5.61719 2.14323 5.41146 1.92969 5.1875 1.72656C4.96354 1.52344 4.73177 1.35156 4.49219 1.21094C4.2526 1.07031 4.0026 1 3.74219 1C3.53906 1 3.34115 1.03906 3.14844 1.11719C2.95573 1.19531 2.78646 1.30729 2.64062 1.45313C2.36979 1.72396 2.13281 1.96615 1.92969 2.17969C1.72656 2.39323 1.55469 2.61458 1.41406 2.84375C1.27344 3.07292 1.16927 3.32812 1.10156 3.60938C1.03385 3.89062 1 4.22917 1 4.625C1 5.17708 1.08854 5.75 1.26562 6.34375C1.44271 6.9375 1.68229 7.52865 1.98438 8.11719C2.28646 8.70573 2.65365 9.28385 3.08594 9.85156C3.51823 10.4193 3.98698 10.9583 4.49219 11.4688C4.9974 11.9792 5.53385 12.4505 6.10156 12.8828C6.66927 13.3151 7.25 13.6875 7.84375 14C8.4375 14.3125 9.03385 14.5573 9.63281 14.7344C10.2318 14.9115 10.8151 15 11.3828 15C11.7682 14.9948 12.1042 14.9583 12.3906 14.8906C12.6771 14.8229 12.9349 14.7188 13.1641 14.5781C13.3932 14.4375 13.6146 14.2656 13.8281 14.0625C14.0417 13.8594 14.2812 13.625 14.5469 13.3594C14.6927 13.2135 14.8047 13.0443 14.8828 12.8516C14.9609 12.6589 15 12.4609 15 12.2578C14.9896 12.0859 14.9557 11.9141 14.8984 11.7422C14.8411 11.5703 14.7552 11.4089 14.6406 11.2578C14.526 11.1068 14.4036 10.9583 14.2734 10.8125C14.1432 10.6667 14.0026 10.526 13.8516 10.3906C13.7005 10.2552 13.5573 10.1276 13.4219 10.0078C13.2865 9.88802 13.1641 9.77344 13.0547 9.66406C12.9089 9.51823 12.7396 9.40625 12.5469 9.32812ZM12.1797 13.9141C11.9661 13.9714 11.7005 14 11.3828 14C10.8984 13.9948 10.3932 13.9141 9.86719 13.7578C9.34115 13.6016 8.8125 13.3802 8.28125 13.0938C7.75 12.8073 7.22396 12.4688 6.70312 12.0781C6.18229 11.6875 5.69271 11.2604 5.23438 10.7969C4.77604 10.3333 4.34635 9.84635 3.94531 9.33594C3.54427 8.82552 3.20052 8.29948 2.91406 7.75781C2.6276 7.21615 2.40365 6.67969 2.24219 6.14844C2.08073 5.61719 2 5.10156 2 4.60156C2.00521 4.29427 2.03646 4.03125 2.09375 3.8125C2.15104 3.59375 2.23698 3.39844 2.35156 3.22656C2.46615 3.05469 2.60677 2.88802 2.77344 2.72656C2.9401 2.5651 3.13021 2.3776 3.34375 2.16406C3.45312 2.05469 3.58594 2 3.74219 2C3.80469 1.99479 3.90104 2.03646 4.03125 2.125C4.16146 2.21354 4.30208 2.32031 4.45312 2.44531C4.60417 2.57031 4.76042 2.71354 4.92188 2.875C5.08333 3.03646 5.22656 3.19271 5.35156 3.34375C5.47656 3.49479 5.58073 3.63281 5.66406 3.75781C5.7474 3.88281 5.78906 3.97917 5.78906 4.04688C5.79427 4.17188 5.76042 4.27604 5.6875 4.35938C5.61458 4.44271 5.52865 4.53906 5.42969 4.64844C5.33073 4.75781 5.22135 4.86198 5.10156 4.96094C4.98177 5.0599 4.8724 5.17708 4.77344 5.3125C4.67448 5.44792 4.59115 5.59375 4.52344 5.75C4.45573 5.90625 4.42188 6.08594 4.42188 6.28906C4.42708 6.5026 4.46875 6.70312 4.54688 6.89062C4.625 7.07812 4.73698 7.24479 4.88281 7.39062L8.60938 11.1172C8.76042 11.2682 8.92969 11.3828 9.11719 11.4609C9.30469 11.5391 9.5026 11.5781 9.71094 11.5781C9.91927 11.5833 10.1016 11.5495 10.2578 11.4766C10.4141 11.4036 10.5573 11.3177 10.6875 11.2188C10.8177 11.1198 10.9375 11.0104 11.0469 10.8906C11.1562 10.7708 11.2578 10.6615 11.3516 10.5625C11.4453 10.4635 11.5417 10.3802 11.6406 10.3125C11.7396 10.2448 11.8438 10.2109 11.9531 10.2109C12.026 10.2109 12.125 10.2526 12.25 10.3359C12.375 10.4193 12.513 10.526 12.6641 10.6562C12.8151 10.7865 12.9714 10.9297 13.1328 11.0859C13.2943 11.2422 13.4375 11.3984 13.5625 11.5547C13.6875 11.7109 13.7917 11.8516 13.875 11.9766C13.9583 12.1016 14 12.1979 14 12.2656C14 12.4167 13.9453 12.5469 13.8359 12.6562C13.612 12.875 13.4219 13.0651 13.2656 13.2266C13.1094 13.388 12.9427 13.5286 12.7656 13.6484C12.5885 13.7682 12.3932 13.8568 12.1797 13.9141ZM15 1.70312L10.3594 6.35156L13.6484 6.35156V7.35156L8.64844 7.35156L8.64844 2.35156L9.64844 2.35156V5.64062L14.2969 1L15 1.70312Z" fill="#424242"/>
</svg>

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.64844 6.64844L13.2891 2H10V1H15V6H14V2.71094L9.35156 7.35156L8.64844 6.64844ZM11.9531 9.21094C12.1562 9.21094 12.3542 9.25 12.5469 9.32812C12.7396 9.40625 12.9089 9.51823 13.0547 9.66406C13.1641 9.77344 13.2865 9.88802 13.4219 10.0078C13.5573 10.1276 13.7005 10.2552 13.8516 10.3906C14.0026 10.526 14.1432 10.6667 14.2734 10.8125C14.4036 10.9583 14.526 11.1068 14.6406 11.2578C14.7552 11.4089 14.8411 11.5703 14.8984 11.7422C14.9557 11.9141 14.9896 12.0859 15 12.2578C15 12.4609 14.9609 12.6589 14.8828 12.8516C14.8047 13.0443 14.6927 13.2135 14.5469 13.3594C14.2812 13.625 14.0417 13.8594 13.8281 14.0625C13.6146 14.2656 13.3932 14.4375 13.1641 14.5781C12.9349 14.7188 12.6771 14.8229 12.3906 14.8906C12.1042 14.9583 11.7682 14.9948 11.3828 15C10.8151 15 10.2318 14.9115 9.63281 14.7344C9.03385 14.5573 8.4375 14.3125 7.84375 14C7.25 13.6875 6.66927 13.3151 6.10156 12.8828C5.53385 12.4505 4.9974 11.9792 4.49219 11.4688C3.98698 10.9583 3.51823 10.4193 3.08594 9.85156C2.65365 9.28385 2.28646 8.70573 1.98438 8.11719C1.68229 7.52865 1.44271 6.9375 1.26562 6.34375C1.08854 5.75 1 5.17708 1 4.625C1 4.22917 1.03385 3.89062 1.10156 3.60938C1.16927 3.32812 1.27344 3.07292 1.41406 2.84375C1.55469 2.61458 1.72656 2.39323 1.92969 2.17969C2.13281 1.96615 2.36979 1.72396 2.64062 1.45312C2.78646 1.30729 2.95573 1.19531 3.14844 1.11719C3.34115 1.03906 3.53906 1 3.74219 1C4.0026 1 4.2526 1.07031 4.49219 1.21094C4.73177 1.35156 4.96354 1.52344 5.1875 1.72656C5.41146 1.92969 5.61719 2.14323 5.80469 2.36719C5.99219 2.59115 6.16927 2.78385 6.33594 2.94531C6.48177 3.09115 6.59375 3.26042 6.67188 3.45312C6.75 3.64583 6.78906 3.84375 6.78906 4.04688C6.78906 4.25 6.75521 4.43229 6.6875 4.59375C6.61979 4.75521 6.53646 4.89844 6.4375 5.02344C6.33854 5.14844 6.22917 5.26562 6.10938 5.375C5.98958 5.48438 5.88021 5.58854 5.78125 5.6875C5.68229 5.78646 5.59635 5.88281 5.52344 5.97656C5.45052 6.07031 5.41667 6.17448 5.42188 6.28906C5.42188 6.35156 5.46875 6.45052 5.5625 6.58594C5.65625 6.72135 5.78646 6.88281 5.95312 7.07031C6.11979 7.25781 6.30469 7.45833 6.50781 7.67188C6.71094 7.88542 6.92969 8.10677 7.16406 8.33594C7.39844 8.5651 7.625 8.78646 7.84375 9C8.0625 9.21354 8.27344 9.41667 8.47656 9.60938C8.67969 9.80208 8.85156 9.96615 8.99219 10.1016C9.13281 10.237 9.24219 10.3411 9.32031 10.4141C9.42969 10.5234 9.5599 10.5781 9.71094 10.5781C9.82031 10.5781 9.92188 10.5443 10.0156 10.4766C10.1094 10.4089 10.2057 10.3255 10.3047 10.2266C10.4036 10.1276 10.5052 10.0182 10.6094 9.89844C10.7135 9.77865 10.8333 9.66927 10.9688 9.57031C11.1042 9.47135 11.2474 9.38542 11.3984 9.3125C11.5495 9.23958 11.7344 9.20573 11.9531 9.21094ZM11.3828 14C11.7005 14 11.9661 13.9714 12.1797 13.9141C12.3932 13.8568 12.5885 13.7682 12.7656 13.6484C12.9427 13.5286 13.1094 13.388 13.2656 13.2266C13.4219 13.0651 13.612 12.875 13.8359 12.6562C13.9453 12.5469 14 12.4167 14 12.2656C14 12.1979 13.9583 12.1016 13.875 11.9766C13.7917 11.8516 13.6875 11.7109 13.5625 11.5547C13.4375 11.3984 13.2943 11.2422 13.1328 11.0859C12.9714 10.9297 12.8151 10.7865 12.6641 10.6562C12.513 10.526 12.375 10.4193 12.25 10.3359C12.125 10.2526 12.026 10.2109 11.9531 10.2109C11.8438 10.2109 11.7396 10.2448 11.6406 10.3125C11.5417 10.3802 11.4453 10.4635 11.3516 10.5625C11.2578 10.6615 11.1562 10.7708 11.0469 10.8906C10.9375 11.0104 10.8177 11.1198 10.6875 11.2188C10.5573 11.3177 10.4141 11.4036 10.2578 11.4766C10.1016 11.5495 9.91927 11.5833 9.71094 11.5781C9.5026 11.5781 9.30469 11.5391 9.11719 11.4609C8.92969 11.3828 8.76042 11.2682 8.60938 11.1172L4.88281 7.39062C4.73698 7.24479 4.625 7.07812 4.54688 6.89062C4.46875 6.70312 4.42708 6.5026 4.42188 6.28906C4.42188 6.08594 4.45573 5.90625 4.52344 5.75C4.59115 5.59375 4.67448 5.44792 4.77344 5.3125C4.8724 5.17708 4.98177 5.0599 5.10156 4.96094C5.22135 4.86198 5.33073 4.75781 5.42969 4.64844C5.52865 4.53906 5.61458 4.44271 5.6875 4.35938C5.76042 4.27604 5.79427 4.17188 5.78906 4.04688C5.78906 3.97917 5.7474 3.88281 5.66406 3.75781C5.58073 3.63281 5.47656 3.49479 5.35156 3.34375C5.22656 3.19271 5.08333 3.03646 4.92188 2.875C4.76042 2.71354 4.60417 2.57031 4.45312 2.44531C4.30208 2.32031 4.16146 2.21354 4.03125 2.125C3.90104 2.03646 3.80469 1.99479 3.74219 2C3.58594 2 3.45312 2.05469 3.34375 2.16406C3.13021 2.3776 2.9401 2.5651 2.77344 2.72656C2.60677 2.88802 2.46615 3.05469 2.35156 3.22656C2.23698 3.39844 2.15104 3.59375 2.09375 3.8125C2.03646 4.03125 2.00521 4.29427 2 4.60156C2 5.10156 2.08073 5.61719 2.24219 6.14844C2.40365 6.67969 2.6276 7.21615 2.91406 7.75781C3.20052 8.29948 3.54427 8.82552 3.94531 9.33594C4.34635 9.84635 4.77604 10.3333 5.23438 10.7969C5.69271 11.2604 6.18229 11.6875 6.70312 12.0781C7.22396 12.4688 7.75 12.8073 8.28125 13.0938C8.8125 13.3802 9.34115 13.6016 9.86719 13.7578C10.3932 13.9141 10.8984 13.9948 11.3828 14Z" fill="#C5C5C5"/>
</svg>

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.64844 6.64844L13.2891 2H10V1H15V6H14V2.71094L9.35156 7.35156L8.64844 6.64844ZM11.9531 9.21094C12.1562 9.21094 12.3542 9.25 12.5469 9.32812C12.7396 9.40625 12.9089 9.51823 13.0547 9.66406C13.1641 9.77344 13.2865 9.88802 13.4219 10.0078C13.5573 10.1276 13.7005 10.2552 13.8516 10.3906C14.0026 10.526 14.1432 10.6667 14.2734 10.8125C14.4036 10.9583 14.526 11.1068 14.6406 11.2578C14.7552 11.4089 14.8411 11.5703 14.8984 11.7422C14.9557 11.9141 14.9896 12.0859 15 12.2578C15 12.4609 14.9609 12.6589 14.8828 12.8516C14.8047 13.0443 14.6927 13.2135 14.5469 13.3594C14.2812 13.625 14.0417 13.8594 13.8281 14.0625C13.6146 14.2656 13.3932 14.4375 13.1641 14.5781C12.9349 14.7188 12.6771 14.8229 12.3906 14.8906C12.1042 14.9583 11.7682 14.9948 11.3828 15C10.8151 15 10.2318 14.9115 9.63281 14.7344C9.03385 14.5573 8.4375 14.3125 7.84375 14C7.25 13.6875 6.66927 13.3151 6.10156 12.8828C5.53385 12.4505 4.9974 11.9792 4.49219 11.4688C3.98698 10.9583 3.51823 10.4193 3.08594 9.85156C2.65365 9.28385 2.28646 8.70573 1.98438 8.11719C1.68229 7.52865 1.44271 6.9375 1.26562 6.34375C1.08854 5.75 1 5.17708 1 4.625C1 4.22917 1.03385 3.89062 1.10156 3.60938C1.16927 3.32812 1.27344 3.07292 1.41406 2.84375C1.55469 2.61458 1.72656 2.39323 1.92969 2.17969C2.13281 1.96615 2.36979 1.72396 2.64062 1.45312C2.78646 1.30729 2.95573 1.19531 3.14844 1.11719C3.34115 1.03906 3.53906 1 3.74219 1C4.0026 1 4.2526 1.07031 4.49219 1.21094C4.73177 1.35156 4.96354 1.52344 5.1875 1.72656C5.41146 1.92969 5.61719 2.14323 5.80469 2.36719C5.99219 2.59115 6.16927 2.78385 6.33594 2.94531C6.48177 3.09115 6.59375 3.26042 6.67188 3.45312C6.75 3.64583 6.78906 3.84375 6.78906 4.04688C6.78906 4.25 6.75521 4.43229 6.6875 4.59375C6.61979 4.75521 6.53646 4.89844 6.4375 5.02344C6.33854 5.14844 6.22917 5.26562 6.10938 5.375C5.98958 5.48438 5.88021 5.58854 5.78125 5.6875C5.68229 5.78646 5.59635 5.88281 5.52344 5.97656C5.45052 6.07031 5.41667 6.17448 5.42188 6.28906C5.42188 6.35156 5.46875 6.45052 5.5625 6.58594C5.65625 6.72135 5.78646 6.88281 5.95312 7.07031C6.11979 7.25781 6.30469 7.45833 6.50781 7.67188C6.71094 7.88542 6.92969 8.10677 7.16406 8.33594C7.39844 8.5651 7.625 8.78646 7.84375 9C8.0625 9.21354 8.27344 9.41667 8.47656 9.60938C8.67969 9.80208 8.85156 9.96615 8.99219 10.1016C9.13281 10.237 9.24219 10.3411 9.32031 10.4141C9.42969 10.5234 9.5599 10.5781 9.71094 10.5781C9.82031 10.5781 9.92188 10.5443 10.0156 10.4766C10.1094 10.4089 10.2057 10.3255 10.3047 10.2266C10.4036 10.1276 10.5052 10.0182 10.6094 9.89844C10.7135 9.77865 10.8333 9.66927 10.9688 9.57031C11.1042 9.47135 11.2474 9.38542 11.3984 9.3125C11.5495 9.23958 11.7344 9.20573 11.9531 9.21094ZM11.3828 14C11.7005 14 11.9661 13.9714 12.1797 13.9141C12.3932 13.8568 12.5885 13.7682 12.7656 13.6484C12.9427 13.5286 13.1094 13.388 13.2656 13.2266C13.4219 13.0651 13.612 12.875 13.8359 12.6562C13.9453 12.5469 14 12.4167 14 12.2656C14 12.1979 13.9583 12.1016 13.875 11.9766C13.7917 11.8516 13.6875 11.7109 13.5625 11.5547C13.4375 11.3984 13.2943 11.2422 13.1328 11.0859C12.9714 10.9297 12.8151 10.7865 12.6641 10.6562C12.513 10.526 12.375 10.4193 12.25 10.3359C12.125 10.2526 12.026 10.2109 11.9531 10.2109C11.8438 10.2109 11.7396 10.2448 11.6406 10.3125C11.5417 10.3802 11.4453 10.4635 11.3516 10.5625C11.2578 10.6615 11.1562 10.7708 11.0469 10.8906C10.9375 11.0104 10.8177 11.1198 10.6875 11.2188C10.5573 11.3177 10.4141 11.4036 10.2578 11.4766C10.1016 11.5495 9.91927 11.5833 9.71094 11.5781C9.5026 11.5781 9.30469 11.5391 9.11719 11.4609C8.92969 11.3828 8.76042 11.2682 8.60938 11.1172L4.88281 7.39062C4.73698 7.24479 4.625 7.07812 4.54688 6.89062C4.46875 6.70312 4.42708 6.5026 4.42188 6.28906C4.42188 6.08594 4.45573 5.90625 4.52344 5.75C4.59115 5.59375 4.67448 5.44792 4.77344 5.3125C4.8724 5.17708 4.98177 5.0599 5.10156 4.96094C5.22135 4.86198 5.33073 4.75781 5.42969 4.64844C5.52865 4.53906 5.61458 4.44271 5.6875 4.35938C5.76042 4.27604 5.79427 4.17188 5.78906 4.04688C5.78906 3.97917 5.7474 3.88281 5.66406 3.75781C5.58073 3.63281 5.47656 3.49479 5.35156 3.34375C5.22656 3.19271 5.08333 3.03646 4.92188 2.875C4.76042 2.71354 4.60417 2.57031 4.45312 2.44531C4.30208 2.32031 4.16146 2.21354 4.03125 2.125C3.90104 2.03646 3.80469 1.99479 3.74219 2C3.58594 2 3.45312 2.05469 3.34375 2.16406C3.13021 2.3776 2.9401 2.5651 2.77344 2.72656C2.60677 2.88802 2.46615 3.05469 2.35156 3.22656C2.23698 3.39844 2.15104 3.59375 2.09375 3.8125C2.03646 4.03125 2.00521 4.29427 2 4.60156C2 5.10156 2.08073 5.61719 2.24219 6.14844C2.40365 6.67969 2.6276 7.21615 2.91406 7.75781C3.20052 8.29948 3.54427 8.82552 3.94531 9.33594C4.34635 9.84635 4.77604 10.3333 5.23438 10.7969C5.69271 11.2604 6.18229 11.6875 6.70312 12.0781C7.22396 12.4688 7.75 12.8073 8.28125 13.0938C8.8125 13.3802 9.34115 13.6016 9.86719 13.7578C10.3932 13.9141 10.8984 13.9948 11.3828 14Z" fill="#424242"/>
</svg>

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

@@ -21,19 +21,27 @@
}
.monaco-workbench .action-label.calls-to {
background-image: url(files_CallTo_CallTo_16x.svg);
background-image: url(action-call-to.svg);
background-size: 14px 14px;
background-repeat: no-repeat;
background-position: left center;
}
.vs-dark .monaco-workbench .action-label.calls-to {
background-image: url(action-call-to-dark.svg);
}
.monaco-workbench .action-label.calls-from {
background-image: url(files_CallFrom_CallFrom_16x.svg);
background-image: url(action-call-from.svg);
background-size: 14px 14px;
background-repeat: no-repeat;
background-position: left center;
}
.vs-dark .monaco-workbench .action-label.calls-from{
background-image: url(action-call-from-dark.svg);
}
.monaco-workbench .call-hierarchy .editor,
.monaco-workbench .call-hierarchy .tree {
height: 100%;

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-bg{fill:#424242}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M12 6v4h2v4.987l-.398.3A3.46 3.46 0 0 1 11.5 16C9.57 16 8 14.43 8 12.5V9.006H6.344l1.318 1.322-2.119 2.119L1 7.92v-.798l4.55-4.55 2.12 2.12-1.309 1.313H8V3.5C8 1.57 9.57 0 11.5 0a3.46 3.46 0 0 1 2.102.713l.398.3V6h-2z" id="outline"/><path class="icon-vs-bg" d="M11 10.051V11h2v3.489a2.476 2.476 0 0 1-1.5.511A2.5 2.5 0 0 1 9 12.5v-9A2.5 2.5 0 0 1 11.5 1c.565 0 1.081.194 1.5.511V5h-2v5.051zM6.257 4.693l-.707-.707L2.016 7.52l3.526 3.514.707-.707-2.314-2.322h4.12v-1H3.953l2.304-2.312z" id="iconBg"/></svg>

Before

Width:  |  Height:  |  Size: 781 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><style>.icon-canvas-transparent{opacity:0;fill:#f6f6f6}.icon-vs-out{fill:#f6f6f6}.icon-vs-bg{fill:#424242}</style><path class="icon-canvas-transparent" d="M16 16H0V0h16v16z" id="canvas"/><path class="icon-vs-out" d="M3.727 9.006H1.016v-3h2.693L2.4 4.692l2.12-2.12L8 6.052V3.5C8 1.57 9.57 0 11.5 0c.758 0 1.485.247 2.103.713l.362.273v14.028l-.362.273A3.465 3.465 0 0 1 11.5 16C9.57 16 8 14.43 8 12.5V8.986l-3.473 3.461-2.119-2.119 1.319-1.322z" id="outline"/><path class="icon-vs-bg" d="M11 10.051V11h2v3.489a2.476 2.476 0 0 1-1.5.511A2.5 2.5 0 0 1 9 12.5v-9A2.5 2.5 0 0 1 11.5 1c.565 0 1.081.194 1.5.511V5h-2v5.051zM3.813 4.693l2.305 2.312H2.016v1h4.12l-2.314 2.322.707.707L8.055 7.52 4.52 3.986l-.707.707z" id="iconBg"/></svg>

Before

Width:  |  Height:  |  Size: 787 B

View File

@@ -20,6 +20,7 @@ import { CONTEXT_FOCUSED_CUSTOM_EDITOR_IS_EDITABLE, CONTEXT_HAS_CUSTOM_EDITORS,
import { getMultiSelectedResources } from 'vs/workbench/contrib/files/browser/files';
import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IExplorerService } from 'vs/workbench/contrib/files/common/files';
const viewCategory = nls.localize('viewCategory', "View");
@@ -34,7 +35,7 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
when: EditorContextKeys.focus.toNegated(),
handler: async (accessor: ServicesAccessor, resource: URI | object) => {
const editorService = accessor.get(IEditorService);
const resources = getMultiSelectedResources(resource, accessor.get(IListService), editorService);
const resources = getMultiSelectedResources(resource, accessor.get(IListService), editorService, accessor.get(IExplorerService));
const targetResource = firstOrDefault(resources);
if (!targetResource) {
return undefined; // {{SQL CARBON EDIT}} strict-null-check

View File

@@ -17,6 +17,7 @@ import { ILabelService } from 'vs/platform/label/common/label';
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
import { GroupIdentifier, IEditorInput, IRevertOptions, ISaveOptions, Verbosity } from 'vs/workbench/common/editor';
import { ICustomEditorModel, ICustomEditorService } from 'vs/workbench/contrib/customEditor/common/customEditor';
import { FileEditorInput } from 'vs/workbench/contrib/files/common/editors/fileEditorInput';
import { WebviewEditorOverlay } from 'vs/workbench/contrib/webview/browser/webview';
import { IWebviewWorkbenchService, LazilyResolvedWebviewEditorInput } from 'vs/workbench/contrib/webview/browser/webviewWorkbenchService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
@@ -117,26 +118,19 @@ export class CustomFileEditorInput extends LazilyResolvedWebviewEditorInput {
return false;
}
// Preserve view state by opening the editor first. In addition
// this allows the user to review the contents of the editor.
// let viewState: IEditorViewState | undefined = undefined;
// const editor = await this.editorService.openEditor(this, undefined, group);
// if (isTextEditor(editor)) {
// viewState = editor.getViewState();
// }
let dialogPath = this._editorResource;
// if (this._editorResource.scheme === Schemas.untitled) {
// dialogPath = this.suggestFileName(resource);
// }
const target = await this.promptForPath(this._editorResource, dialogPath, options?.availableFileSystems);
if (!target) {
return false; // save cancelled
}
await this._model.saveAs(this._editorResource, target, options);
if (!await this._model.saveAs(this._editorResource, target, options)) {
return false;
}
const replacement = this.handleMove(groupId, target) || this.instantiationService.createInstance(FileEditorInput, target, undefined, undefined);
await this.editorService.replaceEditors([{ editor: this, replacement, options: { pinned: true } }], groupId);
return true;
}
@@ -156,15 +150,24 @@ export class CustomFileEditorInput extends LazilyResolvedWebviewEditorInput {
// Help user to find a name for the file by opening it first
await this.editorService.openEditor({ resource, options: { revealIfOpened: true, preserveFocus: true } });
return this.fileDialogService.pickFileToSave({});//this.getSaveDialogOptions(defaultUri, availableFileSystems));
return this.fileDialogService.pickFileToSave({
availableFileSystems,
defaultUri
});
}
public handleMove(groupId: GroupIdentifier, uri: URI, options?: ITextEditorOptions): IEditorInput | undefined {
const webview = assertIsDefined(this.takeOwnershipOfWebview());
return this.instantiationService.createInstance(CustomFileEditorInput,
uri,
this.viewType,
generateUuid(),
new Lazy(() => webview));
const editorInfo = this.customEditorService.getCustomEditor(this.viewType);
if (editorInfo?.matches(uri)) {
const webview = assertIsDefined(this.takeOwnershipOfWebview());
const newInput = this.instantiationService.createInstance(CustomFileEditorInput,
uri,
this.viewType,
generateUuid(),
new Lazy(() => webview));
newInput.updateGroup(groupId);
return newInput;
}
return undefined;
}
}

View File

@@ -4,7 +4,6 @@
*--------------------------------------------------------------------------------------------*/
import { coalesce, distinct, find, mergeSort } from 'vs/base/common/arrays';
import * as glob from 'vs/base/common/glob';
import { Lazy } from 'vs/base/common/lazy';
import { Disposable } from 'vs/base/common/lifecycle';
import { basename, isEqual } from 'vs/base/common/resources';
@@ -32,14 +31,14 @@ import { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/wo
import { CustomFileEditorInput } from './customEditorInput';
const defaultEditorId = 'default';
const defaultEditorInfo: CustomEditorInfo = {
const defaultEditorInfo = new CustomEditorInfo({
id: defaultEditorId,
displayName: nls.localize('promptOpenWith.defaultEditor', "VS Code's standard text editor"),
selector: [
{ filenamePattern: '*' }
],
priority: CustomEditorPriority.default,
};
});
export class CustomEditorInfoStore {
private readonly contributedEditors = new Map<string, CustomEditorInfo>();
@@ -64,7 +63,7 @@ export class CustomEditorInfoStore {
public getContributedEditors(resource: URI): readonly CustomEditorInfo[] {
return Array.from(this.contributedEditors.values()).filter(customEditor =>
customEditor.selector.some(selector => matches(selector, resource)));
customEditor.matches(resource));
}
}
@@ -97,12 +96,12 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ
for (const extension of extensions) {
for (const webviewEditorContribution of extension.value) {
this._editorInfoStore.add({
this._editorInfoStore.add(new CustomEditorInfo({
id: webviewEditorContribution.viewType,
displayName: webviewEditorContribution.displayName,
selector: webviewEditorContribution.selector || [],
priority: webviewEditorContribution.priority || CustomEditorPriority.default,
});
}));
}
}
this.updateContexts();
@@ -127,6 +126,10 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ
return { resource, viewType: activeInput.viewType };
}
public getCustomEditor(viewType: string): CustomEditorInfo | undefined {
return this._editorInfoStore.get(viewType);
}
public getContributedCustomEditors(resource: URI): readonly CustomEditorInfo[] {
return this._editorInfoStore.getContributedEditors(resource);
}
@@ -134,7 +137,7 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ
public getUserConfiguredCustomEditors(resource: URI): readonly CustomEditorInfo[] {
const rawAssociations = this.configurationService.getValue<CustomEditorsAssociations>(customEditorsAssociationsKey) || [];
return coalesce(rawAssociations
.filter(association => matches(association, resource))
.filter(association => CustomEditorInfo.selectorMatches(association, resource))
.map(association => this._editorInfoStore.get(association.viewType)));
}
@@ -332,6 +335,9 @@ export class CustomEditorContribution implements IWorkbenchContribution {
return {
override: (async () => {
const standardEditor = await this.editorService.openEditor(editor, { ...options, ignoreOverrides: true }, group);
// Give a moment to make sure the editor is showing.
// Otherwise the focus shift can cause the prompt to be dismissed right away.
await new Promise(resolve => setTimeout(resolve, 20));
const selectedEditor = await this.customEditorService.promptOpenWith(resource, options, group);
if (selectedEditor && selectedEditor.input) {
await group.replaceEditors([{
@@ -405,16 +411,6 @@ function priorityToRank(priority: CustomEditorPriority): number {
}
}
function matches(selector: CustomEditorSelector, resource: URI): boolean {
if (selector.filenamePattern) {
if (glob.match(selector.filenamePattern.toLowerCase(), basename(resource).toLowerCase())) {
return true;
}
}
return false;
}
registerThemingParticipant((theme, collector) => {
const shadow = theme.getColor(colorRegistry.scrollbarShadow);
if (shadow) {

View File

@@ -4,11 +4,13 @@
*--------------------------------------------------------------------------------------------*/
import { Event } from 'vs/base/common/event';
import * as glob from 'vs/base/common/glob';
import { basename } from 'vs/base/common/resources';
import { URI } from 'vs/base/common/uri';
import { RawContextKey } from 'vs/platform/contextkey/common/contextkey';
import { ITextEditorOptions } from 'vs/platform/editor/common/editor';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { EditorInput, IEditor, ISaveOptions, IRevertOptions } from 'vs/workbench/common/editor';
import { EditorInput, IEditor, IRevertOptions, ISaveOptions } from 'vs/workbench/common/editor';
import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IWorkingCopy } from 'vs/workbench/services/workingCopy/common/workingCopyService';
@@ -29,6 +31,7 @@ export interface ICustomEditorService {
readonly activeCustomEditor: ICustomEditor | undefined;
getCustomEditor(viewType: string): CustomEditorInfo | undefined;
getContributedCustomEditors(resource: URI): readonly CustomEditorInfo[];
getUserConfiguredCustomEditors(resource: URI): readonly CustomEditorInfo[];
@@ -87,9 +90,35 @@ export interface CustomEditorSelector {
readonly filenamePattern?: string;
}
export interface CustomEditorInfo {
readonly id: string;
readonly displayName: string;
readonly priority: CustomEditorPriority;
readonly selector: readonly CustomEditorSelector[];
export class CustomEditorInfo {
public readonly id: string;
public readonly displayName: string;
public readonly priority: CustomEditorPriority;
public readonly selector: readonly CustomEditorSelector[];
constructor(descriptor: {
readonly id: string;
readonly displayName: string;
readonly priority: CustomEditorPriority;
readonly selector: readonly CustomEditorSelector[];
}) {
this.id = descriptor.id;
this.displayName = descriptor.displayName;
this.priority = descriptor.priority;
this.selector = descriptor.selector;
}
matches(resource: URI): boolean {
return this.selector.some(selector => CustomEditorInfo.selectorMatches(selector, resource));
}
static selectorMatches(selector: CustomEditorSelector, resource: URI): boolean {
if (selector.filenamePattern) {
if (glob.match(selector.filenamePattern.toLowerCase(), basename(resource).toLowerCase())) {
return true;
}
}
return false;
}
}

View File

@@ -500,7 +500,7 @@ class DataBreakpointsRenderer implements IListRenderer<DataBreakpoint, IBaseBrea
renderElement(dataBreakpoint: DataBreakpoint, index: number, data: IBaseBreakpointWithIconTemplateData): void {
data.context = dataBreakpoint;
data.name.textContent = dataBreakpoint.label;
data.name.textContent = dataBreakpoint.description;
const { className, message } = getBreakpointMessageAndClassName(this.debugService, dataBreakpoint);
data.icon.className = `codicon ${className}`;
data.icon.title = message ? message : '';
@@ -713,25 +713,6 @@ export function getBreakpointMessageAndClassName(debugService: IDebugService, br
};
}
const focusedThread = debugService.getViewModel().focusedThread;
if (focusedThread) {
const callStack = focusedThread ? focusedThread.getCallStack() : undefined;
const topStackFrame = callStack ? callStack[0] : undefined;
if (topStackFrame && topStackFrame.source.uri.toString() === breakpoint.uri.toString() && topStackFrame.range.startLineNumber === breakpoint.lineNumber) {
if (topStackFrame.range.startColumn === breakpoint.column) {
return {
className: 'codicon-debug-breakpoint-stackframe-dot',
message: breakpoint.message || nls.localize('breakpoint', "Breakpoint")
};
} else if (breakpoint.column === undefined) {
return {
className: 'codicon-debug-breakpoint',
message: breakpoint.message || nls.localize('breakpoint', "Breakpoint")
};
}
}
}
return {
className: 'codicon-debug-breakpoint',
message: breakpoint.message || nls.localize('breakpoint', "Breakpoint")

View File

@@ -505,7 +505,7 @@ class StackFramesRenderer implements ITreeRenderer<IStackFrame, FuzzyScore, ISta
dom.toggleClass(data.stackFrame, 'disabled', !stackFrame.source || !stackFrame.source.available || isDeemphasized(stackFrame));
dom.toggleClass(data.stackFrame, 'label', stackFrame.presentationHint === 'label');
dom.toggleClass(data.stackFrame, 'subtle', stackFrame.presentationHint === 'subtle');
const hasActions = stackFrame.thread.session.capabilities.supportsRestartFrame;
const hasActions = stackFrame.thread.session.capabilities.supportsRestartFrame && stackFrame.presentationHint !== 'label' && stackFrame.presentationHint !== 'subtle';
dom.toggleClass(data.stackFrame, 'has-actions', hasActions);
data.file.title = stackFrame.source.inMemory ? stackFrame.source.uri.path : this.labelService.getUriLabel(stackFrame.source.uri);

View File

@@ -84,7 +84,7 @@ class OpenDebugPanelAction extends TogglePanelAction {
Registry.as<ViewletRegistry>(ViewletExtensions.Viewlets).registerViewlet(ViewletDescriptor.create(
DebugViewlet,
VIEWLET_ID,
nls.localize('debugAndRun', "Debug And Run"),
nls.localize('debugAndRun', "Debug and Run"),
'codicon-debug',
13 // {{SQL CARBON EDIT}}
));

View File

@@ -186,9 +186,9 @@ registerThemingParticipant((theme, collector) => {
.monaco-workbench .codicon-debug-breakpoint-function,
.monaco-workbench .codicon-debug-breakpoint-data,
.monaco-workbench .codicon-debug-breakpoint-unsupported,
.monaco-workbench .codicon-debug-hint:not(*[class*='codicon-debug-breakpoint']) ,
.monaco-workbench .codicon-debug-breakpoint-stackframe-dot,
.monaco-workbench .codicon-debug-breakpoint.codicon-debug-breakpoint-stackframe-focused::after {
.monaco-workbench .codicon-debug-hint:not([class*='codicon-debug-breakpoint']),
.monaco-workbench .codicon-debug-breakpoint.codicon-debug-breakpoint-stackframe-focused::after,
.monaco-workbench .codicon-debug-breakpoint.codicon-debug-breakpoint-stackframe::after {
color: ${debugIconBreakpointColor} !important;
}
`);
@@ -212,17 +212,16 @@ registerThemingParticipant((theme, collector) => {
`);
}
const debugIconBreakpointStackframeColor = theme.getColor(debugIconBreakpointStackframeForeground);
if (debugIconBreakpointStackframeColor) {
const debugIconBreakpointCurrentStackframeForegroundColor = theme.getColor(debugIconBreakpointCurrentStackframeForeground);
if (debugIconBreakpointCurrentStackframeForegroundColor) {
collector.addRule(`
.monaco-workbench .codicon-debug-breakpoint-stackframe,
.monaco-workbench .codicon-debug-breakpoint-stackframe-dot::after {
color: ${debugIconBreakpointStackframeColor} !important;
.monaco-workbench .codicon-debug-breakpoint-stackframe {
color: ${debugIconBreakpointCurrentStackframeForegroundColor} !important;
}
`);
}
const debugIconBreakpointStackframeFocusedColor = theme.getColor(debugIconBreakpointStackframeFocusedForeground);
const debugIconBreakpointStackframeFocusedColor = theme.getColor(debugIconBreakpointStackframeForeground);
if (debugIconBreakpointStackframeFocusedColor) {
collector.addRule(`
.monaco-workbench .codicon-debug-breakpoint-stackframe-focused {
@@ -239,5 +238,5 @@ const focusedStackFrameColor = registerColor('editor.focusedStackFrameHighlightB
const debugIconBreakpointForeground = registerColor('debugIcon.breakpointForeground', { dark: '#E51400', light: '#E51400', hc: '#E51400' }, localize('debugIcon.breakpointForeground', 'Icon color for breakpoints.'));
const debugIconBreakpointDisabledForeground = registerColor('debugIcon.breakpointDisabledForeground', { dark: '#848484', light: '#848484', hc: '#848484' }, localize('debugIcon.breakpointDisabledForeground', 'Icon color for disabled breakpoints.'));
const debugIconBreakpointUnverifiedForeground = registerColor('debugIcon.breakpointUnverifiedForeground', { dark: '#848484', light: '#848484', hc: '#848484' }, localize('debugIcon.breakpointUnverifiedForeground', 'Icon color for unverified breakpoints.'));
const debugIconBreakpointStackframeForeground = registerColor('debugIcon.breakpointStackframeForeground', { dark: '#FFCC00', light: '#FFCC00', hc: '#FFCC00' }, localize('debugIcon.breakpointStackframeForeground', 'Icon color for breakpoints.'));
const debugIconBreakpointStackframeFocusedForeground = registerColor('debugIcon.breakpointStackframeFocusedForeground', { dark: '#89D185', light: '#89D185', hc: '#89D185' }, localize('debugIcon.breakpointStackframeFocusedForeground', 'Icon color for breakpoints.'));
const debugIconBreakpointCurrentStackframeForeground = registerColor('debugIcon.breakpointCurrentStackframeForeground', { dark: '#FFCC00', light: '#FFCC00', hc: '#FFCC00' }, localize('debugIcon.breakpointCurrentStackframeForeground', 'Icon color for the current breakpoint stack frame.'));
const debugIconBreakpointStackframeForeground = registerColor('debugIcon.breakpointStackframeForeground', { dark: '#89D185', light: '#89D185', hc: '#89D185' }, localize('debugIcon.breakpointStackframeForeground', 'Icon color for all breakpoint stack frames.'));

View File

@@ -18,7 +18,7 @@ import { IStorageService, StorageScope } from 'vs/platform/storage/common/storag
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IFileService } from 'vs/platform/files/common/files';
import { IWorkspaceContextService, IWorkspaceFolder, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IWorkspaceContextService, IWorkspaceFolder, WorkbenchState, IWorkspaceFoldersChangeEvent } from 'vs/platform/workspace/common/workspace';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IDebugConfigurationProvider, ICompound, IDebugConfiguration, IConfig, IGlobalConfig, IConfigurationManager, ILaunch, IDebugAdapterDescriptorFactory, IDebugAdapter, IDebugSession, IAdapterDescriptor, CONTEXT_DEBUG_CONFIGURATION_TYPE, IDebugAdapterFactory } from 'vs/workbench/contrib/debug/common/debug';
@@ -80,7 +80,7 @@ export class ConfigurationManager implements IConfigurationManager {
const previousSelectedRoot = this.storageService.get(DEBUG_SELECTED_ROOT, StorageScope.WORKSPACE);
const previousSelectedLaunch = this.launches.filter(l => l.uri.toString() === previousSelectedRoot).pop();
this.debugConfigurationTypeContext = CONTEXT_DEBUG_CONFIGURATION_TYPE.bindTo(contextKeyService);
if (previousSelectedLaunch) {
if (previousSelectedLaunch && previousSelectedLaunch.getConfigurationNames().length) {
this.selectConfiguration(previousSelectedLaunch, this.storageService.get(DEBUG_SELECTED_CONFIG_NAME_KEY, StorageScope.WORKSPACE));
} else if (this.launches.length > 0) {
const rootUri = historyService.getLastActiveWorkspaceRoot();
@@ -284,7 +284,7 @@ export class ConfigurationManager implements IConfigurationManager {
});
});
this.toDispose.push(this.contextService.onDidChangeWorkspaceFolders(() => {
this.toDispose.push(Event.any<IWorkspaceFoldersChangeEvent | WorkbenchState>(this.contextService.onDidChangeWorkspaceFolders, this.contextService.onDidChangeWorkbenchState)(() => {
this.initLaunches();
const toSelect = this.selectedLaunch || (this.launches.length > 0 ? this.launches[0] : undefined);
this.selectConfiguration(toSelect);
@@ -496,10 +496,13 @@ abstract class AbstractLaunch {
getConfigurationNames(includeCompounds = true): string[] {
const config = this.getConfig();
if (!config || !config.configurations || !Array.isArray(config.configurations)) {
if (!config || (!Array.isArray(config.configurations) && !Array.isArray(config.compounds))) {
return [];
} else {
const names = config.configurations.filter(cfg => cfg && typeof cfg.name === 'string').map(cfg => cfg.name);
const names: string[] = [];
if (config.configurations) {
names.push(...config.configurations.filter(cfg => cfg && typeof cfg.name === 'string').map(cfg => cfg.name));
}
if (includeCompounds && config.compounds) {
if (config.compounds) {
names.push(...config.compounds.filter(compound => typeof compound.name === 'string' && compound.configurations && compound.configurations.length)

View File

@@ -41,7 +41,7 @@ import { deepClone, equals } from 'vs/base/common/objects';
import { DebugSession } from 'vs/workbench/contrib/debug/browser/debugSession';
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
import { IDebugService, State, IDebugSession, CONTEXT_DEBUG_TYPE, CONTEXT_DEBUG_STATE, CONTEXT_IN_DEBUG_MODE, IThread, IDebugConfiguration, VIEWLET_ID, REPL_ID, IConfig, ILaunch, IViewModel, IConfigurationManager, IDebugModel, IEnablement, IBreakpoint, IBreakpointData, ICompound, IGlobalConfig, IStackFrame, AdapterEndEvent, getStateLabel, IDebugSessionOptions, CONTEXT_DEBUG_UX } from 'vs/workbench/contrib/debug/common/debug';
import { isExtensionHostDebugging } from 'vs/workbench/contrib/debug/common/debugUtils';
import { getExtensionHostDebugSession } from 'vs/workbench/contrib/debug/common/debugUtils';
import { isErrorWithActions, createErrorWithActions } from 'vs/base/common/errorsWithActions';
import { RunOnceScheduler } from 'vs/base/common/async';
import { IExtensionHostDebugService } from 'vs/platform/debug/common/extensionHostDebug';
@@ -232,7 +232,8 @@ export class DebugService implements IDebugService {
if (this.previousState !== state) {
this.debugState.set(getStateLabel(state));
this.inDebugMode.set(state !== State.Inactive);
this.debugUx.set(!!(state !== State.Inactive || this.configurationManager.selectedConfiguration.name) ? 'default' : 'simple');
// Only show the simple ux if debug is not yet started and if no launch.json exists
this.debugUx.set(((state !== State.Inactive && state !== State.Initializing) || this.configurationManager.selectedConfiguration.name) ? 'default' : 'simple');
this.previousState = state;
this._onDidChangeState.fire(state);
}
@@ -538,8 +539,9 @@ export class DebugService implements IDebugService {
}
// 'Run without debugging' mode VSCode must terminate the extension host. More details: #3905
if (isExtensionHostDebugging(session.configuration) && session.state === State.Running && session.configuration.noDebug) {
this.extensionHostDebugService.close(session.getId());
const extensionDebugSession = getExtensionHostDebugSession(session);
if (extensionDebugSession && extensionDebugSession.state === State.Running && extensionDebugSession.configuration.noDebug) {
this.extensionHostDebugService.close(extensionDebugSession.getId());
}
this.telemetryDebugSessionStop(session, adapterExitEvent);
@@ -589,10 +591,11 @@ export class DebugService implements IDebugService {
return this.runTaskAndCheckErrors(session.root, session.configuration.preLaunchTask);
};
if (isExtensionHostDebugging(session.configuration)) {
const extensionDebugSession = getExtensionHostDebugSession(session);
if (extensionDebugSession) {
const taskResult = await runTasks();
if (taskResult === TaskRunResult.Success) {
this.extensionHostDebugService.reload(session.getId());
this.extensionHostDebugService.reload(extensionDebugSession.getId());
}
return;
@@ -984,8 +987,8 @@ export class DebugService implements IDebugService {
this.storeBreakpoints();
}
async addDataBreakpoint(label: string, dataId: string, canPersist: boolean): Promise<void> {
this.model.addDataBreakpoint(label, dataId, canPersist);
async addDataBreakpoint(label: string, dataId: string, canPersist: boolean, accessTypes: DebugProtocol.DataBreakpointAccessType[] | undefined): Promise<void> {
this.model.addDataBreakpoint(label, dataId, canPersist, accessTypes);
await this.sendDataBreakpoints();
this.storeBreakpoints();
@@ -1097,7 +1100,7 @@ export class DebugService implements IDebugService {
let result: DataBreakpoint[] | undefined;
try {
result = JSON.parse(this.storageService.get(DEBUG_DATA_BREAKPOINTS_KEY, StorageScope.WORKSPACE, '[]')).map((dbp: any) => {
return new DataBreakpoint(dbp.label, dbp.dataId, true, dbp.enabled, dbp.hitCondition, dbp.condition, dbp.logMessage);
return new DataBreakpoint(dbp.description, dbp.dataId, true, dbp.enabled, dbp.hitCondition, dbp.condition, dbp.logMessage, dbp.accessTypes);
});
} catch (e) { }

View File

@@ -15,7 +15,7 @@ import { StartDebugActionViewItem, FocusSessionActionViewItem } from 'vs/workben
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { IProgressService } from 'vs/platform/progress/common/progress';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { IThemeService } from 'vs/platform/theme/common/themeService';
@@ -119,22 +119,27 @@ export class DebugViewlet extends ViewContainerViewlet {
if (CONTEXT_DEBUG_UX.getValue(this.contextKeyService) === 'simple') {
return [];
}
if (this.showInitialDebugActions) {
return [this.startAction, this.configureAction, this.toggleReplAction];
if (!this.showInitialDebugActions) {
if (!this.debugToolBarMenu) {
this.debugToolBarMenu = this.menuService.createMenu(MenuId.DebugToolBar, this.contextKeyService);
this._register(this.debugToolBarMenu);
}
const { actions, disposable } = DebugToolBar.getActions(this.debugToolBarMenu, this.debugService, this.instantiationService);
if (this.disposeOnTitleUpdate) {
dispose(this.disposeOnTitleUpdate);
}
this.disposeOnTitleUpdate = disposable;
return actions;
}
if (!this.debugToolBarMenu) {
this.debugToolBarMenu = this.menuService.createMenu(MenuId.DebugToolBar, this.contextKeyService);
this._register(this.debugToolBarMenu);
if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) {
return [this.toggleReplAction];
}
const { actions, disposable } = DebugToolBar.getActions(this.debugToolBarMenu, this.debugService, this.instantiationService);
if (this.disposeOnTitleUpdate) {
dispose(this.disposeOnTitleUpdate);
}
this.disposeOnTitleUpdate = disposable;
return actions;
return [this.startAction, this.configureAction, this.toggleReplAction];
}
get showInitialDebugActions(): boolean {

View File

@@ -7,7 +7,7 @@
cursor: pointer;
}
.codicon-debug-hint:not(*[class*='codicon-debug-breakpoint']) {
.codicon-debug-hint:not([class*='codicon-debug-breakpoint']) {
opacity: .4 !important;
}
@@ -16,26 +16,10 @@
align-items: center;
}
/* overlapped icons */
.inline-breakpoint-widget.codicon-debug-breakpoint-stackframe-dot::after {
position: absolute;
top: 0;
left: 0;
bottom: 0;
margin: auto;
display: table;
}
.codicon-debug-breakpoint.codicon-debug-breakpoint-stackframe-focused::after {
position: absolute;
}
.inline-breakpoint-widget.codicon-debug-breakpoint-stackframe-dot::after {
content: "\eb8b";
}
.codicon-debug-breakpoint.codicon-debug-breakpoint-stackframe-focused::after {
.codicon-debug-breakpoint.codicon-debug-breakpoint-stackframe-focused::after,
.codicon-debug-breakpoint.codicon-debug-breakpoint-stackframe::after {
content: "\eb8a";
position: absolute;
}
.monaco-editor .inline-breakpoint-widget.line-start {

View File

@@ -5,7 +5,7 @@
.monaco-workbench .debug-toolbar {
position: absolute;
z-index: 200;
z-index: 1000;
height: 32px;
display: flex;
padding-left: 7px;

View File

@@ -374,10 +374,6 @@
justify-content: center;
}
.debug-viewlet .debug-breakpoints .breakpoint > .codicon-debug-breakpoint-stackframe-dot::before {
content: "\ea71";
}
.debug-viewlet .debug-breakpoints .breakpoint > .file-path {
opacity: 0.7;
font-size: 0.9em;

View File

@@ -30,6 +30,9 @@
cursor: pointer;
}
.monaco-workbench.mac .repl .repl-tree .monaco-tl-twistie {
padding-right: 0px;
}
.repl .repl-tree .output.expression.value-and-source {
display: flex;
@@ -42,11 +45,11 @@
.repl .repl-tree .monaco-tl-contents .arrow {
position:absolute;
left: 2px;
opacity: 0.3;
opacity: 0.25;
}
.vs-dark .repl .repl-tree .monaco-tl-contents .arrow {
opacity: 0.45;
opacity: 0.4;
}
.repl .repl-tree .output.expression.value-and-source .source {

View File

@@ -610,7 +610,7 @@ class ReplEvaluationInputsRenderer implements ITreeRenderer<ReplEvaluationInput,
}
renderTemplate(container: HTMLElement): IReplEvaluationInputTemplateData {
dom.append(container, $('span.arrow.codicon.codicon-arrow-small-right'));
dom.append(container, $('span.arrow.codicon.codicon-chevron-right'));
const input = dom.append(container, $('.expression'));
const label = new HighlightedLabel(input, false);
return { label };
@@ -636,7 +636,7 @@ class ReplEvaluationResultsRenderer implements ITreeRenderer<ReplEvaluationResul
constructor(private readonly linkDetector: LinkDetector) { }
renderTemplate(container: HTMLElement): IReplEvaluationResultTemplateData {
dom.append(container, $('span.arrow.codicon.codicon-arrow-small-left'));
dom.append(container, $('span.arrow.codicon.codicon-chevron-left'));
const output = dom.append(container, $('.evaluation-result.expression'));
const value = dom.append(output, $('span.value'));
const annotation = dom.append(output, $('span'));

View File

@@ -21,6 +21,8 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs';
import { equals } from 'vs/base/common/arrays';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { KeyCode } from 'vs/base/common/keyCodes';
const $ = dom.$;
export class StartView extends ViewletPane {
@@ -72,16 +74,12 @@ export class StartView extends ViewletPane {
const setSecondMessage = () => {
secondMessageElement.textContent = localize('specifyHowToRun', "To futher configure Debug and Run");
const clickElement = $('span.click');
clickElement.textContent = localize('configure', " create a launch.json file.");
clickElement.onclick = () => this.commandService.executeCommand(ConfigureAction.ID);
const clickElement = this.createClickElement(localize('configure', " create a launch.json file."), () => this.commandService.executeCommand(ConfigureAction.ID));
this.secondMessageContainer.appendChild(clickElement);
};
const setSecondMessageWithFolder = () => {
secondMessageElement.textContent = localize('noLaunchConfiguration', "To futher configure Debug and Run, ");
const clickElement = $('span.click');
clickElement.textContent = localize('openFolder', " open a folder");
clickElement.onclick = () => this.dialogService.pickFolderAndOpen({ forceNewWindow: false });
const clickElement = this.createClickElement(localize('openFolder', " open a folder"), () => this.dialogService.pickFolderAndOpen({ forceNewWindow: false }));
this.secondMessageContainer.appendChild(clickElement);
const moreText = $('span.moreText');
@@ -106,10 +104,7 @@ export class StartView extends ViewletPane {
}
if (!enabled && emptyWorkbench) {
const clickElement = $('span.click');
clickElement.textContent = localize('openFile', "Open a file");
clickElement.onclick = () => this.dialogService.pickFileAndOpen({ forceNewWindow: false });
const clickElement = this.createClickElement(localize('openFile', "Open a file"), () => this.dialogService.pickFileAndOpen({ forceNewWindow: false }));
this.firstMessageContainer.appendChild(clickElement);
const firstMessageElement = $('span');
this.firstMessageContainer.appendChild(firstMessageElement);
@@ -121,6 +116,21 @@ export class StartView extends ViewletPane {
}
}
private createClickElement(textContent: string, action: () => any): HTMLSpanElement {
const clickElement = $('span.click');
clickElement.textContent = textContent;
clickElement.onclick = action;
clickElement.tabIndex = 0;
clickElement.onkeyup = (e) => {
const keyboardEvent = new StandardKeyboardEvent(e);
if (keyboardEvent.keyCode === KeyCode.Enter || (keyboardEvent.keyCode === KeyCode.Space)) {
action();
}
};
return clickElement;
}
protected renderBody(container: HTMLElement): void {
this.firstMessageContainer = $('.top-section');
container.appendChild(this.firstMessageContainer);

View File

@@ -185,7 +185,7 @@ export class VariablesView extends ViewletPane {
if (dataid) {
actions.push(new Separator());
actions.push(new Action('debug.breakWhenValueChanges', nls.localize('breakWhenValueChanges', "Break When Value Changes"), undefined, true, () => {
return this.debugService.addDataBreakpoint(response.description, dataid, !!response.canPersist);
return this.debugService.addDataBreakpoint(response.description, dataid, !!response.canPersist, response.accessTypes);
}));
}
}

View File

@@ -215,7 +215,7 @@ export interface IDebugSession extends ITreeElement {
sendBreakpoints(modelUri: uri, bpts: IBreakpoint[], sourceModified: boolean): Promise<void>;
sendFunctionBreakpoints(fbps: IFunctionBreakpoint[]): Promise<void>;
dataBreakpointInfo(name: string, variablesReference?: number): Promise<{ dataId: string | null, description: string, canPersist?: boolean }>;
dataBreakpointInfo(name: string, variablesReference?: number): Promise<{ dataId: string | null, description: string, canPersist?: boolean, accessTypes?: DebugProtocol.DataBreakpointAccessType[] }>;
sendDataBreakpoints(dbps: IDataBreakpoint[]): Promise<void>;
sendExceptionBreakpoints(exbpts: IExceptionBreakpoint[]): Promise<void>;
breakpointsLocations(uri: uri, lineNumber: number): Promise<IPosition[]>;
@@ -377,7 +377,7 @@ export interface IExceptionBreakpoint extends IEnablement {
}
export interface IDataBreakpoint extends IBaseBreakpoint {
readonly label: string;
readonly description: string;
readonly dataId: string;
readonly canPersist: boolean;
}
@@ -795,7 +795,7 @@ export interface IDebugService {
/**
* Adds a new data breakpoint.
*/
addDataBreakpoint(label: string, dataId: string, canPersist: boolean): Promise<void>;
addDataBreakpoint(label: string, dataId: string, canPersist: boolean, accessTypes: DebugProtocol.DataBreakpointAccessType[] | undefined): Promise<void>;
/**
* Removes all data breakpoints. If id is passed only removes the data breakpoint with the passed id.

View File

@@ -748,13 +748,14 @@ export class FunctionBreakpoint extends BaseBreakpoint implements IFunctionBreak
export class DataBreakpoint extends BaseBreakpoint implements IDataBreakpoint {
constructor(
public label: string,
public description: string,
public dataId: string,
public canPersist: boolean,
enabled: boolean,
hitCondition: string | undefined,
condition: string | undefined,
logMessage: string | undefined,
private accessTypes: DebugProtocol.DataBreakpointAccessType[] | undefined,
id = generateUuid()
) {
super(enabled, hitCondition, condition, logMessage, id);
@@ -762,8 +763,9 @@ export class DataBreakpoint extends BaseBreakpoint implements IDataBreakpoint {
toJSON(): any {
const result = super.toJSON();
result.label = this.label;
result.dataid = this.dataId;
result.description = this.description;
result.dataId = this.dataId;
result.accessTypes = this.accessTypes;
return result;
}
@@ -777,7 +779,7 @@ export class DataBreakpoint extends BaseBreakpoint implements IDataBreakpoint {
}
toString(): string {
return this.label;
return this.description;
}
}
@@ -1159,8 +1161,8 @@ export class DebugModel implements IDebugModel {
this._onDidChangeBreakpoints.fire({ removed });
}
addDataBreakpoint(label: string, dataId: string, canPersist: boolean): void {
const newDataBreakpoint = new DataBreakpoint(label, dataId, canPersist, true, undefined, undefined, undefined);
addDataBreakpoint(label: string, dataId: string, canPersist: boolean, accessTypes: DebugProtocol.DataBreakpointAccessType[] | undefined): void {
const newDataBreakpoint = new DataBreakpoint(label, dataId, canPersist, true, undefined, undefined, undefined, accessTypes);
this.dataBreakopints.push(newDataBreakpoint);
this._onDidChangeBreakpoints.fire({ added: [newDataBreakpoint] });
}

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { equalsIgnoreCase } from 'vs/base/common/strings';
import { IConfig, IDebuggerContribution, IDebugSession } from 'vs/workbench/contrib/debug/common/debug';
import { IDebuggerContribution, IDebugSession } from 'vs/workbench/contrib/debug/common/debug';
import { URI as uri } from 'vs/base/common/uri';
import { isAbsolute } from 'vs/base/common/path';
import { deepClone } from 'vs/base/common/objects';
@@ -24,19 +24,28 @@ export function formatPII(value: string, excludePII: boolean, args: { [key: stri
}
export function isSessionAttach(session: IDebugSession): boolean {
return !session.parentSession && session.configuration.request === 'attach' && !isExtensionHostDebugging(session.configuration);
return !session.parentSession && session.configuration.request === 'attach' && !getExtensionHostDebugSession(session);
}
export function isExtensionHostDebugging(config: IConfig) {
if (!config.type) {
return false;
/**
* Returns the session or any parent which is an extension host debug session.
* Returns undefined if there's none.
*/
export function getExtensionHostDebugSession(session: IDebugSession): IDebugSession | void {
let type = session.configuration.type;
if (!type) {
return;
}
const type = config.type === 'vslsShare'
? (<any>config).adapterProxy.configuration.type
: config.type;
if (type === 'vslsShare') {
type = (<any>session.configuration).adapterProxy.configuration.type;
}
return equalsIgnoreCase(type, 'extensionhost') || equalsIgnoreCase(type, 'pwa-extensionhost');
if (equalsIgnoreCase(type, 'extensionhost') || equalsIgnoreCase(type, 'pwa-extensionhost')) {
return session;
}
return session.parentSession ? getExtensionHostDebugSession(session.parentSession) : undefined;
}
// only a debugger contributions with a label, program, or runtime attribute is considered a "defining" or "main" debugger contribution

View File

@@ -22,6 +22,10 @@
font-weight: bold;
}
.runtime-extensions-editor .extension .desc .msg .codicon {
vertical-align: middle;
}
.runtime-extensions-editor .extension .time {
padding: 4px;
text-align: right;

View File

@@ -24,6 +24,7 @@ import { distinct } from 'vs/base/common/arrays';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
import { optional } from 'vs/platform/instantiation/common/instantiation';
import { IExplorerService } from 'vs/workbench/contrib/files/common/files';
const OPEN_IN_TERMINAL_COMMAND_ID = 'openInTerminal';
@@ -37,7 +38,7 @@ CommandsRegistry.registerCommand({
const integratedTerminalService = accessor.get(IIntegratedTerminalService);
const remoteAgentService = accessor.get(IRemoteAgentService);
const resources = getMultiSelectedResources(resource, accessor.get(IListService), editorService);
const resources = getMultiSelectedResources(resource, accessor.get(IListService), editorService, accessor.get(IExplorerService));
return fileService.resolveAll(resources.map(r => ({ resource: r }))).then(async stats => {
const targets = distinct(stats.filter(data => data.success));
// Always use integrated terminal when using a remote
@@ -162,4 +163,3 @@ MenuRegistry.appendMenuItem(MenuId.ExplorerContext, {
command: openConsoleCommand,
when: ResourceContextKey.Scheme.isEqualTo(Schemas.vscodeRemote)
});

View File

@@ -1001,7 +1001,12 @@ const downloadFileHandler = (accessor: ServicesAccessor) => {
const explorerService = accessor.get(IExplorerService);
const stats = explorerService.getContext(true);
let canceled = false;
stats.forEach(async s => {
if (canceled) {
return;
}
if (isWeb) {
if (!s.isDirectory) {
triggerDownload(asDomUri(s.resource), s.name);
@@ -1020,6 +1025,9 @@ const downloadFileHandler = (accessor: ServicesAccessor) => {
});
if (destination) {
await textFileService.copy(s.resource, destination);
} else {
// User canceled a download. In case there were multiple files selected we should cancel the remainder of the prompts #86100
canceled = true;
}
}
});

View File

@@ -119,7 +119,8 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
const editorService = accessor.get(IEditorService);
const listService = accessor.get(IListService);
const fileService = accessor.get(IFileService);
const resources = getMultiSelectedResources(resource, listService, editorService);
const explorerService = accessor.get(IExplorerService);
const resources = getMultiSelectedResources(resource, listService, editorService, explorerService);
// Set side input
if (resources.length) {
@@ -201,7 +202,8 @@ CommandsRegistry.registerCommand({
id: COMPARE_SELECTED_COMMAND_ID,
handler: (accessor, resource: URI | object) => {
const editorService = accessor.get(IEditorService);
const resources = getMultiSelectedResources(resource, accessor.get(IListService), editorService);
const explorerService = accessor.get(IExplorerService);
const resources = getMultiSelectedResources(resource, accessor.get(IListService), editorService, explorerService);
if (resources.length === 2) {
return editorService.openEditor({
@@ -251,7 +253,7 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
},
id: COPY_PATH_COMMAND_ID,
handler: async (accessor, resource: URI | object) => {
const resources = getMultiSelectedResources(resource, accessor.get(IListService), accessor.get(IEditorService));
const resources = getMultiSelectedResources(resource, accessor.get(IListService), accessor.get(IEditorService), accessor.get(IExplorerService));
await resourcesToClipboard(resources, false, accessor.get(IClipboardService), accessor.get(INotificationService), accessor.get(ILabelService));
}
});
@@ -265,7 +267,7 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
},
id: COPY_RELATIVE_PATH_COMMAND_ID,
handler: async (accessor, resource: URI | object) => {
const resources = getMultiSelectedResources(resource, accessor.get(IListService), accessor.get(IEditorService));
const resources = getMultiSelectedResources(resource, accessor.get(IListService), accessor.get(IEditorService), accessor.get(IExplorerService));
await resourcesToClipboard(resources, true, accessor.get(IClipboardService), accessor.get(INotificationService), accessor.get(ILabelService));
}
});
@@ -488,7 +490,7 @@ CommandsRegistry.registerCommand({
const workspaceEditingService = accessor.get(IWorkspaceEditingService);
const contextService = accessor.get(IWorkspaceContextService);
const workspace = contextService.getWorkspace();
const resources = getMultiSelectedResources(resource, accessor.get(IListService), accessor.get(IEditorService)).filter(r =>
const resources = getMultiSelectedResources(resource, accessor.get(IListService), accessor.get(IEditorService), accessor.get(IExplorerService)).filter(r =>
// Need to verify resources are workspaces since multi selection can trigger this command on some non workspace resources
workspace.folders.some(f => isEqual(f.uri, r))
);

View File

@@ -5,7 +5,7 @@
import { URI } from 'vs/base/common/uri';
import { IListService } from 'vs/platform/list/browser/listService';
import { OpenEditor } from 'vs/workbench/contrib/files/common/files';
import { OpenEditor, IExplorerService } from 'vs/workbench/contrib/files/common/files';
import { toResource, SideBySideEditor, IEditorIdentifier } from 'vs/workbench/common/editor';
import { List } from 'vs/base/browser/ui/list/listWidget';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
@@ -53,19 +53,15 @@ export function getResourceForCommand(resource: URI | object | undefined, listSe
return editorService.activeEditor ? toResource(editorService.activeEditor, { supportSideBySide: SideBySideEditor.MASTER }) : undefined;
}
export function getMultiSelectedResources(resource: URI | object | undefined, listService: IListService, editorService: IEditorService): Array<URI> {
export function getMultiSelectedResources(resource: URI | object | undefined, listService: IListService, editorService: IEditorService, explorerService: IExplorerService): Array<URI> {
const list = listService.lastFocusedList;
if (list?.getHTMLElement() === document.activeElement) {
// Explorer
if (list instanceof AsyncDataTree) {
const selection = list.getSelection().map((fs: ExplorerItem) => fs.resource);
const focusedElements = list.getFocus();
const focus = focusedElements.length ? focusedElements[0] : undefined;
const mainUriStr = URI.isUri(resource) ? resource.toString() : focus instanceof ExplorerItem ? focus.resource.toString() : undefined;
// If the resource is passed it has to be a part of the returned context.
// We only respect the selection if it contains the focused element.
if (selection.some(s => URI.isUri(s) && s.toString() === mainUriStr)) {
return selection;
// Explorer
const context = explorerService.getContext(true);
if (context.length) {
return context.map(c => c.resource);
}
}

View File

@@ -297,6 +297,13 @@ export class ExplorerView extends ViewletPane {
for (const stat of this.tree.getSelection()) {
const controller = this.renderer.getCompressedNavigationController(stat);
if (controller && focusedStat && controller === this.compressedNavigationController) {
if (stat === focusedStat) {
selectedStats.push(stat);
}
// Ignore stats which are selected but are part of the same compact node as the focused stat
continue;
}
if (controller) {
selectedStats.push(...controller.items);

View File

@@ -197,7 +197,9 @@ export class ExplorerItem {
// Properties
local.resource = disk.resource;
local.updateName(disk.name);
if (!local.isRoot) {
local.updateName(disk.name);
}
local._isDirectory = disk.isDirectory;
local._mtime = disk.mtime;
local._isDirectoryResolved = disk._isDirectoryResolved;

View File

@@ -24,6 +24,7 @@ import { appendToCommandPalette, appendEditorTitleContextMenuItem } from 'vs/wor
import { Registry } from 'vs/platform/registry/common/platform';
import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions';
import { ShowOpenedFileInNewWindow } from 'vs/workbench/contrib/files/browser/fileActions';
import { IExplorerService } from 'vs/workbench/contrib/files/common/files';
const REVEAL_IN_OS_COMMAND_ID = 'revealFileInOS';
const REVEAL_IN_OS_LABEL = isWindows ? nls.localize('revealInWindows', "Reveal in Explorer") : isMacintosh ? nls.localize('revealInMac', "Reveal in Finder") : nls.localize('openContainer', "Open Containing Folder");
@@ -37,7 +38,7 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
primary: KeyMod.Shift | KeyMod.Alt | KeyCode.KEY_R
},
handler: (accessor: ServicesAccessor, resource: URI | object) => {
const resources = getMultiSelectedResources(resource, accessor.get(IListService), accessor.get(IEditorService));
const resources = getMultiSelectedResources(resource, accessor.get(IListService), accessor.get(IEditorService), accessor.get(IExplorerService));
revealResourcesInOS(resources, accessor.get(IElectronService), accessor.get(INotificationService), accessor.get(IWorkspaceContextService));
}
});

View File

@@ -12,7 +12,7 @@ import { SetLogLevelAction, OpenWindowSessionLogFileAction } from 'vs/workbench/
import * as Constants from 'vs/workbench/contrib/logs/common/logConstants';
import { IWorkbenchContribution, IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { IFileService, FileChangeType } from 'vs/platform/files/common/files';
import { IFileService, FileChangeType, whenProviderRegistered } from 'vs/platform/files/common/files';
import { URI } from 'vs/base/common/uri';
import { IOutputChannelRegistry, Extensions as OutputExt } from 'vs/workbench/contrib/output/common/output';
import { Disposable } from 'vs/base/common/lifecycle';
@@ -71,6 +71,7 @@ class LogOutputChannels extends Disposable implements IWorkbenchContribution {
}
private async registerLogChannel(id: string, label: string, file: URI): Promise<void> {
await whenProviderRegistered(file, this.fileService);
const outputChannelRegistry = Registry.as<IOutputChannelRegistry>(OutputExt.OutputChannels);
const exists = await this.fileService.exists(file);
if (exists) {

View File

@@ -37,7 +37,7 @@ import { IContextMenuService } from 'vs/platform/contextview/browser/contextView
import { Separator, ActionViewItem, ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { IMenuService, MenuId } from 'vs/platform/actions/common/actions';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { StandardKeyboardEvent, IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { domEvent } from 'vs/base/browser/event';
import { ResourceLabels } from 'vs/workbench/browser/labels';
import { IMarker } from 'vs/platform/markers/common/markers';
@@ -46,6 +46,7 @@ import { MementoObject } from 'vs/workbench/common/memento';
import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
import { PANEL_BACKGROUND } from 'vs/workbench/common/theme';
import { KeyCode } from 'vs/base/common/keyCodes';
function createResourceMarkersIterator(resourceMarkers: ResourceMarkers): Iterator<ITreeElement<TreeElement>> {
const markersIt = Iterator.fromArray(resourceMarkers.markers);
@@ -439,6 +440,7 @@ export class MarkersPanel extends Panel implements IMarkerFilterController {
}));
this._register(this.tree.onDidChangeSelection(() => this.onSelected()));
this._register(this.filterAction.onDidChange((event: IMarkersFilterActionChangeEvent) => {
this.reportFilteringUsed();
if (event.activeFile) {
this.refreshPanel();
} else if (event.filterText || event.excludedFiles || event.showWarnings || event.showErrors || event.showInfos) {
@@ -520,10 +522,14 @@ export class MarkersPanel extends Panel implements IMarkerFilterController {
if (filtered === 0) {
this.messageBoxContainer.style.display = 'block';
this.messageBoxContainer.setAttribute('tabIndex', '0');
if (total > 0) {
this.renderFilteredByFilterMessage(this.messageBoxContainer);
if (this.filterAction.activeFile) {
this.renderFilterMessageForActiveFile(this.messageBoxContainer);
} else {
this.renderNoProblemsMessage(this.messageBoxContainer);
if (total > 0) {
this.renderFilteredByFilterMessage(this.messageBoxContainer);
} else {
this.renderNoProblemsMessage(this.messageBoxContainer);
}
}
} else {
this.messageBoxContainer.style.display = 'none';
@@ -536,18 +542,52 @@ export class MarkersPanel extends Panel implements IMarkerFilterController {
}
}
private renderFilterMessageForActiveFile(container: HTMLElement): void {
if (this.currentActiveResource && this.markersWorkbenchService.markersModel.getResourceMarkers(this.currentActiveResource)) {
this.renderFilteredByFilterMessage(container);
} else {
this.renderNoProblemsMessageForActiveFile(container);
}
}
private renderFilteredByFilterMessage(container: HTMLElement) {
const span1 = dom.append(container, dom.$('span'));
span1.textContent = Messages.MARKERS_PANEL_NO_PROBLEMS_FILTERS;
const link = dom.append(container, dom.$('a.messageAction'));
link.textContent = localize('clearFilter', "Clear Filters");
link.setAttribute('tabIndex', '0');
const span2 = dom.append(container, dom.$('span'));
span2.textContent = '.';
dom.addStandardDisposableListener(link, dom.EventType.CLICK, () => this.clearFilters());
dom.addStandardDisposableListener(link, dom.EventType.KEY_DOWN, (e: IKeyboardEvent) => {
if (e.equals(KeyCode.Enter) || e.equals(KeyCode.Space)) {
this.clearFilters();
e.stopPropagation();
}
});
this.ariaLabelElement.setAttribute('aria-label', Messages.MARKERS_PANEL_NO_PROBLEMS_FILTERS);
}
private renderNoProblemsMessageForActiveFile(container: HTMLElement) {
const span = dom.append(container, dom.$('span'));
span.textContent = Messages.MARKERS_PANEL_NO_PROBLEMS_ACTIVE_FILE_BUILT;
this.ariaLabelElement.setAttribute('aria-label', Messages.MARKERS_PANEL_NO_PROBLEMS_ACTIVE_FILE_BUILT);
}
private renderNoProblemsMessage(container: HTMLElement) {
const span = dom.append(container, dom.$('span'));
span.textContent = Messages.MARKERS_PANEL_NO_PROBLEMS_BUILT;
this.ariaLabelElement.setAttribute('aria-label', Messages.MARKERS_PANEL_NO_PROBLEMS_BUILT);
}
private clearFilters(): void {
this.filterAction.filterText = '';
this.filterAction.excludedFiles = false;
this.filterAction.showErrors = true;
this.filterAction.showWarnings = true;
this.filterAction.showInfos = true;
}
private autoReveal(focus: boolean = false): void {
// No need to auto reveal if active file filter is on
if (this.filterAction.activeFile) {
@@ -714,6 +754,26 @@ export class MarkersPanel extends Panel implements IMarkerFilterController {
return { source, code };
}
private reportFilteringUsed(): void {
const data = {
errors: this.filterAction.showErrors,
warnings: this.filterAction.showWarnings,
infos: this.filterAction.showInfos,
activeFile: this.filterAction.activeFile,
excludedFiles: this.filterAction.excludedFiles,
};
/* __GDPR__
"problems.filter" : {
"errors" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"warnings": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"infos": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"activeFile": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"excludedFiles": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }
}
*/
this.telemetryService.publicLog('problems.filter', data);
}
protected saveState(): void {
this.panelState['filter'] = this.filterAction.filterText;
this.panelState['filterHistory'] = this.filterAction.filterHistory;

View File

@@ -27,7 +27,6 @@ import { Marker } from 'vs/workbench/contrib/markers/browser/markersModel';
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { Event, Emitter } from 'vs/base/common/event';
import { FilterOptions } from 'vs/workbench/contrib/markers/browser/markersFilterOptions';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { DropdownMenuActionViewItem } from 'vs/base/browser/ui/dropdown/dropdown';
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
@@ -285,7 +284,6 @@ export class MarkersFilterActionViewItem extends BaseActionViewItem {
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IContextViewService private readonly contextViewService: IContextViewService,
@IThemeService private readonly themeService: IThemeService,
@ITelemetryService private readonly telemetryService: ITelemetryService,
@IContextKeyService contextKeyService: IContextKeyService
) {
super(null, action);
@@ -385,7 +383,6 @@ export class MarkersFilterActionViewItem extends BaseActionViewItem {
inputbox.addToHistory();
this.action.filterText = inputbox.value;
this.action.filterHistory = inputbox.getHistory();
this.reportFilteringUsed();
}
private updateBadge(): void {
@@ -426,23 +423,6 @@ export class MarkersFilterActionViewItem extends BaseActionViewItem {
}
}
private reportFilteringUsed(): void {
const filterOptions = this.filterController.getFilterOptions();
const data = {
errors: filterOptions.showErrors,
warnings: filterOptions.showWarnings,
infos: filterOptions.showInfos,
};
/* __GDPR__
"problems.filter" : {
"errors" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"warnings": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"infos": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }
}
*/
this.telemetryService.publicLog('problems.filter', data);
}
protected updateClass(): void {
if (this.element && this.container) {
this.element.className = this.action.class || '';

View File

@@ -21,6 +21,7 @@ export default class Messages {
public static MARKERS_PANEL_TITLE_PROBLEMS: string = nls.localize('markers.panel.title.problems', "Problems");
public static MARKERS_PANEL_NO_PROBLEMS_BUILT: string = nls.localize('markers.panel.no.problems.build', "No problems have been detected in the workspace so far.");
public static MARKERS_PANEL_NO_PROBLEMS_ACTIVE_FILE_BUILT: string = nls.localize('markers.panel.no.problems.activeFile.build', "No problems have been detected in the current file so far.");
public static MARKERS_PANEL_NO_PROBLEMS_FILTERS: string = nls.localize('markers.panel.no.problems.filters', "No results found with provided filter criteria.");
public static MARKERS_PANEL_ACTION_TOOLTIP_MORE_FILTERS: string = nls.localize('markers.panel.action.moreFilters', "More Filters...");

View File

@@ -3,23 +3,17 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IDisposable, dispose, Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { IWorkbenchContributionsRegistry, IWorkbenchContribution, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
import { Disposable } from 'vs/base/common/lifecycle';
import { isMacintosh, isNative } from 'vs/base/common/platform';
import { localize } from 'vs/nls';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { IProductService } from 'vs/platform/product/common/productService';
import { Registry } from 'vs/platform/registry/common/platform';
import { IWindowsConfiguration } from 'vs/platform/windows/common/windows';
import { Extensions as WorkbenchExtensions, IWorkbenchContribution, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions';
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { localize } from 'vs/nls';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { RunOnceScheduler } from 'vs/base/common/async';
import { URI } from 'vs/base/common/uri';
import { isEqual } from 'vs/base/common/resources';
import { isMacintosh, isNative } from 'vs/base/common/platform';
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { IProductService } from 'vs/platform/product/common/productService';
interface IConfiguration extends IWindowsConfiguration {
update: { mode: string; };
@@ -132,82 +126,5 @@ export class SettingsChangeRelauncher extends Disposable implements IWorkbenchCo
}
}
export class WorkspaceChangeExtHostRelauncher extends Disposable implements IWorkbenchContribution {
private firstFolderResource?: URI;
private extensionHostRestarter: RunOnceScheduler;
private onDidChangeWorkspaceFoldersUnbind: IDisposable | undefined;
constructor(
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
@IExtensionService extensionService: IExtensionService,
@IHostService hostService: IHostService,
@IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService
) {
super();
this.extensionHostRestarter = this._register(new RunOnceScheduler(() => {
if (!!environmentService.extensionTestsLocationURI) {
return; // no restart when in tests: see https://github.com/Microsoft/vscode/issues/66936
}
if (environmentService.configuration.remoteAuthority) {
hostService.reload(); // TODO@aeschli, workaround
} else if (isNative) {
extensionService.restartExtensionHost();
}
}, 10));
this.contextService.getCompleteWorkspace()
.then(workspace => {
this.firstFolderResource = workspace.folders.length > 0 ? workspace.folders[0].uri : undefined;
this.handleWorkbenchState();
this._register(this.contextService.onDidChangeWorkbenchState(() => setTimeout(() => this.handleWorkbenchState())));
});
this._register(toDisposable(() => {
if (this.onDidChangeWorkspaceFoldersUnbind) {
this.onDidChangeWorkspaceFoldersUnbind.dispose();
}
}));
}
private handleWorkbenchState(): void {
// React to folder changes when we are in workspace state
if (this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE) {
// Update our known first folder path if we entered workspace
const workspace = this.contextService.getWorkspace();
this.firstFolderResource = workspace.folders.length > 0 ? workspace.folders[0].uri : undefined;
// Install workspace folder listener
if (!this.onDidChangeWorkspaceFoldersUnbind) {
this.onDidChangeWorkspaceFoldersUnbind = this.contextService.onDidChangeWorkspaceFolders(() => this.onDidChangeWorkspaceFolders());
}
}
// Ignore the workspace folder changes in EMPTY or FOLDER state
else {
dispose(this.onDidChangeWorkspaceFoldersUnbind);
this.onDidChangeWorkspaceFoldersUnbind = undefined;
}
}
private onDidChangeWorkspaceFolders(): void {
const workspace = this.contextService.getWorkspace();
// Restart extension host if first root folder changed (impact on deprecated workspace.rootPath API)
const newFirstFolderResource = workspace.folders.length > 0 ? workspace.folders[0].uri : undefined;
if (!isEqual(this.firstFolderResource, newFirstFolderResource)) {
this.firstFolderResource = newFirstFolderResource;
this.extensionHostRestarter.schedule(); // buffer calls to extension host restart
}
}
}
const workbenchRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench);
workbenchRegistry.registerWorkbenchContribution(SettingsChangeRelauncher, LifecyclePhase.Restored);
workbenchRegistry.registerWorkbenchContribution(WorkspaceChangeExtHostRelauncher, LifecyclePhase.Restored);

View File

@@ -20,6 +20,7 @@ import { startsWith } from 'vs/base/common/strings';
import { isStringArray } from 'vs/base/common/types';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
export interface IRemoteSelectItem extends ISelectOptionItem {
authority: string[];
@@ -85,10 +86,10 @@ export class SwitchRemoteViewItem extends SelectActionViewItem {
return this.optionsItems[index];
}
static createOptionItems(views: IViewDescriptor[]): IRemoteSelectItem[] {
static createOptionItems(views: IViewDescriptor[], contextKeyService: IContextKeyService): IRemoteSelectItem[] {
let options: IRemoteSelectItem[] = [];
views.forEach(view => {
if (view.group && startsWith(view.group, 'targets') && view.remoteAuthority) {
if (view.group && startsWith(view.group, 'targets') && view.remoteAuthority && (!view.when || contextKeyService.contextMatchesRules(view.when))) {
options.push({ text: view.name, authority: isStringArray(view.remoteAuthority) ? view.remoteAuthority : [view.remoteAuthority] });
}
});

View File

@@ -72,7 +72,8 @@ class HelpModel {
})),
quickInputService,
environmentService,
openerService
openerService,
remoteExplorerService
));
}
@@ -89,7 +90,8 @@ class HelpModel {
})),
quickInputService,
environmentService,
openerService
openerService,
remoteExplorerService
));
}
@@ -106,7 +108,8 @@ class HelpModel {
})),
quickInputService,
environmentService,
openerService
openerService,
remoteExplorerService
));
}
@@ -123,7 +126,8 @@ class HelpModel {
})),
quickInputService,
environmentService,
openerService
openerService,
remoteExplorerService
));
}
@@ -137,7 +141,8 @@ class HelpModel {
})),
quickInputService,
environmentService,
commandService
commandService,
remoteExplorerService
));
}
@@ -158,14 +163,15 @@ abstract class HelpItemBase implements IHelpItem {
public label: string,
public values: { extensionDescription: IExtensionDescription, url?: string, remoteAuthority: string[] | undefined }[],
private quickInputService: IQuickInputService,
private environmentService: IWorkbenchEnvironmentService
private environmentService: IWorkbenchEnvironmentService,
private remoteExplorerService: IRemoteExplorerService
) {
iconClasses.push('remote-help-tree-node-item-icon');
}
async handleClick() {
const remoteAuthority = this.environmentService.configuration.remoteAuthority;
if (remoteAuthority) {
if (remoteAuthority && startsWith(remoteAuthority, this.remoteExplorerService.targetType)) {
for (let value of this.values) {
if (value.remoteAuthority) {
for (let authority of value.remoteAuthority) {
@@ -207,9 +213,10 @@ class HelpItem extends HelpItemBase {
values: { extensionDescription: IExtensionDescription; url: string, remoteAuthority: string[] | undefined }[],
quickInputService: IQuickInputService,
environmentService: IWorkbenchEnvironmentService,
private openerService: IOpenerService
private openerService: IOpenerService,
remoteExplorerService: IRemoteExplorerService
) {
super(iconClasses, label, values, quickInputService, environmentService);
super(iconClasses, label, values, quickInputService, environmentService, remoteExplorerService);
}
protected async takeAction(extensionDescription: IExtensionDescription, url: string): Promise<void> {
@@ -225,8 +232,9 @@ class IssueReporterItem extends HelpItemBase {
quickInputService: IQuickInputService,
environmentService: IWorkbenchEnvironmentService,
private commandService: ICommandService,
remoteExplorerService: IRemoteExplorerService
) {
super(iconClasses, label, values, quickInputService, environmentService);
super(iconClasses, label, values, quickInputService, environmentService, remoteExplorerService);
}
protected async takeAction(extensionDescription: IExtensionDescription): Promise<void> {
@@ -236,7 +244,7 @@ class IssueReporterItem extends HelpItemBase {
class HelpAction extends Action {
static readonly ID = 'remote.explorer.help';
static readonly LABEL = nls.localize('remote.explorer.help', "Help and Feedback");
static readonly LABEL = nls.localize('remote.explorer.help', "Help, Documentation, and Feedback");
private helpModel: HelpModel;
constructor(id: string,
@@ -280,6 +288,7 @@ export class RemoteViewlet extends FilterViewContainerViewlet {
@IExtensionService extensionService: IExtensionService,
@IRemoteExplorerService private readonly remoteExplorerService: IRemoteExplorerService,
@IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService,
@IContextKeyService private readonly contextKeyService: IContextKeyService
) {
super(VIEWLET_ID, remoteExplorerService.onDidChangeTargetType, configurationService, layoutService, telemetryService, storageService, instantiationService, themeService, contextMenuService, extensionService, contextService);
}
@@ -290,7 +299,7 @@ export class RemoteViewlet extends FilterViewContainerViewlet {
public getActionViewItem(action: Action): IActionViewItem | undefined {
if (action.id === SwitchRemoteAction.ID) {
return this.instantiationService.createInstance(SwitchRemoteViewItem, action, SwitchRemoteViewItem.createOptionItems(Registry.as<IViewsRegistry>(Extensions.ViewsRegistry).getViews(VIEW_CONTAINER)));
return this.instantiationService.createInstance(SwitchRemoteViewItem, action, SwitchRemoteViewItem.createOptionItems(Registry.as<IViewsRegistry>(Extensions.ViewsRegistry).getViews(VIEW_CONTAINER), this.contextKeyService));
}
return super.getActionViewItem(action);

View File

@@ -29,11 +29,15 @@
margin-top: 7px;
}
.monaco-workbench.mac .part > .title > .title-actions .switch-remote {
border-radius: 4px;
}
.switch-remote > .monaco-select-box {
border: none;
display: block;
}
.monaco-workbench .part > .title > .title-actions .switch-remote > .monaco-select-box {
padding-left: 3px;
padding: 0 22px 0 6px;
}

View File

@@ -809,37 +809,37 @@ export class DirtyDiffController extends Disposable implements IEditorContributi
export const editorGutterModifiedBackground = registerColor('editorGutter.modifiedBackground', {
dark: new Color(new RGBA(12, 125, 157)),
light: new Color(new RGBA(102, 175, 224)),
hc: new Color(new RGBA(0, 73, 122))
hc: new Color(new RGBA(0, 155, 249))
}, nls.localize('editorGutterModifiedBackground', "Editor gutter background color for lines that are modified."));
export const editorGutterAddedBackground = registerColor('editorGutter.addedBackground', {
dark: new Color(new RGBA(88, 124, 12)),
light: new Color(new RGBA(129, 184, 139)),
hc: new Color(new RGBA(27, 82, 37))
hc: new Color(new RGBA(51, 171, 78))
}, nls.localize('editorGutterAddedBackground', "Editor gutter background color for lines that are added."));
export const editorGutterDeletedBackground = registerColor('editorGutter.deletedBackground', {
dark: new Color(new RGBA(148, 21, 27)),
light: new Color(new RGBA(202, 75, 81)),
hc: new Color(new RGBA(141, 14, 20))
hc: new Color(new RGBA(252, 93, 109))
}, nls.localize('editorGutterDeletedBackground', "Editor gutter background color for lines that are deleted."));
export const minimapGutterModifiedBackground = registerColor('minimapGutter.modifiedBackground', {
dark: new Color(new RGBA(12, 125, 157)),
light: new Color(new RGBA(102, 175, 224)),
hc: new Color(new RGBA(0, 73, 122))
hc: new Color(new RGBA(0, 155, 249))
}, nls.localize('minimapGutterModifiedBackground', "Minimap gutter background color for lines that are modified."));
export const minimapGutterAddedBackground = registerColor('minimapGutter.addedBackground', {
dark: new Color(new RGBA(88, 124, 12)),
light: new Color(new RGBA(129, 184, 139)),
hc: new Color(new RGBA(27, 82, 37))
hc: new Color(new RGBA(51, 171, 78))
}, nls.localize('minimapGutterAddedBackground', "Minimap gutter background color for lines that are added."));
export const minimapGutterDeletedBackground = registerColor('minimapGutter.deletedBackground', {
dark: new Color(new RGBA(148, 21, 27)),
light: new Color(new RGBA(202, 75, 81)),
hc: new Color(new RGBA(141, 14, 20))
hc: new Color(new RGBA(252, 93, 109))
}, nls.localize('minimapGutterDeletedBackground', "Minimap gutter background color for lines that are deleted."));
const overviewRulerDefault = new Color(new RGBA(0, 122, 204, 0.6));

View File

@@ -81,6 +81,13 @@ Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration).regis
'scm.diffDecorations': {
type: 'string',
enum: ['all', 'gutter', 'overview', 'minimap', 'none'],
enumDescriptions: [
localize('scm.diffDecorations.all', "Show the diff decorations in all available locations."),
localize('scm.diffDecorations.gutter', "Show the diff decorations only in the editor gutter."),
localize('scm.diffDecorations.overviewRuler', "Show the diff decorations only in the overview ruler."),
localize('scm.diffDecorations.minimap', "Show the diff decorations only in the minimap."),
localize('scm.diffDecorations.none', "Do not show the diff decorations.")
],
default: 'all',
description: localize('diffDecorations', "Controls diff decorations in the editor.")
},

View File

@@ -149,12 +149,6 @@ export class PatternInputWidget extends Widget {
this._register(attachInputBoxStyler(this.inputBox, this.themeService));
this.inputFocusTracker = dom.trackFocus(this.inputBox.inputElement);
this.onkeyup(this.inputBox.inputElement, (keyboardEvent) => this.onInputKeyUp(keyboardEvent));
this._register(this.inputBox.onDidChange(() => {
if (this.searchConfig.searchOnType) {
this._onCancel.fire();
this.searchOnTypeDelayer.trigger(() => this._onSubmit.fire(true), this.searchConfig.searchOnTypeDebouncePeriod);
}
}));
const controls = document.createElement('div');
controls.className = 'controls';
@@ -176,6 +170,10 @@ export class PatternInputWidget extends Widget {
this._onCancel.fire();
return;
default:
if (this.searchConfig.searchOnType) {
this._onCancel.fire();
this.searchOnTypeDelayer.trigger(() => this._onSubmit.fire(true), this.searchConfig.searchOnTypeDebouncePeriod);
}
return;
}
}

View File

@@ -41,7 +41,7 @@ import { ExplorerFolderContext, ExplorerRootContext, FilesExplorerFocusCondition
import { OpenAnythingHandler } from 'vs/workbench/contrib/search/browser/openAnythingHandler';
import { OpenSymbolHandler } from 'vs/workbench/contrib/search/browser/openSymbolHandler';
import { registerContributions as replaceContributions } from 'vs/workbench/contrib/search/browser/replaceContributions';
import { clearHistoryCommand, ClearSearchResultsAction, CloseReplaceAction, CollapseDeepestExpandedLevelAction, copyAllCommand, copyMatchCommand, copyPathCommand, FocusNextInputAction, FocusNextSearchResultAction, FocusPreviousInputAction, FocusPreviousSearchResultAction, focusSearchListCommand, getSearchView, openSearchView, OpenSearchViewletAction, RefreshAction, RemoveAction, ReplaceAction, ReplaceAllAction, ReplaceAllInFolderAction, ReplaceInFilesAction, toggleCaseSensitiveCommand, toggleRegexCommand, toggleWholeWordCommand, FindInFilesCommand, ToggleSearchOnTypeAction, OpenResultsInEditorAction, RerunEditorSearchAction } from 'vs/workbench/contrib/search/browser/searchActions';
import { clearHistoryCommand, ClearSearchResultsAction, CloseReplaceAction, CollapseDeepestExpandedLevelAction, copyAllCommand, copyMatchCommand, copyPathCommand, FocusNextInputAction, FocusNextSearchResultAction, FocusPreviousInputAction, FocusPreviousSearchResultAction, focusSearchListCommand, getSearchView, openSearchView, OpenSearchViewletAction, RefreshAction, RemoveAction, ReplaceAction, ReplaceAllAction, ReplaceAllInFolderAction, ReplaceInFilesAction, toggleCaseSensitiveCommand, toggleRegexCommand, toggleWholeWordCommand, FindInFilesCommand, ToggleSearchOnTypeAction, OpenResultsInEditorAction, RerunEditorSearchAction, RerunEditorSearchWithContextAction } from 'vs/workbench/contrib/search/browser/searchActions';
import { SearchPanel } from 'vs/workbench/contrib/search/browser/searchPanel';
import { SearchView, SearchViewPosition } from 'vs/workbench/contrib/search/browser/searchView';
import { SearchViewlet } from 'vs/workbench/contrib/search/browser/searchViewlet';
@@ -396,7 +396,7 @@ const searchInFolderCommand: ICommandHandler = (accessor, resource?: URI) => {
const panelService = accessor.get(IPanelService);
const fileService = accessor.get(IFileService);
const configurationService = accessor.get(IConfigurationService);
const resources = getMultiSelectedResources(resource, listService, accessor.get(IEditorService));
const resources = getMultiSelectedResources(resource, listService, accessor.get(IEditorService), accessor.get(IExplorerService));
return openSearchView(viewletService, panelService, configurationService, true).then(searchView => {
if (resources && resources.length && searchView) {
@@ -651,6 +651,11 @@ registry.registerWorkbenchAction(
'Search Editor: Search Again', category,
ContextKeyExpr.and(EditorContextKeys.languageId.isEqualTo('search-result')));
registry.registerWorkbenchAction(
SyncActionDescriptor.create(RerunEditorSearchWithContextAction, RerunEditorSearchWithContextAction.ID, RerunEditorSearchWithContextAction.LABEL),
'Search Editor: Search Again (With Context)', category,
ContextKeyExpr.and(EditorContextKeys.languageId.isEqualTo('search-result')));
// Register Quick Open Handler
Registry.as<IQuickOpenRegistry>(QuickOpenExtensions.Quickopen).registerDefaultQuickOpenHandler(
@@ -690,7 +695,7 @@ configurationRegistry.registerConfiguration({
'search.exclude': {
type: 'object',
markdownDescription: nls.localize('exclude', "Configure glob patterns for excluding files and folders in searches. Inherits all glob patterns from the `#files.exclude#` setting. Read more about glob patterns [here](https://code.visualstudio.com/docs/editor/codebasics#_advanced-search-options)."),
default: { '**/node_modules': true, '**/bower_components': true },
default: { '**/node_modules': true, '**/bower_components': true, '**/*.code-search': true },
additionalProperties: {
anyOf: [
{

View File

@@ -32,6 +32,7 @@ import { ITreeNavigator } from 'vs/base/browser/ui/tree/tree';
import { createEditorFromSearchResult, refreshActiveEditorSearch } from 'vs/workbench/contrib/search/browser/searchEditor';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress';
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
export function isSearchViewFocused(viewletService: IViewletService, panelService: IPanelService): boolean {
const searchView = getSearchView(viewletService, panelService);
@@ -472,7 +473,38 @@ export class RerunEditorSearchAction extends Action {
async run() {
if (this.configurationService.getValue<ISearchConfigurationProperties>('search').enableSearchEditorPreview) {
await this.progressService.withProgress({ location: ProgressLocation.Window },
() => refreshActiveEditorSearch(this.editorService, this.instantiationService, this.contextService, this.labelService, this.configurationService));
() => refreshActiveEditorSearch(undefined, this.editorService, this.instantiationService, this.contextService, this.labelService, this.configurationService));
}
}
}
export class RerunEditorSearchWithContextAction extends Action {
static readonly ID: string = Constants.RerunEditorSearchWithContextCommandId;
static readonly LABEL = nls.localize('search.rerunEditorSearchContext', "Search Again (With Context)");
constructor(id: string, label: string,
@IInstantiationService private instantiationService: IInstantiationService,
@IEditorService private editorService: IEditorService,
@IConfigurationService private configurationService: IConfigurationService,
@IWorkspaceContextService private contextService: IWorkspaceContextService,
@ILabelService private labelService: ILabelService,
@IProgressService private progressService: IProgressService,
@IQuickInputService private quickPickService: IQuickInputService
) {
super(id, label);
}
async run() {
const lines = await this.quickPickService.input({
prompt: nls.localize('lines', "Lines of Context"),
value: '2',
validateInput: async (value) => isNaN(parseInt(value)) ? nls.localize('mustBeInteger', "Must enter an integer") : undefined
});
if (lines === undefined) { return; }
if (this.configurationService.getValue<ISearchConfigurationProperties>('search').enableSearchEditorPreview) {
await this.progressService.withProgress({ location: ProgressLocation.Window },
() => refreshActiveEditorSearch(+lines, this.editorService, this.instantiationService, this.contextService, this.labelService, this.configurationService));
}
}
}

View File

@@ -12,7 +12,7 @@ import { URI } from 'vs/base/common/uri';
import { ITextQuery, IPatternInfo, ISearchConfigurationProperties } from 'vs/workbench/services/search/common/search';
import * as network from 'vs/base/common/network';
import { Range } from 'vs/editor/common/core/range';
import { ITextModel, TrackedRangeStickiness } from 'vs/editor/common/model';
import { ITextModel, TrackedRangeStickiness, EndOfLinePreference } from 'vs/editor/common/model';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ITextQueryBuilderOptions, QueryBuilder } from 'vs/workbench/contrib/search/common/queryBuilder';
import { getOutOfWorkspaceEditorResources } from 'vs/workbench/contrib/search/common/search';
@@ -20,6 +20,8 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { searchEditorFindMatch, searchEditorFindMatchBorder } from 'vs/platform/theme/common/colorRegistry';
import { UntitledTextEditorInput } from 'vs/workbench/common/editor/untitledTextEditorInput';
import { localize } from 'vs/nls';
// Using \r\n on Windows inserts an extra newline between results.
const lineDelimiter = '\n';
@@ -45,7 +47,7 @@ const matchToSearchResultFormat = (match: Match): { line: string, ranges: Range[
const prefix = ` ${lineNumber}: ${paddingStr}`;
const prefixOffset = prefix.length;
const line = (prefix + sourceLine);
const line = (prefix + sourceLine).replace(/\r?\n?$/, '');
const rangeOnThisLine = ({ start, end }: { start?: number; end?: number; }) => new Range(1, (start ?? 1) + prefixOffset, 1, (end ?? sourceLine.length + 1) + prefixOffset);
@@ -65,6 +67,7 @@ const matchToSearchResultFormat = (match: Match): { line: string, ranges: Range[
};
type SearchResultSerialization = { text: string[], matchRanges: Range[] };
function fileMatchToSearchResultFormat(fileMatch: FileMatch, labelFormatter: (x: URI) => string): SearchResultSerialization {
const serializedMatches = flatten(fileMatch.matches()
.sort(searchMatchComparer)
@@ -76,17 +79,37 @@ function fileMatchToSearchResultFormat(fileMatch: FileMatch, labelFormatter: (x:
const targetLineNumberToOffset: Record<string, number> = {};
const context: { line: string, lineNumber: number }[] = [];
fileMatch.context.forEach((line, lineNumber) => context.push({ line, lineNumber }));
context.sort((a, b) => a.lineNumber - b.lineNumber);
let lastLine: number | undefined = undefined;
const seenLines = new Set<string>();
serializedMatches.forEach(match => {
if (!seenLines.has(match.line)) {
while (context.length && context[0].lineNumber < +match.lineNumber) {
const { line, lineNumber } = context.shift()!;
if (lastLine !== undefined && lineNumber !== lastLine + 1) {
text.push('');
}
text.push(` ${lineNumber} ${line}`);
lastLine = lineNumber;
}
targetLineNumberToOffset[match.lineNumber] = text.length;
seenLines.add(match.line);
text.push(match.line);
lastLine = +match.lineNumber;
}
matchRanges.push(...match.ranges.map(translateRangeLines(targetLineNumberToOffset[match.lineNumber])));
});
while (context.length) {
const { line, lineNumber } = context.shift()!;
text.push(` ${lineNumber} ${line}`);
}
return { text, matchRanges };
}
@@ -104,7 +127,7 @@ const flattenSearchResultSerializations = (serializations: SearchResultSerializa
return { text, matchRanges };
};
const contentPatternToSearchResultHeader = (pattern: ITextQuery | null, includes: string, excludes: string): string[] => {
const contentPatternToSearchResultHeader = (pattern: ITextQuery | null, includes: string, excludes: string, contextLines: number): string[] => {
if (!pattern) { return []; }
const removeNullFalseAndUndefined = <T>(a: (T | null | false | undefined)[]) => a.filter(a => a !== false && a !== null && a !== undefined) as T[];
@@ -123,19 +146,56 @@ const contentPatternToSearchResultHeader = (pattern: ITextQuery | null, includes
]).join(' ')}`,
includes ? `# Including: ${includes}` : undefined,
excludes ? `# Excluding: ${excludes}` : undefined,
contextLines ? `# ContextLines: ${contextLines}` : undefined,
''
]);
};
const searchHeaderToContentPattern = (header: string[]): { pattern: string, flags: { regex: boolean, wholeWord: boolean, caseSensitive: boolean, ignoreExcludes: boolean }, includes: string, excludes: string } => {
const query = {
type SearchHeader = {
pattern: string;
flags: {
regex: boolean;
wholeWord: boolean;
caseSensitive: boolean;
ignoreExcludes: boolean;
};
includes: string;
excludes: string;
context: number | undefined;
};
const searchHeaderToContentPattern = (header: string[]): SearchHeader => {
const query: SearchHeader = {
pattern: '',
flags: { regex: false, caseSensitive: false, ignoreExcludes: false, wholeWord: false },
includes: '',
excludes: ''
excludes: '',
context: undefined
};
const unescapeNewlines = (str: string) => str.replace(/\\\\/g, '\\').replace(/\\n/g, '\n');
const unescapeNewlines = (str: string) => {
let out = '';
for (let i = 0; i < str.length; i++) {
if (str[i] === '\\') {
i++;
const escaped = str[i];
if (escaped === 'n') {
out += '\n';
}
else if (escaped === '\\') {
out += '\\';
}
else {
throw Error(localize('invalidQueryStringError', "All backslashes in Query string must be escaped (\\\\)"));
}
} else {
out += str[i];
}
}
return out;
};
const parseYML = /^# ([^:]*): (.*)$/;
for (const line of header) {
const parsed = parseYML.exec(line);
@@ -145,6 +205,7 @@ const searchHeaderToContentPattern = (header: string[]): { pattern: string, flag
case 'Query': query.pattern = unescapeNewlines(value); break;
case 'Including': query.includes = value; break;
case 'Excluding': query.excludes = value; break;
case 'ContextLines': query.context = +value; break;
case 'Flags': {
query.flags = {
regex: value.indexOf('RegExp') !== -1,
@@ -159,25 +220,26 @@ const searchHeaderToContentPattern = (header: string[]): { pattern: string, flag
return query;
};
const serializeSearchResultForEditor = (searchResult: SearchResult, rawIncludePattern: string, rawExcludePattern: string, labelFormatter: (x: URI) => string): SearchResultSerialization => {
const header = contentPatternToSearchResultHeader(searchResult.query, rawIncludePattern, rawExcludePattern);
const serializeSearchResultForEditor = (searchResult: SearchResult, rawIncludePattern: string, rawExcludePattern: string, contextLines: number, labelFormatter: (x: URI) => string): SearchResultSerialization => {
const header = contentPatternToSearchResultHeader(searchResult.query, rawIncludePattern, rawExcludePattern, contextLines);
const allResults =
flattenSearchResultSerializations(
flatten(searchResult.folderMatches().sort(searchMatchComparer)
.map(folderMatch => folderMatch.matches().sort(searchMatchComparer)
.map(fileMatch => fileMatchToSearchResultFormat(fileMatch, labelFormatter)))));
flatten(
searchResult.folderMatches().sort(searchMatchComparer)
.map(folderMatch => folderMatch.matches().sort(searchMatchComparer)
.map(fileMatch => fileMatchToSearchResultFormat(fileMatch, labelFormatter)))));
return { matchRanges: allResults.matchRanges.map(translateRangeLines(header.length)), text: header.concat(allResults.text) };
};
export const refreshActiveEditorSearch =
async (editorService: IEditorService, instantiationService: IInstantiationService, contextService: IWorkspaceContextService, labelService: ILabelService, configurationService: IConfigurationService) => {
async (contextLines: number | undefined, editorService: IEditorService, instantiationService: IInstantiationService, contextService: IWorkspaceContextService, labelService: ILabelService, configurationService: IConfigurationService) => {
const model = editorService.activeTextEditorWidget?.getModel();
if (!model) { return; }
const textModel = model as ITextModel;
const header = textModel.getValueInRange(new Range(1, 1, 5, 1))
const header = textModel.getValueInRange(new Range(1, 1, 5, 1), EndOfLinePreference.LF)
.split(lineDelimiter)
.filter(line => line.indexOf('# ') === 0);
@@ -190,6 +252,8 @@ export const refreshActiveEditorSearch =
isWordMatch: contentPattern.flags.wholeWord
};
contextLines = contextLines ?? contentPattern.context ?? 0;
const options: ITextQueryBuilderOptions = {
_reason: 'searchEditor',
extraFileResources: instantiationService.invokeFunction(getOutOfWorkspaceEditorResources),
@@ -202,6 +266,8 @@ export const refreshActiveEditorSearch =
matchLines: 1,
charsPerLine: 1000
},
afterContext: contextLines,
beforeContext: contextLines,
isSmartCase: configurationService.getValue<ISearchConfigurationProperties>('search').smartCase,
expandPatterns: true
};
@@ -220,7 +286,7 @@ export const refreshActiveEditorSearch =
await searchModel.search(query);
const labelFormatter = (uri: URI): string => labelService.getUriLabel(uri, { relative: true });
const results = serializeSearchResultForEditor(searchModel.searchResult, '', '', labelFormatter);
const results = serializeSearchResultForEditor(searchModel.searchResult, contentPattern.includes, contentPattern.excludes, contextLines, labelFormatter);
textModel.setValue(results.text.join(lineDelimiter));
textModel.deltaDecorations([], results.matchRanges.map(range => ({ range, options: { className: 'searchEditorFindMatch', stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges } })));
@@ -233,29 +299,35 @@ export const createEditorFromSearchResult =
const labelFormatter = (uri: URI): string => labelService.getUriLabel(uri, { relative: true });
const results = serializeSearchResultForEditor(searchResult, rawIncludePattern, rawExcludePattern, labelFormatter);
const results = serializeSearchResultForEditor(searchResult, rawIncludePattern, rawExcludePattern, 0, labelFormatter);
const contents = results.text.join(lineDelimiter);
let possible = {
contents: results.text.join(lineDelimiter),
contents,
mode: 'search-result',
resource: URI.from({ scheme: network.Schemas.untitled, path: searchTerm })
};
let id = 0;
while (editorService.getOpened(possible)) {
let existing = editorService.getOpened(possible);
while (existing) {
if (existing instanceof UntitledTextEditorInput) {
const model = await existing.resolve();
const existingContents = model.textEditorModel.getValue(EndOfLinePreference.LF);
if (existingContents === contents) {
break;
}
}
possible.resource = possible.resource.with({ path: searchTerm + '-' + ++id });
existing = editorService.getOpened(possible);
}
const editor = await editorService.openEditor(possible);
const control = editor?.getControl()!;
control.updateOptions({ lineNumbers: 'off' });
const model = control.getModel() as ITextModel;
model.deltaDecorations([], results.matchRanges.map(range => ({ range, options: { className: 'searchEditorFindMatch', stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges } })));
};
// theming
registerThemingParticipant((theme, collector) => {
collector.addRule(`.monaco-editor .searchEditorFindMatch { background-color: ${theme.getColor(searchEditorFindMatch)}; }`);

View File

@@ -206,7 +206,7 @@ export class SearchView extends ViewletPane {
this.delayedRefresh = this._register(new Delayer<void>(250));
this.addToSearchHistoryDelayer = this._register(new Delayer<void>(500));
this.addToSearchHistoryDelayer = this._register(new Delayer<void>(2000));
this.actions = [
this._register(this.instantiationService.createInstance(ClearSearchResultsAction, ClearSearchResultsAction.ID, ClearSearchResultsAction.LABEL)),
@@ -963,13 +963,15 @@ export class SearchView extends ViewletPane {
return this.searchWidget && this.searchWidget.searchInput.getValue().length > 0;
}
clearSearchResults(): void {
clearSearchResults(clearInput = true): void {
this.viewModel.searchResult.clear();
this.showEmptyStage(true);
if (this.contextService.getWorkbenchState() === WorkbenchState.EMPTY) {
this.showSearchWithoutFolderMessage();
}
this.searchWidget.clear();
if (clearInput) {
this.searchWidget.clear();
}
this.viewModel.cancelSearch();
this.updateActions();
@@ -1202,7 +1204,7 @@ export class SearchView extends ViewletPane {
const useExcludesAndIgnoreFiles = this.inputPatternExcludes.useExcludesAndIgnoreFiles();
if (contentPattern.length === 0) {
this.clearSearchResults();
this.clearSearchResults(false);
this.clearMessage();
return;
}

View File

@@ -466,6 +466,7 @@ export class SearchWidget extends Widget {
}
if (keyboardEvent.equals(KeyCode.Enter)) {
this.searchInput.onSearchSubmit();
this.submitSearch();
keyboardEvent.preventDefault();
}

View File

@@ -17,6 +17,7 @@ export const CopyMatchCommandId = 'search.action.copyMatch';
export const CopyAllCommandId = 'search.action.copyAll';
export const OpenInEditorCommandId = 'search.action.openInEditor';
export const RerunEditorSearchCommandId = 'search.action.rerunEditorSearch';
export const RerunEditorSearchWithContextCommandId = 'search.action.rerunEditorSearchWithContext';
export const ClearSearchHistoryCommandId = 'search.action.clearHistory';
export const FocusSearchListCommandID = 'search.action.focusSearchList';
export const ReplaceActionId = 'search.action.replace';

View File

@@ -20,7 +20,7 @@ import { IModelService } from 'vs/editor/common/services/modelService';
import { createDecorator, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IProgress, IProgressStep } from 'vs/platform/progress/common/progress';
import { ReplacePattern } from 'vs/workbench/services/search/common/replace';
import { IFileMatch, IPatternInfo, ISearchComplete, ISearchProgressItem, ISearchConfigurationProperties, ISearchService, ITextQuery, ITextSearchPreviewOptions, ITextSearchMatch, ITextSearchStats, resultIsMatch, ISearchRange, OneLineRange } from 'vs/workbench/services/search/common/search';
import { IFileMatch, IPatternInfo, ISearchComplete, ISearchProgressItem, ISearchConfigurationProperties, ISearchService, ITextQuery, ITextSearchPreviewOptions, ITextSearchMatch, ITextSearchStats, resultIsMatch, ISearchRange, OneLineRange, ITextSearchContext, ITextSearchResult } from 'vs/workbench/services/search/common/search';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { overviewRulerFindMatchForeground, minimapFindMatch } from 'vs/platform/theme/common/colorRegistry';
import { themeColorFromId } from 'vs/platform/theme/common/themeService';
@@ -197,6 +197,11 @@ export class FileMatch extends Disposable implements IFileMatch {
private _updateScheduler: RunOnceScheduler;
private _modelDecorations: string[] = [];
private _context: Map<number, string> = new Map();
public get context(): Map<number, string> {
return new Map(this._context);
}
constructor(private _query: IPatternInfo, private _previewOptions: ITextSearchPreviewOptions | undefined, private _maxResults: number | undefined, private _parent: FolderMatch, private rawMatch: IFileMatch,
@IModelService private readonly modelService: IModelService, @IReplaceService private readonly replaceService: IReplaceService
) {
@@ -221,6 +226,8 @@ export class FileMatch extends Disposable implements IFileMatch {
textSearchResultToMatches(rawMatch, this)
.forEach(m => this.add(m));
});
this.addContext(this.rawMatch.results);
}
}
@@ -375,6 +382,14 @@ export class FileMatch extends Disposable implements IFileMatch {
return getBaseLabel(this.resource);
}
addContext(results: ITextSearchResult[] | undefined) {
if (!results) { return; }
results
.filter((result => !resultIsMatch(result)) as ((a: any) => a is ITextSearchContext))
.forEach(context => this._context.set(context.lineNumber, context.text));
}
add(match: Match, trigger?: boolean) {
this._matches.set(match.id(), match);
if (trigger) {
@@ -479,6 +494,8 @@ export class FolderMatch extends Disposable {
.forEach(m => existingFileMatch.add(m));
});
updated.push(existingFileMatch);
existingFileMatch.addContext(rawFileMatch.results);
} else {
const fileMatch = this.instantiationService.createInstance(FileMatch, this._query.contentPattern, this._query.previewOptions, this._query.maxResults, this, rawFileMatch);
this.doAdd(fileMatch);
@@ -965,11 +982,6 @@ export class SearchModel extends Disposable {
search(query: ITextQuery, onProgress?: (result: ISearchProgressItem) => void): Promise<ISearchComplete> {
this.cancelSearch();
// Exclude Search Editor results unless explicity included
const searchEditorFilenameGlob = `**/*.code-search`;
if (!query.includePattern || !query.includePattern[searchEditorFilenameGlob]) {
query.excludePattern = { ...(query.excludePattern ?? {}), [searchEditorFilenameGlob]: true };
}
this._searchQuery = query;
if (!this.searchConfig.searchOnType) {
@@ -982,7 +994,7 @@ export class SearchModel extends Disposable {
this._replacePattern = new ReplacePattern(this.replaceString, this._searchQuery.contentPattern);
// In search on type case, delay the streaming of results just a bit, so that we don't flash the only "local results" fast path
this._startStreamDelay = new Promise(resolve => setTimeout(resolve, this.searchConfig.searchOnType ? 100 : 0));
this._startStreamDelay = new Promise(resolve => setTimeout(resolve, this.searchConfig.searchOnType ? 150 : 0));
const tokenSource = this.currentCancelTokenSource = new CancellationTokenSource();
const currentRequest = this.searchService.textSearch(this._searchQuery, this.currentCancelTokenSource.token, p => {

View File

@@ -33,7 +33,7 @@ const taskDefinitionSchema: IJSONSchema = {
type: 'object',
description: nls.localize('TaskDefinition.properties', 'Additional properties of the task type'),
additionalProperties: {
$ref: 'http://json-schema.org/draft-04/schema#'
$ref: 'http://json-schema.org/draft-07/schema#'
}
}
}

View File

@@ -170,7 +170,7 @@ configurationRegistry.registerConfiguration({
default: DEFAULT_LINE_HEIGHT
},
'terminal.integrated.minimumContrastRatio': {
description: nls.localize('terminal.integrated.minimumContrastRatio', "When set the foreground color of each cell will change to try meet the contrast ratio specified. Example values:\n\n- 1: The default, do nothing.\n- 4.5: Minimum for WCAG AA compliance.\n- 7: Minimum for WCAG AAA compliance.\n- 21: White on black or black on white."),
markdownDescription: nls.localize('terminal.integrated.minimumContrastRatio', "When set the foreground color of each cell will change to try meet the contrast ratio specified. Example values:\n\n- 1: The default, do nothing.\n- 4.5: Minimum for [WCAG AA compliance](https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html).\n- 7: Minimum for [WCAG AAA compliance](https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast7.html).\n- 21: White on black or black on white."),
type: 'number',
default: 1
},
@@ -205,7 +205,7 @@ configurationRegistry.registerConfiguration({
markdownDescription: nls.localize('terminal.integrated.detectLocale', "Controls whether to detect and set the `$LANG` environment variable to a UTF-8 compliant option since Azure Data Studio's terminal only supports UTF-8 encoded data coming from the shell."), // {{SQL CARBON EDIT}} Change product name to ADS
type: 'string',
enum: ['auto', 'off', 'on'],
enumDescriptions: [
markdownEnumDescriptions: [
nls.localize('terminal.integrated.detectLocale.auto', "Set the `$LANG` environment variable if the existing variable does not exist or it does not end in `'.UTF-8'`."),
nls.localize('terminal.integrated.detectLocale.off', "Do not set the `$LANG` environment variable."),
nls.localize('terminal.integrated.detectLocale.on', "Always set the `$LANG` environment variable.")
@@ -215,8 +215,8 @@ configurationRegistry.registerConfiguration({
'terminal.integrated.rendererType': {
type: 'string',
enum: ['auto', 'canvas', 'dom', 'experimentalWebgl'],
enumDescriptions: [
nls.localize('terminal.integrated.rendererType.auto', "Let Azure Data Studio which renderer to use."), // {{SQL CARBON EDIT}} Change product name to ADS
markdownEnumDescriptions: [
nls.localize('terminal.integrated.rendererType.auto', "Let Azure Data Studio guess which renderer to use."), // {{SQL CARBON EDIT}} Change product name to ADS
nls.localize('terminal.integrated.rendererType.canvas', "Use the standard GPU/canvas-based renderer."),
nls.localize('terminal.integrated.rendererType.dom', "Use the fallback DOM-based renderer."),
nls.localize('terminal.integrated.rendererType.experimentalWebgl', "Use the experimental webgl-based renderer. Note that this has some [known issues](https://github.com/xtermjs/xterm.js/issues?q=is%3Aopen+is%3Aissue+label%3Aarea%2Faddon%2Fwebgl) and this will only be enabled for new terminals (not hot swappable like the other renderers).")
@@ -252,7 +252,7 @@ configurationRegistry.registerConfiguration({
default: false
},
'terminal.integrated.commandsToSkipShell': {
description: nls.localize('terminal.integrated.commandsToSkipShell', "A set of command IDs whose keybindings will not be sent to the shell and instead always be handled by Code. This allows the use of keybindings that would normally be consumed by the shell to act the same as when the terminal is not focused, for example ctrl+p to launch Quick Open.\nDefault Skipped Commands:\n\n{0}", DEFAULT_COMMANDS_TO_SKIP_SHELL.sort().map(command => `- ${command}`).join('\n')),
markdownDescription: nls.localize('terminal.integrated.commandsToSkipShell', "A set of command IDs whose keybindings will not be sent to the shell and instead always be handled by Code. This allows the use of keybindings that would normally be consumed by the shell to act the same as when the terminal is not focused, for example ctrl+p to launch Quick Open.\nDefault Skipped Commands:\n\n{0}", DEFAULT_COMMANDS_TO_SKIP_SHELL.sort().map(command => `- ${command}`).join('\n')),
type: 'array',
items: {
type: 'string'
@@ -260,7 +260,7 @@ configurationRegistry.registerConfiguration({
default: []
},
'terminal.integrated.allowChords': {
markdownDescription: nls.localize('terminal.integrated.allowChords', "Whether or not to allow chord keybindings in the terminal. Note that when this is true and the keystroke results in a chord it will bypass `terminal.integrated.commandsToSkipShell`, setting this to false is particularly useful when you want ctrl+k to go to your shell (not VS Code)."),
markdownDescription: nls.localize('terminal.integrated.allowChords', "Whether or not to allow chord keybindings in the terminal. Note that when this is true and the keystroke results in a chord it will bypass `#terminal.integrated.commandsToSkipShell#`, setting this to false is particularly useful when you want ctrl+k to go to your shell (not VS Code)."),
type: 'boolean',
default: true
},

View File

@@ -1,252 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as nls from 'vs/nls';
import { Action } from 'vs/base/common/actions';
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
import { IEditorInputFactory, EditorInput, IEditorInputFactoryRegistry, Extensions as EditorInputExtensions, EditorModel, EditorOptions, GroupIdentifier, ISaveOptions, IRevertOptions } from 'vs/workbench/common/editor';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IEditorModel } from 'vs/platform/editor/common/editor';
import { Dimension, addDisposableListener, EventType } from 'vs/base/browser/dom';
import { Registry } from 'vs/platform/registry/common/platform';
import { IEditorRegistry, EditorDescriptor, Extensions as EditorExtensions } from 'vs/workbench/browser/editor';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions';
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { URI } from 'vs/base/common/uri';
import { isEqual } from 'vs/base/common/resources';
import { generateUuid } from 'vs/base/common/uuid';
import { CancellationToken } from 'vs/base/common/cancellation';
import { editorBackground, editorForeground } from 'vs/platform/theme/common/colorRegistry';
import { IWorkingCopy, IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/workingCopyService';
import { env } from 'vs/base/common/process';
const CUSTOM_SCHEME = 'testCustomEditor';
const ENABLE = !!env['VSCODE_DEV'];
class TestCustomEditorsAction extends Action {
static readonly ID = 'workbench.action.openCustomEditor';
static readonly LABEL = nls.localize('openCustomEditor', "Test Open Custom Editor");
constructor(
id: string,
label: string,
@IEditorService private readonly editorService: IEditorService,
@IInstantiationService private readonly instantiationService: IInstantiationService
) {
super(id, label);
}
async run(): Promise<boolean> {
const input = this.instantiationService.createInstance(TestCustomEditorInput, URI.parse(`${CUSTOM_SCHEME}:/${generateUuid()}`));
await this.editorService.openEditor(input);
return true;
}
}
class TestCustomEditor extends BaseEditor {
static ID = 'testCustomEditor';
private textArea: HTMLTextAreaElement | undefined = undefined;
constructor(
@ITelemetryService telemetryService: ITelemetryService,
@IThemeService themeService: IThemeService,
@IStorageService storageService: IStorageService
) {
super(TestCustomEditor.ID, telemetryService, themeService, storageService);
}
updateStyles(): void {
super.updateStyles();
if (this.textArea) {
this.textArea.style.backgroundColor = this.getColor(editorBackground)!.toString();
this.textArea.style.color = this.getColor(editorForeground)!.toString();
}
}
protected createEditor(parent: HTMLElement): void {
this.textArea = document.createElement('textarea');
this.textArea.style.width = '100%';
this.textArea.style.height = '100%';
parent.appendChild(this.textArea);
addDisposableListener(this.textArea, EventType.CHANGE, e => this.onDidType());
addDisposableListener(this.textArea, EventType.KEY_UP, e => this.onDidType());
this.updateStyles();
}
private onDidType(): void {
if (this._input instanceof TestCustomEditorInput) {
this._input.setValue(this.textArea!.value);
}
}
async setInput(input: EditorInput, options: EditorOptions | undefined, token: CancellationToken): Promise<void> {
await super.setInput(input, options, token);
const model = await input.resolve();
if (model instanceof TestCustomEditorModel) {
this.textArea!.value = model.value;
}
}
clearInput() {
super.clearInput();
this.textArea!.value = '';
}
focus(): void {
this.textArea!.focus();
}
layout(dimension: Dimension): void { }
}
class TestCustomEditorInput extends EditorInput implements IWorkingCopy {
private model: TestCustomEditorModel | undefined = undefined;
private dirty = false;
readonly capabilities = 0;
constructor(public readonly resource: URI, @IWorkingCopyService workingCopyService: IWorkingCopyService) {
super();
this._register(workingCopyService.registerWorkingCopy(this));
}
getResource(): URI {
return this.resource;
}
getTypeId(): string {
return TestCustomEditor.ID;
}
getName(): string {
return this.resource.toString();
}
setValue(value: string) {
if (this.model) {
if (this.model.value === value) {
return;
}
this.model.value = value;
}
this.setDirty(value.length > 0);
}
private setDirty(dirty: boolean) {
if (this.dirty !== dirty) {
this.dirty = dirty;
this._onDidChangeDirty.fire();
}
}
isReadonly(): boolean {
return false;
}
isDirty(): boolean {
return this.dirty;
}
async save(groupId: GroupIdentifier, options?: ISaveOptions): Promise<boolean> {
this.setDirty(false);
return true;
}
async saveAs(groupId: GroupIdentifier, options?: ISaveOptions): Promise<boolean> {
this.setDirty(false);
return true;
}
async revert(options?: IRevertOptions): Promise<boolean> {
this.setDirty(false);
return true;
}
async resolve(): Promise<IEditorModel | null> {
if (!this.model) {
this.model = new TestCustomEditorModel(this.resource);
}
return this.model;
}
matches(other: EditorInput) {
return other instanceof TestCustomEditorInput && isEqual(other.resource, this.resource);
}
dispose(): void {
this.setDirty(false);
if (this.model) {
this.model.dispose();
this.model = undefined;
}
super.dispose();
}
}
class TestCustomEditorModel extends EditorModel {
public value: string = '';
constructor(public readonly resource: URI) {
super();
}
}
if (ENABLE) {
Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditor(
EditorDescriptor.create(
TestCustomEditor,
TestCustomEditor.ID,
nls.localize('testCustomEditor', "Test Custom Editor")
),
[
new SyncDescriptor<EditorInput>(TestCustomEditorInput),
]
);
const registry = Registry.as<IWorkbenchActionRegistry>(Extensions.WorkbenchActions);
registry.registerWorkbenchAction(SyncActionDescriptor.create(TestCustomEditorsAction, TestCustomEditorsAction.ID, TestCustomEditorsAction.LABEL), 'Test Open Custom Editor');
class TestCustomEditorInputFactory implements IEditorInputFactory {
serialize(editorInput: TestCustomEditorInput): string {
return JSON.stringify({
resource: editorInput.resource.toString()
});
}
deserialize(instantiationService: IInstantiationService, serializedEditorInput: string): TestCustomEditorInput {
return instantiationService.createInstance(TestCustomEditorInput, URI.parse(JSON.parse(serializedEditorInput).resource));
}
}
Registry.as<IEditorInputFactoryRegistry>(EditorInputExtensions.EditorInputFactories).registerEditorInputFactory(TestCustomEditor.ID, TestCustomEditorInputFactory);
}