Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
connor4312 committed Jul 9, 2024
1 parent 4e928f7 commit 4dfddac
Show file tree
Hide file tree
Showing 7 changed files with 209 additions and 61 deletions.
10 changes: 9 additions & 1 deletion src/vs/editor/common/viewModel/glyphLanesModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ export class GlyphMarginLanesModel implements IGlyphMarginLanesModel {
this.lanes = new Uint8Array(Math.ceil(((maxLine + 1) * MAX_LANE) / 8));
}

private another2() {
this.another1();
}

public reset(maxLine: number) {
const bytes = Math.ceil(((maxLine + 1) * MAX_LANE) / 8);
if (this.lanes.length < bytes) {
Expand All @@ -40,9 +44,9 @@ export class GlyphMarginLanesModel implements IGlyphMarginLanesModel {
const bit = (MAX_LANE * i) + (lane - 1);
this.lanes[bit >>> 3] |= (1 << (bit % 8));
this._requiredLanes = Math.max(this._requiredLanes, this.countAtLine(i));
this.another2();
}
}

public getLanesAtLine(lineNumber: number): GlyphMarginLane[] {
const lanes: GlyphMarginLane[] = [];
let bit = MAX_LANE * lineNumber;
Expand All @@ -67,4 +71,8 @@ export class GlyphMarginLanesModel implements IGlyphMarginLanesModel {
}
return count;
}

private another1() {
throw new Error('oh no!');
}
}
34 changes: 34 additions & 0 deletions src/vs/workbench/contrib/testing/browser/media/testing.css
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,40 @@
}
}

.test-output-call-stack {
height: 100%;

.monaco-list-row {
padding: 0 3px 0 8px;
display: flex;
gap: 3px;

.location, .label {
white-space: nowrap;
}

.location {
/*Use direction so the source shows elipses on the left*/
direction: rtl;
overflow: hidden;
text-overflow: ellipsis;
font-size: 0.9em;
}

&:hover {
.label {
overflow: hidden;
text-overflow: ellipsis;
}

.location {
overflow: visible;
text-overflow: unset;
}
}
}
}

/** -- filter */
.monaco-action-bar.testing-filter-action-bar {
flex-shrink: 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,29 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import * as dom from 'vs/base/browser/dom';
import { IListRenderer, IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
import { Emitter } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
import { localize } from 'vs/nls';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ILabelService } from 'vs/platform/label/common/label';
import { WorkbenchList } from 'vs/platform/list/browser/listService';
import { ITestMessageStackTrace } from 'vs/workbench/contrib/testing/common/testTypes';
import { ITestMessageStackFrame } from 'vs/workbench/contrib/testing/common/testTypes';

const stackItemDelegate: IListVirtualDelegate<void> = {
getHeight: () => 22,
getTemplateId: () => 's',
};

export class TestResultStackWidget extends Disposable {
private readonly list: WorkbenchList<ITestMessageStackTrace>;
private readonly list: WorkbenchList<ITestMessageStackFrame>;
private readonly changeStackFrameEmitter = this._register(new Emitter<ITestMessageStackFrame>());

public readonly onDidChangeStackFrame = this.changeStackFrameEmitter.event;

constructor(
container: HTMLElement,
private readonly container: HTMLElement,
@IInstantiationService instantiationService: IInstantiationService,
@ILabelService labelService: ILabelService,
) {
Expand All @@ -33,39 +38,72 @@ export class TestResultStackWidget extends Disposable {
stackItemDelegate,
[instantiationService.createInstance(StackRenderer)],
{
multipleSelectionSupport: false,
accessibilityProvider: {
getWidgetAriaLabel: () => localize('testStackTrace', 'Test stack trace'),
getAriaLabel: (e: ITestMessageStackTrace) => e.position && e.uri ? localize({
getAriaLabel: (e: ITestMessageStackFrame) => e.position && e.uri ? localize({
comment: ['{0} is an extension-defined label, then line number and filename'],
key: 'stackTraceLabel',
}, '{0}, line {1} in {2}', e.label, e.position.lineNumber, labelService.getUriLabel(e.uri)) : e.label,
}, '{0}, line {1} in {2}', e.label, e.position.lineNumber, labelService.getUriLabel(e.uri, { relative: true })) : e.label,
}
}
) as WorkbenchList<ITestMessageStackTrace>);
) as WorkbenchList<ITestMessageStackFrame>);

this._register(this.list.onDidChangeSelection(e => {
if (e.elements.length) {
this.changeStackFrameEmitter.fire(e.elements[0]);
}
}));
}

public update(stack: ITestMessageStackTrace[]) {
public update(stack: ITestMessageStackFrame[], selection?: ITestMessageStackFrame) {
this.list.splice(0, this.list.length, stack);
this.list.layout();

const i = selection && stack.indexOf(selection);
if (i && i !== -1) {
this.list.setSelection([i]);
this.list.setFocus([i]);
// selection is triggered actioning on the call stack from a different
// editor, ensure the stack item is still focused in this editor
this.list.domFocus();
}
}

public layout(height?: number, width?: number) {
this.list.layout(height, width);
this.list.layout(height ?? this.container.clientHeight, width);
}
}

interface ITemplateData {
container: HTMLElement;
label: HTMLElement;
location: HTMLElement;
}

