Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adopts more injected text #136653

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/vs/base/common/strings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1030,3 +1030,5 @@ const enum CodePoint {
*/
enclosingKeyCap = 0x20E3,
}

export const noBreakWhitespace = '\xa0';
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import { registerColor } from 'vs/platform/theme/common/colorRegistry';
import { ILabelService } from 'vs/platform/label/common/label';
import * as icons from 'vs/workbench/contrib/debug/browser/debugIcons';
import { onUnexpectedError } from 'vs/base/common/errors';
import { noBreakWhitespace } from 'vs/base/common/strings';

const $ = dom.$;

Expand Down Expand Up @@ -100,7 +101,11 @@ function getBreakpointDecorationOptions(model: ITextModel, breakpoint: IBreakpoi
glyphMarginClassName: ThemeIcon.asClassName(icon),
glyphMarginHoverMessage,
stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,
beforeContentClassName: renderInline ? `debug-breakpoint-placeholder` : undefined,
before: renderInline ? {
content: noBreakWhitespace,
inlineClassName: `debug-breakpoint-placeholder`,
inlineClassNameAffectsLetterSpacing: true
} : undefined,
overviewRuler: overviewRulerDecoration
};
}
Expand Down Expand Up @@ -133,7 +138,11 @@ async function createCandidateDecorations(model: ITextModel, breakpointDecoratio
options: {
description: 'breakpoint-placeholder-decoration',
stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,
beforeContentClassName: breakpointAtPosition ? undefined : `debug-breakpoint-placeholder`
before: breakpointAtPosition ? undefined : {
content: noBreakWhitespace,
inlineClassName: `debug-breakpoint-placeholder`,
inlineClassNameAffectsLetterSpacing: true
},
},
breakpoint: breakpointAtPosition ? breakpointAtPosition.breakpoint : undefined
});
Expand Down Expand Up @@ -466,7 +475,7 @@ export class BreakpointEditorContribution implements IBreakpointEditorContributi
this.breakpointDecorations = decorationIds.map((decorationId, index) => {
let inlineWidget: InlineBreakpointWidget | undefined = undefined;
const breakpoint = breakpoints[index];
if (desiredBreakpointDecorations[index].options.beforeContentClassName) {
if (desiredBreakpointDecorations[index].options.before) {
const contextMenuActions = () => this.getContextMenuActions([breakpoint], activeCodeEditor.getModel().uri, breakpoint.lineNumber, breakpoint.column);
inlineWidget = new InlineBreakpointWidget(activeCodeEditor, decorationId, desiredBreakpointDecorations[index].options.glyphMarginClassName, breakpoint, this.debugService, this.contextMenuService, contextMenuActions);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { distinct } from 'vs/base/common/arrays';
import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity';
import { debugStackframe, debugStackframeFocused } from 'vs/workbench/contrib/debug/browser/debugIcons';
import { noBreakWhitespace } from 'vs/base/common/strings';

export const topStackFrameColor = registerColor('editor.stackFrameHighlightBackground', { dark: '#ffff0033', light: '#ffff6673', hc: '#ffff0033' }, localize('topStackFrameLineHighlight', 'Background color for the highlight of line at the top stack frame position.'));
export const focusedStackFrameColor = registerColor('editor.focusedStackFrameHighlightBackground', { dark: '#7abd7a4d', light: '#cee7ce73', hc: '#7abd7a4d' }, localize('focusedStackFrameLineHighlight', 'Background color for the highlight of line at focused stack frame position.'));
Expand Down Expand Up @@ -80,7 +81,11 @@ export function createDecorationsForStackFrame(stackFrame: IStackFrame, isFocuse
result.push({
options: {
description: 'top-stack-frame-inline-decoration',
beforeContentClassName: noCharactersBefore ? 'debug-top-stack-frame-column start-of-line' : 'debug-top-stack-frame-column'
before: {
content: noBreakWhitespace,
inlineClassName: noCharactersBefore ? 'debug-top-stack-frame-column start-of-line' : 'debug-top-stack-frame-column',
inlineClassNameAffectsLetterSpacing: true
},
},
range: columnUntilEOLRange
});
Expand Down
44 changes: 24 additions & 20 deletions src/vs/workbench/contrib/debug/browser/debugEditorContribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ import { distinct, flatten } from 'vs/base/common/arrays';
import { onUnexpectedExternalError } from 'vs/base/common/errors';
import { DEFAULT_WORD_REGEXP } from 'vs/editor/common/model/wordHelper';
import { ICodeEditor, IEditorMouseEvent, MouseTargetType, IPartialEditorMouseEvent } from 'vs/editor/browser/editorBrowser';
import { IDecorationOptions } from 'vs/editor/common/editorCommon';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { Range } from 'vs/editor/common/core/range';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
Expand All @@ -33,7 +31,7 @@ import { CoreEditingCommands } from 'vs/editor/browser/controller/coreCommands';
import { memoize } from 'vs/base/common/decorators';
import { IEditorHoverOptions, EditorOption } from 'vs/editor/common/config/editorOptions';
import { DebugHoverWidget } from 'vs/workbench/contrib/debug/browser/debugHover';
import { ITextModel } from 'vs/editor/common/model';
import { IModelDeltaDecoration, ITextModel } from 'vs/editor/common/model';
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
import { EditOperation } from 'vs/editor/common/core/editOperation';
import { basename } from 'vs/base/common/path';
Expand All @@ -44,13 +42,11 @@ import { Event } from 'vs/base/common/event';
import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity';
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { Expression } from 'vs/workbench/contrib/debug/common/debugModel';
import { themeColorFromId } from 'vs/platform/theme/common/themeService';
import { registerColor } from 'vs/platform/theme/common/colorRegistry';
import { addDisposableListener } from 'vs/base/browser/dom';
import { DomEmitter } from 'vs/base/browser/event';

const LAUNCH_JSON_REGEX = /\.vscode\/launch\.json$/;
const INLINE_VALUE_DECORATION_KEY = 'inlinevaluedecoration';
const MAX_NUM_INLINE_VALUES = 100; // JS Global scope can have 700+ entries. We want to limit ourselves for perf reasons
const MAX_INLINE_DECORATOR_LENGTH = 150; // Max string length of each inline decorator when debugging. If exceeded ... is added
const MAX_TOKENIZATION_LINE_LEN = 500; // If line is too long, then inline values for the line are skipped
Expand All @@ -72,7 +68,7 @@ class InlineSegment {
}
}

function createInlineValueDecoration(lineNumber: number, contentText: string, column = Constants.MAX_SAFE_SMALL_INTEGER): IDecorationOptions {
function createInlineValueDecoration(lineNumber: number, contentText: string, column = Constants.MAX_SAFE_SMALL_INTEGER): IModelDeltaDecoration {
// If decoratorText is too long, trim and add ellipses. This could happen for minified files with everything on a single line
if (contentText.length > MAX_INLINE_DECORATOR_LENGTH) {
contentText = contentText.substr(0, MAX_INLINE_DECORATOR_LENGTH) + '...';
Expand All @@ -85,18 +81,23 @@ function createInlineValueDecoration(lineNumber: number, contentText: string, co
startColumn: column,
endColumn: column
},
renderOptions: {
options: {
description: 'debug-inline-value-decoration',
after: {
contentText,
backgroundColor: themeColorFromId(debugInlineBackground),
margin: '10px',
color: themeColorFromId(debugInlineForeground)
}
content: replaceWsWithNoBreakWs(contentText),
inlineClassName: 'debug-inline-value',
inlineClassNameAffectsLetterSpacing: true,
},
showIfCollapsed: true
}
};
}

function createInlineValueDecorationsInsideRange(expressions: ReadonlyArray<IExpression>, range: Range, model: ITextModel, wordToLineNumbersMap: Map<string, number[]>): IDecorationOptions[] {
function replaceWsWithNoBreakWs(str: string): string {
return str.replace(/[ \t]/g, strings.noBreakWhitespace);
}

function createInlineValueDecorationsInsideRange(expressions: ReadonlyArray<IExpression>, range: Range, model: ITextModel, wordToLineNumbersMap: Map<string, number[]>): IModelDeltaDecoration[] {
const nameValueMap = new Map<string, string>();
for (let expr of expressions) {
nameValueMap.set(expr.name, expr.value);
Expand Down Expand Up @@ -126,7 +127,7 @@ function createInlineValueDecorationsInsideRange(expressions: ReadonlyArray<IExp
}
});

const decorations: IDecorationOptions[] = [];
const decorations: IModelDeltaDecoration[] = [];
// Compute decorators for each line
lineToNamesMap.forEach((names, line) => {
const contentText = names.sort((first, second) => {
Expand Down Expand Up @@ -196,13 +197,13 @@ export class DebugEditorContribution implements IDebugEditorContribution {
private configurationWidget: FloatingClickWidget | undefined;
private altListener: IDisposable | undefined;
private altPressed = false;
private oldDecorations: string[] = [];

constructor(
private editor: ICodeEditor,
@IDebugService private readonly debugService: IDebugService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@ICommandService private readonly commandService: ICommandService,
@ICodeEditorService private readonly codeEditorService: ICodeEditorService,
@ITelemetryService private readonly telemetryService: ITelemetryService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IHostService private readonly hostService: IHostService,
Expand All @@ -213,7 +214,6 @@ export class DebugEditorContribution implements IDebugEditorContribution {
this.toDispose = [];
this.registerListeners();
this.updateConfigurationWidgetVisibility();
this.codeEditorService.registerDecorationType('debug-inline-value-decoration', INLINE_VALUE_DECORATION_KEY, {});
this.exceptionWidgetVisible = CONTEXT_EXCEPTION_WIDGET_VISIBLE.bindTo(contextKeyService);
this.toggleExceptionWidget();
}
Expand Down Expand Up @@ -575,7 +575,9 @@ export class DebugEditorContribution implements IDebugEditorContribution {
@memoize
private get removeInlineValuesScheduler(): RunOnceScheduler {
return new RunOnceScheduler(
() => this.editor.removeDecorations(INLINE_VALUE_DECORATION_KEY),
() => {
this.oldDecorations = this.editor.deltaDecorations(this.oldDecorations, []);
},
100
);
}
Expand Down Expand Up @@ -605,7 +607,7 @@ export class DebugEditorContribution implements IDebugEditorContribution {

this.removeInlineValuesScheduler.cancel();

let allDecorations: IDecorationOptions[];
let allDecorations: IModelDeltaDecoration[];

if (InlineValuesProviderRegistry.has(model)) {

Expand Down Expand Up @@ -717,10 +719,10 @@ export class DebugEditorContribution implements IDebugEditorContribution {

allDecorations = distinct(decorationsPerScope.reduce((previous, current) => previous.concat(current), []),
// Deduplicate decorations since same variable can appear in multiple scopes, leading to duplicated decorations #129770
decoration => `${decoration.range.startLineNumber}:${decoration.renderOptions?.after?.contentText}`);
decoration => `${decoration.range.startLineNumber}:${decoration?.options.after?.content}`);
}

this.editor.setDecorations('debug-inline-value-decoration', INLINE_VALUE_DECORATION_KEY, allDecorations);
this.oldDecorations = this.editor.deltaDecorations(this.oldDecorations, allDecorations);
}

dispose(): void {
Expand All @@ -731,5 +733,7 @@ export class DebugEditorContribution implements IDebugEditorContribution {
this.configurationWidget.dispose();
}
this.toDispose = dispose(this.toDispose);

this.oldDecorations = this.editor.deltaDecorations(this.oldDecorations, []);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,22 @@
left: -8px !important;
}

.monaco-editor .debug-breakpoint-placeholder::before,
.monaco-editor .debug-top-stack-frame-column::before {
content: ' ';
.monaco-editor .debug-breakpoint-placeholder {
width: 0.9em;
display: inline-flex;
vertical-align: middle;
margin-top: -1px;
}

.monaco-editor .debug-top-stack-frame-column {
width: 0.9em;
display: inline-flex;
vertical-align: middle;
margin-top: -1px; /* TODO @misolori: figure out a way to not use negative margin for alignment */
}

/* Do not push text with inline decoration when decoration on start of line */
.monaco-editor .debug-top-stack-frame-column.start-of-line::before {
.monaco-editor .debug-top-stack-frame-column.start-of-line {
position: absolute;
top: 50%;
transform: translate(-17px, -50%);
Expand Down Expand Up @@ -117,3 +122,9 @@
.monaco-workbench .monaco-list-row .expression .unavailable {
font-style: italic;
}

.monaco-workbench .debug-inline-value {
background-color: var(--vscode-editor-inlineValuesBackground);
margin: 10px;
color: var(--vscode-editor-inlineValuesForeground);
}
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ suite('Debug - Breakpoints', () => {
assert.deepStrictEqual(decorations[1].range, new Range(2, 4, 2, 5));
assert.deepStrictEqual(decorations[2].range, new Range(3, 5, 3, 6));
assert.strictEqual(decorations[0].options.beforeContentClassName, undefined);
assert.strictEqual(decorations[1].options.beforeContentClassName, `debug-breakpoint-placeholder`);
assert.strictEqual(decorations[1].options.before?.inlineClassName, `debug-breakpoint-placeholder`);
assert.strictEqual(decorations[0].options.overviewRuler?.position, OverviewRulerLane.Left);
const expected = new MarkdownString().appendCodeblock(languageId, 'Expression condition: x > 5');
assert.deepStrictEqual(decorations[0].options.glyphMarginHoverMessage, expected);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ suite('Debug - CallStack', () => {
assert.strictEqual(decorations[1].options.className, 'debug-top-stack-frame-line');
assert.strictEqual(decorations[1].options.isWholeLine, true);
// Inline decoration gets rendered in this case
assert.strictEqual(decorations[2].options.beforeContentClassName, 'debug-top-stack-frame-column');
assert.strictEqual(decorations[2].options.before?.inlineClassName, 'debug-top-stack-frame-column');
assert.deepStrictEqual(decorations[2].range, new Range(1, 2, 1, Constants.MAX_SAFE_SMALL_INTEGER));
});

Expand Down