
import { registerCss } from '../../../../../../../../css.js';
import { __decorate, __param } from '../../../../../../../../external/tslib/tslib.es6.js';
import * as inspectEditorTokens from './inspectEditorTokens.css';
import { localize2, localize } from '../../../../../nls.js';
import { $ as $$1, createElement, clearNode, createTextNode, reset, append, isHTMLElement } from '../../../../../base/browser/dom.js';
import { CharCode } from '../../../../../base/common/charCode.js';
import { Color } from '../../../../../base/common/color.js';
import { KeyCode } from '../../../../../base/common/keyCodes.js';
import { Disposable } from '../../../../../base/common/lifecycle.js';
import { ContentWidgetPositionPreference } from '../../../../../editor/browser/editorBrowser.js';
import { EditorAction, registerEditorContribution, EditorContributionInstantiation, registerEditorAction } from '../../../../../editor/browser/editorExtensions.js';
import { Range } from '../../../../../editor/common/core/range.js';
import { StandardTokenType, TokenMetadata, FontStyle, ColorId } from '../../../../../editor/common/encodedTokenAttributes.js';
import { ILanguageService } from '../../../../../editor/common/languages/language.service.js';
import { INotificationService } from '../../../../../platform/notification/common/notification.service.js';
import { findMatchingThemeRule } from '../../../../services/textMate/common/TMHelper.js';
import { ITextMateTokenizationService } from '../../../../services/textMate/browser/textMateTokenizationFeature.service.js';
import { IWorkbenchThemeService } from '../../../../services/themes/common/workbenchThemeService.service.js';
import { CancellationTokenSource } from '../../../../../base/common/cancellation.js';
import { SemanticTokenRule } from '../../../../../platform/theme/common/tokenClassificationRegistry.js';
import { IConfigurationService } from '../../../../../platform/configuration/common/configuration.service.js';
import { SEMANTIC_HIGHLIGHTING_SETTING_ID } from '../../../../../editor/contrib/semanticTokens/common/semanticTokensConfig.js';
import { Schemas } from '../../../../../base/common/network.js';
import { ILanguageFeaturesService } from '../../../../../editor/common/services/languageFeatures.service.js';
import { TreeSitterSyntaxTokenBackend } from '../../../../../editor/common/model/tokens/treeSitter/treeSitterSyntaxTokenBackend.js';