class StackRenderer implements IListRenderer<ITestMessageStackTrace, ITemplateData> {
class StackRenderer implements IListRenderer<ITestMessageStackFrame, ITemplateData> {
public readonly templateId = 's';

constructor(@ILabelService private readonly labelService: ILabelService) { }

renderTemplate(container: HTMLElement): ITemplateData {
return { container };
const label = dom.$('.label');
const location = dom.$('.location');
container.appendChild(label);
container.appendChild(location);
return { container, label, location };
}

renderElement(element: ITestMessageStackTrace, index: number, templateData: ITemplateData, height: number | undefined): void {
templateData.container.innerText = element.label;
renderElement(element: ITestMessageStackFrame, index: number, templateData: ITemplateData, height: number | undefined): void {
templateData.label.innerText = element.label;

if (element.uri) {
templateData.location.innerText = this.labelService.getUriBasenameLabel(element.uri);
templateData.location.title = this.labelService.getUriLabel(element.uri, { relative: true });
if (element.position) {
templateData.location.innerText += `:${element.position.lineNumber}:${element.position.column}`;
}
}
}

disposeTemplate(_templateData: ITemplateData): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ const commonEditorOptions: IEditorOptions = {
scrollBeyondLastLine: false,
links: true,
lineNumbers: 'off',
glyphMargin: false,
scrollbar: {
verticalScrollbarSize: 14,
horizontal: 'auto',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { OutputPeekTree } from 'vs/workbench/contrib/testing/browser/testResults
import { IObservableValue } from 'vs/workbench/contrib/testing/common/observableValue';
import { LiveTestResult } from 'vs/workbench/contrib/testing/common/testResult';
import { ITestFollowup, ITestService } from 'vs/workbench/contrib/testing/common/testService';
import { ITestMessageStackFrame } from 'vs/workbench/contrib/testing/common/testTypes';
import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys';

const enum SubView {
Expand All @@ -37,12 +38,18 @@ const enum SubView {
History = 2,
}

/** UI state that can be saved/restored, used to give a nice experience when switching stack frames */
export interface ITestResultsViewContentUiState {
splitViewWidths: number[];
}

export class TestResultsViewContent extends Disposable {
private static lastSplitWidth?: number;

private readonly didReveal = this._register(new Emitter<{ subject: InspectSubject; preserveFocus: boolean }>());
private readonly currentSubjectStore = this._register(new DisposableStore());
private readonly onCloseEmitter = this._register(new Relay<void>());
private readonly onDidChangeStackFrameEmitter = this._register(new Relay<ITestMessageStackFrame>());
private followupWidget!: FollowupActionWidget;
private messageContextKeyService!: IContextKeyService;
private contextKeyTestMessage!: IContextKey<string>;
Expand All @@ -62,6 +69,16 @@ export class TestResultsViewContent extends Disposable {
public onDidRequestReveal!: Event<InspectSubject>;

public readonly onClose = this.onCloseEmitter.event;
public readonly onDidChangeStackFrame = this.onDidChangeStackFrameEmitter.event;

public get uiState(): ITestResultsViewContentUiState {
return {
splitViewWidths: Array.from(
{ length: this.splitView.length },
(_, i) => this.splitView.getViewSize(i)
),
};
}

constructor(
private readonly editor: ICodeEditor | undefined,
Expand Down Expand Up @@ -151,7 +168,12 @@ export class TestResultsViewContent extends Disposable {
* Shows a message in-place without showing or changing the peek location.
* This is mostly used if peeking a message without a location.
*/
public reveal(opts: { subject: InspectSubject; preserveFocus: boolean }) {
public reveal(opts: {
subject: InspectSubject;
preserveFocus: boolean;
frame?: ITestMessageStackFrame;
uiState?: ITestResultsViewContentUiState;
}) {
this.didReveal.fire(opts);

if (this.current && equalsSubject(this.current, opts.subject)) {
Expand All @@ -163,13 +185,16 @@ export class TestResultsViewContent extends Disposable {
await Promise.all(this.contentProviders.map(p => p.update(opts.subject)));
this.followupWidget.show(opts.subject);
this.currentSubjectStore.clear();
// todo@connor4312: disabled for next Insiders, finish implementing this!
if (Date.now() < 0) { this.updateVisiblityOfStackView(opts.subject); }
this.updateVisiblityOfStackView(opts.subject, opts.frame);
this.populateFloatingClick(opts.subject);

if (opts.uiState) {
opts.uiState.splitViewWidths.forEach((width, i) => this.splitView.resizeView(i, width));
}
});
}

private updateVisiblityOfStackView(subject: InspectSubject) {
private updateVisiblityOfStackView(subject: InspectSubject, frame?: ITestMessageStackFrame) {
const stack = subject instanceof MessageSubject && subject.stack;

if (stack) {
Expand All @@ -182,11 +207,13 @@ export class TestResultsViewContent extends Disposable {
maximumSize: Number.MAX_VALUE,
layout: width => widget.layout(undefined, width),
}, 150, 0);
this.onDidChangeStackFrameEmitter.input = widget.onDidChangeStackFrame;
}

this.callStackWidget.value.update(stack);
this.callStackWidget.value.update(stack, frame);
} else if (this.callStackWidget.value) {
this.splitView.removeView(0);
this.onDidChangeStackFrameEmitter.input = Event.None;
this.callStackWidget.dispose();
}
}
Expand Down
Loading

0 comments on commit 4dfddac

Please sign in to comment.