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

feature: Allow diagnostics messages to have markdown content #214051

Open
wants to merge 65 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
0a10206
feature: update markdown string
SimonSiefke Jun 1, 2024
e727796
update string
SimonSiefke Jun 1, 2024
b2e0f83
allow diagnostic markdown string
SimonSiefke Jun 1, 2024
6796ac4
add extension sample
SimonSiefke Jun 1, 2024
66ef328
Merge remote-tracking branch 'origin/main' into feature/diagnostic-me…
SimonSiefke Jun 1, 2024
55cdd0b
fix compile
SimonSiefke Jun 1, 2024
d84d930
remove unused code
SimonSiefke Jun 1, 2024
f12869e
fix rendering
SimonSiefke Jun 1, 2024
cb4719b
tsc
SimonSiefke Jun 1, 2024
93b0c62
tsc
SimonSiefke Jun 1, 2024
9b5e92a
fix import
SimonSiefke Jun 1, 2024
1b72b5b
try to fix type conversion
SimonSiefke Jun 1, 2024
3f3ab1b
tsc
SimonSiefke Jun 1, 2024
3a921f0
add sample text
SimonSiefke Jun 1, 2024
c6a7a1a
fix error
SimonSiefke Jun 1, 2024
d5f2bed
add markdown link
SimonSiefke Jun 1, 2024
3539a00
update extension
SimonSiefke Jun 1, 2024
62d1325
render markdown as text
SimonSiefke Jun 1, 2024
4d55b0c
render markdown
SimonSiefke Jun 1, 2024
fc499cf
simplify markdown rendering
SimonSiefke Jun 1, 2024
acdfc65
fix import
SimonSiefke Jun 1, 2024
19df729
fix type conversion
SimonSiefke Jun 1, 2024
cc77320
remove log
SimonSiefke Jun 1, 2024
72a8a4e
update extension
SimonSiefke Jun 1, 2024
8602662
Discard changes to extensions/sample-diagnostic-extension/README.md
SimonSiefke Jun 1, 2024
d640f28
Discard changes to extensions/sample-diagnostic-extension/.gitignore
SimonSiefke Jun 1, 2024
e0f6fa1
tsc
SimonSiefke Jun 1, 2024
2f5733d
update sample extension
SimonSiefke Jun 1, 2024
c847fd8
fix formatting
SimonSiefke Jun 1, 2024
d7da79a
fix formatting
SimonSiefke Jun 1, 2024
7fa6309
fix import
SimonSiefke Jun 1, 2024
6abd1b9
Merge remote-tracking branch 'origin/main' into feature/diagnostic-me…
SimonSiefke Jul 3, 2024
b24ba65
try to fix error
SimonSiefke Jul 3, 2024
c6e54b7
fix types
SimonSiefke Jul 3, 2024
07ff068
tsc
SimonSiefke Jul 3, 2024
4a72137
fix error
SimonSiefke Jul 3, 2024
3850a7f
tsc
SimonSiefke Jul 3, 2024
af865e7
tsc
SimonSiefke Jul 3, 2024
400f2fc
tsc
SimonSiefke Jul 3, 2024
a982abc
fix markdown rendering
SimonSiefke Jul 3, 2024
a78c93e
Merge branch 'main' into feature/diagnostic-messages-markdown
SimonSiefke Aug 8, 2024
7eab81e
update snapshots
SimonSiefke Aug 8, 2024
55da8b4
fix eslint
SimonSiefke Aug 8, 2024
e09dd8e
fix lint
SimonSiefke Aug 13, 2024
c311b46
Merge branch 'main' into feature/diagnostic-messages-markdown
SimonSiefke Aug 13, 2024
7b77815
Merge remote-tracking branch origin/main into feature/diagnostic-mess…
SimonSiefke Sep 9, 2024
fffa445
use npm
SimonSiefke Sep 9, 2024
fe6948c
fix import
SimonSiefke Sep 10, 2024
d6a60b1
Merge remote-tracking branch 'origin/main' into feature/diagnostic-me…
SimonSiefke Oct 1, 2024
e432a9f
update activation event
SimonSiefke Oct 1, 2024
79050df
Discard changes to extensions/json-language-features/client/src/jsonC…
SimonSiefke Oct 1, 2024
38b5d06
Discard changes to src/vs/workbench/contrib/chat/test/common/__snapsh…
SimonSiefke Oct 1, 2024
5ae65c7
Discard changes to src/vs/workbench/contrib/chat/test/common/__snapsh…
SimonSiefke Oct 1, 2024
2cc4874
Discard changes to src/vs/workbench/contrib/chat/test/common/__snapsh…
SimonSiefke Oct 1, 2024
1d107dc
Discard changes to src/vs/workbench/contrib/chat/test/common/__snapsh…
SimonSiefke Oct 1, 2024
a2ecedf
Discard changes to src/vs/workbench/contrib/chat/test/common/__snapsh…
SimonSiefke Oct 1, 2024
82da3b1
add import
SimonSiefke Oct 1, 2024
0230901
add import
SimonSiefke Oct 1, 2024
f33be19
add import
SimonSiefke Oct 1, 2024
29ac6de
add import
SimonSiefke Oct 1, 2024
2db71ac
add copyright
SimonSiefke Oct 1, 2024
538688c
Merge branch 'main' into feature/diagnostic-messages-markdown
SimonSiefke Oct 1, 2024
5d1102f
tsc
SimonSiefke Oct 1, 2024
b67d27c
Merge remote-tracking branch 'origin/main' into feature/diagnostic-me…
SimonSiefke Oct 13, 2024
075a3d4
Merge remote-tracking branch 'origin/main' into feature/diagnostic-me…
SimonSiefke Nov 28, 2024
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
1 change: 1 addition & 0 deletions .eslint-ignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
**/extensions/**/build/**
**/extensions/**/colorize-fixtures/**
**/extensions/css-language-features/server/test/pathCompletionFixtures/**
**/extensions/sample-diagnostic-extension/**
**/extensions/html-language-features/server/lib/jquery.d.ts
**/extensions/html-language-features/server/src/test/pathCompletionFixtures/**
**/extensions/ipynb/notebook-out/**
Expand Down
4 changes: 2 additions & 2 deletions extensions/json-language-features/client/src/jsonClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ async function startClientWithParticipants(context: ExtensionContext, languagePa
const schemaErrorIndex = diagnostics.findIndex(isSchemaResolveError);
if (schemaErrorIndex !== -1) {
const schemaResolveDiagnostic = diagnostics[schemaErrorIndex];
fileSchemaErrors.set(uri.toString(), schemaResolveDiagnostic.message);
fileSchemaErrors.set(uri.toString(), schemaResolveDiagnostic.message.toString());
if (!schemaDownloadEnabled) {
diagnostics = diagnostics.filter(d => !isSchemaResolveError(d));
}
Expand Down Expand Up @@ -484,7 +484,7 @@ async function startClientWithParticipants(context: ExtensionContext, languagePa
if (schemaErrorIndex !== -1) {
// Show schema resolution errors in status bar only; ref: #51032
const schemaResolveDiagnostic = diagnostics[schemaErrorIndex];
fileSchemaErrors.set(activeDocUri, schemaResolveDiagnostic.message);
fileSchemaErrors.set(activeDocUri, schemaResolveDiagnostic.message.toString());
} else {
schemaResolutionErrorStatusBarItem.hide();
}
Expand Down
17 changes: 17 additions & 0 deletions extensions/sample-diagnostic-extension/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions extensions/sample-diagnostic-extension/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"name": "diagnostic-related-information-sample",
"displayName": "Diagnostic Related Information Sample",
"description": "Diagnostic Related Information Sample",
"version": "0.0.1",
"publisher": "vscode-samples",
"private": true,
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/Microsoft/vscode-extension-samples"
},
"engines": {
"vscode": "^1.73.0"
},
"categories": [
"Other"
],
"activationEvents": [
"onStartupFinished"
],
"main": "./out/extension.js",
"scripts": {
"vscode:prepublish": "npm run compile",
"compile": "tsc -p ./",
"lint": "eslint \"src/**/*.ts\"",
"watch": "tsc -watch -p ./"
},
"devDependencies": {}
}
11 changes: 11 additions & 0 deletions extensions/sample-diagnostic-extension/sample-demo.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