var InspectEditorTokensController_1;
registerCss(inspectEditorTokens);
const $ = $$1;
let InspectEditorTokensController = class InspectEditorTokensController extends Disposable {
    static {
        InspectEditorTokensController_1 = this;
    }
    static {
        this.ID = "editor.contrib.inspectEditorTokens";
    }
    static get(editor) {
        return editor.getContribution(InspectEditorTokensController_1.ID);
    }
    constructor(
        editor,
        textMateService,
        languageService,
        themeService,
        notificationService,
        configurationService,
        languageFeaturesService
    ) {
        super();
        this._editor = editor;
        this._textMateService = textMateService;
        this._themeService = themeService;
        this._languageService = languageService;
        this._notificationService = notificationService;
        this._configurationService = configurationService;
        this._languageFeaturesService = languageFeaturesService;
        this._widget = null;
        this._register(this._editor.onDidChangeModel(e => this.stop()));
        this._register(this._editor.onDidChangeModelLanguage(e => this.stop()));
        this._register(this._editor.onKeyUp(e => e.keyCode === KeyCode.Escape && this.stop()));
    }
    dispose() {
        this.stop();
        super.dispose();
    }
    launch() {
        if (this._widget) {
            return;
        }
        if (!this._editor.hasModel()) {
            return;
        }
        if (this._editor.getModel().uri.scheme === Schemas.vscodeNotebookCell) {
            return;
        }
        this._widget = ( new InspectEditorTokensWidget(
            this._editor,
            this._textMateService,
            this._languageService,
            this._themeService,
            this._notificationService,
            this._configurationService,
            this._languageFeaturesService
        ));
    }
    stop() {
        if (this._widget) {
            this._widget.dispose();
            this._widget = null;
        }
    }
    toggle() {
        if (!this._widget) {
            this.launch();
        } else {
            this.stop();
        }
    }
};
InspectEditorTokensController = InspectEditorTokensController_1 = ( __decorate([( __param(1, ITextMateTokenizationService)), ( __param(2, ILanguageService)), ( __param(3, IWorkbenchThemeService)), ( __param(4, INotificationService)), ( __param(5, IConfigurationService)), ( __param(6, ILanguageFeaturesService))], InspectEditorTokensController));
class InspectEditorTokens extends EditorAction {
    constructor() {
        super({
            id: "editor.action.inspectTMScopes",
            label: ( localize2(8459, "Developer: Inspect Editor Tokens and Scopes")),
            precondition: undefined
        });
    }
    run(accessor, editor) {
        const controller = InspectEditorTokensController.get(editor);
        controller?.toggle();
    }
}
function renderTokenText(tokenText) {
    if (tokenText.length > 40) {
        tokenText = tokenText.substr(0, 20) + "…" + tokenText.substr(tokenText.length - 20);
    }
    let result = "";
    for (let charIndex = 0, len = tokenText.length; charIndex < len; charIndex++) {
        const charCode = tokenText.charCodeAt(charIndex);
        switch (charCode) {
        case CharCode.Tab:
            result += "→";
            break;
        case CharCode.Space:
            result += "·";
            break;
        default:
            result += String.fromCharCode(charCode);
        }
    }
    return result;
}
class InspectEditorTokensWidget extends Disposable {
    static {
        this._ID = "editor.contrib.inspectEditorTokensWidget";
    }
    constructor(
        editor,
        textMateService,
        languageService,
        themeService,
        notificationService,
        configurationService,
        languageFeaturesService
    ) {
        super();
        this.allowEditorOverflow = true;
        this._isDisposed = false;
        this._editor = editor;
        this._languageService = languageService;
        this._themeService = themeService;
        this._textMateService = textMateService;
        this._notificationService = notificationService;
        this._configurationService = configurationService;
        this._languageFeaturesService = languageFeaturesService;
        this._model = this._editor.getModel();
        this._domNode = createElement("div");
        this._domNode.className = "token-inspect-widget";
        this._currentRequestCancellationTokenSource = ( new CancellationTokenSource());
        this._beginCompute(this._editor.getPosition());
        this._register(
            this._editor.onDidChangeCursorPosition(e => this._beginCompute(this._editor.getPosition()))
        );
        this._register(
            themeService.onDidColorThemeChange(_ => this._beginCompute(this._editor.getPosition()))
        );
        this._register(configurationService.onDidChangeConfiguration(
            e => e.affectsConfiguration("editor.semanticHighlighting.enabled") && this._beginCompute(this._editor.getPosition())
        ));
        this._editor.addContentWidget(this);
    }
    dispose() {
        this._isDisposed = true;
        this._editor.removeContentWidget(this);
        this._currentRequestCancellationTokenSource.cancel();
        super.dispose();
    }
    getId() {
        return InspectEditorTokensWidget._ID;
    }
    _beginCompute(position) {
        const grammar = this._textMateService.createTokenizer(this._model.getLanguageId());
        const semanticTokens = this._computeSemanticTokens(position);
        const backend = this._model.tokenization.tokens.get();
        const asTreeSitterBackend = backend instanceof TreeSitterSyntaxTokenBackend ? backend : undefined;
        clearNode(this._domNode);
        this._domNode.appendChild(createTextNode(( localize(8460, "Loading..."))));
        Promise.all([grammar, semanticTokens]).then(([grammar, semanticTokens]) => {
            if (this._isDisposed) {
                return;
            }
            const treeSitterTree = asTreeSitterBackend?.tree.get();
            this._compute(grammar, semanticTokens, treeSitterTree, position);
            this._domNode.style.maxWidth = `${Math.max(this._editor.getLayoutInfo().width * 0.66, 500)}px`;
            this._editor.layoutContentWidget(this);
        }, err => {
            this._notificationService.warn(err);
            setTimeout(() => {
                InspectEditorTokensController.get(this._editor)?.stop();
            });
        });
    }
    _isSemanticColoringEnabled() {
        const setting = this._configurationService.getValue(SEMANTIC_HIGHLIGHTING_SETTING_ID, {
            overrideIdentifier: this._model.getLanguageId(),
            resource: this._model.uri
        })?.enabled;
        if (typeof setting === "boolean") {
            return setting;
        }
        return this._themeService.getColorTheme().semanticHighlighting;
    }
    _compute(grammar, semanticTokens, tree, position) {
        const textMateTokenInfo = grammar && this._getTokensAtPosition(grammar, position);
        const semanticTokenInfo = semanticTokens && this._getSemanticTokenAtPosition(semanticTokens, position);
        const treeSitterTokenInfo = tree && this._getTreeSitterTokenAtPosition(tree, position);
        if (!textMateTokenInfo && !semanticTokenInfo && !treeSitterTokenInfo) {
            reset(this._domNode, "No grammar or semantic tokens available.");
            return;
        }
        const tmMetadata = textMateTokenInfo?.metadata;
        const semMetadata = semanticTokenInfo?.metadata;
        const semTokenText = semanticTokenInfo && renderTokenText(this._model.getValueInRange(semanticTokenInfo.range));
        const tmTokenText = textMateTokenInfo && renderTokenText(
            this._model.getLineContent(position.lineNumber).substring(textMateTokenInfo.token.startIndex, textMateTokenInfo.token.endIndex)
        );
        const semTokenLength = semanticTokenInfo && this._model.getValueLengthInRange(semanticTokenInfo.range);
        const tmTokenLength = textMateTokenInfo && (textMateTokenInfo.token.endIndex - textMateTokenInfo.token.startIndex);
        const tokenText = semTokenText || tmTokenText || "";
        const tokenLength = semTokenLength || tmTokenLength || 0;
        reset(this._domNode, $("h2.tiw-token", undefined, tokenText, $(
            "span.tiw-token-length",
            undefined,
            `${tokenLength} ${tokenLength === 1 ? "char" : "chars"}`
        )));
        append(this._domNode, $("hr.tiw-metadata-separator", {
            "style": "clear:both"
        }));
        append(
            this._domNode,
            $("table.tiw-metadata-table", undefined, $("tbody", undefined, $(
                "tr",
                undefined,
                $("td.tiw-metadata-key", undefined, "language"),
                $("td.tiw-metadata-value", undefined, tmMetadata?.languageId || "")
            ), $(
                "tr",
                undefined,
                $("td.tiw-metadata-key", undefined, "standard token type"),
                $(
                    "td.tiw-metadata-value",
                    undefined,
                    this._tokenTypeToString(tmMetadata?.tokenType || StandardTokenType.Other)
                )
            ), ...this._formatMetadata(semMetadata, tmMetadata)))
        );
        if (semanticTokenInfo) {
            append(this._domNode, $("hr.tiw-metadata-separator"));
            const table = append(this._domNode, $("table.tiw-metadata-table", undefined));
            const tbody = append(table, $("tbody", undefined, $(
                "tr",
                undefined,
                $("td.tiw-metadata-key", undefined, "semantic token type"),
                $("td.tiw-metadata-value", undefined, semanticTokenInfo.type)
            )));
            if (semanticTokenInfo.modifiers.length) {
                append(tbody, $(
                    "tr",
                    undefined,
                    $("td.tiw-metadata-key", undefined, "modifiers"),
                    $("td.tiw-metadata-value", undefined, semanticTokenInfo.modifiers.join(" "))
                ));
            }
            if (semanticTokenInfo.metadata) {
                const properties = ["foreground", "bold", "italic", "underline", "strikethrough"];
                const propertiesByDefValue = {};
                const allDefValues = ( new Array());
                for (const property of properties) {
                    if (semanticTokenInfo.metadata[property] !== undefined) {
                        const definition = semanticTokenInfo.definitions[property];
                        const defValue = this._renderTokenStyleDefinition(definition, property);
                        const defValueStr = ( defValue.map(el => isHTMLElement(el) ? el.outerHTML : el)).join();
                        let properties = propertiesByDefValue[defValueStr];
                        if (!properties) {
                            propertiesByDefValue[defValueStr] = properties = [];
                            allDefValues.push([defValue, defValueStr]);
                        }
                        properties.push(property);
                    }
                }
                for (const [defValue, defValueStr] of allDefValues) {
                    append(tbody, $("tr", undefined, $(
                        "td.tiw-metadata-key",
                        undefined,
                        propertiesByDefValue[defValueStr].join(", ")
                    ), $("td.tiw-metadata-value", undefined, ...defValue)));
                }
            }
        }
        if (textMateTokenInfo) {
            const theme = this._themeService.getColorTheme();
            append(this._domNode, $("hr.tiw-metadata-separator"));
            const table = append(this._domNode, $("table.tiw-metadata-table"));
            const tbody = append(table, $("tbody"));
            if (tmTokenText && tmTokenText !== tokenText) {
                append(
                    tbody,
                    $("tr", undefined, $("td.tiw-metadata-key", undefined, "textmate token"), $(
                        "td.tiw-metadata-value",
                        undefined,
                        `${tmTokenText} (${tmTokenText.length})`
                    ))
                );
            }
            const scopes = ( new Array());
            for (let i = textMateTokenInfo.token.scopes.length - 1; i >= 0; i--) {
                scopes.push(textMateTokenInfo.token.scopes[i]);
                if (i > 0) {
                    scopes.push($("br"));
                }
            }
            append(tbody, $(
                "tr",
                undefined,
                $("td.tiw-metadata-key", undefined, "textmate scopes"),
                $("td.tiw-metadata-value.tiw-metadata-scopes", undefined, ...scopes)
            ));
            const matchingRule = findMatchingThemeRule(theme, textMateTokenInfo.token.scopes, false);
            const semForeground = semanticTokenInfo?.metadata?.foreground;
            if (matchingRule) {
                if (semForeground !== textMateTokenInfo.metadata.foreground) {
                    let defValue = $(
                        "code.tiw-theme-selector",
                        undefined,
                        matchingRule.rawSelector,
                        $("br"),
                        JSON.stringify(matchingRule.settings, null, "\t")
                    );
                    if (semForeground) {
                        defValue = $("s", undefined, defValue);
                    }
                    append(tbody, $(
                        "tr",
                        undefined,
                        $("td.tiw-metadata-key", undefined, "foreground"),
                        $("td.tiw-metadata-value", undefined, defValue)
                    ));
                }
            } else if (!semForeground) {
                append(tbody, $(
                    "tr",
                    undefined,
                    $("td.tiw-metadata-key", undefined, "foreground"),
                    $("td.tiw-metadata-value", undefined, "No theme selector")
                ));
            }
        }
        if (treeSitterTokenInfo) {
            const lastTokenInfo = treeSitterTokenInfo[treeSitterTokenInfo.length - 1];
            append(this._domNode, $("hr.tiw-metadata-separator"));
            const table = append(this._domNode, $("table.tiw-metadata-table"));
            const tbody = append(table, $("tbody"));
            append(tbody, $(
                "tr",
                undefined,
                $("td.tiw-metadata-key", undefined, `tree-sitter token ${lastTokenInfo.id}`),
                $("td.tiw-metadata-value", undefined, `${lastTokenInfo.text}`)
            ));
            const scopes = ( new Array());
            let i = treeSitterTokenInfo.length - 1;
            let node = treeSitterTokenInfo[i];
            while (node.parent || i > 0) {
                scopes.push(node.type);
                node = node.parent ?? treeSitterTokenInfo[--i];
                if (node) {
                    scopes.push($("br"));
                }
            }
            append(tbody, $(
                "tr",
                undefined,
                $("td.tiw-metadata-key", undefined, "tree-sitter tree"),
                $("td.tiw-metadata-value.tiw-metadata-scopes", undefined, ...scopes)
            ));
            const tokenizationSupport = this._model.tokenization.tokens.get().tokenizationImpl.get();
            const captures = tokenizationSupport?.captureAtPosition(position.lineNumber, position.column);
            if (captures && captures.length > 0) {
                append(tbody, $(
                    "tr",
                    undefined,
                    $("td.tiw-metadata-key", undefined, "foreground"),
                    $("td.tiw-metadata-value", undefined, ( captures.map(cap => cap.name)).join(" "))
                ));
            }
        }
    }
    _formatMetadata(semantic, tm) {
        const elements = ( new Array());
        function render(property) {
            const value = semantic?.[property] || tm?.[property];
            if (value !== undefined) {
                const semanticStyle = semantic?.[property] ? "tiw-metadata-semantic" : "";
                elements.push($(
                    "tr",
                    undefined,
                    $("td.tiw-metadata-key", undefined, property),
                    $(`td.tiw-metadata-value.${semanticStyle}`, undefined, value)
                ));
            }
            return value;
        }
        const foreground = render("foreground");
        const background = render("background");
        if (foreground && background) {
            const backgroundColor = ( Color.fromHex(background)),
                  foregroundColor = ( Color.fromHex(foreground));
            if (backgroundColor.isOpaque()) {
                elements.push(
                    $("tr", undefined, $("td.tiw-metadata-key", undefined, "contrast ratio"), $(
                        "td.tiw-metadata-value",
                        undefined,
                        backgroundColor.getContrastRatio(foregroundColor.makeOpaque(backgroundColor)).toFixed(2)
                    ))
                );
            } else {
                elements.push($("tr", undefined, $(
                    "td.tiw-metadata-key",
                    undefined,
                    "Contrast ratio cannot be precise for background colors that use transparency"
                ), $("td.tiw-metadata-value")));
            }
        }
        const fontStyleLabels = ( new Array());
        function addStyle(key) {
            let label;
            if (semantic && semantic[key]) {
                label = $("span.tiw-metadata-semantic", undefined, key);
            } else if (tm && tm[key]) {
                label = key;
            }
            if (label) {
                if (fontStyleLabels.length) {
                    fontStyleLabels.push(" ");
                }
                fontStyleLabels.push(label);
            }
        }
        addStyle("bold");
        addStyle("italic");
        addStyle("underline");
        addStyle("strikethrough");
        if (fontStyleLabels.length) {
            elements.push($(
                "tr",
                undefined,
                $("td.tiw-metadata-key", undefined, "font style"),
                $("td.tiw-metadata-value", undefined, ...fontStyleLabels)
            ));
        }
        return elements;
    }
    _decodeMetadata(metadata) {
        const colorMap = this._themeService.getColorTheme().tokenColorMap;
        const languageId = TokenMetadata.getLanguageId(metadata);
        const tokenType = TokenMetadata.getTokenType(metadata);
        const fontStyle = TokenMetadata.getFontStyle(metadata);
        const foreground = TokenMetadata.getForeground(metadata);
        const background = TokenMetadata.getBackground(metadata);
        return {
            languageId: this._languageService.languageIdCodec.decodeLanguageId(languageId),
            tokenType: tokenType,
            bold: (fontStyle & FontStyle.Bold) ? true : undefined,
            italic: (fontStyle & FontStyle.Italic) ? true : undefined,
            underline: (fontStyle & FontStyle.Underline) ? true : undefined,
            strikethrough: (fontStyle & FontStyle.Strikethrough) ? true : undefined,
            foreground: colorMap[foreground],
            background: colorMap[background]
        };
    }
    _tokenTypeToString(tokenType) {
        switch (tokenType) {
        case StandardTokenType.Other:
            return "Other";
        case StandardTokenType.Comment:
            return "Comment";
        case StandardTokenType.String:
            return "String";
        case StandardTokenType.RegEx:
            return "RegEx";
        default:
            return "??";
        }
    }
    _getTokensAtPosition(grammar, position) {
        const lineNumber = position.lineNumber;
        const stateBeforeLine = this._getStateBeforeLine(grammar, lineNumber);
        const tokenizationResult1 = grammar.tokenizeLine(this._model.getLineContent(lineNumber), stateBeforeLine);
        const tokenizationResult2 = grammar.tokenizeLine2(this._model.getLineContent(lineNumber), stateBeforeLine);
        let token1Index = 0;
        for (let i = tokenizationResult1.tokens.length - 1; i >= 0; i--) {
            const t = tokenizationResult1.tokens[i];
            if (position.column - 1 >= t.startIndex) {
                token1Index = i;
                break;
            }
        }
        let token2Index = 0;
        for (let i = (tokenizationResult2.tokens.length >>> 1); i >= 0; i--) {
            if (position.column - 1 >= tokenizationResult2.tokens[(i << 1)]) {
                token2Index = i;
                break;
            }
        }
        return {
            token: tokenizationResult1.tokens[token1Index],
            metadata: this._decodeMetadata(tokenizationResult2.tokens[(token2Index << 1) + 1])
        };
    }
    _getStateBeforeLine(grammar, lineNumber) {
        let state = null;
        for (let i = 1; i < lineNumber; i++) {
            const tokenizationResult = grammar.tokenizeLine(this._model.getLineContent(i), state);
            state = tokenizationResult.ruleStack;
        }
        return state;
    }
    isSemanticTokens(token) {
        return token && token.data;
    }
    async _computeSemanticTokens(position) {
        if (!this._isSemanticColoringEnabled()) {
            return null;
        }
        const tokenProviders = this._languageFeaturesService.documentSemanticTokensProvider.ordered(this._model);
        if (tokenProviders.length) {
            const provider = tokenProviders[0];
            const tokens = await Promise.resolve(
                provider.provideDocumentSemanticTokens(this._model, null, this._currentRequestCancellationTokenSource.token)
            );
            if (this.isSemanticTokens(tokens)) {
                return {
                    tokens,
                    legend: provider.getLegend()
                };
            }
        }
        const rangeTokenProviders = this._languageFeaturesService.documentRangeSemanticTokensProvider.ordered(this._model);
        if (rangeTokenProviders.length) {
            const provider = rangeTokenProviders[0];
            const lineNumber = position.lineNumber;
            const range = ( new Range(lineNumber, 1, lineNumber, this._model.getLineMaxColumn(lineNumber)));
            const tokens = await Promise.resolve(
                provider.provideDocumentRangeSemanticTokens(this._model, range, this._currentRequestCancellationTokenSource.token)
            );
            if (this.isSemanticTokens(tokens)) {
                return {
                    tokens,
                    legend: provider.getLegend()
                };
            }
        }
        return null;
    }
    _getSemanticTokenAtPosition(semanticTokens, pos) {
        const tokenData = semanticTokens.tokens.data;
        const defaultLanguage = this._model.getLanguageId();
        let lastLine = 0;
        let lastCharacter = 0;
        const posLine = pos.lineNumber - 1, posCharacter = pos.column - 1;
        for (let i = 0; i < tokenData.length; i += 5) {
            const lineDelta = tokenData[i], charDelta = tokenData[i + 1], len = tokenData[i + 2], typeIdx = tokenData[i + 3], modSet = tokenData[i + 4];
            const line = lastLine + lineDelta;
            const character = lineDelta === 0 ? lastCharacter + charDelta : charDelta;
            if (posLine === line && character <= posCharacter && posCharacter < character + len) {
                const type = semanticTokens.legend.tokenTypes[typeIdx] || "not in legend (ignored)";
                const modifiers = [];
                let modifierSet = modSet;
                for (let modifierIndex = 0; modifierSet > 0 && modifierIndex < semanticTokens.legend.tokenModifiers.length; modifierIndex++) {
                    if (modifierSet & 1) {
                        modifiers.push(semanticTokens.legend.tokenModifiers[modifierIndex]);
                    }
                    modifierSet = modifierSet >> 1;
                }
                if (modifierSet > 0) {
                    modifiers.push("not in legend (ignored)");
                }
                const range = ( new Range(line + 1, character + 1, line + 1, character + 1 + len));
                const definitions = {};
                const colorMap = this._themeService.getColorTheme().tokenColorMap;
                const theme = this._themeService.getColorTheme();
                const tokenStyle = theme.getTokenStyleMetadata(type, modifiers, defaultLanguage, true, definitions);
                let metadata = undefined;
                if (tokenStyle) {
                    metadata = {
                        languageId: undefined,
                        tokenType: StandardTokenType.Other,
                        bold: tokenStyle?.bold,
                        italic: tokenStyle?.italic,
                        underline: tokenStyle?.underline,
                        strikethrough: tokenStyle?.strikethrough,
                        foreground: colorMap[tokenStyle?.foreground || ColorId.None],
                        background: undefined
                    };
                }
                return {
                    type,
                    modifiers,
                    range,
                    metadata,
                    definitions
                };
            }
            lastLine = line;
            lastCharacter = character;
        }
        return null;
    }
    _walkTreeforPosition(cursor, pos) {
        const offset = this._model.getOffsetAt(pos);
        cursor.gotoFirstChild();
        let goChild = false;
        let lastGoodNode = null;
        do {
            if (cursor.currentNode.startIndex <= offset && offset < cursor.currentNode.endIndex) {
                goChild = true;
                lastGoodNode = cursor.currentNode;
            } else {
                goChild = false;
            }
        } while (goChild ? cursor.gotoFirstChild() : cursor.gotoNextSibling());
        return lastGoodNode;
    }
    _getTreeSitterTokenAtPosition(treeSitterTree, pos) {
        const nodes = [];
        let tree = treeSitterTree?.tree.get();
        while (tree) {
            const cursor = tree.walk();
            const node = this._walkTreeforPosition(cursor, pos);
            cursor.delete();
            if (node) {
                nodes.push(node);
                treeSitterTree = treeSitterTree?.getInjectionTrees(node.startIndex, treeSitterTree.languageId);
                tree = treeSitterTree?.tree.get();
            } else {
                tree = undefined;
            }
        }
        return nodes.length > 0 ? nodes : null;
    }
    _renderTokenStyleDefinition(definition, property) {
        const elements = ( new Array());
        if (definition === undefined) {
            return elements;
        }
        const theme = this._themeService.getColorTheme();
        if (Array.isArray(definition)) {
            const scopesDefinition = {};
            theme.resolveScopes(definition, scopesDefinition);
            const matchingRule = scopesDefinition[property];
            if (matchingRule && scopesDefinition.scope) {
                const scopes = $("ul.tiw-metadata-values");
                const strScopes = Array.isArray(matchingRule.scope) ? matchingRule.scope : [String(matchingRule.scope)];
                for (const strScope of strScopes) {
                    scopes.appendChild($("li.tiw-metadata-value.tiw-metadata-scopes", undefined, strScope));
                }
                elements.push(scopesDefinition.scope.join(" "), scopes, $(
                    "code.tiw-theme-selector",
                    undefined,
                    JSON.stringify(matchingRule.settings, null, "\t")
                ));
                return elements;
            }
            return elements;
        } else if (SemanticTokenRule.is(definition)) {
            const scope = theme.getTokenStylingRuleScope(definition);
            if (scope === "setting") {
                elements.push(
                    `User settings: ${definition.selector.id} - ${this._renderStyleProperty(definition.style, property)}`
                );
                return elements;
            } else if (scope === "theme") {
                elements.push(
                    `Color theme: ${definition.selector.id} - ${this._renderStyleProperty(definition.style, property)}`
                );
                return elements;
            }
            return elements;
        } else {
            const style = theme.resolveTokenStyleValue(definition);
            elements.push(`Default: ${style ? this._renderStyleProperty(style, property) : ""}`);
            return elements;
        }
    }
    _renderStyleProperty(style, property) {
        switch (property) {
        case "foreground":
            return style.foreground ? Color.Format.CSS.formatHexA(style.foreground, true) : "";
        default:
            return style[property] !== undefined ? String(style[property]) : "";
        }
    }
    getDomNode() {
        return this._domNode;
    }
    getPosition() {
        return {
            position: this._editor.getPosition(),
            preference: [
                ContentWidgetPositionPreference.BELOW,
                ContentWidgetPositionPreference.ABOVE
            ]
        };
    }
}
registerEditorContribution(
    InspectEditorTokensController.ID,
    InspectEditorTokensController,
    EditorContributionInstantiation.Lazy
);
registerEditorAction(InspectEditorTokens);

export { InspectEditorTokensController };
