(function (factory) {
    if (typeof module === "object" && typeof module.exports === "object") {
        var v = factory(require, exports);
        if (v !== undefined) module.exports = v;
    }
    else if (typeof define === "function" && define.amd) {
        define(["require", "exports", "../utils/strings"], factory);
    }
})(function (require, exports) {
    /*---------------------------------------------------------------------------------------------
     *  Copyright (c) Microsoft Corporation. All rights reserved.
     *  Licensed under the MIT License. See License.txt in the project root for license information.
     *--------------------------------------------------------------------------------------------*/
    'use strict';
    Object.defineProperty(exports, "__esModule", { value: true });
    exports.ParseErrorCollector = exports.Marker = exports.Level = exports.Module = exports.GuardCondition = exports.LessGuard = exports.ListEntry = exports.UnknownAtRule = exports.MixinDeclaration = exports.MixinReference = exports.MixinContentDeclaration = exports.MixinContentReference = exports.ExtendsReference = exports.Variable = exports.Interpolation = exports.VariableDeclaration = exports.NumericValue = exports.RatioValue = exports.HexColorValue = exports.Operator = exports.AttributeSelector = exports.Term = exports.BinaryExpression = exports.Expression = exports.PageBoxMarginBox = exports.Page = exports.SupportsCondition = exports.MediaFeature = exports.MediaCondition = exports.MediaQuery = exports.Medialist = exports.Document = exports.PropertyAtRule = exports.Layer = exports.Supports = exports.Media = exports.Namespace = exports.ForwardVisibility = exports.Forward = exports.ModuleConfiguration = exports.Use = exports.Import = exports.KeyframeSelector = exports.Keyframe = exports.NestedProperties = exports.FontFace = exports.ViewPort = exports.FunctionDeclaration = exports.ElseStatement = exports.WhileStatement = exports.EachStatement = exports.ForStatement = exports.IfStatement = exports.FunctionArgument = exports.FunctionParameter = exports.Function = exports.Invocation = exports.Property = exports.CustomPropertyDeclaration = exports.Declaration = exports.CustomPropertySet = exports.AbstractDeclaration = exports.AtApplyRule = exports.SimpleSelector = exports.Selector = exports.RuleSet = exports.BodyDeclaration = exports.Declarations = exports.Stylesheet = exports.Identifier = exports.UnicodeRange = exports.Nodelist = exports.Node = exports.getParentDeclaration = exports.getNodePath = exports.getNodeAtOffset = exports.ReferenceType = exports.NodeType = void 0;
    const strings_1 = require("../utils/strings");
    /// <summary>
    /// Nodes for the css 2.1 specification. See for reference:
    /// http://www.w3.org/TR/CSS21/grammar.html#grammar
    /// </summary>
    var NodeType;
    (function (NodeType) {
        NodeType[NodeType["Undefined"] = 0] = "Undefined";
        NodeType[NodeType["Identifier"] = 1] = "Identifier";
        NodeType[NodeType["Stylesheet"] = 2] = "Stylesheet";
        NodeType[NodeType["Ruleset"] = 3] = "Ruleset";
        NodeType[NodeType["Selector"] = 4] = "Selector";
        NodeType[NodeType["SimpleSelector"] = 5] = "SimpleSelector";
        NodeType[NodeType["SelectorInterpolation"] = 6] = "SelectorInterpolation";
        NodeType[NodeType["SelectorCombinator"] = 7] = "SelectorCombinator";
        NodeType[NodeType["SelectorCombinatorParent"] = 8] = "SelectorCombinatorParent";
        NodeType[NodeType["SelectorCombinatorSibling"] = 9] = "SelectorCombinatorSibling";
        NodeType[NodeType["SelectorCombinatorAllSiblings"] = 10] = "SelectorCombinatorAllSiblings";
        NodeType[NodeType["SelectorCombinatorShadowPiercingDescendant"] = 11] = "SelectorCombinatorShadowPiercingDescendant";
        NodeType[NodeType["Page"] = 12] = "Page";
        NodeType[NodeType["PageBoxMarginBox"] = 13] = "PageBoxMarginBox";
        NodeType[NodeType["ClassSelector"] = 14] = "ClassSelector";
        NodeType[NodeType["IdentifierSelector"] = 15] = "IdentifierSelector";
        NodeType[NodeType["ElementNameSelector"] = 16] = "ElementNameSelector";
        NodeType[NodeType["PseudoSelector"] = 17] = "PseudoSelector";
        NodeType[NodeType["AttributeSelector"] = 18] = "AttributeSelector";
        NodeType[NodeType["Declaration"] = 19] = "Declaration";
        NodeType[NodeType["Declarations"] = 20] = "Declarations";
        NodeType[NodeType["Property"] = 21] = "Property";
        NodeType[NodeType["Expression"] = 22] = "Expression";
        NodeType[NodeType["BinaryExpression"] = 23] = "BinaryExpression";
        NodeType[NodeType["Term"] = 24] = "Term";
        NodeType[NodeType["Operator"] = 25] = "Operator";
        NodeType[NodeType["Value"] = 26] = "Value";
        NodeType[NodeType["StringLiteral"] = 27] = "StringLiteral";
        NodeType[NodeType["URILiteral"] = 28] = "URILiteral";
        NodeType[NodeType["EscapedValue"] = 29] = "EscapedValue";
        NodeType[NodeType["Function"] = 30] = "Function";
        NodeType[NodeType["NumericValue"] = 31] = "NumericValue";
        NodeType[NodeType["HexColorValue"] = 32] = "HexColorValue";
        NodeType[NodeType["RatioValue"] = 33] = "RatioValue";
        NodeType[NodeType["MixinDeclaration"] = 34] = "MixinDeclaration";
        NodeType[NodeType["MixinReference"] = 35] = "MixinReference";
        NodeType[NodeType["VariableName"] = 36] = "VariableName";
        NodeType[NodeType["VariableDeclaration"] = 37] = "VariableDeclaration";
        NodeType[NodeType["Prio"] = 38] = "Prio";
        NodeType[NodeType["Interpolation"] = 39] = "Interpolation";
        NodeType[NodeType["NestedProperties"] = 40] = "NestedProperties";
        NodeType[NodeType["ExtendsReference"] = 41] = "ExtendsReference";
        NodeType[NodeType["SelectorPlaceholder"] = 42] = "SelectorPlaceholder";
        NodeType[NodeType["Debug"] = 43] = "Debug";
        NodeType[NodeType["If"] = 44] = "If";
        NodeType[NodeType["Else"] = 45] = "Else";
        NodeType[NodeType["For"] = 46] = "For";
        NodeType[NodeType["Each"] = 47] = "Each";
        NodeType[NodeType["While"] = 48] = "While";
        NodeType[NodeType["MixinContentReference"] = 49] = "MixinContentReference";
        NodeType[NodeType["MixinContentDeclaration"] = 50] = "MixinContentDeclaration";
        NodeType[NodeType["Media"] = 51] = "Media";
        NodeType[NodeType["Keyframe"] = 52] = "Keyframe";
        NodeType[NodeType["FontFace"] = 53] = "FontFace";
        NodeType[NodeType["Import"] = 54] = "Import";
        NodeType[NodeType["Namespace"] = 55] = "Namespace";
        NodeType[NodeType["Invocation"] = 56] = "Invocation";
        NodeType[NodeType["FunctionDeclaration"] = 57] = "FunctionDeclaration";
        NodeType[NodeType["ReturnStatement"] = 58] = "ReturnStatement";
        NodeType[NodeType["MediaQuery"] = 59] = "MediaQuery";
        NodeType[NodeType["MediaCondition"] = 60] = "MediaCondition";
        NodeType[NodeType["MediaFeature"] = 61] = "MediaFeature";
        NodeType[NodeType["FunctionParameter"] = 62] = "FunctionParameter";
        NodeType[NodeType["FunctionArgument"] = 63] = "FunctionArgument";
        NodeType[NodeType["KeyframeSelector"] = 64] = "KeyframeSelector";
        NodeType[NodeType["ViewPort"] = 65] = "ViewPort";
        NodeType[NodeType["Document"] = 66] = "Document";
        NodeType[NodeType["AtApplyRule"] = 67] = "AtApplyRule";
        NodeType[NodeType["CustomPropertyDeclaration"] = 68] = "CustomPropertyDeclaration";
        NodeType[NodeType["CustomPropertySet"] = 69] = "CustomPropertySet";
        NodeType[NodeType["ListEntry"] = 70] = "ListEntry";
        NodeType[NodeType["Supports"] = 71] = "Supports";
        NodeType[NodeType["SupportsCondition"] = 72] = "SupportsCondition";
        NodeType[NodeType["NamespacePrefix"] = 73] = "NamespacePrefix";
        NodeType[NodeType["GridLine"] = 74] = "GridLine";
        NodeType[NodeType["Plugin"] = 75] = "Plugin";
        NodeType[NodeType["UnknownAtRule"] = 76] = "UnknownAtRule";
        NodeType[NodeType["Use"] = 77] = "Use";
        NodeType[NodeType["ModuleConfiguration"] = 78] = "ModuleConfiguration";
        NodeType[NodeType["Forward"] = 79] = "Forward";
        NodeType[NodeType["ForwardVisibility"] = 80] = "ForwardVisibility";
        NodeType[NodeType["Module"] = 81] = "Module";
        NodeType[NodeType["UnicodeRange"] = 82] = "UnicodeRange";
        NodeType[NodeType["Layer"] = 83] = "Layer";
        NodeType[NodeType["LayerNameList"] = 84] = "LayerNameList";
        NodeType[NodeType["LayerName"] = 85] = "LayerName";
        NodeType[NodeType["PropertyAtRule"] = 86] = "PropertyAtRule";
    })(NodeType = exports.NodeType || (exports.NodeType = {}));
    var ReferenceType;
    (function (ReferenceType) {
        ReferenceType[ReferenceType["Mixin"] = 0] = "Mixin";
        ReferenceType[ReferenceType["Rule"] = 1] = "Rule";
        ReferenceType[ReferenceType["Variable"] = 2] = "Variable";
        ReferenceType[ReferenceType["Function"] = 3] = "Function";
        ReferenceType[ReferenceType["Keyframe"] = 4] = "Keyframe";
        ReferenceType[ReferenceType["Unknown"] = 5] = "Unknown";
        ReferenceType[ReferenceType["Module"] = 6] = "Module";
        ReferenceType[ReferenceType["Forward"] = 7] = "Forward";
        ReferenceType[ReferenceType["ForwardVisibility"] = 8] = "ForwardVisibility";
        ReferenceType[ReferenceType["Property"] = 9] = "Property";
    })(ReferenceType = exports.ReferenceType || (exports.ReferenceType = {}));
    function getNodeAtOffset(node, offset) {
        let candidate = null;
        if (!node || offset < node.offset || offset > node.end) {
            return null;
        }
        // Find the shortest node at the position
        node.accept((node) => {
            if (node.offset === -1 && node.length === -1) {
                return true;
            }
            if (node.offset <= offset && node.end >= offset) {
                if (!candidate) {
                    candidate = node;
                }
                else if (node.length <= candidate.length) {
                    candidate = node;
                }
                return true;
            }
            return false;
        });
        return candidate;
    }
    exports.getNodeAtOffset = getNodeAtOffset;
    function getNodePath(node, offset) {
        let candidate = getNodeAtOffset(node, offset);
        const path = [];
        while (candidate) {
            path.unshift(candidate);
            candidate = candidate.parent;
        }
        return path;
    }
    exports.getNodePath = getNodePath;
    function getParentDeclaration(node) {
        const decl = node.findParent(NodeType.Declaration);
        const value = decl && decl.getValue();
        if (value && value.encloses(node)) {
            return decl;
        }
        return null;
    }
    exports.getParentDeclaration = getParentDeclaration;
    class Node {
        get end() { return this.offset + this.length; }
        constructor(offset = -1, len = -1, nodeType) {
            this.parent = null;
            this.offset = offset;
            this.length = len;
            if (nodeType) {
                this.nodeType = nodeType;
            }
        }
        set type(type) {
            this.nodeType = type;
        }
        get type() {
            return this.nodeType || NodeType.Undefined;
        }
        getTextProvider() {
            let node = this;
            while (node && !node.textProvider) {
                node = node.parent;
            }
            if (node) {
                return node.textProvider;
            }
            return () => { return 'unknown'; };
        }
        getText() {
            return this.getTextProvider()(this.offset, this.length);
        }
        matches(str) {
            return this.length === str.length && this.getTextProvider()(this.offset, this.length) === str;
        }
        startsWith(str) {
            return this.length >= str.length && this.getTextProvider()(this.offset, str.length) === str;
        }
        endsWith(str) {
            return this.length >= str.length && this.getTextProvider()(this.end - str.length, str.length) === str;
        }
        accept(visitor) {
            if (visitor(this) && this.children) {
                for (const child of this.children) {
                    child.accept(visitor);
                }
            }
        }
        acceptVisitor(visitor) {
            this.accept(visitor.visitNode.bind(visitor));
        }
        adoptChild(node, index = -1) {
            if (node.parent && node.parent.children) {
                const idx = node.parent.children.indexOf(node);
                if (idx >= 0) {
                    node.parent.children.splice(idx, 1);
                }
            }
            node.parent = this;
            let children = this.children;
            if (!children) {
                children = this.children = [];
            }
            if (index !== -1) {
                children.splice(index, 0, node);
            }
            else {
                children.push(node);
            }
            return node;
        }
        attachTo(parent, index = -1) {
            if (parent) {
                parent.adoptChild(this, index);
            }
            return this;
        }
        collectIssues(results) {
            if (this.issues) {
                results.push.apply(results, this.issues);
            }
        }
        addIssue(issue) {
            if (!this.issues) {
                this.issues = [];
            }
            this.issues.push(issue);
        }
        hasIssue(rule) {
            return Array.isArray(this.issues) && this.issues.some(i => i.getRule() === rule);
        }
        isErroneous(recursive = false) {
            if (this.issues && this.issues.length > 0) {
                return true;
            }
            return recursive && Array.isArray(this.children) && this.children.some(c => c.isErroneous(true));
        }
        setNode(field, node, index = -1) {
            if (node) {
                node.attachTo(this, index);
                this[field] = node;
                return true;
            }
            return false;
        }
        addChild(node) {
            if (node) {
                if (!this.children) {
                    this.children = [];
                }
                node.attachTo(this);
                this.updateOffsetAndLength(node);
                return true;
            }
            return false;
        }
        updateOffsetAndLength(node) {
            if (node.offset < this.offset || this.offset === -1) {
                this.offset = node.offset;
            }
            const nodeEnd = node.end;
            if ((nodeEnd > this.end) || this.length === -1) {
                this.length = nodeEnd - this.offset;
            }
        }
        hasChildren() {
            return !!this.children && this.children.length > 0;
        }
        getChildren() {
            return this.children ? this.children.slice(0) : [];
        }
        getChild(index) {
            if (this.children && index < this.children.length) {
                return this.children[index];
            }
            return null;
        }
        addChildren(nodes) {
            for (const node of nodes) {
                this.addChild(node);
            }
        }
        findFirstChildBeforeOffset(offset) {
            if (this.children) {
                let current = null;
                for (let i = this.children.length - 1; i >= 0; i--) {
                    // iterate until we find a child that has a start offset smaller than the input offset
                    current = this.children[i];
                    if (current.offset <= offset) {
                        return current;
                    }
                }
            }
            return null;
        }
        findChildAtOffset(offset, goDeep) {
            const current = this.findFirstChildBeforeOffset(offset);
            if (current && current.end >= offset) {
                if (goDeep) {
                    return current.findChildAtOffset(offset, true) || current;
                }
                return current;
            }
            return null;
        }
        encloses(candidate) {
            return this.offset <= candidate.offset && this.offset + this.length >= candidate.offset + candidate.length;
        }
        getParent() {
            let result = this.parent;
            while (result instanceof Nodelist) {
                result = result.parent;
            }
            return result;
        }
        findParent(type) {
            let result = this;
            while (result && result.type !== type) {
                result = result.parent;
            }
            return result;
        }
        findAParent(...types) {
            let result = this;
            while (result && !types.some(t => result.type === t)) {
                result = result.parent;
            }
            return result;
        }
        setData(key, value) {
            if (!this.options) {
                this.options = {};
            }
            this.options[key] = value;
        }
        getData(key) {
            if (!this.options || !this.options.hasOwnProperty(key)) {
                return null;
            }
            return this.options[key];
        }
    }
    exports.Node = Node;
    class Nodelist extends Node {
        constructor(parent, index = -1) {
            super(-1, -1);
            this.attachTo(parent, index);
            this.offset = -1;
            this.length = -1;
        }
    }
    exports.Nodelist = Nodelist;
    class UnicodeRange extends Node {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.UnicodeRange;
        }
        setRangeStart(rangeStart) {
            return this.setNode('rangeStart', rangeStart);
        }
        getRangeStart() {
            return this.rangeStart;
        }
        setRangeEnd(rangeEnd) {
            return this.setNode('rangeEnd', rangeEnd);
        }
        getRangeEnd() {
            return this.rangeEnd;
        }
    }
    exports.UnicodeRange = UnicodeRange;
    class Identifier extends Node {
        constructor(offset, length) {
            super(offset, length);
            this.isCustomProperty = false;
        }
        get type() {
            return NodeType.Identifier;
        }
        containsInterpolation() {
            return this.hasChildren();
        }
    }
    exports.Identifier = Identifier;
    class Stylesheet extends Node {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.Stylesheet;
        }
    }
    exports.Stylesheet = Stylesheet;
    class Declarations extends Node {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.Declarations;
        }
    }
    exports.Declarations = Declarations;
    class BodyDeclaration extends Node {
        constructor(offset, length) {
            super(offset, length);
        }
        getDeclarations() {
            return this.declarations;
        }
        setDeclarations(decls) {
            return this.setNode('declarations', decls);
        }
    }
    exports.BodyDeclaration = BodyDeclaration;
    class RuleSet extends BodyDeclaration {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.Ruleset;
        }
        getSelectors() {
            if (!this.selectors) {
                this.selectors = new Nodelist(this);
            }
            return this.selectors;
        }
        isNested() {
            return !!this.parent && this.parent.findParent(NodeType.Declarations) !== null;
        }
    }
    exports.RuleSet = RuleSet;
    class Selector extends Node {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.Selector;
        }
    }
    exports.Selector = Selector;
    class SimpleSelector extends Node {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.SimpleSelector;
        }
    }
    exports.SimpleSelector = SimpleSelector;
    class AtApplyRule extends Node {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.AtApplyRule;
        }
        setIdentifier(node) {
            return this.setNode('identifier', node, 0);
        }
        getIdentifier() {
            return this.identifier;
        }
        getName() {
            return this.identifier ? this.identifier.getText() : '';
        }
    }
    exports.AtApplyRule = AtApplyRule;
    class AbstractDeclaration extends Node {
        constructor(offset, length) {
            super(offset, length);
        }
    }
    exports.AbstractDeclaration = AbstractDeclaration;
    class CustomPropertySet extends BodyDeclaration {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.CustomPropertySet;
        }
    }
    exports.CustomPropertySet = CustomPropertySet;
    class Declaration extends AbstractDeclaration {
        constructor(offset, length) {
            super(offset, length);
            this.property = null;
        }
        get type() {
            return NodeType.Declaration;
        }
        setProperty(node) {
            return this.setNode('property', node);
        }
        getProperty() {
            return this.property;
        }
        getFullPropertyName() {
            const propertyName = this.property ? this.property.getName() : 'unknown';
            if (this.parent instanceof Declarations && this.parent.getParent() instanceof NestedProperties) {
                const parentDecl = this.parent.getParent().getParent();
                if (parentDecl instanceof Declaration) {
                    return parentDecl.getFullPropertyName() + propertyName;
                }
            }
            return propertyName;
        }
        getNonPrefixedPropertyName() {
            const propertyName = this.getFullPropertyName();
            if (propertyName && propertyName.charAt(0) === '-') {
                const vendorPrefixEnd = propertyName.indexOf('-', 1);
                if (vendorPrefixEnd !== -1) {
                    return propertyName.substring(vendorPrefixEnd + 1);
                }
            }
            return propertyName;
        }
        setValue(value) {
            return this.setNode('value', value);
        }
        getValue() {
            return this.value;
        }
        setNestedProperties(value) {
            return this.setNode('nestedProperties', value);
        }
        getNestedProperties() {
            return this.nestedProperties;
        }
    }
    exports.Declaration = Declaration;
    class CustomPropertyDeclaration extends Declaration {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.CustomPropertyDeclaration;
        }
        setPropertySet(value) {
            return this.setNode('propertySet', value);
        }
        getPropertySet() {
            return this.propertySet;
        }
    }
    exports.CustomPropertyDeclaration = CustomPropertyDeclaration;
    class Property extends Node {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.Property;
        }
        setIdentifier(value) {
            return this.setNode('identifier', value);
        }
        getIdentifier() {
            return this.identifier;
        }
        getName() {
            return (0, strings_1.trim)(this.getText(), /[_\+]+$/); /* +_: less merge */
        }
        isCustomProperty() {
            return !!this.identifier && this.identifier.isCustomProperty;
        }
    }
    exports.Property = Property;
    class Invocation extends Node {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.Invocation;
        }
        getArguments() {
            if (!this.arguments) {
                this.arguments = new Nodelist(this);
            }
            return this.arguments;
        }
    }
    exports.Invocation = Invocation;
    class Function extends Invocation {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.Function;
        }
        setIdentifier(node) {
            return this.setNode('identifier', node, 0);
        }
        getIdentifier() {
            return this.identifier;
        }
        getName() {
            return this.identifier ? this.identifier.getText() : '';
        }
    }
    exports.Function = Function;
    class FunctionParameter extends Node {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.FunctionParameter;
        }
        setIdentifier(node) {
            return this.setNode('identifier', node, 0);
        }
        getIdentifier() {
            return this.identifier;
        }
        getName() {
            return this.identifier ? this.identifier.getText() : '';
        }
        setDefaultValue(node) {
            return this.setNode('defaultValue', node, 0);
        }
        getDefaultValue() {
            return this.defaultValue;
        }
    }
    exports.FunctionParameter = FunctionParameter;
    class FunctionArgument extends Node {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.FunctionArgument;
        }
        setIdentifier(node) {
            return this.setNode('identifier', node, 0);
        }
        getIdentifier() {
            return this.identifier;
        }
        getName() {
            return this.identifier ? this.identifier.getText() : '';
        }
        setValue(node) {
            return this.setNode('value', node, 0);
        }
        getValue() {
            return this.value;
        }
    }
    exports.FunctionArgument = FunctionArgument;
    class IfStatement extends BodyDeclaration {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.If;
        }
        setExpression(node) {
            return this.setNode('expression', node, 0);
        }
        setElseClause(elseClause) {
            return this.setNode('elseClause', elseClause);
        }
    }
    exports.IfStatement = IfStatement;
    class ForStatement extends BodyDeclaration {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.For;
        }
        setVariable(node) {
            return this.setNode('variable', node, 0);
        }
    }
    exports.ForStatement = ForStatement;
    class EachStatement extends BodyDeclaration {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.Each;
        }
        getVariables() {
            if (!this.variables) {
                this.variables = new Nodelist(this);
            }
            return this.variables;
        }
    }
    exports.EachStatement = EachStatement;
    class WhileStatement extends BodyDeclaration {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.While;
        }
    }
    exports.WhileStatement = WhileStatement;
    class ElseStatement extends BodyDeclaration {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.Else;
        }
    }
    exports.ElseStatement = ElseStatement;
    class FunctionDeclaration extends BodyDeclaration {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.FunctionDeclaration;
        }
        setIdentifier(node) {
            return this.setNode('identifier', node, 0);
        }
        getIdentifier() {
            return this.identifier;
        }
        getName() {
            return this.identifier ? this.identifier.getText() : '';
        }
        getParameters() {
            if (!this.parameters) {
                this.parameters = new Nodelist(this);
            }
            return this.parameters;
        }
    }
    exports.FunctionDeclaration = FunctionDeclaration;
    class ViewPort extends BodyDeclaration {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.ViewPort;
        }
    }
    exports.ViewPort = ViewPort;
    class FontFace extends BodyDeclaration {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.FontFace;
        }
    }
    exports.FontFace = FontFace;
    class NestedProperties extends BodyDeclaration {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.NestedProperties;
        }
    }
    exports.NestedProperties = NestedProperties;
    class Keyframe extends BodyDeclaration {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.Keyframe;
        }
        setKeyword(keyword) {
            return this.setNode('keyword', keyword, 0);
        }
        getKeyword() {
            return this.keyword;
        }
        setIdentifier(node) {
            return this.setNode('identifier', node, 0);
        }
        getIdentifier() {
            return this.identifier;
        }
        getName() {
            return this.identifier ? this.identifier.getText() : '';
        }
    }
    exports.Keyframe = Keyframe;
    class KeyframeSelector extends BodyDeclaration {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.KeyframeSelector;
        }
    }
    exports.KeyframeSelector = KeyframeSelector;
    class Import extends Node {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.Import;
        }
        setMedialist(node) {
            if (node) {
                node.attachTo(this);
                return true;
            }
            return false;
        }
    }
    exports.Import = Import;
    class Use extends Node {
        get type() {
            return NodeType.Use;
        }
        getParameters() {
            if (!this.parameters) {
                this.parameters = new Nodelist(this);
            }
            return this.parameters;
        }
        setIdentifier(node) {
            return this.setNode('identifier', node, 0);
        }
        getIdentifier() {
            return this.identifier;
        }
    }
    exports.Use = Use;
    class ModuleConfiguration extends Node {
        get type() {
            return NodeType.ModuleConfiguration;
        }
        setIdentifier(node) {
            return this.setNode('identifier', node, 0);
        }
        getIdentifier() {
            return this.identifier;
        }
        getName() {
            return this.identifier ? this.identifier.getText() : '';
        }
        setValue(node) {
            return this.setNode('value', node, 0);
        }
        getValue() {
            return this.value;
        }
    }
    exports.ModuleConfiguration = ModuleConfiguration;
    class Forward extends Node {
        get type() {
            return NodeType.Forward;
        }
        setIdentifier(node) {
            return this.setNode('identifier', node, 0);
        }
        getIdentifier() {
            return this.identifier;
        }
        getMembers() {
            if (!this.members) {
                this.members = new Nodelist(this);
            }
            return this.members;
        }
        getParameters() {
            if (!this.parameters) {
                this.parameters = new Nodelist(this);
            }
            return this.parameters;
        }
    }
    exports.Forward = Forward;
    class ForwardVisibility extends Node {
        get type() {
            return NodeType.ForwardVisibility;
        }
        setIdentifier(node) {
            return this.setNode('identifier', node, 0);
        }
        getIdentifier() {
            return this.identifier;
        }
    }
    exports.ForwardVisibility = ForwardVisibility;
    class Namespace extends Node {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.Namespace;
        }
    }
    exports.Namespace = Namespace;
    class Media extends BodyDeclaration {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.Media;
        }
    }
    exports.Media = Media;
    class Supports extends BodyDeclaration {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.Supports;
        }
    }
    exports.Supports = Supports;
    class Layer extends BodyDeclaration {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.Layer;
        }
        setNames(names) {
            return this.setNode('names', names);
        }
        getNames() {
            return this.names;
        }
    }
    exports.Layer = Layer;
    class PropertyAtRule extends BodyDeclaration {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.PropertyAtRule;
        }
        setName(node) {
            if (node) {
                node.attachTo(this);
                this.name = node;
                return true;
            }
            return false;
        }
        getName() {
            return this.name;
        }
    }
    exports.PropertyAtRule = PropertyAtRule;
    class Document extends BodyDeclaration {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.Document;
        }
    }
    exports.Document = Document;
    class Medialist extends Node {
        constructor(offset, length) {
            super(offset, length);
        }
    }
    exports.Medialist = Medialist;
    class MediaQuery extends Node {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.MediaQuery;
        }
    }
    exports.MediaQuery = MediaQuery;
    class MediaCondition extends Node {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.MediaCondition;
        }
    }
    exports.MediaCondition = MediaCondition;
    class MediaFeature extends Node {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.MediaFeature;
        }
    }
    exports.MediaFeature = MediaFeature;
    class SupportsCondition extends Node {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.SupportsCondition;
        }
    }
    exports.SupportsCondition = SupportsCondition;
    class Page extends BodyDeclaration {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.Page;
        }
    }
    exports.Page = Page;
    class PageBoxMarginBox extends BodyDeclaration {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.PageBoxMarginBox;
        }
    }
    exports.PageBoxMarginBox = PageBoxMarginBox;
    class Expression extends Node {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.Expression;
        }
    }
    exports.Expression = Expression;
    class BinaryExpression extends Node {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.BinaryExpression;
        }
        setLeft(left) {
            return this.setNode('left', left);
        }
        getLeft() {
            return this.left;
        }
        setRight(right) {
            return this.setNode('right', right);
        }
        getRight() {
            return this.right;
        }
        setOperator(value) {
            return this.setNode('operator', value);
        }
        getOperator() {
            return this.operator;
        }
    }
    exports.BinaryExpression = BinaryExpression;
    class Term extends Node {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.Term;
        }
        setOperator(value) {
            return this.setNode('operator', value);
        }
        getOperator() {
            return this.operator;
        }
        setExpression(value) {
            return this.setNode('expression', value);
        }
        getExpression() {
            return this.expression;
        }
    }
    exports.Term = Term;
    class AttributeSelector extends Node {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.AttributeSelector;
        }
        setNamespacePrefix(value) {
            return this.setNode('namespacePrefix', value);
        }
        getNamespacePrefix() {
            return this.namespacePrefix;
        }
        setIdentifier(value) {
            return this.setNode('identifier', value);
        }
        getIdentifier() {
            return this.identifier;
        }
        setOperator(operator) {
            return this.setNode('operator', operator);
        }
        getOperator() {
            return this.operator;
        }
        setValue(value) {
            return this.setNode('value', value);
        }
        getValue() {
            return this.value;
        }
    }
    exports.AttributeSelector = AttributeSelector;
    class Operator extends Node {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.Operator;
        }
    }
    exports.Operator = Operator;
    class HexColorValue extends Node {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.HexColorValue;
        }
    }
    exports.HexColorValue = HexColorValue;
    class RatioValue extends Node {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.RatioValue;
        }
    }
    exports.RatioValue = RatioValue;
    const _dot = '.'.charCodeAt(0), _0 = '0'.charCodeAt(0), _9 = '9'.charCodeAt(0);
    class NumericValue extends Node {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.NumericValue;
        }
        getValue() {
            const raw = this.getText();
            let unitIdx = 0;
            let code;
            for (let i = 0, len = raw.length; i < len; i++) {
                code = raw.charCodeAt(i);
                if (!(_0 <= code && code <= _9 || code === _dot)) {
                    break;
                }
                unitIdx += 1;
            }
            return {
                value: raw.substring(0, unitIdx),
                unit: unitIdx < raw.length ? raw.substring(unitIdx) : undefined
            };
        }
    }
    exports.NumericValue = NumericValue;
    class VariableDeclaration extends AbstractDeclaration {
        constructor(offset, length) {
            super(offset, length);
            this.needsSemicolon = true;
        }
        get type() {
            return NodeType.VariableDeclaration;
        }
        setVariable(node) {
            if (node) {
                node.attachTo(this);
                this.variable = node;
                return true;
            }
            return false;
        }
        getVariable() {
            return this.variable;
        }
        getName() {
            return this.variable ? this.variable.getName() : '';
        }
        setValue(node) {
            if (node) {
                node.attachTo(this);
                this.value = node;
                return true;
            }
            return false;
        }
        getValue() {
            return this.value;
        }
    }
    exports.VariableDeclaration = VariableDeclaration;
    class Interpolation extends Node {
        // private _interpolations: void; // workaround for https://github.com/Microsoft/TypeScript/issues/18276
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.Interpolation;
        }
    }
    exports.Interpolation = Interpolation;
    class Variable extends Node {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.VariableName;
        }
        getName() {
            return this.getText();
        }
    }
    exports.Variable = Variable;
    class ExtendsReference extends Node {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.ExtendsReference;
        }
        getSelectors() {
            if (!this.selectors) {
                this.selectors = new Nodelist(this);
            }
            return this.selectors;
        }
    }
    exports.ExtendsReference = ExtendsReference;
    class MixinContentReference extends Node {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.MixinContentReference;
        }
        getArguments() {
            if (!this.arguments) {
                this.arguments = new Nodelist(this);
            }
            return this.arguments;
        }
    }
    exports.MixinContentReference = MixinContentReference;
    class MixinContentDeclaration extends BodyDeclaration {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.MixinContentDeclaration;
        }
        getParameters() {
            if (!this.parameters) {
                this.parameters = new Nodelist(this);
            }
            return this.parameters;
        }
    }
    exports.MixinContentDeclaration = MixinContentDeclaration;
    class MixinReference extends Node {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.MixinReference;
        }
        getNamespaces() {
            if (!this.namespaces) {
                this.namespaces = new Nodelist(this);
            }
            return this.namespaces;
        }
        setIdentifier(node) {
            return this.setNode('identifier', node, 0);
        }
        getIdentifier() {
            return this.identifier;
        }
        getName() {
            return this.identifier ? this.identifier.getText() : '';
        }
        getArguments() {
            if (!this.arguments) {
                this.arguments = new Nodelist(this);
            }
            return this.arguments;
        }
        setContent(node) {
            return this.setNode('content', node);
        }
        getContent() {
            return this.content;
        }
    }
    exports.MixinReference = MixinReference;
    class MixinDeclaration extends BodyDeclaration {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.MixinDeclaration;
        }
        setIdentifier(node) {
            return this.setNode('identifier', node, 0);
        }
        getIdentifier() {
            return this.identifier;
        }
        getName() {
            return this.identifier ? this.identifier.getText() : '';
        }
        getParameters() {
            if (!this.parameters) {
                this.parameters = new Nodelist(this);
            }
            return this.parameters;
        }
        setGuard(node) {
            if (node) {
                node.attachTo(this);
                this.guard = node;
            }
            return false;
        }
    }
    exports.MixinDeclaration = MixinDeclaration;
    class UnknownAtRule extends BodyDeclaration {
        constructor(offset, length) {
            super(offset, length);
        }
        get type() {
            return NodeType.UnknownAtRule;
        }
        setAtRuleName(atRuleName) {
            this.atRuleName = atRuleName;
        }
        getAtRuleName() {
            return this.atRuleName;
        }
    }
    exports.UnknownAtRule = UnknownAtRule;
    class ListEntry extends Node {
        get type() {
            return NodeType.ListEntry;
        }
        setKey(node) {
            return this.setNode('key', node, 0);
        }
        setValue(node) {
            return this.setNode('value', node, 1);
        }
    }
    exports.ListEntry = ListEntry;
    class LessGuard extends Node {
        getConditions() {
            if (!this.conditions) {
                this.conditions = new Nodelist(this);
            }
            return this.conditions;
        }
    }
    exports.LessGuard = LessGuard;
    class GuardCondition extends Node {
        setVariable(node) {
            return this.setNode('variable', node);
        }
    }
    exports.GuardCondition = GuardCondition;
    class Module extends Node {
        get type() {
            return NodeType.Module;
        }
        setIdentifier(node) {
            return this.setNode('identifier', node, 0);
        }
        getIdentifier() {
            return this.identifier;
        }
    }
    exports.Module = Module;
    var Level;
    (function (Level) {
        Level[Level["Ignore"] = 1] = "Ignore";
        Level[Level["Warning"] = 2] = "Warning";
        Level[Level["Error"] = 4] = "Error";
    })(Level = exports.Level || (exports.Level = {}));
    class Marker {
        constructor(node, rule, level, message, offset = node.offset, length = node.length) {
            this.node = node;
            this.rule = rule;
            this.level = level;
            this.message = message || rule.message;
            this.offset = offset;
            this.length = length;
        }
        getRule() {
            return this.rule;
        }
        getLevel() {
            return this.level;
        }
        getOffset() {
            return this.offset;
        }
        getLength() {
            return this.length;
        }
        getNode() {
            return this.node;
        }
        getMessage() {
            return this.message;
        }
    }
    exports.Marker = Marker;
    /*
    export class DefaultVisitor implements IVisitor {
    
        public visitNode(node:Node):boolean {
            switch (node.type) {
                case NodeType.Stylesheet:
                    return this.visitStylesheet(<Stylesheet> node);
                case NodeType.FontFace:
                    return this.visitFontFace(<FontFace> node);
                case NodeType.Ruleset:
                    return this.visitRuleSet(<RuleSet> node);
                case NodeType.Selector:
                    return this.visitSelector(<Selector> node);
                case NodeType.SimpleSelector:
                    return this.visitSimpleSelector(<SimpleSelector> node);
                case NodeType.Declaration:
                    return this.visitDeclaration(<Declaration> node);
                case NodeType.Function:
                    return this.visitFunction(<Function> node);
                case NodeType.FunctionDeclaration:
                    return this.visitFunctionDeclaration(<FunctionDeclaration> node);
                case NodeType.FunctionParameter:
                    return this.visitFunctionParameter(<FunctionParameter> node);
                case NodeType.FunctionArgument:
                    return this.visitFunctionArgument(<FunctionArgument> node);
                case NodeType.Term:
                    return this.visitTerm(<Term> node);
                case NodeType.Declaration:
                    return this.visitExpression(<Expression> node);
                case NodeType.NumericValue:
                    return this.visitNumericValue(<NumericValue> node);
                case NodeType.Page:
                    return this.visitPage(<Page> node);
                case NodeType.PageBoxMarginBox:
                    return this.visitPageBoxMarginBox(<PageBoxMarginBox> node);
                case NodeType.Property:
                    return this.visitProperty(<Property> node);
                case NodeType.NumericValue:
                    return this.visitNodelist(<Nodelist> node);
                case NodeType.Import:
                    return this.visitImport(<Import> node);
                case NodeType.Namespace:
                    return this.visitNamespace(<Namespace> node);
                case NodeType.Keyframe:
                    return this.visitKeyframe(<Keyframe> node);
                case NodeType.KeyframeSelector:
                    return this.visitKeyframeSelector(<KeyframeSelector> node);
                case NodeType.MixinDeclaration:
                    return this.visitMixinDeclaration(<MixinDeclaration> node);
                case NodeType.MixinReference:
                    return this.visitMixinReference(<MixinReference> node);
                case NodeType.Variable:
                    return this.visitVariable(<Variable> node);
                case NodeType.VariableDeclaration:
                    return this.visitVariableDeclaration(<VariableDeclaration> node);
            }
            return this.visitUnknownNode(node);
        }
    
        public visitFontFace(node:FontFace):boolean {
            return true;
        }
    
        public visitKeyframe(node:Keyframe):boolean {
            return true;
        }
    
        public visitKeyframeSelector(node:KeyframeSelector):boolean {
            return true;
        }
    
        public visitStylesheet(node:Stylesheet):boolean {
            return true;
        }
    
        public visitProperty(Node:Property):boolean {
            return true;
        }
    
        public visitRuleSet(node:RuleSet):boolean {
            return true;
        }
    
        public visitSelector(node:Selector):boolean {
            return true;
        }
    
        public visitSimpleSelector(node:SimpleSelector):boolean {
            return true;
        }
    
        public visitDeclaration(node:Declaration):boolean {
            return true;
        }
    
        public visitFunction(node:Function):boolean {
            return true;
        }
    
        public visitFunctionDeclaration(node:FunctionDeclaration):boolean {
            return true;
        }
    
        public visitInvocation(node:Invocation):boolean {
            return true;
        }
    
        public visitTerm(node:Term):boolean {
            return true;
        }
    
        public visitImport(node:Import):boolean {
            return true;
        }
    
        public visitNamespace(node:Namespace):boolean {
            return true;
        }
    
        public visitExpression(node:Expression):boolean {
            return true;
        }
    
        public visitNumericValue(node:NumericValue):boolean {
            return true;
        }
    
        public visitPage(node:Page):boolean {
            return true;
        }
    
        public visitPageBoxMarginBox(node:PageBoxMarginBox):boolean {
            return true;
        }
    
        public visitNodelist(node:Nodelist):boolean {
            return true;
        }
    
        public visitVariableDeclaration(node:VariableDeclaration):boolean {
            return true;
        }
    
        public visitVariable(node:Variable):boolean {
            return true;
        }
    
        public visitMixinDeclaration(node:MixinDeclaration):boolean {
            return true;
        }
    
        public visitMixinReference(node:MixinReference):boolean {
            return true;
        }
    
        public visitUnknownNode(node:Node):boolean {
            return true;
        }
    }
    */
    class ParseErrorCollector {
        static entries(node) {
            const visitor = new ParseErrorCollector();
            node.acceptVisitor(visitor);
            return visitor.entries;
        }
        constructor() {
            this.entries = [];
        }
        visitNode(node) {
            if (node.isErroneous()) {
                node.collectIssues(this.entries);
            }
            return true;
        }
    }
    exports.ParseErrorCollector = ParseErrorCollector;
});
