
import { __decorate, __param } from '../../../../../../../external/tslib/tslib.es6.js';
import { localize } from '../../../../nls.js';
import { ExtensionsRegistry } from '../../extensions/common/extensionsRegistry.js';
import { getTokenClassificationRegistry, typeAndModifierIdPattern } from '../../../../platform/theme/common/tokenClassificationRegistry.js';
import { registerWorkbenchContribution2, WorkbenchPhase } from '../../../common/contributions.js';
import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';

const tokenClassificationRegistry = getTokenClassificationRegistry();
const tokenTypeExtPoint = ExtensionsRegistry.registerExtensionPoint({
    extensionPoint: "semanticTokenTypes",
    jsonSchema: {
        description: ( localize(16498, "Contributes semantic token types.")),
        type: "array",
        items: {
            type: "object",
            properties: {
                id: {
                    type: "string",
                    description: ( localize(16499, "The identifier of the semantic token type")),
                    pattern: typeAndModifierIdPattern,
                    patternErrorMessage: ( localize(16500, "Identifiers should be in the form letterOrDigit[_-letterOrDigit]*"))
                },
                superType: {
                    type: "string",
                    description: ( localize(16501, "The super type of the semantic token type")),
                    pattern: typeAndModifierIdPattern,
                    patternErrorMessage: ( localize(16502, "Super types should be in the form letterOrDigit[_-letterOrDigit]*"))
                },
                description: {
                    type: "string",
                    description: ( localize(16503, "The description of the semantic token type"))
                }
            }
        }
    }
});
const tokenModifierExtPoint = ExtensionsRegistry.registerExtensionPoint({
    extensionPoint: "semanticTokenModifiers",
    jsonSchema: {
        description: ( localize(16504, "Contributes semantic token modifiers.")),
        type: "array",
        items: {
            type: "object",
            properties: {
                id: {
                    type: "string",
                    description: ( localize(16505, "The identifier of the semantic token modifier")),
                    pattern: typeAndModifierIdPattern,
                    patternErrorMessage: ( localize(16506, "Identifiers should be in the form letterOrDigit[_-letterOrDigit]*"))
                },
                description: {
                    type: "string",
                    description: ( localize(16507, "The description of the semantic token modifier"))
                }
            }
        }
    }
});
const tokenStyleDefaultsExtPoint = ExtensionsRegistry.registerExtensionPoint({
    extensionPoint: "semanticTokenScopes",
    jsonSchema: {
        description: ( localize(16508, "Contributes semantic token scope maps.")),
        type: "array",
        items: {
            type: "object",
            properties: {
                language: {
                    description: ( localize(16509, "Lists the languge for which the defaults are.")),
                    type: "string"
                },
                scopes: {
                    description: ( localize(
                        16510,
                        "Maps a semantic token (described by semantic token selector) to one or more textMate scopes used to represent that token."
                    )),
                    type: "object",
                    additionalProperties: {
                        type: "array",
                        items: {
                            type: "string"
                        }
                    }
                }
            }
        }
    }
});
class TokenClassificationExtensionPoints {
    constructor() {
        function validateTypeOrModifier(contribution, extensionPoint, collector) {
            if (typeof contribution.id !== "string" || contribution.id.length === 0) {
                collector.error(( localize(
                    16511,
                    "'configuration.{0}.id' must be defined and can not be empty",
                    extensionPoint
                )));
                return false;
            }
            if (!contribution.id.match(typeAndModifierIdPattern)) {
                collector.error(( localize(
                    16512,
                    "'configuration.{0}.id' must follow the pattern letterOrDigit[-_letterOrDigit]*",
                    extensionPoint
                )));
                return false;
            }
            const superType = contribution.superType;
            if (superType && !superType.match(typeAndModifierIdPattern)) {
                collector.error(( localize(
                    16513,
                    "'configuration.{0}.superType' must follow the pattern letterOrDigit[-_letterOrDigit]*",
                    extensionPoint
                )));
                return false;
            }
            if (typeof contribution.description !== "string" || contribution.id.length === 0) {
                collector.error(( localize(
                    16514,
                    "'configuration.{0}.description' must be defined and can not be empty",
                    extensionPoint
                )));
                return false;
            }
            return true;
        }
        tokenTypeExtPoint.setHandler((extensions, delta) => {
            for (const extension of delta.added) {
                const extensionValue = extension.value;
                const collector = extension.collector;
                if (!extensionValue || !Array.isArray(extensionValue)) {
                    collector.error(( localize(16515, "'configuration.semanticTokenType' must be an array")));
                    return;
                }
                for (const contribution of extensionValue) {
                    if (validateTypeOrModifier(contribution, "semanticTokenType", collector)) {
                        tokenClassificationRegistry.registerTokenType(contribution.id, contribution.description, contribution.superType);
                    }
                }
            }
            for (const extension of delta.removed) {
                const extensionValue = extension.value;
                for (const contribution of extensionValue) {
                    tokenClassificationRegistry.deregisterTokenType(contribution.id);
                }
            }
        });
        tokenModifierExtPoint.setHandler((extensions, delta) => {
            for (const extension of delta.added) {
                const extensionValue = extension.value;
                const collector = extension.collector;
                if (!extensionValue || !Array.isArray(extensionValue)) {
                    collector.error(( localize(16516, "'configuration.semanticTokenModifier' must be an array")));
                    return;
                }
                for (const contribution of extensionValue) {
                    if (validateTypeOrModifier(contribution, "semanticTokenModifier", collector)) {
                        tokenClassificationRegistry.registerTokenModifier(contribution.id, contribution.description);
                    }
                }
            }
            for (const extension of delta.removed) {
                const extensionValue = extension.value;
                for (const contribution of extensionValue) {
                    tokenClassificationRegistry.deregisterTokenModifier(contribution.id);
                }
            }
        });
        tokenStyleDefaultsExtPoint.setHandler((extensions, delta) => {
            for (const extension of delta.added) {
                const extensionValue = extension.value;
                const collector = extension.collector;
                if (!extensionValue || !Array.isArray(extensionValue)) {
                    collector.error(( localize(16517, "'configuration.semanticTokenScopes' must be an array")));
                    return;
                }
                for (const contribution of extensionValue) {
                    if (contribution.language && typeof contribution.language !== "string") {
                        collector.error(( localize(16518, "'configuration.semanticTokenScopes.language' must be a string")));
                        continue;
                    }
                    if (!contribution.scopes || typeof contribution.scopes !== "object") {
                        collector.error(( localize(
                            16519,
                            "'configuration.semanticTokenScopes.scopes' must be defined as an object"
                        )));
                        continue;
                    }
                    for (const selectorString in contribution.scopes) {
                        const tmScopes = contribution.scopes[selectorString];
                        if (!Array.isArray(tmScopes) || ( tmScopes.some(l => typeof l !== "string"))) {
                            collector.error(( localize(
                                16520,
                                "'configuration.semanticTokenScopes.scopes' values must be an array of strings"
                            )));
                            continue;
                        }
                        try {
                            const selector = tokenClassificationRegistry.parseTokenSelector(selectorString, contribution.language);
                            tokenClassificationRegistry.registerTokenStyleDefault(selector, {
                                scopesToProbe: ( tmScopes.map(s => s.split(" ")))
                            });
                        } catch (e) {
                            collector.error(( localize(
                                16521,
                                "configuration.semanticTokenScopes.scopes': Problems parsing selector {0}.",
                                selectorString
                            )));
                        }
                    }
                }
            }
            for (const extension of delta.removed) {
                const extensionValue = extension.value;
                for (const contribution of extensionValue) {
                    for (const selectorString in contribution.scopes) {
                        const tmScopes = contribution.scopes[selectorString];
                        try {
                            const selector = tokenClassificationRegistry.parseTokenSelector(selectorString, contribution.language);
                            tokenClassificationRegistry.registerTokenStyleDefault(selector, {
                                scopesToProbe: ( tmScopes.map(s => s.split(" ")))
                            });
                        } catch (e) {}
                    }
                }
            }
        });
    }
}
let TokenClassificationExtensionPointWorkbenchContribution = class TokenClassificationExtensionPointWorkbenchContribution {
    static {
        this.ID = "workbench.contrib.tokenClassificationExtensionPoint";
    }
    constructor(instantiationService) {
        this.instantiationService = instantiationService;
        this.instantiationService.createInstance(TokenClassificationExtensionPoints);
    }
};
TokenClassificationExtensionPointWorkbenchContribution = ( __decorate([( __param(0, IInstantiationService))], TokenClassificationExtensionPointWorkbenchContribution));
registerWorkbenchContribution2(
    TokenClassificationExtensionPointWorkbenchContribution.ID,
    TokenClassificationExtensionPointWorkbenchContribution,
    WorkbenchPhase.BlockStartup
);

export { TokenClassificationExtensionPoints };
