"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var ll = require("../lowLevelAST");
var hlimpl = require("../highLevelImpl");
var yaml = require("yaml-ast-parser");
var jsyaml = require("../jsyaml/jsyaml2lowLevel");
var json = require("../jsyaml/json2lowLevel");
var util = require("../../util/index");
var proxy = require("./LowLevelASTProxy");
var universeDef = require("../tools/universe");
var _ = require("underscore");
var universeHelpers = require("../tools/universeHelpers");
var namespaceResolver = require("./namespaceResolver");
var def = require("raml-definition-system");
var typeExpressions = def.rt.typeExpressions;
var PatchMode;
(function (PatchMode) {
    PatchMode[PatchMode["DEFAULT"] = 0] = "DEFAULT";
    PatchMode[PatchMode["PATH"] = 1] = "PATH";
})(PatchMode = exports.PatchMode || (exports.PatchMode = {}));
var ReferencePatcher = /** @class */ (function () {
    function ReferencePatcher(mode) {
        if (mode === void 0) { mode = PatchMode.DEFAULT; }
        this.mode = mode;
        this._outerDependencies = {};
        this._libModels = {};
    }
    ReferencePatcher.prototype.process = function (hlNode, rootNode, removeUses, patchNodeName) {
        if (rootNode === void 0) { rootNode = hlNode; }
        if (removeUses === void 0) { removeUses = false; }
        if (patchNodeName === void 0) { patchNodeName = false; }
        if (hlNode.lowLevel()["libProcessed"]) {
            return;
        }
        var resolver = hlNode.lowLevel().unit().project().namespaceResolver();
        this.patchReferences(hlNode, rootNode, resolver);
        if (patchNodeName) {
            this.patchNodeName(hlNode, rootNode.lowLevel().unit(), resolver);
        }
        if (removeUses) {
            this.removeUses(hlNode);
        }
        else {
            this.patchUses(hlNode, resolver);
        }
        //hlNode.elements().forEach(ch=>this.removeUses(ch));
        this.resetTypes(hlNode);
        hlNode.lowLevel()["libProcessed"] = true;
    };
    ReferencePatcher.prototype.patchReferences = function (node, rootNode, resolver, units) {
        if (rootNode === void 0) { rootNode = node; }
        if (resolver === void 0) { resolver = new namespaceResolver.NamespaceResolver(); }
        if (units === void 0) { units = [rootNode.lowLevel().unit()]; }
        if (node.isReused()) {
            return;
        }
        var isNode;
        if (node.definition().property(universeDef.Universe10.TypeDeclaration.properties.annotations.name) != null) {
            var cNode = node.lowLevel();
            if (!(proxy.LowLevelCompositeNode.isInstance(cNode))) {
                return;
            }
            var isPropertyName = universeDef.Universe10.MethodBase.properties.is.name;
            var traitNodes = node.attributes(isPropertyName);
            if (traitNodes.length != 0) {
                var llIsNodes = node.lowLevel().children().filter(function (x) { return x.key() == universeDef.Universe10.MethodBase.properties.is.name; });
                if (llIsNodes.length == 1 && llIsNodes[0].valueKind() == yaml.Kind.SEQ) {
                    isNode = patchMethodIs(node, traitNodes.map(function (x) { return x.lowLevel(); }).map(function (x) {
                        if (!proxy.LowLevelProxyNode.isInstance(x)) {
                            return {
                                node: x,
                                transformer: null
                            };
                        }
                        return {
                            node: x,
                            transformer: x.transformer()
                        };
                    }), units[0].absolutePath());
                }
            }
        }
        var attrs = node.attrs();
        for (var _i = 0, attrs_1 = attrs; _i < attrs_1.length; _i++) {
            var attr = attrs_1[_i];
            var appended = this.appendUnitIfNeeded(attr, units);
            this.patchReferenceAttr(attr, rootNode, resolver, units);
            this.popUnitIfNeeded(units, appended);
        }
        if (universeHelpers.isTypeDeclarationDescendant(node.definition())) {
            var appended = this.appendUnitIfNeeded(node, units);
            this.patchType(node, rootNode, resolver, units);
            if (appended) {
                this.removeUses(node);
            }
            this.popUnitIfNeeded(units, appended);
        }
        var childNodes = node.elements();
        for (var _a = 0, childNodes_1 = childNodes; _a < childNodes_1.length; _a++) {
            var ch = childNodes_1[_a];
            var appended = this.appendUnitIfNeeded(ch, units);
            this.patchReferences(ch, rootNode, resolver, units);
            this.popUnitIfNeeded(units, appended);
            ch.lowLevel()["libProcessed"] = true;
        }
        if (isNode) {
            isNode.filterChildren();
            var directChildren = node.directChildren();
            if (directChildren) {
                node._children = this.filterTraitReferences(directChildren);
            }
            var mergedChildren = node.children();
            if (mergedChildren) {
                node._mergedChildren = this.filterTraitReferences(mergedChildren);
            }
        }
    };
    ReferencePatcher.prototype.filterTraitReferences = function (children) {
        var newChildren = [];
        var map = {};
        for (var _i = 0, children_1 = children; _i < children_1.length; _i++) {
            var ch = children_1[_i];
            var p = ch.property();
            if (!p || !universeHelpers.isIsProperty(p)) {
                newChildren.push(ch);
                continue;
            }
            var key = JSON.stringify(json.serialize(ch.lowLevel()));
            if (map[key]) {
                continue;
            }
            map[key] = true;
            newChildren.push(ch);
        }
        return newChildren;
    };
    ReferencePatcher.prototype.patchReferenceAttr = function (attr, rootNode, resolver, units, force) {
        if (force === void 0) { force = false; }
        var property = attr.property();
        var range = property.range();
        if (!force && !range.isAssignableFrom(universeDef.Universe10.Reference.name)) {
            return;
        }
        var value = attr.value();
        if (value == null) {
            return;
        }
        var llNode = attr.lowLevel();
        if (!(proxy.LowLevelProxyNode.isInstance(llNode))) {
            return;
        }
        var transformer = llNode.transformer();
        var isAnnotation = universeHelpers.isAnnotationsProperty(property);
        if (!isAnnotation && property && def.UserDefinedProp.isInstance(property)) {
            var defNode = property.node();
            var srcProp = defNode && defNode.property();
            isAnnotation = srcProp && universeHelpers.isAnnotationsProperty(defNode.property());
            if (srcProp && isAnnotation) {
                range = srcProp.range();
            }
        }
        if (typeof value == "string") {
            var stringToPatch = value;
            if (transformer != null) {
                var actualNode = toOriginal(llNode);
                stringToPatch = actualNode.value();
            }
            var embraceAnotation = isAnnotation && stringToPatch.charAt(0) == "(";
            if (embraceAnotation) {
                stringToPatch = stringToPatch.substring(1, stringToPatch.length - 1);
            }
            var newValue = this.resolveReferenceValue(stringToPatch, rootNode.lowLevel().unit(), units, resolver, transformer, range);
            if (newValue != null) {
                var newValue1 = embraceAnotation ? "(" + newValue.value() + ")" : newValue.value();
                attr.lowLevel().setValueOverride(newValue1);
                attr.overrideValue(newValue1);
                this.registerPatchedReference(newValue);
            }
        }
        else if (hlimpl.StructuredValue.isInstance(value)) {
            var sValue = value;
            var hlNode = sValue.toHighLevel();
            if (hlNode) {
                for (var _i = 0, _a = hlNode.attrs(); _i < _a.length; _i++) {
                    var attr = _a[_i];
                    if (universeHelpers.isSchemaStringType(attr.definition())) {
                        this.patchReferenceAttr(attr, rootNode, resolver, units, true);
                    }
                }
            }
            var key = sValue.lowLevel().key();
            var stringToPatch = key;
            if (transformer != null) {
                var actualNode = toOriginal(sValue.lowLevel());
                stringToPatch = actualNode.key();
            }
            if (key != null) {
                if (isAnnotation) {
                    stringToPatch = stringToPatch.substring(1, stringToPatch.length - 1);
                }
                var newValue_1 = this.resolveReferenceValue(stringToPatch, rootNode.lowLevel().unit(), units, resolver, transformer, range);
                if (newValue_1 != null) {
                    var newValue1 = isAnnotation ? "(" + newValue_1.value() + ")" : newValue_1.value();
                    sValue.lowLevel().setKeyOverride(newValue1);
                    this.registerPatchedReference(newValue_1);
                    if (newValue_1.isChained()) {
                        var metaVal = isAnnotation
                            ? { value: newValue_1.value(), kind: 'annotationRef' }
                            : { value: newValue_1.value(), kind: 'typeRef' };
                        sValue.lowLevel().addMeta("chaining", metaVal);
                    }
                }
            }
        }
    };
    ReferencePatcher.prototype.patchType = function (node, rootNode, resolver, units) {
        var _this = this;
        var nodeType = node.definition();
        var localType = node.localType();
        if (localType.isAnnotationType()) {
            var superTypes = localType.superTypes();
            if (superTypes.length > 0) {
                localType = superTypes[0];
            }
        }
        var isExternal = isExternalType(localType);
        if (!isExternal && localType.isArray()) {
            isExternal = isExternalType(localType.componentType());
        }
        if (!isExternal) {
            var rootUnit = rootNode.lowLevel().unit();
            var rootPath = rootUnit.absolutePath();
            //if(rootPath != localPath) {
            var typeAttributes = node.attributes(universeDef.Universe10.TypeDeclaration.properties.type.name);
            if (typeAttributes.length == 0) {
                typeAttributes = node.attributes(universeDef.Universe10.TypeDeclaration.properties.schema.name);
            }
            var itemsAttrs = node.attributes(universeDef.Universe10.ArrayTypeDeclaration.properties.items.name);
            typeAttributes = typeAttributes.concat(itemsAttrs);
            var _loop_1 = function () {
                llNode = typeAttr.lowLevel();
                if (!(proxy.LowLevelProxyNode.isInstance(llNode))) {
                    return "continue";
                }
                localUnit = typeAttr.lowLevel().unit();
                localPath = localUnit.absolutePath();
                value = typeAttr.value();
                if (value == null) {
                    return "continue";
                }
                if (typeof value == "string") {
                    gotExpression = checkExpression(value);
                    transformer = llNode.transformer();
                    stringToPatch = value;
                    escapeData = { status: ParametersEscapingStatus.NOT_REQUIRED };
                    additionalUnits = transformer ? transformer.unitsChain : null;
                    if (transformer != null || value.indexOf("<<") >= 0) {
                        actualNode = toOriginal(llNode);
                        actualValue = actualNode.value();
                        escapeData = escapeTemplateParameters(actualValue);
                        if (escapeData.status == ParametersEscapingStatus.OK) {
                            if (gotExpression) {
                                stringToPatch = escapeData.resultingString;
                            }
                            else {
                                stringToPatch = actualValue;
                            }
                        }
                        else if (escapeData.status == ParametersEscapingStatus.ERROR) {
                            return { value: void 0 };
                        }
                        else {
                            transformer = null;
                        }
                    }
                    if (additionalUnits) {
                        appendedAdditional = [];
                        for (var _i = 0, additionalUnits_1 = additionalUnits; _i < additionalUnits_1.length; _i++) {
                            var u = additionalUnits_1[_i];
                            appendedAdditional.push(this_1.appendUnitIfNeeded(u, units));
                        }
                    }
                    appendedAttrUnit = this_1.appendUnitIfNeeded(typeAttr, units);
                    var newValue = void 0;
                    var chainingData_1 = [];
                    try {
                        parsedExpression = gotExpression && typeExpressions.parse(stringToPatch);
                    }
                    catch (exception) {
                        parsedExpression = null;
                    }
                    if (gotExpression && parsedExpression !== null) {
                        expressionPatchFailed = false;
                        expr = typeExpressions.parse(stringToPatch);
                        gotPatch = false;
                        typeExpressions.visit(expr, function (x) {
                            if (x.type == "name") {
                                var lit = x;
                                var typeName = lit.value;
                                var unescapeData = { status: ParametersEscapingStatus.NOT_REQUIRED };
                                var unescaped;
                                if (escapeData.status == ParametersEscapingStatus.OK) {
                                    unescaped = escapeData.substitutions[typeName];
                                    if (unescaped == null) {
                                        unescapeData = unescapeTemplateParameters(typeName, escapeData.substitutions);
                                        if (unescapeData.status == ParametersEscapingStatus.OK) {
                                            typeName = unescapeData.resultingString;
                                        }
                                        else if (unescapeData.status == ParametersEscapingStatus.ERROR) {
                                            expressionPatchFailed = true;
                                            return;
                                        }
                                    }
                                    else {
                                        typeName = unescaped;
                                    }
                                }
                                if (transformer == null && (unescaped != null || unescapeData.status == ParametersEscapingStatus.OK)) {
                                    lit.value = typeName;
                                    return;
                                }
                                var patchTransformedValue = true;
                                if (typeName.indexOf("<<") >= 0 && isCompoundValue(typeName)) {
                                    patchTransformedValue = false;
                                }
                                var patched = _this.resolveReferenceValue(typeName, rootUnit, units, resolver, transformer, nodeType, patchTransformedValue);
                                if (patched != null) {
                                    lit.value = patched.value();
                                    gotPatch = true;
                                    _this.registerPatchedReference(patched);
                                    if (patched.isChained()) {
                                        chainingData_1.push({
                                            kind: 'type',
                                            value: lit.value
                                        });
                                    }
                                }
                            }
                        });
                        if (gotPatch && !expressionPatchFailed) {
                            newValue = typeExpressions.serializeToString(expr);
                        }
                        else {
                            newValue = value;
                        }
                    }
                    else if (!(escapeData.status == ParametersEscapingStatus.OK && transformer == null)) {
                        if (stringToPatch.indexOf("<<") >= 0 && isCompoundValue(stringToPatch)) {
                            stringToPatch = value;
                            transformer = null;
                        }
                        patched = this_1.resolveReferenceValue(stringToPatch, rootUnit, units, resolver, transformer, nodeType);
                        if (patched != null) {
                            this_1.registerPatchedReference(patched);
                            newValue = patched.value();
                            if (patched.isChained()) {
                                chainingData_1.push({
                                    kind: 'type',
                                    value: newValue
                                });
                            }
                        }
                    }
                    if (newValue != null) {
                        typeAttr.lowLevel().setValueOverride(newValue);
                        typeAttr.overrideValue(null);
                        if (chainingData_1.length > 0) {
                            typeAttr.lowLevel().addMeta("chaining", chainingData_1);
                        }
                    }
                    this_1.popUnitIfNeeded(units, appendedAttrUnit);
                    if (appendedAdditional) {
                        for (var _a = 0, _b = appendedAdditional.reverse(); _a < _b.length; _a++) {
                            var ap = _b[_a];
                            this_1.popUnitIfNeeded(units, ap);
                        }
                    }
                }
                else {
                    llTypeNode = typeAttr.lowLevel();
                    if (llTypeNode.key() != typeAttr.property().nameId()) {
                        llTypeNode = _.find(node.lowLevel().children(), function (x) { return x.key() == typeAttr.property().nameId(); });
                    }
                    if (llTypeNode) {
                        def = node.definition().universe().type(universeDef.Universe10.TypeDeclaration.name);
                        newNode = new hlimpl.ASTNodeImpl(llTypeNode, null, def, null);
                        appended = this_1.appendUnitIfNeeded(newNode, units);
                        this_1.patchReferences(newNode, rootNode, resolver, units);
                        this_1.popUnitIfNeeded(units, appended);
                    }
                }
            };
            var this_1 = this, llNode, localUnit, localPath, value, gotExpression, transformer, stringToPatch, escapeData, additionalUnits, actualNode, actualValue, appendedAdditional, appendedAttrUnit, parsedExpression, expressionPatchFailed, expr, gotPatch, patched, llTypeNode, def, newNode, appended;
            for (var _i = 0, typeAttributes_1 = typeAttributes; _i < typeAttributes_1.length; _i++) {
                var typeAttr = typeAttributes_1[_i];
                var state_1 = _loop_1();
                if (typeof state_1 === "object")
                    return state_1.value;
            }
            // }
        }
    };
    ReferencePatcher.prototype.resolveReferenceValue = function (stringToPatch, rootUnit, units, resolver, transformer, range, patchTransformedValue) {
        var _this = this;
        if (patchTransformedValue === void 0) { patchTransformedValue = true; }
        var isAnnotation = universeHelpers.isAnnotationRefTypeOrDescendant(range);
        var newValue;
        if (transformer) {
            if (stringToPatch && stringToPatch.indexOf("<<") >= 0) {
                var doContinue = true;
                var types = rootUnit.highLevel().types();
                var newValue1 = transformer.transform(stringToPatch, true, function () { return doContinue; }, function (val, tr) {
                    var newVal = _this.resolveReferenceValueBasic(val, rootUnit, resolver, tr.unitsChain, range);
                    if (newVal == null) {
                        newVal = new PatchedReference(null, val, _this.collectionName(range), rootUnit, false, PatchMode.DEFAULT);
                    }
                    if (isAnnotation) {
                        if (types.getAnnotationType(newVal.value()) != null) {
                            doContinue = false;
                        }
                        else {
                            doContinue = false;
                        }
                    }
                    else if (types.getType(newVal.value()) != null) {
                        doContinue = false;
                    }
                    else {
                        doContinue = false;
                    }
                    return newVal;
                });
                newValue = newValue1.value;
            }
        }
        if (newValue === undefined || !instanceOfPatchedReference(newValue)) {
            newValue = this.resolveReferenceValueBasic(stringToPatch, rootUnit, resolver, units, range);
        }
        return newValue;
    };
    ReferencePatcher.prototype.patchNodeName = function (hlNode, rootUnit, resolver) {
        var llNode = hlNode.lowLevel();
        var key = llNode.key();
        var range = hlNode.definition();
        if (universeHelpers.isTypeDeclarationSibling(range)) {
            var localType = hlNode.localType();
            if (localType.isAnnotationType()) {
                range = localType;
            }
        }
        var patched = this.resolveReferenceValueBasic(key, rootUnit, resolver, [llNode.unit()], range);
        if (patched != null) {
            llNode.setKeyOverride(patched.value());
            hlNode.resetIDs();
        }
    };
    ReferencePatcher.prototype.resolveReferenceValueBasic = function (_value, rootUnit, resolver, units, range) {
        if (_value == null || typeof (_value) != "string") {
            return null;
        }
        var isType = universeHelpers.isTypeDeclarationDescendant(range);
        var gotQuestion = isType && util.stringEndsWith(_value, "?");
        var value = gotQuestion ? _value.substring(0, _value.length - 1) : _value;
        if (value.indexOf("<<") >= 0) {
            return;
        }
        var ind = value.lastIndexOf(".");
        var referencedUnit;
        var plainName;
        var oldNS;
        if (ind >= 0) {
            oldNS = value.substring(0, ind);
            plainName = value.substring(ind + 1);
            for (var i = units.length; i > 0; i--) {
                var localUnit = units[i - 1];
                var nsMap = resolver.nsMap(localUnit);
                var info = nsMap && nsMap[oldNS];
                if (info == null) {
                    continue;
                }
                referencedUnit = info.unit;
                if (referencedUnit != null) {
                    break;
                }
            }
        }
        else {
            if (isType && def.rt.builtInTypes().get(value) != null) {
                return null;
            }
            plainName = value;
            referencedUnit = units[units.length - 1];
        }
        var collectionName = this.collectionName(range);
        if (referencedUnit) {
            if (referencedUnit.absolutePath() == rootUnit.absolutePath()) {
                if (oldNS != null) {
                    return new PatchedReference(null, plainName, collectionName, referencedUnit, false, this.mode);
                }
                return null;
            }
        }
        else {
            if (oldNS && oldNS.length > 0) {
                var chainedUnit = void 0;
                for (var i = units.length; i > 0; i--) {
                    var localUnit = units[i - 1];
                    var expandedNSMap = resolver.expandedNSMap(localUnit);
                    var info = expandedNSMap && expandedNSMap[oldNS];
                    if (info == null) {
                        continue;
                    }
                    chainedUnit = info.unit;
                    if (chainedUnit != null) {
                        break;
                    }
                }
                if (chainedUnit != null) {
                    var usesInfo_1 = resolver.resolveNamespace(rootUnit, chainedUnit);
                    if (usesInfo_1 != null) {
                        var newNS_1 = usesInfo_1.namespace();
                        if (gotQuestion) {
                            plainName += "?";
                        }
                        return new PatchedReference(newNS_1, plainName, collectionName, chainedUnit, true, this.mode);
                    }
                }
            }
            return null;
        }
        var usesInfo = resolver.resolveNamespace(rootUnit, referencedUnit);
        if (usesInfo == null) {
            return null;
        }
        var newNS = usesInfo.namespace();
        if (newNS == null) {
            return null;
        }
        if (this.mode == PatchMode.PATH) {
            var aPath = referencedUnit.absolutePath().replace(/\\/g, "/");
            if (!ll.isWebPath(aPath)) {
                aPath = "file://" + aPath;
            }
            newNS = aPath + "#/" + collectionName;
        }
        if (gotQuestion) {
            plainName += "?";
        }
        return new PatchedReference(newNS, plainName, collectionName, referencedUnit, false, this.mode);
    };
    ReferencePatcher.prototype.patchUses = function (hlNode, resolver) {
        var node = hlNode.lowLevel();
        hlNode.children();
        if (!(proxy.LowLevelCompositeNode.isInstance(node))) {
            return;
        }
        var unit = node.unit();
        var extendedUnitMap = resolver.expandedPathMap(unit);
        if (extendedUnitMap == null) {
            return;
        }
        var unitMap = resolver.pathMap(unit);
        if (!unitMap) {
            unitMap = {};
        }
        var cNode = node;
        var originalChildren = node.children();
        var usesPropName = universeDef.Universe10.FragmentDeclaration.properties.uses.name;
        var usesNodes = originalChildren.filter(function (x) { return x.key() == usesPropName; });
        var oNode = toOriginal(node);
        var yamlNode = oNode;
        while (proxy.LowLevelProxyNode.isInstance(yamlNode)) {
            yamlNode = yamlNode.originalNode();
        }
        var usesInfos = Object.keys(unitMap).map(function (x) { return extendedUnitMap[x]; });
        var extendedUsesInfos = Object.keys(extendedUnitMap).map(function (x) { return extendedUnitMap[x]; })
            .filter(function (x) { return !unitMap[x.absolutePath()]; } /*&&this.usedNamespaces[x.namespace()]*/);
        var unitPath = unit.absolutePath();
        var existingLibs = {};
        var usesNode;
        if (usesNodes.length > 0) {
            usesNode = usesNodes[0];
            usesNode.children().forEach(function (x) { return existingLibs[x.key()] = true; });
        }
        else {
            var newUses = jsyaml.createMapNode("uses");
            newUses["_parent"] = yamlNode;
            newUses.setUnit(yamlNode.unit());
            usesNode = cNode.replaceChild(null, newUses);
        }
        var usesProp = hlNode.definition().property(usesPropName);
        var usesType = usesProp.range();
        var directChildren = hlNode._children.filter(function (x) {
            if (x.lowLevel().unit().absolutePath() == unitPath) {
                return true;
            }
            var p = x.property();
            return !p || !universeHelpers.isUsesProperty(p);
        });
        var mergedChildren = hlNode._mergedChildren.filter(function (x) {
            if (x.lowLevel().unit().absolutePath() == unitPath) {
                return true;
            }
            var p = x.property();
            return !p || !universeHelpers.isUsesProperty(p);
        });
        ;
        for (var _i = 0, _a = usesInfos.concat(extendedUsesInfos); _i < _a.length; _i++) {
            var ui = _a[_i];
            var up = ui.absolutePath();
            if (existingLibs[ui.namespace()]) {
                continue;
            }
            var ip = ui.includePath;
            var mapping = jsyaml.createMapping(ui.namespace(), ip);
            mapping.setUnit(yamlNode.unit());
            var hlUses = new hlimpl.ASTNodeImpl(mapping, hlNode, usesType, usesProp);
            directChildren.push(hlUses);
            mergedChildren.push(hlUses);
            usesNode.replaceChild(null, mapping);
        }
        hlNode._children = directChildren;
        hlNode._mergedChildren = mergedChildren;
    };
    ReferencePatcher.prototype.removeUses = function (hlNode) {
        var node = hlNode.lowLevel();
        if (!(proxy.LowLevelCompositeNode.isInstance(node))) {
            return;
        }
        var cNode = node;
        var originalChildren = node.children();
        var usesNodes = originalChildren.filter(function (x) {
            return x.key() == universeDef.Universe10.FragmentDeclaration.properties.uses.name;
        });
        if (usesNodes.length > 0) {
            cNode.removeChild(usesNodes[0]);
        }
        hlNode._children = hlNode.directChildren().filter(function (x) {
            var p = x.property();
            return p == null || !universeHelpers.isUsesProperty(p);
        });
        hlNode._mergedChildren = hlNode.children().filter(function (x) {
            var p = x.property();
            return p == null || !universeHelpers.isUsesProperty(p);
        });
    };
    ReferencePatcher.prototype.resetTypes = function (hlNode) {
        for (var _i = 0, _a = hlNode.elements(); _i < _a.length; _i++) {
            var ch = _a[_i];
            this.resetTypes(ch);
        }
        for (var _b = 0, _c = hlNode.attrs(); _b < _c.length; _b++) {
            var attr = _c[_b];
            var aVal = attr.value();
            if (hlimpl.StructuredValue.isInstance(aVal)) {
                aVal.resetHighLevelNode();
            }
        }
        delete hlNode.lowLevel().actual().types;
        delete hlNode["_ptype"];
        delete hlNode["_types"];
        hlNode.setAssociatedType(null);
    };
    ;
    ReferencePatcher.prototype.appendUnitIfNeeded = function (node, units) {
        if (jsyaml.CompilationUnit.isInstance(node)) {
            var unit = node;
            if (unit.absolutePath() != units[units.length - 1].absolutePath()) {
                units.push(unit);
                return true;
            }
            return false;
        }
        var originalNode = toOriginal(node.lowLevel());
        var originalUnit = originalNode.unit();
        if (originalNode.valueKind() == yaml.Kind.INCLUDE_REF) {
            var ref = originalNode.includePath();
            var includedUnit = originalUnit.resolve(ref);
            if (includedUnit) {
                units.push(includedUnit);
                return true;
            }
            return false;
        }
        else {
            if (originalUnit.absolutePath() != units[units.length - 1].absolutePath()) {
                units.push(originalUnit);
                return true;
            }
            return false;
        }
    };
    ReferencePatcher.prototype.popUnitIfNeeded = function (units, appended) {
        if (appended) {
            units.pop();
        }
    };
    ReferencePatcher.prototype.registerPatchedReference = function (ref) {
        var collectionName = ref.collectionName();
        if (!collectionName) {
            return;
        }
        var aPath = ref.referencedUnit().absolutePath();
        var libMap = this._outerDependencies[aPath];
        if (libMap == null) {
            libMap = {};
            this._outerDependencies[aPath] = libMap;
        }
        var collectionMap = libMap[collectionName];
        if (collectionMap == null) {
            collectionMap = {};
            libMap[collectionName] = collectionMap;
        }
        collectionMap[ref.name()] = ref;
    };
    ReferencePatcher.prototype.collectionName = function (range) {
        var collectionName;
        if (universeHelpers.isResourceTypeRefType(range) || universeHelpers.isResourceTypeType(range)) {
            collectionName = def.universesInfo.Universe10.LibraryBase.properties.resourceTypes.name;
        }
        else if (universeHelpers.isTraitRefType(range) || universeHelpers.isTraitType(range)) {
            collectionName = def.universesInfo.Universe10.LibraryBase.properties.traits.name;
        }
        else if (universeHelpers.isSecuritySchemeRefType(range) || universeHelpers.isSecuritySchemaTypeDescendant(range)) {
            collectionName = def.universesInfo.Universe10.LibraryBase.properties.securitySchemes.name;
        }
        else if (universeHelpers.isAnnotationRefTypeOrDescendant(range) || range.isAnnotationType()) {
            collectionName = def.universesInfo.Universe10.LibraryBase.properties.annotationTypes.name;
        }
        else if (universeHelpers.isTypeDeclarationDescendant(range) || universeHelpers.isSchemaStringType(range)) {
            collectionName = def.universesInfo.Universe10.LibraryBase.properties.types.name;
        }
        return collectionName;
    };
    ReferencePatcher.prototype.expandLibraries = function (api, excessive) {
        if (excessive === void 0) { excessive = false; }
        if (api.lowLevel().actual().libExpanded) {
            return;
        }
        var llNode = api.lowLevel();
        var unit = llNode.unit();
        var rootPath = unit.absolutePath();
        var project = unit.project();
        var libModels = [];
        var resolver = llNode.unit().project().namespaceResolver();
        var expandedPathMap = resolver.expandedPathMap(unit);
        if (expandedPathMap != null) {
            var libPaths = Object.keys(expandedPathMap).sort();
            for (var _i = 0, libPaths_1 = libPaths; _i < libPaths_1.length; _i++) {
                var ns = libPaths_1[_i];
                var libModel = this._libModels[ns];
                if (libModel == null) {
                    var libUnit = project.unit(ns, true);
                    var usesInfo = resolver.resolveNamespace(unit, libUnit);
                    if (libUnit && usesInfo != null && usesInfo.namespace() != null) {
                        libModel = this.extractLibModel(libUnit, unit);
                    }
                }
                if (libModel) {
                    libModels.push(libModel);
                }
            }
            var gotContribution = false;
            for (var _a = 0, libModels_1 = libModels; _a < libModels_1.length; _a++) {
                var libModel = libModels_1[_a];
                for (var _b = 0, _c = Object.keys(libModel); _b < _c.length; _b++) {
                    var cName = _c[_b];
                    var collection = libModel[cName];
                    if (ElementsCollection.isInstance(collection)) {
                        gotContribution = this.contributeCollection(api, collection) || gotContribution;
                    }
                }
            }
            if (gotContribution) {
                var gotPatch = false;
                do {
                    gotPatch = this.patchDependencies(api, excessive);
                } while (gotPatch);
                if (!excessive) {
                    this.removeUnusedDependencies(api);
                }
            }
        }
        this.removeUses(api); //this.patchUses(api,resolver);
        api.lowLevel().actual().libExpanded = true;
        this.resetTypes(api);
    };
    ReferencePatcher.prototype.patchDependencies = function (api, excessive) {
        var result = false;
        var rootUnit = api.lowLevel().unit();
        var apiPath = rootUnit.absolutePath();
        for (var _i = 0, _a = api.children(); _i < _a.length; _i++) {
            var ch = _a[_i];
            if (!ch.isElement() || ch.lowLevel()["libProcessed"]) {
                continue;
            }
            var chNode = ch.asElement();
            this.removeUses(chNode);
            var pName = chNode.property().nameId();
            if (pName != universeDef.Universe10.LibraryBase.properties.types.name
                && pName != universeDef.Universe10.LibraryBase.properties.annotationTypes.name
                && pName != universeDef.Universe10.LibraryBase.properties.resourceTypes.name
                && pName != universeDef.Universe10.LibraryBase.properties.traits.name
                && pName != universeDef.Universe10.LibraryBase.properties.securitySchemes.name) {
                continue;
            }
            if (!excessive) {
                var chPath = ch.lowLevel().unit().absolutePath();
                if (chPath == apiPath && ch.lowLevel().includePath() == null) {
                    continue;
                }
                var dependencies = this._outerDependencies[chPath];
                if (dependencies == null) {
                    continue;
                }
                var depCollection = dependencies[pName];
                if (depCollection == null) {
                    continue;
                }
                var chName = chNode.name();
                if (depCollection[chName] == null) {
                    continue;
                }
                if (pName == def.universesInfo.Universe10.LibraryBase.properties.types.name) {
                    var discriminator = chNode.attr(def.universesInfo.Universe10.ObjectTypeDeclaration.properties.discriminator.name);
                    if (discriminator) {
                        var localType = chNode.localType();
                        if (localType) {
                            var resolver = rootUnit.project().namespaceResolver();
                            for (var _b = 0, _c = localType.allSubTypes(); _b < _c.length; _b++) {
                                var st = _c[_b];
                                var typeName = st.nameId();
                                if (!typeName) {
                                    continue;
                                }
                                var unit = typeUnit(st);
                                if (!unit) {
                                    continue;
                                }
                                var usesInfo = resolver.resolveNamespace(rootUnit, unit);
                                if (!usesInfo) {
                                    continue;
                                }
                                var ns = usesInfo.namespace();
                                var ref = new PatchedReference(ns, typeName, def.universesInfo.Universe10.LibraryBase.properties.types.name, unit, false, this.mode);
                                this.registerPatchedReference(ref);
                            }
                        }
                    }
                }
            }
            this.process(chNode, api, true, true);
            result = true;
        }
        return result;
    };
    ReferencePatcher.prototype.removeUnusedDependencies = function (api) {
        var llNode = api.lowLevel();
        var apiPath = llNode.unit().absolutePath();
        var directChildren = api._children;
        //var mergedChildren = (<hlimpl.ASTNodeImpl>api)._mergedChildren;
        var newDirectChildren = [];
        //var newMergedChildren:hl.IParseResult[] = [];
        for (var _i = 0, directChildren_1 = directChildren; _i < directChildren_1.length; _i++) {
            var ch = directChildren_1[_i];
            var chLl = ch.lowLevel();
            if (ch.isElement() && chLl["libProcessed"]) {
                newDirectChildren.push(ch);
                continue;
            }
            var chPath = chLl.unit().absolutePath();
            if (chPath == apiPath) {
                newDirectChildren.push(ch);
                continue;
            }
            chLl.parent().removeChild(chLl);
        }
        api._children = newDirectChildren;
        api._mergedChildren = null;
    };
    ReferencePatcher.prototype.contributeCollection = function (api, collection) {
        var llApi = api.lowLevel();
        if (collection.array.length == 0) {
            return false;
        }
        var name = collection.name;
        var prop = api.definition().property(name);
        var propRange = prop.range();
        var llNode = _.find(llApi.children(), function (x) { return x.key() == name; });
        if (llNode == null) {
            var n = jsyaml.createMapNode(name);
            llNode = llApi.replaceChild(null, n);
        }
        var result = false;
        var directChildren = api._children;
        var mergedChildren = api._mergedChildren;
        var _loop_2 = function () {
            if (llNode.children().some(function (x) {
                var oNode = toOriginal(x);
                if (oNode.unit().absolutePath() != e.lowLevel().unit().absolutePath()) {
                    return false;
                }
                return e.lowLevel().key() == oNode.key() && e.lowLevel().unit().absolutePath() == oNode.unit().absolutePath();
            })) {
                return "continue";
            }
            var newLlNode = llNode.replaceChild(null, e.lowLevel());
            if (collection.name == def.universesInfo.Universe10.LibraryBase.properties.types.name) {
                var dValPropName_1 = def.universesInfo.Universe10.ObjectTypeDeclaration.properties.discriminatorValue.name;
                var discriminatorValue = newLlNode.children().filter(function (x) { return x.key() == dValPropName_1; });
                if (!discriminatorValue.length) {
                    var dValNode = jsyaml.createMapNode(dValPropName_1, newLlNode.unit());
                    var strictProp = jsyaml.createMapping("strict", false);
                    var valueProp = jsyaml.createMapping("value", newLlNode.key());
                    dValNode.addChild(valueProp);
                    dValNode.addChild(strictProp);
                    newLlNode.replaceChild(null, dValNode);
                }
            }
            definition = (e.isElement() && e.asElement().definition()) || propRange;
            newHLNode = new hlimpl.ASTNodeImpl(newLlNode, api, definition, prop);
            directChildren.push(newHLNode);
            if (mergedChildren) {
                mergedChildren.push(newHLNode);
            }
            result = true;
        };
        var definition, newHLNode;
        for (var _i = 0, _a = collection.array; _i < _a.length; _i++) {
            var e = _a[_i];
            _loop_2();
        }
        return result;
    };
    ReferencePatcher.prototype.extractLibModel = function (unit, rootUnit) {
        var result = this._libModels[unit.absolutePath()];
        if (result != null) {
            return result;
        }
        result = new LibModel(unit);
        this._libModels[unit.absolutePath()] = result;
        var hlNode = unit.highLevel();
        if (hlNode && hlNode.isElement()) {
            var eNode = hlNode.asElement();
            for (var _i = 0, _a = ["resourceTypes", "traits", "types", "annotationTypes", "securitySchemes"]; _i < _a.length; _i++) {
                var cName = _a[_i];
                var collection = new ElementsCollection(cName);
                for (var _b = 0, _c = eNode.elementsOfKind(cName); _b < _c.length; _b++) {
                    var el = _c[_b];
                    collection.array.push(el);
                }
                result[cName] = collection;
            }
            var annotations = eNode.attributes(def.universesInfo.Universe10.Annotable.properties.annotations.name);
            if (annotations.length > 0) {
                var resolver = rootUnit.project().namespaceResolver();
                for (var _d = 0, annotations_1 = annotations; _d < annotations_1.length; _d++) {
                    var aNode = annotations_1[_d];
                    var aName = aNode.lowLevel().key();
                    var l = aName.length;
                    if (aName.charAt(0) == "(" && aName.charAt(l - 1) == ")") {
                        aName = aName.substring(1, l - 1);
                    }
                    var range = aNode.property().range();
                    var patchedReference = this.resolveReferenceValueBasic(aName, rootUnit, resolver, [rootUnit, unit], range);
                    if (patchedReference) {
                        this.registerPatchedReference(patchedReference);
                    }
                }
            }
        }
        return result;
    };
    return ReferencePatcher;
}());
exports.ReferencePatcher = ReferencePatcher;
var ParametersEscapingStatus;
(function (ParametersEscapingStatus) {
    ParametersEscapingStatus[ParametersEscapingStatus["OK"] = 0] = "OK";
    ParametersEscapingStatus[ParametersEscapingStatus["NOT_REQUIRED"] = 1] = "NOT_REQUIRED";
    ParametersEscapingStatus[ParametersEscapingStatus["ERROR"] = 2] = "ERROR";
})(ParametersEscapingStatus = exports.ParametersEscapingStatus || (exports.ParametersEscapingStatus = {}));
var PARAM_OCCURENCE_STR = "__P_A_R_A_M_E_T_E_R__";
function escapeTemplateParameters(str) {
    if (str == null || typeof str != "string") {
        return { status: ParametersEscapingStatus.NOT_REQUIRED };
    }
    var resultingString = "";
    var map = {};
    var prev = 0;
    for (var i = str.indexOf("<<"); i >= 0; i = str.indexOf("<<", prev)) {
        resultingString += str.substring(prev, i);
        prev = str.indexOf(">>", i);
        if (prev < 0) {
            return { status: ParametersEscapingStatus.ERROR };
        }
        prev += ">>".length;
        var paramStr = str.substring(i, prev);
        var substitution = PARAM_OCCURENCE_STR + i + PARAM_OCCURENCE_STR;
        map[substitution] = paramStr;
        resultingString += substitution;
    }
    if (resultingString.length == 0) {
        return { status: ParametersEscapingStatus.NOT_REQUIRED };
    }
    resultingString += str.substring(prev, str.length);
    return {
        resultingString: resultingString,
        substitutions: map,
        status: ParametersEscapingStatus.OK
    };
}
exports.escapeTemplateParameters = escapeTemplateParameters;
function unescapeTemplateParameters(str, substitutions) {
    if (str == null) {
        return { status: ParametersEscapingStatus.NOT_REQUIRED };
    }
    var resultingString = "";
    var prev = 0;
    for (var i = str.indexOf(PARAM_OCCURENCE_STR); i >= 0; i = str.indexOf(PARAM_OCCURENCE_STR, prev)) {
        resultingString += str.substring(prev, i);
        prev = str.indexOf(PARAM_OCCURENCE_STR, i + 1);
        if (prev < 0) {
            return { status: ParametersEscapingStatus.ERROR };
        }
        prev += PARAM_OCCURENCE_STR.length;
        var substitution = str.substring(i, prev);
        var originalParamOccurence = substitutions[substitution];
        if (originalParamOccurence == null) {
            return { status: ParametersEscapingStatus.ERROR };
        }
        resultingString += originalParamOccurence;
    }
    if (resultingString.length == 0) {
        return { status: ParametersEscapingStatus.NOT_REQUIRED };
    }
    resultingString += str.substring(prev, str.length);
    return {
        resultingString: resultingString,
        substitutions: substitutions,
        status: ParametersEscapingStatus.OK
    };
}
exports.unescapeTemplateParameters = unescapeTemplateParameters;
function checkExpression(value) {
    var gotExpression = false;
    if (!value) {
        return false;
    }
    else if (value.charAt(value.length - 1) == '?') {
        gotExpression = true;
    }
    else {
        for (var i = 0; i < value.length; i++) {
            var ch = value.charAt(i);
            if (ch == "|" || ch == "(" || ch == "[") {
                gotExpression = true;
                break;
            }
        }
    }
    return gotExpression;
}
exports.checkExpression = checkExpression;
function isFromResourceType(node) {
    var parent = node.parent && node.parent();
    parent = parent && parent.parent && parent.parent();
    parent = parent && parent.parent && parent.parent();
    parent = parent && parent.parent && parent.parent();
    return parent && parent.key && parent.key() === universeDef.Universe10.Api.properties.resourceTypes.name;
}
function patchMethodIs(node, traits, rootPath) {
    var llMethod = node.lowLevel();
    var ramlVersion = node.definition().universe().version();
    var originalLlMethod = toOriginal(llMethod);
    var isFromResourceTypeMethod = isFromResourceType(originalLlMethod);
    var isPropertyName = universeDef.Universe10.MethodBase.properties.is.name;
    var ownIsNode = _.find(llMethod.children(), function (x) { return x.key() == isPropertyName; });
    var isNode = ownIsNode;
    if (isNode == null) {
        var newLLIsNode = new jsyaml.ASTNode(yaml.newMapping(yaml.newScalar(isPropertyName), yaml.newItems()), originalLlMethod.unit(), originalLlMethod, null, null);
        isNode = llMethod.replaceChild(null, newLLIsNode);
    }
    var originalIsNode = isFromResourceTypeMethod ? null : _.find(originalLlMethod.children(), function (x) { return x.key() == isPropertyName; });
    var childrenToPreserve = (originalIsNode != null && (originalIsNode.unit().absolutePath() == rootPath))
        ? originalIsNode.children() : [];
    var newTraits = childrenToPreserve.concat(traits.map(function (x) {
        var llChNode = prepareTraitRefNode(x.node, isNode);
        if (llChNode != null) {
            var cNode = new proxy.LowLevelCompositeNode(llChNode, isNode, x.transformer, ramlVersion);
            return cNode;
        }
        return null;
    })).filter(function (x) { return x != null; });
    if (newTraits.length == 0 && traits.length <= 1) {
        return ownIsNode;
    }
    isNode.setChildren(newTraits);
    isNode.filterChildren();
    newTraits = isNode.children();
    var directChildren = node.directChildren();
    var isProp = node.definition().property("is");
    var isPropRange = isProp.range();
    if (directChildren) {
        directChildren = directChildren.filter(function (x) {
            var p = x.property();
            return p == null || !universeHelpers.isIsProperty(p);
        });
        node._children = directChildren.concat(newTraits.map(function (x) {
            return new hlimpl.ASTPropImpl(x, node, isPropRange, isProp);
        }));
    }
    var mergedChildren = node.children();
    if (mergedChildren) {
        mergedChildren = mergedChildren.filter(function (x) {
            var p = x.property();
            return p == null || !universeHelpers.isIsProperty(p);
        });
        node._mergedChildren = mergedChildren.concat(newTraits.map(function (x) {
            return new hlimpl.ASTPropImpl(x, node, isPropRange, isProp);
        }));
    }
    return isNode;
}
exports.patchMethodIs = patchMethodIs;
function prepareTraitRefNode(llNode, llParent) {
    llParent = toOriginal(llParent);
    llNode = toOriginal(llNode);
    var yNode = llNode.actual();
    if (yNode == null) {
        return null;
    }
    if (llNode.key() == universeDef.Universe10.MethodBase.properties.is.name) {
        yNode = llNode.yamlNode().value;
    }
    if (yNode == null) {
        return null;
    }
    if (yNode.kind == yaml.Kind.SEQ) {
        yNode = yNode.items[0];
    }
    if (yNode == null) {
        return null;
    }
    var result = new jsyaml.ASTNode(yNode, llNode.unit(), llParent, null, null);
    return result;
}
exports.prepareTraitRefNode = prepareTraitRefNode;
function toOriginal(node) {
    for (var i = 0; i < 2 && proxy.LowLevelProxyNode.isInstance(node); i++) {
        node = node.originalNode();
    }
    return node;
}
exports.toOriginal = toOriginal;
var PatchedReference = /** @class */ (function () {
    function PatchedReference(_namespace, _name, _collectionName, _referencedUnit, _isChained, _mode) {
        this._namespace = _namespace;
        this._name = _name;
        this._collectionName = _collectionName;
        this._referencedUnit = _referencedUnit;
        this._isChained = _isChained;
        this._mode = _mode;
        this.gotQuestion = false;
        var l = this._name.length;
        if (typeof this._name !== "string") {
            this._name = "" + this._name;
        }
        if (this._name && this._name.charAt(l - 1) == "?") {
            this.gotQuestion = true;
            this._name = this._name.substring(0, l - 1);
        }
    }
    PatchedReference.isInstance = function (instance) {
        return instance != null && instance.getClassIdentifier
            && typeof (instance.getClassIdentifier) == "function"
            && _.contains(instance.getClassIdentifier(), PatchedReference.CLASS_IDENTIFIER_PatchedReference);
    };
    PatchedReference.prototype.getClassIdentifier = function () {
        return [PatchedReference.CLASS_IDENTIFIER_PatchedReference];
    };
    PatchedReference.prototype.namespace = function () { return this._namespace; };
    PatchedReference.prototype.name = function () { return this._name; };
    PatchedReference.prototype.collectionName = function () { return this._collectionName; };
    PatchedReference.prototype.referencedUnit = function () { return this._referencedUnit; };
    PatchedReference.prototype.mode = function () { return this._mode; };
    PatchedReference.prototype.value = function () {
        if (this._namespace == null) {
            return this._name;
        }
        var delim = this._mode == PatchMode.PATH ? "/" : ".";
        return this._namespace + delim + this._name + (this.gotQuestion ? "?" : "");
    };
    PatchedReference.prototype.isChained = function () {
        return this._isChained;
    };
    PatchedReference.CLASS_IDENTIFIER_PatchedReference = "referencePatcher.PatchedReference";
    return PatchedReference;
}());
exports.PatchedReference = PatchedReference;
function instanceOfPatchedReference(instance) {
    if (!instance)
        return false;
    return instance.namespace != null && typeof (instance.namespace) == "function" &&
        instance.name != null && typeof (instance.name) == "function" &&
        instance.collectionName != null && typeof (instance.collectionName) == "function" &&
        instance.referencedUnit != null && typeof (instance.referencedUnit) == "function" &&
        instance.mode != null && typeof (instance.mode) == "function";
}
exports.instanceOfPatchedReference = instanceOfPatchedReference;
var ElementsCollection = /** @class */ (function () {
    function ElementsCollection(name) {
        this.name = name;
        this.array = [];
    }
    ElementsCollection.isInstance = function (instance) {
        return instance != null && instance.getClassIdentifier
            && typeof (instance.getClassIdentifier) == "function"
            && _.contains(instance.getClassIdentifier(), ElementsCollection.CLASS_IDENTIFIER);
    };
    ElementsCollection.prototype.getClassIdentifier = function () {
        var superIdentifiers = [];
        return superIdentifiers.concat(ElementsCollection.CLASS_IDENTIFIER);
    };
    ElementsCollection.CLASS_IDENTIFIER = "referencePatcher.ElementsCollection";
    return ElementsCollection;
}());
var LibModel = /** @class */ (function () {
    function LibModel(unit) {
        this.unit = unit;
    }
    return LibModel;
}());
function getDeclaration(elementName, typeName, units) {
    var resolver = units[0].project().namespaceResolver();
    if (!elementName) {
        return null;
    }
    var ns = "";
    var name = elementName;
    var ind = elementName.lastIndexOf(".");
    if (ind >= 0) {
        ns = elementName.substring(0, ind);
        name = elementName.substring(ind + 1);
    }
    var result;
    var gotLibrary = false;
    for (var i = units.length; i > 0; i--) {
        var u = units[i - 1];
        var hl = u.highLevel();
        if (hl.isElement()) {
            if (universeHelpers.isLibraryType(hl.asElement().definition())) {
                if (gotLibrary) {
                    break;
                }
                gotLibrary = true;
            }
        }
        var actualUnit = u;
        if (ns) {
            actualUnit = null;
            var map = resolver.nsMap(u);
            if (map) {
                var info = map[ns];
                if (info) {
                    actualUnit = info.unit;
                }
            }
        }
        if (!actualUnit) {
            continue;
        }
        var ahl = actualUnit.highLevel();
        if (!ahl || !ahl.isElement()) {
            continue;
        }
        result = _.find(ahl.asElement().elementsOfKind(typeName), function (x) { return x.name() == name; });
        if (result) {
            break;
        }
    }
    return result;
}
exports.getDeclaration = getDeclaration;
function isCompoundValue(str) {
    var i0 = str.indexOf("<<");
    if (i0 < 0) {
        return false;
    }
    if (i0 != 0) {
        return true;
    }
    var i1 = str.indexOf(">>", i0);
    if (i1 + ">>".length != str.length) {
        return true;
    }
    return false;
}
exports.isCompoundValue = isCompoundValue;
var isExternalType = function (localType) {
    var isExternal = !localType || localType.isExternal();
    if (!isExternal) {
        for (var _i = 0, _a = localType.superTypes(); _i < _a.length; _i++) {
            var st = _a[_i];
            isExternal = st.isExternal();
            if (isExternal) {
                break;
            }
        }
    }
    return isExternal;
};
function typeUnit(t) {
    var src = t.getExtra("SOURCE");
    var llNode;
    if (hlimpl.LowLevelWrapperForTypeSystem.isInstance(src)) {
        llNode = src.node();
    }
    else if (hlimpl.ASTNodeImpl.isInstance(src)) {
        llNode = src.lowLevel();
    }
    else if (jsyaml.ASTNode.isInstance(src)
        || proxy.LowLevelProxyNode.isInstance(src)
        || json.AstNode.isInstance(src)) {
        var llNode_1 = src;
    }
    if (!llNode) {
        return null;
    }
    var unit = llNode.unit();
    return unit;
}
exports.typeUnit = typeUnit;
//# sourceMappingURL=referencePatcher.js.map