fn main() {
let x = 5;
println!("The value of x is: {}", x);
x = 6;
println!("The value of x is: {}", x);
}
75 changes: 75 additions & 0 deletions extensions/sample-diagnostic-extension/src/extension.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import * as vscode from 'vscode';
import * as path from 'path';

export const activate = (context: vscode.ExtensionContext) => {
const collection = vscode.languages.createDiagnosticCollection('test');
if (vscode.window.activeTextEditor) {
updateDiagnostics(vscode.window.activeTextEditor.document, collection);
}
context.subscriptions.push(
vscode.window.onDidChangeActiveTextEditor((editor) => {
if (editor) {
updateDiagnostics(editor.document, collection);
}
})
);
};

function updateDiagnostics(
document: vscode.TextDocument,
collection: vscode.DiagnosticCollection
): void {
if (document && path.basename(document.uri.fsPath) === 'sample-demo.rs') {
const message = new vscode.MarkdownString(
'cannot assign twice to immutable variable `x`',
);
message.appendText('\n');
message.appendMarkdown(`https://example.com`);
message.appendText('\n');
message.appendMarkdown(`**This is bold text**

__This is bold text__

*This is italic text*

_This is italic text_

~~Strikethrough~~



`);
message.plainTextValue = 'cannot assign twice to immutable variable `x`';
collection.set(document.uri, [
{
code: '',
message,
range: new vscode.Range(
new vscode.Position(3, 4),
new vscode.Position(3, 10)
),
severity: vscode.DiagnosticSeverity.Error,
source: '',
relatedInformation: [
new vscode.DiagnosticRelatedInformation(
new vscode.Location(
document.uri,
new vscode.Range(
new vscode.Position(1, 8),
new vscode.Position(1, 9)
)
),
'first assignment to `x`'
),
],
},
]);
} else {
collection.clear();
}
}
8 changes: 8 additions & 0 deletions extensions/sample-diagnostic-extension/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"extends": "../tsconfig.base.json",
"compilerOptions": {
"outDir": "./out",
"skipLibCheck": true
},
"include": ["src/**/*", "../../src/vscode-dts/vscode.d.ts"]
}
5 changes: 4 additions & 1 deletion src/vs/base/common/htmlContent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export interface MarkdownStringTrustedOptions {

export interface IMarkdownString {
readonly value: string;
readonly plainTextValue?: string;
readonly isTrusted?: boolean | MarkdownStringTrustedOptions;
readonly supportThemeIcons?: boolean;
readonly supportHtml?: boolean;
Expand All @@ -30,16 +31,18 @@ export const enum MarkdownStringTextNewlineStyle {
export class MarkdownString implements IMarkdownString {

public value: string;
public plainTextValue?: string;
public isTrusted?: boolean | MarkdownStringTrustedOptions;
public supportThemeIcons?: boolean;
public supportHtml?: boolean;
public baseUri?: URI;

constructor(
value: string = '',
isTrustedOrOptions: boolean | { isTrusted?: boolean | MarkdownStringTrustedOptions; supportThemeIcons?: boolean; supportHtml?: boolean } = false,
isTrustedOrOptions: boolean | { isTrusted?: boolean | MarkdownStringTrustedOptions; supportThemeIcons?: boolean; supportHtml?: boolean; plainTextValue?: string } = false,
) {
this.value = value;
this.plainTextValue = value;
if (typeof this.value !== 'string') {
throw illegalArgument('value');
}
Expand Down
4 changes: 3 additions & 1 deletion src/vs/editor/contrib/gotoError/browser/gotoErrorWidget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { IOpenerService } from '../../../../platform/opener/common/opener.js';
import { SeverityIcon } from '../../../../platform/severityIcon/browser/severityIcon.js';
import { contrastBorder, editorBackground, editorErrorBorder, editorErrorForeground, editorInfoBorder, editorInfoForeground, editorWarningBorder, editorWarningForeground, oneOf, registerColor, transparent } from '../../../../platform/theme/common/colorRegistry.js';
import { IColorTheme, IThemeService } from '../../../../platform/theme/common/themeService.js';
import { isMarkdownString } from '../../../../base/common/htmlContent.js';

class MessageWidget {

Expand Down Expand Up @@ -102,7 +103,8 @@ class MessageWidget {
}
}

const lines = splitLines(message);
const plainTextMessage = isMarkdownString(message) ? (message.plainTextValue || '') : message;
const lines = splitLines(plainTextMessage);
this._lines = lines.length;
this._longestLineLength = 0;
for (const line of lines) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ export function renderMarkdownHovers(
return new RenderedHoverParts(renderedHoverParts);
}

function renderMarkdownInContainer(
export function renderMarkdownInContainer(
editor: ICodeEditor,
markdownHover: MarkdownHover,
languageService: ILanguageService,
Expand Down
48 changes: 30 additions & 18 deletions src/vs/editor/contrib/hover/browser/markerHoverParticipant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,24 @@ import { ITextEditorOptions } from '../../../../platform/editor/common/editor.js
import { IMarker, IMarkerData, MarkerSeverity } from '../../../../platform/markers/common/markers.js';
import { IOpenerService } from '../../../../platform/opener/common/opener.js';
import { Progress } from '../../../../platform/progress/common/progress.js';
import { IMarkdownString, isMarkdownString } from '../../../../base/common/htmlContent.js';
import { MarkdownHover, renderMarkdownInContainer } from './markdownHoverParticipant.js';
import { ILanguageService } from '../../../common/languages/language.js';


const $ = dom.$;

export class MarkerHover implements IHoverPart {
export class MarkerHover extends MarkdownHover implements IHoverPart {
readonly marker: IMarker;

constructor(
public readonly owner: IEditorHoverParticipant<MarkerHover>,
public readonly range: Range,
public readonly marker: IMarker,
) { }

public isValidForHoverAnchor(anchor: HoverAnchor): boolean {
return (
anchor.type === HoverAnchorType.Range
&& this.range.startColumn <= anchor.range.startColumn
&& this.range.endColumn >= anchor.range.endColumn
);
owner: IEditorHoverParticipant<MarkerHover>,
range: Range,
contents: IMarkdownString[],
marker: IMarker,
) {
super(owner, range, contents, false, 1, undefined);
this.marker = marker;
}
}

Expand All @@ -62,6 +63,7 @@ export class MarkerHoverParticipant implements IEditorHoverParticipant<MarkerHov
private readonly _editor: ICodeEditor,
@IMarkerDecorationsService private readonly _markerDecorationsService: IMarkerDecorationsService,
@IOpenerService private readonly _openerService: IOpenerService,
@ILanguageService private readonly _languageService: ILanguageService,
@ILanguageFeaturesService private readonly _languageFeaturesService: ILanguageFeaturesService,
) { }

Expand All @@ -84,7 +86,9 @@ export class MarkerHoverParticipant implements IEditorHoverParticipant<MarkerHov
}

const range = new Range(anchor.range.startLineNumber, startColumn, anchor.range.startLineNumber, endColumn);
result.push(new MarkerHover(this, range, marker));
if (isMarkdownString(marker.message)) {
result.push(new MarkerHover(this, range, [marker.message], marker));
}
}

return result;
Expand All @@ -97,7 +101,7 @@ export class MarkerHoverParticipant implements IEditorHoverParticipant<MarkerHov
const disposables = new DisposableStore();
const renderedHoverParts: IRenderedHoverPart<MarkerHover>[] = [];
hoverParts.forEach(hoverPart => {
const renderedMarkerHover = this._renderMarkerHover(hoverPart);
const renderedMarkerHover = this._renderMarkerHover(hoverPart, context,);
context.fragment.appendChild(renderedMarkerHover.hoverElement);
renderedHoverParts.push(renderedMarkerHover);
});
Expand All @@ -107,19 +111,27 @@ export class MarkerHoverParticipant implements IEditorHoverParticipant<MarkerHov
}

public getAccessibleContent(hoverPart: MarkerHover): string {
return hoverPart.marker.message;
return hoverPart.marker.message.toString();
}

private _renderMarkerHover(markerHover: MarkerHover): IRenderedHoverPart<MarkerHover> {
private _renderMarkerHover(markerHover: MarkerHover, context: IEditorHoverRenderContext): IRenderedHoverPart<MarkerHover> {
const disposables: DisposableStore = new DisposableStore();
const hoverElement = $('div.hover-row');
const markerElement = dom.append(hoverElement, $('div.marker.hover-contents'));
const { source, message, code, relatedInformation } = markerHover.marker;
const { source, message, code, relatedInformation, } = markerHover.marker;

console.log({ marker: markerHover.marker });
this._editor.applyFontInfo(markerElement);
const messageElement = dom.append(markerElement, $('span'));
messageElement.style.whiteSpace = 'pre-wrap';
messageElement.innerText = message;
if (isMarkdownString(message)) {
const renderedMarkdownPart = renderMarkdownInContainer(this._editor, markerHover, this._languageService, this._openerService, context.onContentsChanged);
disposables.add(renderedMarkdownPart);
const renderedMarkdownElement = renderedMarkdownPart.hoverElement;
messageElement.append(renderedMarkdownElement);
} else {
messageElement.innerText = message;
}

if (source || code) {
// Code has link
Expand Down
5 changes: 3 additions & 2 deletions src/vs/monaco.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,7 @@ declare namespace monaco {

export interface IMarkdownString {
readonly value: string;
readonly plainTextValue?: string;
readonly isTrusted?: boolean | MarkdownStringTrustedOptions;
readonly supportThemeIcons?: boolean;
readonly supportHtml?: boolean;
Expand Down Expand Up @@ -1465,7 +1466,7 @@ declare namespace monaco.editor {
value: string;
target: Uri;
};
message: string;
message: string | IMarkdownString;
source?: string;
startLineNumber: number;
startColumn: number;
Expand All @@ -1485,7 +1486,7 @@ declare namespace monaco.editor {
target: Uri;
};
severity: MarkerSeverity;
message: string;
message: string | IMarkdownString;
source?: string;
startLineNumber: number;
startColumn: number;
Expand Down
8 changes: 5 additions & 3 deletions src/vs/platform/markers/common/markers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/

import { Event } from '../../../base/common/event.js';
import { type IMarkdownString, isMarkdownString } from '../../../base/common/htmlContent.js';
import Severity from '../../../base/common/severity.js';
import { URI } from '../../../base/common/uri.js';
import { localize } from '../../../nls.js';
Expand Down Expand Up @@ -89,7 +90,7 @@ export namespace MarkerSeverity {
export interface IMarkerData {
code?: string | { value: string; target: URI };
severity: MarkerSeverity;
message: string;
message: string | IMarkdownString;
source?: string;
startLineNumber: number;
startColumn: number;
Expand All @@ -110,7 +111,7 @@ export interface IMarker {
resource: URI;
severity: MarkerSeverity;
code?: string | { value: string; target: URI };
message: string;
message: string | IMarkdownString;
source?: string;
startLineNumber: number;
startColumn: number;
Expand Down Expand Up @@ -159,7 +160,8 @@ export namespace IMarkerData {
// Modifed to not include the message as part of the marker key to work around
// https://github.com/microsoft/vscode/issues/77475
if (markerData.message && useMessage) {
result.push(markerData.message.replace('¦', '\\¦'));
const value = isMarkdownString(markerData.message) ? (markerData.message.plainTextValue || '') : markerData.message;
result.push(value.replace('¦', '\\¦'));
} else {
result.push(emptyString);
}
Expand Down
Loading