monaco-editor-core
Version:
A browser based code editor
668 lines (667 loc) • 32.1 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
import { RunOnceScheduler } from '../../../../base/common/async.js';
import { Codicon } from '../../../../base/common/codicons.js';
import { MarkdownString } from '../../../../base/common/htmlContent.js';
import { Disposable } from '../../../../base/common/lifecycle.js';
import * as platform from '../../../../base/common/platform.js';
import { InvisibleCharacters, isBasicASCII } from '../../../../base/common/strings.js';
import './unicodeHighlighter.css';
import { EditorAction, registerEditorAction, registerEditorContribution } from '../../../browser/editorExtensions.js';
import { inUntrustedWorkspace, unicodeHighlightConfigKeys } from '../../../common/config/editorOptions.js';
import { ModelDecorationOptions } from '../../../common/model/textModel.js';
import { UnicodeTextModelHighlighter } from '../../../common/services/unicodeTextModelHighlighter.js';
import { IEditorWorkerService } from '../../../common/services/editorWorker.js';
import { ILanguageService } from '../../../common/languages/language.js';
import { isModelDecorationInComment, isModelDecorationInString, isModelDecorationVisible } from '../../../common/viewModel/viewModelDecorations.js';
import { HoverParticipantRegistry } from '../../hover/browser/hoverTypes.js';
import { MarkdownHover, renderMarkdownHovers } from '../../hover/browser/markdownHoverParticipant.js';
import { BannerController } from './bannerController.js';
import * as nls from '../../../../nls.js';
import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';
import { IOpenerService } from '../../../../platform/opener/common/opener.js';
import { IQuickInputService } from '../../../../platform/quickinput/common/quickInput.js';
import { registerIcon } from '../../../../platform/theme/common/iconRegistry.js';
import { IWorkspaceTrustManagementService } from '../../../../platform/workspace/common/workspaceTrust.js';
export const warningIcon = registerIcon('extensions-warning-message', Codicon.warning, nls.localize('warningIcon', 'Icon shown with a warning message in the extensions editor.'));
let UnicodeHighlighter = class UnicodeHighlighter extends Disposable {
static { this.ID = 'editor.contrib.unicodeHighlighter'; }
constructor(_editor, _editorWorkerService, _workspaceTrustService, instantiationService) {
super();
this._editor = _editor;
this._editorWorkerService = _editorWorkerService;
this._workspaceTrustService = _workspaceTrustService;
this._highlighter = null;
this._bannerClosed = false;
this._updateState = (state) => {
if (state && state.hasMore) {
if (this._bannerClosed) {
return;
}
// This document contains many non-basic ASCII characters.
const max = Math.max(state.ambiguousCharacterCount, state.nonBasicAsciiCharacterCount, state.invisibleCharacterCount);
let data;
if (state.nonBasicAsciiCharacterCount >= max) {
data = {
message: nls.localize('unicodeHighlighting.thisDocumentHasManyNonBasicAsciiUnicodeCharacters', 'This document contains many non-basic ASCII unicode characters'),
command: new DisableHighlightingOfNonBasicAsciiCharactersAction(),
};
}
else if (state.ambiguousCharacterCount >= max) {
data = {
message: nls.localize('unicodeHighlighting.thisDocumentHasManyAmbiguousUnicodeCharacters', 'This document contains many ambiguous unicode characters'),
command: new DisableHighlightingOfAmbiguousCharactersAction(),
};
}
else if (state.invisibleCharacterCount >= max) {
data = {
message: nls.localize('unicodeHighlighting.thisDocumentHasManyInvisibleUnicodeCharacters', 'This document contains many invisible unicode characters'),
command: new DisableHighlightingOfInvisibleCharactersAction(),
};
}
else {
throw new Error('Unreachable');
}
this._bannerController.show({
id: 'unicodeHighlightBanner',
message: data.message,
icon: warningIcon,
actions: [
{
label: data.command.shortLabel,
href: `command:${data.command.id}`
}
],
onClose: () => {
this._bannerClosed = true;
},
});
}
else {
this._bannerController.hide();
}
};
this._bannerController = this._register(instantiationService.createInstance(BannerController, _editor));
this._register(this._editor.onDidChangeModel(() => {
this._bannerClosed = false;
this._updateHighlighter();
}));
this._options = _editor.getOption(126 /* EditorOption.unicodeHighlighting */);
this._register(_workspaceTrustService.onDidChangeTrust(e => {
this._updateHighlighter();
}));
this._register(_editor.onDidChangeConfiguration(e => {
if (e.hasChanged(126 /* EditorOption.unicodeHighlighting */)) {
this._options = _editor.getOption(126 /* EditorOption.unicodeHighlighting */);
this._updateHighlighter();
}
}));
this._updateHighlighter();
}
dispose() {
if (this._highlighter) {
this._highlighter.dispose();
this._highlighter = null;
}
super.dispose();
}
_updateHighlighter() {
this._updateState(null);
if (this._highlighter) {
this._highlighter.dispose();
this._highlighter = null;
}
if (!this._editor.hasModel()) {
return;
}
const options = resolveOptions(this._workspaceTrustService.isWorkspaceTrusted(), this._options);
if ([
options.nonBasicASCII,
options.ambiguousCharacters,
options.invisibleCharacters,
].every((option) => option === false)) {
// Don't do anything if the feature is fully disabled
return;
}
const highlightOptions = {
nonBasicASCII: options.nonBasicASCII,
ambiguousCharacters: options.ambiguousCharacters,
invisibleCharacters: options.invisibleCharacters,
includeComments: options.includeComments,
includeStrings: options.includeStrings,
allowedCodePoints: Object.keys(options.allowedCharacters).map(c => c.codePointAt(0)),
allowedLocales: Object.keys(options.allowedLocales).map(locale => {
if (locale === '_os') {
const osLocale = new Intl.NumberFormat().resolvedOptions().locale;
return osLocale;
}
else if (locale === '_vscode') {
return platform.language;
}
return locale;
}),
};
if (this._editorWorkerService.canComputeUnicodeHighlights(this._editor.getModel().uri)) {
this._highlighter = new DocumentUnicodeHighlighter(this._editor, highlightOptions, this._updateState, this._editorWorkerService);
}
else {
this._highlighter = new ViewportUnicodeHighlighter(this._editor, highlightOptions, this._updateState);
}
}
getDecorationInfo(decoration) {
if (this._highlighter) {
return this._highlighter.getDecorationInfo(decoration);
}
return null;
}
};
UnicodeHighlighter = __decorate([
__param(1, IEditorWorkerService),
__param(2, IWorkspaceTrustManagementService),
__param(3, IInstantiationService)
], UnicodeHighlighter);
export { UnicodeHighlighter };
function resolveOptions(trusted, options) {
return {
nonBasicASCII: options.nonBasicASCII === inUntrustedWorkspace ? !trusted : options.nonBasicASCII,
ambiguousCharacters: options.ambiguousCharacters,
invisibleCharacters: options.invisibleCharacters,
includeComments: options.includeComments === inUntrustedWorkspace ? !trusted : options.includeComments,
includeStrings: options.includeStrings === inUntrustedWorkspace ? !trusted : options.includeStrings,
allowedCharacters: options.allowedCharacters,
allowedLocales: options.allowedLocales,
};
}
let DocumentUnicodeHighlighter = class DocumentUnicodeHighlighter extends Disposable {
constructor(_editor, _options, _updateState, _editorWorkerService) {
super();
this._editor = _editor;
this._options = _options;
this._updateState = _updateState;
this._editorWorkerService = _editorWorkerService;
this._model = this._editor.getModel();
this._decorations = this._editor.createDecorationsCollection();
this._updateSoon = this._register(new RunOnceScheduler(() => this._update(), 250));
this._register(this._editor.onDidChangeModelContent(() => {
this._updateSoon.schedule();
}));
this._updateSoon.schedule();
}
dispose() {
this._decorations.clear();
super.dispose();
}
_update() {
if (this._model.isDisposed()) {
return;
}
if (!this._model.mightContainNonBasicASCII()) {
this._decorations.clear();
return;
}
const modelVersionId = this._model.getVersionId();
this._editorWorkerService
.computedUnicodeHighlights(this._model.uri, this._options)
.then((info) => {
if (this._model.isDisposed()) {
return;
}
if (this._model.getVersionId() !== modelVersionId) {
// model changed in the meantime
return;
}
this._updateState(info);
const decorations = [];
if (!info.hasMore) {
// Don't show decoration if there are too many.
// In this case, a banner is shown.
for (const range of info.ranges) {
decorations.push({
range: range,
options: Decorations.instance.getDecorationFromOptions(this._options),
});
}
}
this._decorations.set(decorations);
});
}
getDecorationInfo(decoration) {
if (!this._decorations.has(decoration)) {
return null;
}
const model = this._editor.getModel();
if (!isModelDecorationVisible(model, decoration)) {
return null;
}
const text = model.getValueInRange(decoration.range);
return {
reason: computeReason(text, this._options),
inComment: isModelDecorationInComment(model, decoration),
inString: isModelDecorationInString(model, decoration),
};
}
};
DocumentUnicodeHighlighter = __decorate([
__param(3, IEditorWorkerService)
], DocumentUnicodeHighlighter);
class ViewportUnicodeHighlighter extends Disposable {
constructor(_editor, _options, _updateState) {
super();
this._editor = _editor;
this._options = _options;
this._updateState = _updateState;
this._model = this._editor.getModel();
this._decorations = this._editor.createDecorationsCollection();
this._updateSoon = this._register(new RunOnceScheduler(() => this._update(), 250));
this._register(this._editor.onDidLayoutChange(() => {
this._updateSoon.schedule();
}));
this._register(this._editor.onDidScrollChange(() => {
this._updateSoon.schedule();
}));
this._register(this._editor.onDidChangeHiddenAreas(() => {
this._updateSoon.schedule();
}));
this._register(this._editor.onDidChangeModelContent(() => {
this._updateSoon.schedule();
}));
this._updateSoon.schedule();
}
dispose() {
this._decorations.clear();
super.dispose();
}
_update() {
if (this._model.isDisposed()) {
return;
}
if (!this._model.mightContainNonBasicASCII()) {
this._decorations.clear();
return;
}
const ranges = this._editor.getVisibleRanges();
const decorations = [];
const totalResult = {
ranges: [],
ambiguousCharacterCount: 0,
invisibleCharacterCount: 0,
nonBasicAsciiCharacterCount: 0,
hasMore: false,
};
for (const range of ranges) {
const result = UnicodeTextModelHighlighter.computeUnicodeHighlights(this._model, this._options, range);
for (const r of result.ranges) {
totalResult.ranges.push(r);
}
totalResult.ambiguousCharacterCount += totalResult.ambiguousCharacterCount;
totalResult.invisibleCharacterCount += totalResult.invisibleCharacterCount;
totalResult.nonBasicAsciiCharacterCount += totalResult.nonBasicAsciiCharacterCount;
totalResult.hasMore = totalResult.hasMore || result.hasMore;
}
if (!totalResult.hasMore) {
// Don't show decorations if there are too many.
// A banner will be shown instead.
for (const range of totalResult.ranges) {
decorations.push({ range, options: Decorations.instance.getDecorationFromOptions(this._options) });
}
}
this._updateState(totalResult);
this._decorations.set(decorations);
}
getDecorationInfo(decoration) {
if (!this._decorations.has(decoration)) {
return null;
}
const model = this._editor.getModel();
const text = model.getValueInRange(decoration.range);
if (!isModelDecorationVisible(model, decoration)) {
return null;
}
return {
reason: computeReason(text, this._options),
inComment: isModelDecorationInComment(model, decoration),
inString: isModelDecorationInString(model, decoration),
};
}
}
const configureUnicodeHighlightOptionsStr = nls.localize('unicodeHighlight.configureUnicodeHighlightOptions', 'Configure Unicode Highlight Options');
let UnicodeHighlighterHoverParticipant = class UnicodeHighlighterHoverParticipant {
constructor(_editor, _languageService, _openerService) {
this._editor = _editor;
this._languageService = _languageService;
this._openerService = _openerService;
this.hoverOrdinal = 5;
}
computeSync(anchor, lineDecorations) {
if (!this._editor.hasModel() || anchor.type !== 1 /* HoverAnchorType.Range */) {
return [];
}
const model = this._editor.getModel();
const unicodeHighlighter = this._editor.getContribution(UnicodeHighlighter.ID);
if (!unicodeHighlighter) {
return [];
}
const result = [];
const existedReason = new Set();
let index = 300;
for (const d of lineDecorations) {
const highlightInfo = unicodeHighlighter.getDecorationInfo(d);
if (!highlightInfo) {
continue;
}
const char = model.getValueInRange(d.range);
// text refers to a single character.
const codePoint = char.codePointAt(0);
const codePointStr = formatCodePointMarkdown(codePoint);
let reason;
switch (highlightInfo.reason.kind) {
case 0 /* UnicodeHighlighterReasonKind.Ambiguous */: {
if (isBasicASCII(highlightInfo.reason.confusableWith)) {
reason = nls.localize('unicodeHighlight.characterIsAmbiguousASCII', 'The character {0} could be confused with the ASCII character {1}, which is more common in source code.', codePointStr, formatCodePointMarkdown(highlightInfo.reason.confusableWith.codePointAt(0)));
}
else {
reason = nls.localize('unicodeHighlight.characterIsAmbiguous', 'The character {0} could be confused with the character {1}, which is more common in source code.', codePointStr, formatCodePointMarkdown(highlightInfo.reason.confusableWith.codePointAt(0)));
}
break;
}
case 1 /* UnicodeHighlighterReasonKind.Invisible */:
reason = nls.localize('unicodeHighlight.characterIsInvisible', 'The character {0} is invisible.', codePointStr);
break;
case 2 /* UnicodeHighlighterReasonKind.NonBasicAscii */:
reason = nls.localize('unicodeHighlight.characterIsNonBasicAscii', 'The character {0} is not a basic ASCII character.', codePointStr);
break;
}
if (existedReason.has(reason)) {
continue;
}
existedReason.add(reason);
const adjustSettingsArgs = {
codePoint: codePoint,
reason: highlightInfo.reason,
inComment: highlightInfo.inComment,
inString: highlightInfo.inString,
};
const adjustSettings = nls.localize('unicodeHighlight.adjustSettings', 'Adjust settings');
const uri = `command:${ShowExcludeOptions.ID}?${encodeURIComponent(JSON.stringify(adjustSettingsArgs))}`;
const markdown = new MarkdownString('', true)
.appendMarkdown(reason)
.appendText(' ')
.appendLink(uri, adjustSettings, configureUnicodeHighlightOptionsStr);
result.push(new MarkdownHover(this, d.range, [markdown], false, index++));
}
return result;
}
renderHoverParts(context, hoverParts) {
return renderMarkdownHovers(context, hoverParts, this._editor, this._languageService, this._openerService);
}
};
UnicodeHighlighterHoverParticipant = __decorate([
__param(1, ILanguageService),
__param(2, IOpenerService)
], UnicodeHighlighterHoverParticipant);
export { UnicodeHighlighterHoverParticipant };
function codePointToHex(codePoint) {
return `U+${codePoint.toString(16).padStart(4, '0')}`;
}
function formatCodePointMarkdown(codePoint) {
let value = `\`${codePointToHex(codePoint)}\``;
if (!InvisibleCharacters.isInvisibleCharacter(codePoint)) {
// Don't render any control characters or any invisible characters, as they cannot be seen anyways.
value += ` "${`${renderCodePointAsInlineCode(codePoint)}`}"`;
}
return value;
}
function renderCodePointAsInlineCode(codePoint) {
if (codePoint === 96 /* CharCode.BackTick */) {
return '`` ` ``';
}
return '`' + String.fromCodePoint(codePoint) + '`';
}
function computeReason(char, options) {
return UnicodeTextModelHighlighter.computeUnicodeHighlightReason(char, options);
}
class Decorations {
constructor() {
this.map = new Map();
}
static { this.instance = new Decorations(); }
getDecorationFromOptions(options) {
return this.getDecoration(!options.includeComments, !options.includeStrings);
}
getDecoration(hideInComments, hideInStrings) {
const key = `${hideInComments}${hideInStrings}`;
let options = this.map.get(key);
if (!options) {
options = ModelDecorationOptions.createDynamic({
description: 'unicode-highlight',
stickiness: 1 /* TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges */,
className: 'unicode-highlight',
showIfCollapsed: true,
overviewRuler: null,
minimap: null,
hideInCommentTokens: hideInComments,
hideInStringTokens: hideInStrings,
});
this.map.set(key, options);
}
return options;
}
}
export class DisableHighlightingInCommentsAction extends EditorAction {
constructor() {
super({
id: DisableHighlightingOfAmbiguousCharactersAction.ID,
label: nls.localize('action.unicodeHighlight.disableHighlightingInComments', 'Disable highlighting of characters in comments'),
alias: 'Disable highlighting of characters in comments',
precondition: undefined
});
this.shortLabel = nls.localize('unicodeHighlight.disableHighlightingInComments.shortLabel', 'Disable Highlight In Comments');
}
async run(accessor, editor, args) {
const configurationService = accessor?.get(IConfigurationService);
if (configurationService) {
this.runAction(configurationService);
}
}
async runAction(configurationService) {
await configurationService.updateValue(unicodeHighlightConfigKeys.includeComments, false, 2 /* ConfigurationTarget.USER */);
}
}
export class DisableHighlightingInStringsAction extends EditorAction {
constructor() {
super({
id: DisableHighlightingOfAmbiguousCharactersAction.ID,
label: nls.localize('action.unicodeHighlight.disableHighlightingInStrings', 'Disable highlighting of characters in strings'),
alias: 'Disable highlighting of characters in strings',
precondition: undefined
});
this.shortLabel = nls.localize('unicodeHighlight.disableHighlightingInStrings.shortLabel', 'Disable Highlight In Strings');
}
async run(accessor, editor, args) {
const configurationService = accessor?.get(IConfigurationService);
if (configurationService) {
this.runAction(configurationService);
}
}
async runAction(configurationService) {
await configurationService.updateValue(unicodeHighlightConfigKeys.includeStrings, false, 2 /* ConfigurationTarget.USER */);
}
}
export class DisableHighlightingOfAmbiguousCharactersAction extends EditorAction {
static { this.ID = 'editor.action.unicodeHighlight.disableHighlightingOfAmbiguousCharacters'; }
constructor() {
super({
id: DisableHighlightingOfAmbiguousCharactersAction.ID,
label: nls.localize('action.unicodeHighlight.disableHighlightingOfAmbiguousCharacters', 'Disable highlighting of ambiguous characters'),
alias: 'Disable highlighting of ambiguous characters',
precondition: undefined
});
this.shortLabel = nls.localize('unicodeHighlight.disableHighlightingOfAmbiguousCharacters.shortLabel', 'Disable Ambiguous Highlight');
}
async run(accessor, editor, args) {
const configurationService = accessor?.get(IConfigurationService);
if (configurationService) {
this.runAction(configurationService);
}
}
async runAction(configurationService) {
await configurationService.updateValue(unicodeHighlightConfigKeys.ambiguousCharacters, false, 2 /* ConfigurationTarget.USER */);
}
}
export class DisableHighlightingOfInvisibleCharactersAction extends EditorAction {
static { this.ID = 'editor.action.unicodeHighlight.disableHighlightingOfInvisibleCharacters'; }
constructor() {
super({
id: DisableHighlightingOfInvisibleCharactersAction.ID,
label: nls.localize('action.unicodeHighlight.disableHighlightingOfInvisibleCharacters', 'Disable highlighting of invisible characters'),
alias: 'Disable highlighting of invisible characters',
precondition: undefined
});
this.shortLabel = nls.localize('unicodeHighlight.disableHighlightingOfInvisibleCharacters.shortLabel', 'Disable Invisible Highlight');
}
async run(accessor, editor, args) {
const configurationService = accessor?.get(IConfigurationService);
if (configurationService) {
this.runAction(configurationService);
}
}
async runAction(configurationService) {
await configurationService.updateValue(unicodeHighlightConfigKeys.invisibleCharacters, false, 2 /* ConfigurationTarget.USER */);
}
}
export class DisableHighlightingOfNonBasicAsciiCharactersAction extends EditorAction {
static { this.ID = 'editor.action.unicodeHighlight.disableHighlightingOfNonBasicAsciiCharacters'; }
constructor() {
super({
id: DisableHighlightingOfNonBasicAsciiCharactersAction.ID,
label: nls.localize('action.unicodeHighlight.disableHighlightingOfNonBasicAsciiCharacters', 'Disable highlighting of non basic ASCII characters'),
alias: 'Disable highlighting of non basic ASCII characters',
precondition: undefined
});
this.shortLabel = nls.localize('unicodeHighlight.disableHighlightingOfNonBasicAsciiCharacters.shortLabel', 'Disable Non ASCII Highlight');
}
async run(accessor, editor, args) {
const configurationService = accessor?.get(IConfigurationService);
if (configurationService) {
this.runAction(configurationService);
}
}
async runAction(configurationService) {
await configurationService.updateValue(unicodeHighlightConfigKeys.nonBasicASCII, false, 2 /* ConfigurationTarget.USER */);
}
}
export class ShowExcludeOptions extends EditorAction {
static { this.ID = 'editor.action.unicodeHighlight.showExcludeOptions'; }
constructor() {
super({
id: ShowExcludeOptions.ID,
label: nls.localize('action.unicodeHighlight.showExcludeOptions', "Show Exclude Options"),
alias: 'Show Exclude Options',
precondition: undefined
});
}
async run(accessor, editor, args) {
const { codePoint, reason, inString, inComment } = args;
const char = String.fromCodePoint(codePoint);
const quickPickService = accessor.get(IQuickInputService);
const configurationService = accessor.get(IConfigurationService);
function getExcludeCharFromBeingHighlightedLabel(codePoint) {
if (InvisibleCharacters.isInvisibleCharacter(codePoint)) {
return nls.localize('unicodeHighlight.excludeInvisibleCharFromBeingHighlighted', 'Exclude {0} (invisible character) from being highlighted', codePointToHex(codePoint));
}
return nls.localize('unicodeHighlight.excludeCharFromBeingHighlighted', 'Exclude {0} from being highlighted', `${codePointToHex(codePoint)} "${char}"`);
}
const options = [];
if (reason.kind === 0 /* UnicodeHighlighterReasonKind.Ambiguous */) {
for (const locale of reason.notAmbiguousInLocales) {
options.push({
label: nls.localize("unicodeHighlight.allowCommonCharactersInLanguage", "Allow unicode characters that are more common in the language \"{0}\".", locale),
run: async () => {
excludeLocaleFromBeingHighlighted(configurationService, [locale]);
},
});
}
}
options.push({
label: getExcludeCharFromBeingHighlightedLabel(codePoint),
run: () => excludeCharFromBeingHighlighted(configurationService, [codePoint])
});
if (inComment) {
const action = new DisableHighlightingInCommentsAction();
options.push({ label: action.label, run: async () => action.runAction(configurationService) });
}
else if (inString) {
const action = new DisableHighlightingInStringsAction();
options.push({ label: action.label, run: async () => action.runAction(configurationService) });
}
if (reason.kind === 0 /* UnicodeHighlighterReasonKind.Ambiguous */) {
const action = new DisableHighlightingOfAmbiguousCharactersAction();
options.push({ label: action.label, run: async () => action.runAction(configurationService) });
}
else if (reason.kind === 1 /* UnicodeHighlighterReasonKind.Invisible */) {
const action = new DisableHighlightingOfInvisibleCharactersAction();
options.push({ label: action.label, run: async () => action.runAction(configurationService) });
}
else if (reason.kind === 2 /* UnicodeHighlighterReasonKind.NonBasicAscii */) {
const action = new DisableHighlightingOfNonBasicAsciiCharactersAction();
options.push({ label: action.label, run: async () => action.runAction(configurationService) });
}
else {
expectNever(reason);
}
const result = await quickPickService.pick(options, { title: configureUnicodeHighlightOptionsStr });
if (result) {
await result.run();
}
}
}
async function excludeCharFromBeingHighlighted(configurationService, charCodes) {
const existingValue = configurationService.getValue(unicodeHighlightConfigKeys.allowedCharacters);
let value;
if ((typeof existingValue === 'object') && existingValue) {
value = existingValue;
}
else {
value = {};
}
for (const charCode of charCodes) {
value[String.fromCodePoint(charCode)] = true;
}
await configurationService.updateValue(unicodeHighlightConfigKeys.allowedCharacters, value, 2 /* ConfigurationTarget.USER */);
}
async function excludeLocaleFromBeingHighlighted(configurationService, locales) {
const existingValue = configurationService.inspect(unicodeHighlightConfigKeys.allowedLocales).user?.value;
let value;
if ((typeof existingValue === 'object') && existingValue) {
// Copy value, as the existing value is read only
value = Object.assign({}, existingValue);
}
else {
value = {};
}
for (const locale of locales) {
value[locale] = true;
}
await configurationService.updateValue(unicodeHighlightConfigKeys.allowedLocales, value, 2 /* ConfigurationTarget.USER */);
}
function expectNever(value) {
throw new Error(`Unexpected value: ${value}`);
}
registerEditorAction(DisableHighlightingOfAmbiguousCharactersAction);
registerEditorAction(DisableHighlightingOfInvisibleCharactersAction);
registerEditorAction(DisableHighlightingOfNonBasicAsciiCharactersAction);
registerEditorAction(ShowExcludeOptions);
registerEditorContribution(UnicodeHighlighter.ID, UnicodeHighlighter, 1 /* EditorContributionInstantiation.AfterFirstRender */);
HoverParticipantRegistry.register(UnicodeHighlighterHoverParticipant);