"use strict";
/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.walkAllowedTypes = exports.walkNodeSchema = void 0;
const allowedTypes_js_1 = require("./allowedTypes.js");
const treeNodeSchema_js_1 = require("./treeNodeSchema.js");
/**
 * Traverses all {@link TreeNodeSchema} schema reachable from `schema`, applying the visitor pattern.
 * @internal
 */
function walkNodeSchema(schema, visitor, visitedSet) {
    if (visitedSet.has(schema)) {
        return;
    }
    visitedSet.add(schema);
    // Ensure all reachable schema are marked as most derived.
    // This ensures if multiple schema extending the same schema factory generated class are present (or have had instances of them constructed, or get instances of them constructed in the future),
    // an error is reported.
    (0, allowedTypes_js_1.markSchemaMostDerived)(schema, false);
    // Since walkNodeSchema is used in the implementation of TreeNodeSchemaPrivateData.idempotentInitialize,
    // Avoid depending on it here to avoid circular dependencies for recursive schema.
    // Instead normalize/evaluate the allowed types as needed.
    const annotatedAllowedTypes = (0, treeNodeSchema_js_1.getTreeNodeSchemaPrivateData)(schema).childAllowedTypes;
    for (const fieldAllowedTypes of annotatedAllowedTypes) {
        walkAllowedTypes((0, allowedTypes_js_1.normalizeAndEvaluateAnnotatedAllowedTypes)(fieldAllowedTypes), visitor, visitedSet);
    }
    // This visit is done at the end so the traversal order is most inner types first.
    // This was picked since when fixing errors,
    // working from the inner types out to the types that use them will probably go better than the reverse.
    // This does not however ensure all types referenced by a type are visited before it, since in recursive cases thats impossible.
    visitor.node?.(schema);
}
exports.walkNodeSchema = walkNodeSchema;
/**
 * Traverses all {@link TreeNodeSchema} schema reachable from `allowedTypes`, applying the visitor pattern.
 * @internal
 */
function walkAllowedTypes(annotatedAllowedTypes, visitor, visitedSet = new Set()) {
    for (const allowedType of annotatedAllowedTypes.types) {
        if ((visitor.allowedTypeFilter ?? (() => true))(allowedType)) {
            walkNodeSchema(allowedType.type, visitor, visitedSet);
        }
    }
    visitor.allowedTypes?.(annotatedAllowedTypes);
}
exports.walkAllowedTypes = walkAllowedTypes;
//# sourceMappingURL=walkSchema.js.map