diff --git a/src/vs/workbench/contrib/codeEditor/browser/inspectEditorTokens/inspectEditorTokens.ts b/src/vs/workbench/contrib/codeEditor/browser/inspectEditorTokens/inspectEditorTokens.ts
index d4ca7479c7f..16f632117f0 100644
--- a/src/vs/workbench/contrib/codeEditor/browser/inspectEditorTokens/inspectEditorTokens.ts
+++ b/src/vs/workbench/contrib/codeEditor/browser/inspectEditorTokens/inspectEditorTokens.ts
@@ -10,7 +10,6 @@ import { CharCode } from 'vs/base/common/charCode';
import { Color } from 'vs/base/common/color';
import { KeyCode } from 'vs/base/common/keyCodes';
import { Disposable } from 'vs/base/common/lifecycle';
-import { escape } from 'vs/base/common/strings';
import { ContentWidgetPositionPreference, IActiveCodeEditor, ICodeEditor, IContentWidget, IContentWidgetPosition } from 'vs/editor/browser/editorBrowser';
import { EditorAction, ServicesAccessor, registerEditorAction, registerEditorContribution } from 'vs/editor/browser/editorExtensions';
import { Position } from 'vs/editor/common/core/position';
@@ -31,6 +30,8 @@ import { SemanticTokenRule, TokenStyleData, TokenStyle } from 'vs/platform/theme
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { SEMANTIC_HIGHLIGHTING_SETTING_ID, IEditorSemanticHighlightingOptions } from 'vs/editor/common/services/modelServiceImpl';
+const $ = dom.$;
+
class InspectEditorTokensController extends Disposable implements IEditorContribution {
public static readonly ID = 'editor.contrib.inspectEditorTokens';
@@ -151,23 +152,11 @@ function renderTokenText(tokenText: string): string {
let charCode = tokenText.charCodeAt(charIndex);
switch (charCode) {
case CharCode.Tab:
- result += '→';
+ result += '\u2192'; // →
break;
case CharCode.Space:
- result += '·';
- break;
-
- case CharCode.LessThan:
- result += '<';
- break;
-
- case CharCode.GreaterThan:
- result += '>';
- break;
-
- case CharCode.Ampersand:
- result += '&';
+ result += '\u00B7'; // ·
break;
default:
@@ -246,8 +235,7 @@ class InspectEditorTokensWidget extends Disposable implements IContentWidget {
if (this._isDisposed) {
return;
}
- let text = this._compute(grammar, semanticTokens, position);
- this._domNode.innerHTML = text;
+ this._compute(grammar, semanticTokens, position);
this._domNode.style.maxWidth = `${Math.max(this._editor.getLayoutInfo().width * 0.66, 500)}px`;
this._editor.layoutContentWidget(this);
}, (err) => {
@@ -268,11 +256,12 @@ class InspectEditorTokensWidget extends Disposable implements IContentWidget {
return this._themeService.getColorTheme().semanticHighlighting;
}
- private _compute(grammar: IGrammar | null, semanticTokens: SemanticTokensResult | null, position: Position): string {
+ private _compute(grammar: IGrammar | null, semanticTokens: SemanticTokensResult | null, position: Position) {
const textMateTokenInfo = grammar && this._getTokensAtPosition(grammar, position);
const semanticTokenInfo = semanticTokens && this._getSemanticTokenAtPosition(semanticTokens, position);
if (!textMateTokenInfo && !semanticTokenInfo) {
- return 'No grammar or semantic tokens available.';
+ dom.reset(this._domNode, 'No grammar or semantic tokens available.');
+ return;
}
let tmMetadata = textMateTokenInfo?.metadata;
@@ -283,91 +272,125 @@ class InspectEditorTokensWidget extends Disposable implements IContentWidget {
const tokenText = semTokenText || tmTokenText || '';
- let result = '';
- result += `
${tokenText}(${tokenText.length} ${tokenText.length === 1 ? 'char' : 'chars'})
`;
- result += `
`;
-
- result += ``;
+ dom.reset(this._domNode,
+ $('h2.tiw-token', undefined,
+ tokenText,
+ $('span.tiw-token-length', undefined, `${tokenText.length} ${tokenText.length === 1 ? 'char' : 'chars'}`)));
+ dom.append(this._domNode, $('hr.tiw-metadata-separator', { 'style': 'clear:both' }));
+ dom.append(this._domNode, $('table.tiw-metadata-table', undefined,
+ $('tbody', undefined,
+ $('tr', undefined,
+ $('td.tiw-metadata-key', undefined, 'language'),
+ $('td.tiw-metadata-value', undefined, tmMetadata?.languageIdentifier.language || '')
+ ),
+ $('tr', undefined,
+ $('td.tiw-metadata-key', undefined, 'standard token type' as string),
+ $('td.tiw-metadata-value', undefined, this._tokenTypeToString(tmMetadata?.tokenType || StandardTokenType.Other))
+ ),
+ ...this._formatMetadata(semMetadata, tmMetadata)
+ )
+ ));
if (semanticTokenInfo) {
- result += `
`;
- result += ``;
}
if (textMateTokenInfo) {
let theme = this._themeService.getColorTheme();
- result += `
`;
- result += ``;
}
- return result;
}
- private _formatMetadata(semantic?: IDecodedMetadata, tm?: IDecodedMetadata) {
- let result = '';
+ private _formatMetadata(semantic?: IDecodedMetadata, tm?: IDecodedMetadata): Array {
+ const elements = new Array();
function render(property: 'foreground' | 'background') {
let value = semantic?.[property] || tm?.[property];
if (value !== undefined) {
const semanticStyle = semantic?.[property] ? 'tiw-metadata-semantic' : '';
- result += `| ${property} | ${value} |
`;
-
+ elements.push($('tr', undefined,
+ $('td.tiw-metadata-key', undefined, property),
+ $(`td.tiw-metadata-value.${semanticStyle}`, undefined, value)
+ ));
}
return value;
}
@@ -377,17 +400,23 @@ class InspectEditorTokensWidget extends Disposable implements IContentWidget {
if (foreground && background) {
const backgroundColor = Color.fromHex(background), foregroundColor = Color.fromHex(foreground);
if (backgroundColor.isOpaque()) {
- result += `| contrast ratio | ${backgroundColor.getContrastRatio(foregroundColor.makeOpaque(backgroundColor)).toFixed(2)} |
`;
+ elements.push($('tr', undefined,
+ $('td.tiw-metadata-key', undefined, 'contrast ratio' as string),
+ $('td.tiw-metadata-value', undefined, backgroundColor.getContrastRatio(foregroundColor.makeOpaque(backgroundColor)).toFixed(2))
+ ));
} else {
- result += '| Contrast ratio cannot be precise for background colors that use transparency | |
';
+ elements.push($('tr', undefined,
+ $('td.tiw-metadata-key', undefined, 'Contrast ratio cannot be precise for background colors that use transparency' as string),
+ $('td.tiw-metadata-value')
+ ));
}
}
- let fontStyleLabels: string[] = [];
+ const fontStyleLabels = new Array();
function addStyle(key: 'bold' | 'italic' | 'underline') {
if (semantic && semantic[key]) {
- fontStyleLabels.push(`${key}`);
+ fontStyleLabels.push($('span.tiw-metadata-semantic', undefined, key));
} else if (tm && tm[key]) {
fontStyleLabels.push(key);
}
@@ -396,9 +425,12 @@ class InspectEditorTokensWidget extends Disposable implements IContentWidget {
addStyle('italic');
addStyle('underline');
if (fontStyleLabels.length) {
- result += `| font style | ${fontStyleLabels.join(' ')} |
`;
+ elements.push($('tr', undefined,
+ $('td.tiw-metadata-key', undefined, 'font style' as string),
+ $('td.tiw-metadata-value', undefined, fontStyleLabels.join(' '))
+ ));
}
- return result;
+ return elements;
}
private _decodeMetadata(metadata: number): IDecodedMetadata {
@@ -549,9 +581,10 @@ class InspectEditorTokensWidget extends Disposable implements IContentWidget {
return null;
}
- private _renderTokenStyleDefinition(definition: TokenStyleDefinition | undefined, property: keyof TokenStyleData): string {
+ private _renderTokenStyleDefinition(definition: TokenStyleDefinition | undefined, property: keyof TokenStyleData): Array {
+ const elements = new Array();
if (definition === undefined) {
- return '';
+ return elements;
}
const theme = this._themeService.getColorTheme() as ColorThemeData;
@@ -561,20 +594,27 @@ class InspectEditorTokensWidget extends Disposable implements IContentWidget {
const matchingRule = scopesDefinition[property];
if (matchingRule && scopesDefinition.scope) {
const strScopes = Array.isArray(matchingRule.scope) ? matchingRule.scope.join(', ') : String(matchingRule.scope);
- return `${escape(scopesDefinition.scope.join(' '))}
${strScopes}\n${JSON.stringify(matchingRule.settings, null, '\t')}`;
+ elements.push(
+ scopesDefinition.scope.join(' '),
+ $('br'),
+ $('code.tiw-theme-selector', undefined, strScopes, $('br'), JSON.stringify(matchingRule.settings, null, '\t')));
+ return elements;
}
- return '';
+ return elements;
} else if (SemanticTokenRule.is(definition)) {
const scope = theme.getTokenStylingRuleScope(definition);
if (scope === 'setting') {
- return `User settings: ${definition.selector.id} - ${this._renderStyleProperty(definition.style, property)}`;
+ elements.push(`User settings: ${definition.selector.id} - ${this._renderStyleProperty(definition.style, property)}`);
+ return elements;
} else if (scope === 'theme') {
- return `Color theme: ${definition.selector.id} - ${this._renderStyleProperty(definition.style, property)}`;
+ elements.push(`Color theme: ${definition.selector.id} - ${this._renderStyleProperty(definition.style, property)}`);
+ return elements;
}
- return '';
+ return elements;
} else {
const style = theme.resolveTokenStyleValue(definition);
- return `Default: ${style ? this._renderStyleProperty(style, property) : ''}`;
+ elements.push(`Default: ${style ? this._renderStyleProperty(style, property) : ''}`);
+ return elements;
}
}