@microsoft/tsdoc
Version:
A parser for the TypeScript doc comment syntax
1,363 lines • 51 kB
JavaScript
"use strict";
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
// See LICENSE in the project root for license information.
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.SymbolReference = exports.Meaning = exports.ComponentNavigation = exports.ComponentRoot = exports.ComponentPathBase = exports.ComponentReference = exports.ComponentString = exports.Component = exports.GlobalSource = exports.ModuleSource = exports.Navigation = exports.DeclarationReference = void 0;
/* eslint-disable @typescript-eslint/no-use-before-define */
/* eslint-disable @typescript-eslint/naming-convention */
// NOTE: See DeclarationReference.grammarkdown for information on the underlying grammar.
var StringChecks_1 = require("../parser/StringChecks");
/**
* Represents a reference to a declaration.
* @beta
*/
var DeclarationReference = /** @class */ (function () {
function DeclarationReference(source, navigation, symbol) {
this._source = source;
this._navigation = navigation;
this._symbol = symbol;
}
Object.defineProperty(DeclarationReference.prototype, "source", {
get: function () {
return this._source;
},
enumerable: false,
configurable: true
});
Object.defineProperty(DeclarationReference.prototype, "navigation", {
get: function () {
if (!this._source || !this._symbol) {
return undefined;
}
if (this._source === GlobalSource.instance) {
return Navigation.Locals;
}
if (this._navigation === undefined) {
return Navigation.Exports;
}
return this._navigation;
},
enumerable: false,
configurable: true
});
Object.defineProperty(DeclarationReference.prototype, "symbol", {
get: function () {
return this._symbol;
},
enumerable: false,
configurable: true
});
Object.defineProperty(DeclarationReference.prototype, "isEmpty", {
get: function () {
return this.source === undefined && this.symbol === undefined;
},
enumerable: false,
configurable: true
});
DeclarationReference.parse = function (text) {
var parser = new Parser(text);
var reference = parser.parseDeclarationReference();
if (parser.errors.length) {
throw new SyntaxError("Invalid DeclarationReference '".concat(text, "':\n ").concat(parser.errors.join('\n ')));
}
if (!parser.eof) {
throw new SyntaxError("Invalid DeclarationReference '".concat(text, "'"));
}
return reference;
};
DeclarationReference.parseComponent = function (text) {
if (text[0] === '[') {
return ComponentReference.parse(text);
}
else {
return new ComponentString(text, true);
}
};
/**
* Determines whether the provided string is a well-formed symbol navigation component string.
*/
DeclarationReference.isWellFormedComponentString = function (text) {
var scanner = new Scanner(text);
return scanner.scan() === Token.String
? scanner.scan() === Token.EofToken
: scanner.token() === Token.Text
? scanner.scan() === Token.EofToken
: scanner.token() === Token.EofToken;
};
/**
* Escapes a string for use as a symbol navigation component. If the string contains any of `!.#~:,"{}()@` or starts
* with `[`, it is enclosed in quotes.
*/
DeclarationReference.escapeComponentString = function (text) {
if (text.length === 0) {
return '""';
}
var ch = text.charAt(0);
if (ch === '[' || ch === '"' || !this.isWellFormedComponentString(text)) {
return JSON.stringify(text);
}
return text;
};
/**
* Unescapes a string used as a symbol navigation component.
*/
DeclarationReference.unescapeComponentString = function (text) {
if (text.length >= 2 && text.charAt(0) === '"' && text.charAt(text.length - 1) === '"') {
try {
return JSON.parse(text);
}
catch (_a) {
throw new SyntaxError("Invalid Component '".concat(text, "'"));
}
}
if (!this.isWellFormedComponentString(text)) {
throw new SyntaxError("Invalid Component '".concat(text, "'"));
}
return text;
};
/**
* Determines whether the provided string is a well-formed module source string. The string may not
* have a trailing `!` character.
*/
DeclarationReference.isWellFormedModuleSourceString = function (text) {
var scanner = new Scanner(text + '!');
return (scanner.rescanModuleSource() === Token.ModuleSource &&
!scanner.stringIsUnterminated &&
scanner.scan() === Token.ExclamationToken &&
scanner.scan() === Token.EofToken);
};
/**
* Escapes a string for use as a module source. If the string contains any of `!"` it is enclosed in quotes.
*/
DeclarationReference.escapeModuleSourceString = function (text) {
if (text.length === 0) {
return '""';
}
var ch = text.charAt(0);
if (ch === '"' || !this.isWellFormedModuleSourceString(text)) {
return JSON.stringify(text);
}
return text;
};
/**
* Unescapes a string used as a module source. The string may not have a trailing `!` character.
*/
DeclarationReference.unescapeModuleSourceString = function (text) {
if (text.length >= 2 && text.charAt(0) === '"' && text.charAt(text.length - 1) === '"') {
try {
return JSON.parse(text);
}
catch (_a) {
throw new SyntaxError("Invalid Module source '".concat(text, "'"));
}
}
if (!this.isWellFormedModuleSourceString(text)) {
throw new SyntaxError("Invalid Module source '".concat(text, "'"));
}
return text;
};
DeclarationReference.empty = function () {
return new DeclarationReference();
};
DeclarationReference.package = function (packageName, importPath) {
return new DeclarationReference(ModuleSource.fromPackage(packageName, importPath));
};
DeclarationReference.module = function (path, userEscaped) {
return new DeclarationReference(new ModuleSource(path, userEscaped));
};
DeclarationReference.global = function () {
return new DeclarationReference(GlobalSource.instance);
};
DeclarationReference.from = function (base) {
return base || this.empty();
};
DeclarationReference.prototype.withSource = function (source) {
return this._source === source ? this : new DeclarationReference(source, this._navigation, this._symbol);
};
DeclarationReference.prototype.withNavigation = function (navigation) {
return this._navigation === navigation
? this
: new DeclarationReference(this._source, navigation, this._symbol);
};
DeclarationReference.prototype.withSymbol = function (symbol) {
return this._symbol === symbol ? this : new DeclarationReference(this._source, this._navigation, symbol);
};
DeclarationReference.prototype.withComponentPath = function (componentPath) {
return this.withSymbol(this.symbol ? this.symbol.withComponentPath(componentPath) : new SymbolReference(componentPath));
};
DeclarationReference.prototype.withMeaning = function (meaning) {
if (!this.symbol) {
if (meaning === undefined) {
return this;
}
return this.withSymbol(SymbolReference.empty().withMeaning(meaning));
}
return this.withSymbol(this.symbol.withMeaning(meaning));
};
DeclarationReference.prototype.withOverloadIndex = function (overloadIndex) {
if (!this.symbol) {
if (overloadIndex === undefined) {
return this;
}
return this.withSymbol(SymbolReference.empty().withOverloadIndex(overloadIndex));
}
return this.withSymbol(this.symbol.withOverloadIndex(overloadIndex));
};
DeclarationReference.prototype.addNavigationStep = function (navigation, component) {
if (this.symbol) {
return this.withSymbol(this.symbol.addNavigationStep(navigation, component));
}
if (navigation === Navigation.Members) {
navigation = Navigation.Exports;
}
var symbol = new SymbolReference(new ComponentRoot(Component.from(component)));
return new DeclarationReference(this.source, navigation, symbol);
};
DeclarationReference.prototype.toString = function () {
var navigation = this._source instanceof ModuleSource && this._symbol && this.navigation === Navigation.Locals
? '~'
: '';
return "".concat(this.source || '').concat(navigation).concat(this.symbol || '');
};
return DeclarationReference;
}());
exports.DeclarationReference = DeclarationReference;
/**
* Indicates the symbol table from which to resolve the next symbol component.
* @beta
*/
var Navigation;
(function (Navigation) {
Navigation["Exports"] = ".";
Navigation["Members"] = "#";
Navigation["Locals"] = "~";
})(Navigation || (exports.Navigation = Navigation = {}));
/**
* Represents a module.
* @beta
*/
var ModuleSource = /** @class */ (function () {
function ModuleSource(path, userEscaped) {
if (userEscaped === void 0) { userEscaped = true; }
this.escapedPath =
this instanceof ParsedModuleSource ? path : escapeModuleSourceIfNeeded(path, userEscaped);
}
Object.defineProperty(ModuleSource.prototype, "path", {
get: function () {
return this._path || (this._path = DeclarationReference.unescapeModuleSourceString(this.escapedPath));
},
enumerable: false,
configurable: true
});
Object.defineProperty(ModuleSource.prototype, "packageName", {
get: function () {
return this._getOrParsePathComponents().packageName;
},
enumerable: false,
configurable: true
});
Object.defineProperty(ModuleSource.prototype, "scopeName", {
get: function () {
var scopeName = this._getOrParsePathComponents().scopeName;
return scopeName ? '@' + scopeName : '';
},
enumerable: false,
configurable: true
});
Object.defineProperty(ModuleSource.prototype, "unscopedPackageName", {
get: function () {
return this._getOrParsePathComponents().unscopedPackageName;
},
enumerable: false,
configurable: true
});
Object.defineProperty(ModuleSource.prototype, "importPath", {
get: function () {
return this._getOrParsePathComponents().importPath || '';
},
enumerable: false,
configurable: true
});
ModuleSource.fromScopedPackage = function (scopeName, unscopedPackageName, importPath) {
var packageName = unscopedPackageName;
if (scopeName) {
if (scopeName.charAt(0) === '@') {
scopeName = scopeName.slice(1);
}
packageName = "@".concat(scopeName, "/").concat(unscopedPackageName);
}
var parsed = { packageName: packageName, scopeName: scopeName || '', unscopedPackageName: unscopedPackageName };
return this._fromPackageName(parsed, packageName, importPath);
};
ModuleSource.fromPackage = function (packageName, importPath) {
return this._fromPackageName(parsePackageName(packageName), packageName, importPath);
};
ModuleSource._fromPackageName = function (parsed, packageName, importPath) {
if (!parsed) {
throw new Error('Parsed package must be provided.');
}
var packageNameError = StringChecks_1.StringChecks.explainIfInvalidPackageName(packageName);
if (packageNameError) {
throw new SyntaxError("Invalid NPM package name: ".concat(packageNameError));
}
var path = packageName;
if (importPath) {
if (invalidImportPathRegExp.test(importPath)) {
throw new SyntaxError("Invalid import path '".concat(importPath));
}
path += '/' + importPath;
parsed.importPath = importPath;
}
var source = new ModuleSource(path);
source._pathComponents = parsed;
return source;
};
ModuleSource.prototype.toString = function () {
return "".concat(this.escapedPath, "!");
};
ModuleSource.prototype._getOrParsePathComponents = function () {
if (!this._pathComponents) {
var path = this.path;
var parsed = parsePackageName(path);
if (parsed && !StringChecks_1.StringChecks.explainIfInvalidPackageName(parsed.packageName)) {
this._pathComponents = parsed;
}
else {
this._pathComponents = {
packageName: '',
scopeName: '',
unscopedPackageName: '',
importPath: path
};
}
}
return this._pathComponents;
};
return ModuleSource;
}());
exports.ModuleSource = ModuleSource;
var ParsedModuleSource = /** @class */ (function (_super) {
__extends(ParsedModuleSource, _super);
function ParsedModuleSource() {
return _super !== null && _super.apply(this, arguments) || this;
}
return ParsedModuleSource;
}(ModuleSource));
// matches the following:
// 'foo' -> ["foo", "foo", undefined, "foo", undefined]
// 'foo/bar' -> ["foo/bar", "foo", undefined, "foo", "bar"]
// '@scope/foo' -> ["@scope/foo", "@scope/foo", "scope", "foo", undefined]
// '@scope/foo/bar' -> ["@scope/foo/bar", "@scope/foo", "scope", "foo", "bar"]
// does not match:
// '/'
// '@/'
// '@scope/'
// capture groups:
// 1. The package name (including scope)
// 2. The scope name (excluding the leading '@')
// 3. The unscoped package name
// 4. The package-relative import path
var packageNameRegExp = /^((?:@([^/]+?)\/)?([^/]+?))(?:\/(.+))?$/;
// no leading './' or '.\'
// no leading '../' or '..\'
// no leading '/' or '\'
// not '.' or '..'
var invalidImportPathRegExp = /^(\.\.?([\\/]|$)|[\\/])/;
// eslint-disable-next-line @rushstack/no-new-null
function parsePackageName(text) {
var match = packageNameRegExp.exec(text);
if (!match) {
return match;
}
var _a = match[1], packageName = _a === void 0 ? '' : _a, _b = match[2], scopeName = _b === void 0 ? '' : _b, _c = match[3], unscopedPackageName = _c === void 0 ? '' : _c, importPath = match[4];
return { packageName: packageName, scopeName: scopeName, unscopedPackageName: unscopedPackageName, importPath: importPath };
}
/**
* Represents the global scope.
* @beta
*/
var GlobalSource = /** @class */ (function () {
function GlobalSource() {
}
GlobalSource.prototype.toString = function () {
return '!';
};
GlobalSource.instance = new GlobalSource();
return GlobalSource;
}());
exports.GlobalSource = GlobalSource;
/**
* @beta
*/
// eslint-disable-next-line @typescript-eslint/no-namespace
var Component;
(function (Component) {
function from(value) {
if (typeof value === 'string') {
return new ComponentString(value);
}
if (value instanceof DeclarationReference) {
return new ComponentReference(value);
}
return value;
}
Component.from = from;
})(Component || (exports.Component = Component = {}));
/**
* @beta
*/
var ComponentString = /** @class */ (function () {
function ComponentString(text, userEscaped) {
this.text = this instanceof ParsedComponentString ? text : escapeComponentIfNeeded(text, userEscaped);
}
ComponentString.prototype.toString = function () {
return this.text;
};
return ComponentString;
}());
exports.ComponentString = ComponentString;
var ParsedComponentString = /** @class */ (function (_super) {
__extends(ParsedComponentString, _super);
function ParsedComponentString() {
return _super !== null && _super.apply(this, arguments) || this;
}
return ParsedComponentString;
}(ComponentString));
/**
* @beta
*/
var ComponentReference = /** @class */ (function () {
function ComponentReference(reference) {
this.reference = reference;
}
ComponentReference.parse = function (text) {
if (text.length > 2 && text.charAt(0) === '[' && text.charAt(text.length - 1) === ']') {
return new ComponentReference(DeclarationReference.parse(text.slice(1, -1)));
}
throw new SyntaxError("Invalid component reference: '".concat(text, "'"));
};
ComponentReference.prototype.withReference = function (reference) {
return this.reference === reference ? this : new ComponentReference(reference);
};
ComponentReference.prototype.toString = function () {
return "[".concat(this.reference, "]");
};
return ComponentReference;
}());
exports.ComponentReference = ComponentReference;
/**
* @beta
*/
var ComponentPathBase = /** @class */ (function () {
function ComponentPathBase(component) {
this.component = component;
}
ComponentPathBase.prototype.addNavigationStep = function (navigation, component) {
// tslint:disable-next-line:no-use-before-declare
return new ComponentNavigation(this, navigation, Component.from(component));
};
return ComponentPathBase;
}());
exports.ComponentPathBase = ComponentPathBase;
/**
* @beta
*/
var ComponentRoot = /** @class */ (function (_super) {
__extends(ComponentRoot, _super);
function ComponentRoot() {
return _super !== null && _super.apply(this, arguments) || this;
}
ComponentRoot.prototype.withComponent = function (component) {
return this.component === component ? this : new ComponentRoot(Component.from(component));
};
ComponentRoot.prototype.toString = function () {
return this.component.toString();
};
return ComponentRoot;
}(ComponentPathBase));
exports.ComponentRoot = ComponentRoot;
/**
* @beta
*/
var ComponentNavigation = /** @class */ (function (_super) {
__extends(ComponentNavigation, _super);
function ComponentNavigation(parent, navigation, component) {
var _this = _super.call(this, component) || this;
_this.parent = parent;
_this.navigation = navigation;
return _this;
}
ComponentNavigation.prototype.withParent = function (parent) {
return this.parent === parent ? this : new ComponentNavigation(parent, this.navigation, this.component);
};
ComponentNavigation.prototype.withNavigation = function (navigation) {
return this.navigation === navigation
? this
: new ComponentNavigation(this.parent, navigation, this.component);
};
ComponentNavigation.prototype.withComponent = function (component) {
return this.component === component
? this
: new ComponentNavigation(this.parent, this.navigation, Component.from(component));
};
ComponentNavigation.prototype.toString = function () {
return "".concat(this.parent).concat(formatNavigation(this.navigation)).concat(this.component);
};
return ComponentNavigation;
}(ComponentPathBase));
exports.ComponentNavigation = ComponentNavigation;
/**
* @beta
*/
var Meaning;
(function (Meaning) {
Meaning["Class"] = "class";
Meaning["Interface"] = "interface";
Meaning["TypeAlias"] = "type";
Meaning["Enum"] = "enum";
Meaning["Namespace"] = "namespace";
Meaning["Function"] = "function";
Meaning["Variable"] = "var";
Meaning["Constructor"] = "constructor";
Meaning["Member"] = "member";
Meaning["Event"] = "event";
Meaning["CallSignature"] = "call";
Meaning["ConstructSignature"] = "new";
Meaning["IndexSignature"] = "index";
Meaning["ComplexType"] = "complex"; // Any complex type
})(Meaning || (exports.Meaning = Meaning = {}));
/**
* Represents a reference to a TypeScript symbol.
* @beta
*/
var SymbolReference = /** @class */ (function () {
function SymbolReference(component, _a) {
var _b = _a === void 0 ? {} : _a, meaning = _b.meaning, overloadIndex = _b.overloadIndex;
this.componentPath = component;
this.overloadIndex = overloadIndex;
this.meaning = meaning;
}
SymbolReference.empty = function () {
return new SymbolReference(/*component*/ undefined);
};
SymbolReference.prototype.withComponentPath = function (componentPath) {
return this.componentPath === componentPath
? this
: new SymbolReference(componentPath, {
meaning: this.meaning,
overloadIndex: this.overloadIndex
});
};
SymbolReference.prototype.withMeaning = function (meaning) {
return this.meaning === meaning
? this
: new SymbolReference(this.componentPath, {
meaning: meaning,
overloadIndex: this.overloadIndex
});
};
SymbolReference.prototype.withOverloadIndex = function (overloadIndex) {
return this.overloadIndex === overloadIndex
? this
: new SymbolReference(this.componentPath, {
meaning: this.meaning,
overloadIndex: overloadIndex
});
};
SymbolReference.prototype.addNavigationStep = function (navigation, component) {
if (!this.componentPath) {
throw new Error('Cannot add a navigation step to an empty symbol reference.');
}
return new SymbolReference(this.componentPath.addNavigationStep(navigation, component));
};
SymbolReference.prototype.toString = function () {
var result = "".concat(this.componentPath || '');
if (this.meaning && this.overloadIndex !== undefined) {
result += ":".concat(this.meaning, "(").concat(this.overloadIndex, ")");
}
else if (this.meaning) {
result += ":".concat(this.meaning);
}
else if (this.overloadIndex !== undefined) {
result += ":".concat(this.overloadIndex);
}
return result;
};
return SymbolReference;
}());
exports.SymbolReference = SymbolReference;
var Token;
(function (Token) {
Token[Token["None"] = 0] = "None";
Token[Token["EofToken"] = 1] = "EofToken";
// Punctuator
Token[Token["OpenBraceToken"] = 2] = "OpenBraceToken";
Token[Token["CloseBraceToken"] = 3] = "CloseBraceToken";
Token[Token["OpenParenToken"] = 4] = "OpenParenToken";
Token[Token["CloseParenToken"] = 5] = "CloseParenToken";
Token[Token["OpenBracketToken"] = 6] = "OpenBracketToken";
Token[Token["CloseBracketToken"] = 7] = "CloseBracketToken";
Token[Token["ExclamationToken"] = 8] = "ExclamationToken";
Token[Token["DotToken"] = 9] = "DotToken";
Token[Token["HashToken"] = 10] = "HashToken";
Token[Token["TildeToken"] = 11] = "TildeToken";
Token[Token["ColonToken"] = 12] = "ColonToken";
Token[Token["CommaToken"] = 13] = "CommaToken";
Token[Token["AtToken"] = 14] = "AtToken";
Token[Token["DecimalDigits"] = 15] = "DecimalDigits";
Token[Token["String"] = 16] = "String";
Token[Token["Text"] = 17] = "Text";
Token[Token["ModuleSource"] = 18] = "ModuleSource";
// Keywords
Token[Token["ClassKeyword"] = 19] = "ClassKeyword";
Token[Token["InterfaceKeyword"] = 20] = "InterfaceKeyword";
Token[Token["TypeKeyword"] = 21] = "TypeKeyword";
Token[Token["EnumKeyword"] = 22] = "EnumKeyword";
Token[Token["NamespaceKeyword"] = 23] = "NamespaceKeyword";
Token[Token["FunctionKeyword"] = 24] = "FunctionKeyword";
Token[Token["VarKeyword"] = 25] = "VarKeyword";
Token[Token["ConstructorKeyword"] = 26] = "ConstructorKeyword";
Token[Token["MemberKeyword"] = 27] = "MemberKeyword";
Token[Token["EventKeyword"] = 28] = "EventKeyword";
Token[Token["CallKeyword"] = 29] = "CallKeyword";
Token[Token["NewKeyword"] = 30] = "NewKeyword";
Token[Token["IndexKeyword"] = 31] = "IndexKeyword";
Token[Token["ComplexKeyword"] = 32] = "ComplexKeyword"; // 'complex'
})(Token || (Token = {}));
function tokenToString(token) {
switch (token) {
case Token.OpenBraceToken:
return '{';
case Token.CloseBraceToken:
return '}';
case Token.OpenParenToken:
return '(';
case Token.CloseParenToken:
return ')';
case Token.OpenBracketToken:
return '[';
case Token.CloseBracketToken:
return ']';
case Token.ExclamationToken:
return '!';
case Token.DotToken:
return '.';
case Token.HashToken:
return '#';
case Token.TildeToken:
return '~';
case Token.ColonToken:
return ':';
case Token.CommaToken:
return ',';
case Token.AtToken:
return '@';
case Token.ClassKeyword:
return 'class';
case Token.InterfaceKeyword:
return 'interface';
case Token.TypeKeyword:
return 'type';
case Token.EnumKeyword:
return 'enum';
case Token.NamespaceKeyword:
return 'namespace';
case Token.FunctionKeyword:
return 'function';
case Token.VarKeyword:
return 'var';
case Token.ConstructorKeyword:
return 'constructor';
case Token.MemberKeyword:
return 'member';
case Token.EventKeyword:
return 'event';
case Token.CallKeyword:
return 'call';
case Token.NewKeyword:
return 'new';
case Token.IndexKeyword:
return 'index';
case Token.ComplexKeyword:
return 'complex';
case Token.None:
return '<none>';
case Token.EofToken:
return '<eof>';
case Token.DecimalDigits:
return '<decimal digits>';
case Token.String:
return '<string>';
case Token.Text:
return '<text>';
case Token.ModuleSource:
return '<module source>';
}
}
var Scanner = /** @class */ (function () {
function Scanner(text) {
this._pos = 0;
this._tokenPos = 0;
this._stringIsUnterminated = false;
this._token = Token.None;
this._text = text;
}
Object.defineProperty(Scanner.prototype, "stringIsUnterminated", {
get: function () {
return this._stringIsUnterminated;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Scanner.prototype, "text", {
get: function () {
return this._text;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Scanner.prototype, "tokenText", {
get: function () {
return this._text.slice(this._tokenPos, this._pos);
},
enumerable: false,
configurable: true
});
Object.defineProperty(Scanner.prototype, "eof", {
get: function () {
return this._pos >= this._text.length;
},
enumerable: false,
configurable: true
});
Scanner.prototype.token = function () {
return this._token;
};
Scanner.prototype.speculate = function (cb) {
var tokenPos = this._tokenPos;
var pos = this._pos;
var text = this._text;
var token = this._token;
var stringIsUnterminated = this._stringIsUnterminated;
var accepted = false;
try {
var accept = function () {
accepted = true;
};
return cb(accept);
}
finally {
if (!accepted) {
this._tokenPos = tokenPos;
this._pos = pos;
this._text = text;
this._token = token;
this._stringIsUnterminated = stringIsUnterminated;
}
}
};
Scanner.prototype.scan = function () {
if (!this.eof) {
this._tokenPos = this._pos;
this._stringIsUnterminated = false;
while (!this.eof) {
var ch = this._text.charAt(this._pos++);
switch (ch) {
case '{':
return (this._token = Token.OpenBraceToken);
case '}':
return (this._token = Token.CloseBraceToken);
case '(':
return (this._token = Token.OpenParenToken);
case ')':
return (this._token = Token.CloseParenToken);
case '[':
return (this._token = Token.OpenBracketToken);
case ']':
return (this._token = Token.CloseBracketToken);
case '!':
return (this._token = Token.ExclamationToken);
case '.':
return (this._token = Token.DotToken);
case '#':
return (this._token = Token.HashToken);
case '~':
return (this._token = Token.TildeToken);
case ':':
return (this._token = Token.ColonToken);
case ',':
return (this._token = Token.CommaToken);
case '@':
return (this._token = Token.AtToken);
case '"':
this.scanString();
return (this._token = Token.String);
default:
this.scanText();
return (this._token = Token.Text);
}
}
}
return (this._token = Token.EofToken);
};
Scanner.prototype.rescanModuleSource = function () {
var _this = this;
switch (this._token) {
case Token.ModuleSource:
case Token.ExclamationToken:
case Token.EofToken:
return this._token;
}
return this.speculate(function (accept) {
if (!_this.eof) {
_this._pos = _this._tokenPos;
_this._stringIsUnterminated = false;
var scanned = 'none';
while (!_this.eof) {
var ch = _this._text[_this._pos];
if (ch === '!') {
if (scanned === 'none') {
return _this._token;
}
accept();
return (_this._token = Token.ModuleSource);
}
_this._pos++;
if (ch === '"') {
if (scanned === 'other') {
// strings not allowed after scanning any other characters
return _this._token;
}
scanned = 'string';
_this.scanString();
}
else {
if (scanned === 'string') {
// no other tokens allowed after string
return _this._token;
}
scanned = 'other';
if (!isPunctuator(ch)) {
_this.scanText();
}
}
}
}
return _this._token;
});
};
Scanner.prototype.rescanMeaning = function () {
if (this._token === Token.Text) {
var tokenText = this.tokenText;
switch (tokenText) {
case 'class':
return (this._token = Token.ClassKeyword);
case 'interface':
return (this._token = Token.InterfaceKeyword);
case 'type':
return (this._token = Token.TypeKeyword);
case 'enum':
return (this._token = Token.EnumKeyword);
case 'namespace':
return (this._token = Token.NamespaceKeyword);
case 'function':
return (this._token = Token.FunctionKeyword);
case 'var':
return (this._token = Token.VarKeyword);
case 'constructor':
return (this._token = Token.ConstructorKeyword);
case 'member':
return (this._token = Token.MemberKeyword);
case 'event':
return (this._token = Token.EventKeyword);
case 'call':
return (this._token = Token.CallKeyword);
case 'new':
return (this._token = Token.NewKeyword);
case 'index':
return (this._token = Token.IndexKeyword);
case 'complex':
return (this._token = Token.ComplexKeyword);
}
}
return this._token;
};
Scanner.prototype.rescanDecimalDigits = function () {
if (this._token === Token.Text) {
var tokenText = this.tokenText;
if (/^\d+$/.test(tokenText)) {
return (this._token = Token.DecimalDigits);
}
}
return this._token;
};
Scanner.prototype.scanString = function () {
while (!this.eof) {
var ch = this._text.charAt(this._pos++);
switch (ch) {
case '"':
return;
case '\\':
this.scanEscapeSequence();
break;
default:
if (isLineTerminator(ch)) {
this._stringIsUnterminated = true;
return;
}
}
}
this._stringIsUnterminated = true;
};
Scanner.prototype.scanEscapeSequence = function () {
if (this.eof) {
this._stringIsUnterminated = true;
return;
}
var ch = this._text.charAt(this._pos);
// EscapeSequence:: CharacterEscapeSequence
if (isCharacterEscapeSequence(ch)) {
this._pos++;
return;
}
// EscapeSequence:: `0` [lookahead != DecimalDigit]
if (ch === '0' &&
(this._pos + 1 === this._text.length || !isDecimalDigit(this._text.charAt(this._pos + 1)))) {
this._pos++;
return;
}
// EscapeSequence:: HexEscapeSequence
if (ch === 'x' &&
this._pos + 3 <= this._text.length &&
isHexDigit(this._text.charAt(this._pos + 1)) &&
isHexDigit(this._text.charAt(this._pos + 2))) {
this._pos += 3;
return;
}
// EscapeSequence:: UnicodeEscapeSequence
// UnicodeEscapeSequence:: `u` Hex4Digits
if (ch === 'u' &&
this._pos + 5 <= this._text.length &&
isHexDigit(this._text.charAt(this._pos + 1)) &&
isHexDigit(this._text.charAt(this._pos + 2)) &&
isHexDigit(this._text.charAt(this._pos + 3)) &&
isHexDigit(this._text.charAt(this._pos + 4))) {
this._pos += 5;
return;
}
// EscapeSequence:: UnicodeEscapeSequence
// UnicodeEscapeSequence:: `u` `{` CodePoint `}`
if (ch === 'u' && this._pos + 4 <= this._text.length && this._text.charAt(this._pos + 1) === '{') {
var hexDigits = this._text.charAt(this._pos + 2);
if (isHexDigit(hexDigits)) {
for (var i = this._pos + 3; i < this._text.length; i++) {
var ch2 = this._text.charAt(i);
if (ch2 === '}') {
var mv = parseInt(hexDigits, 16);
if (mv <= 0x10ffff) {
this._pos = i + 1;
return;
}
break;
}
if (!isHexDigit(ch2)) {
hexDigits += ch2;
break;
}
}
}
}
this._stringIsUnterminated = true;
};
Scanner.prototype.scanText = function () {
while (this._pos < this._text.length) {
var ch = this._text.charAt(this._pos);
if (isPunctuator(ch) || ch === '"') {
return;
}
this._pos++;
}
};
return Scanner;
}());
var Parser = /** @class */ (function () {
function Parser(text) {
this._errors = [];
this._scanner = new Scanner(text);
this._scanner.scan();
}
Object.defineProperty(Parser.prototype, "eof", {
get: function () {
return this.token() === Token.EofToken;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Parser.prototype, "errors", {
get: function () {
return this._errors;
},
enumerable: false,
configurable: true
});
Parser.prototype.parseDeclarationReference = function () {
var source;
var navigation;
var symbol;
if (this.optionalToken(Token.ExclamationToken)) {
// Reference to global symbol
source = GlobalSource.instance;
}
else if (this._scanner.rescanModuleSource() === Token.ModuleSource) {
source = this.parseModuleSource();
// Check for optional `~` navigation token.
if (this.optionalToken(Token.TildeToken)) {
navigation = Navigation.Locals;
}
}
if (this.isStartOfComponent()) {
symbol = this.parseSymbol();
}
else if (this.token() === Token.ColonToken) {
symbol = this.parseSymbolRest(new ComponentRoot(new ComponentString('', /*userEscaped*/ true)));
}
return new DeclarationReference(source, navigation, symbol);
};
Parser.prototype.parseModuleSourceString = function () {
this._scanner.rescanModuleSource();
return this.parseTokenString(Token.ModuleSource, 'Module source');
};
Parser.prototype.parseComponentString = function () {
switch (this._scanner.token()) {
case Token.String:
return this.parseString();
default:
return this.parseComponentCharacters();
}
};
Parser.prototype.token = function () {
return this._scanner.token();
};
Parser.prototype.parseModuleSource = function () {
var source = this.parseModuleSourceString();
this.expectToken(Token.ExclamationToken);
return new ParsedModuleSource(source, /*userEscaped*/ true);
};
Parser.prototype.parseSymbol = function () {
var component = this.parseComponentRest(this.parseRootComponent());
return this.parseSymbolRest(component);
};
Parser.prototype.parseSymbolRest = function (component) {
var meaning;
var overloadIndex;
if (this.optionalToken(Token.ColonToken)) {
meaning = this.tryParseMeaning();
overloadIndex = this.tryParseOverloadIndex(!!meaning);
}
return new SymbolReference(component, { meaning: meaning, overloadIndex: overloadIndex });
};
Parser.prototype.parseRootComponent = function () {
if (!this.isStartOfComponent()) {
return this.fail('Component expected', new ComponentRoot(new ComponentString('', /*userEscaped*/ true)));
}
var component = this.parseComponent();
return new ComponentRoot(component);
};
Parser.prototype.parseComponentRest = function (component) {
for (;;) {
switch (this.token()) {
case Token.DotToken:
case Token.HashToken:
case Token.TildeToken:
var navigation = this.parseNavigation();
var right = this.parseComponent();
component = new ComponentNavigation(component, navigation, right);
break;
default:
return component;
}
}
};
Parser.prototype.parseNavigation = function () {
switch (this._scanner.token()) {
case Token.DotToken: {
this._scanner.scan();
return Navigation.Exports;
}
case Token.HashToken: {
this._scanner.scan();
return Navigation.Members;
}
case Token.TildeToken: {
this._scanner.scan();
return Navigation.Locals;
}
default: {
return this.fail("Expected '.', '#', or '~'", Navigation.Exports);
}
}
};
Parser.prototype.tryParseMeaning = function () {
switch (this._scanner.rescanMeaning()) {
case Token.ClassKeyword: {
this._scanner.scan();
return Meaning.Class;
}
case Token.InterfaceKeyword: {
this._scanner.scan();
return Meaning.Interface;
}
case Token.TypeKeyword: {
this._scanner.scan();
return Meaning.TypeAlias;
}
case Token.EnumKeyword: {
this._scanner.scan();
return Meaning.Enum;
}
case Token.NamespaceKeyword: {
this._scanner.scan();
return Meaning.Namespace;
}
case Token.FunctionKeyword: {
this._scanner.scan();
return Meaning.Function;
}
case Token.VarKeyword: {
this._scanner.scan();
return Meaning.Variable;
}
case Token.ConstructorKeyword: {
this._scanner.scan();
return Meaning.Constructor;
}
case Token.MemberKeyword: {
this._scanner.scan();
return Meaning.Member;
}
case Token.EventKeyword: {
this._scanner.scan();
return Meaning.Event;
}
case Token.CallKeyword: {
this._scanner.scan();
return Meaning.CallSignature;
}
case Token.NewKeyword: {
this._scanner.scan();
return Meaning.ConstructSignature;
}
case Token.IndexKeyword: {
this._scanner.scan();
return Meaning.IndexSignature;
}
case Token.ComplexKeyword: {
this._scanner.scan();
return Meaning.ComplexType;
}
}
};
Parser.prototype.tryParseOverloadIndex = function (hasMeaning) {
if (this.optionalToken(Token.OpenParenToken)) {
var overloadIndex = this.parseDecimalDigits();
this.expectToken(Token.CloseParenToken);
return overloadIndex;
}
else if (!hasMeaning) {
return this.parseDecimalDigits();
}
return undefined;
};
Parser.prototype.parseDecimalDigits = function () {
switch (this._scanner.rescanDecimalDigits()) {
case Token.DecimalDigits:
var value = +this._scanner.tokenText;
this._scanner.scan();
return value;
default:
return this.fail('Decimal digit expected', 0);
}
};
Parser.prototype.isStartOfComponent = function () {
switch (this.token()) {
case Token.Text:
case Token.String:
case Token.OpenBracketToken:
return true;
default:
return false;
}
};
Parser.prototype.parseComponentCharacters = function () {
var text = '';
for (;;) {
switch (this._scanner.token()) {
case Token.Text:
text += this.parseText();
break;
default:
return text;
}
}
};
Parser.prototype.parseTokenString = function (token, tokenString) {
if (this._scanner.token() === token) {
var text = this._scanner.tokenText;
var stringIsUnterminated = this._scanner.stringIsUnterminated;
this._scanner.scan();
if (stringIsUnterminated) {
return this.fail("".concat(tokenString || tokenToString(token), " is unterminated"), text);
}
return text;
}
return this.fail("".concat(tokenString || tokenToString(token), " expected"), '');
};
Parser.prototype.parseText = function () {
return this.parseTokenString(Token.Text, 'Text');
};
Parser.prototype.parseString = function () {
return this.parseTokenString(Token.String, 'String');
};
Parser.prototype.parseComponent = function () {
switch (this._scanner.token()) {
case Token.OpenBracketToken:
return this.parseBracketedComponent();
default:
return new ParsedComponentString(this.parseComponentString(), /*userEscaped*/ true);
}
};
Parser.prototype.parseBracketedComponent = function () {
this.expectToken(Token.OpenBracketToken);
var reference = this.parseDeclarationReference();
this.expectToken(Token.CloseBracketToken);
return new ComponentReference(reference);
};
Parser.prototype.optionalToken = function (token) {
if (this._scanner.token() === token) {
this._scanner.scan();
return true;
}
return false;
};
Parser.prototype.expectToken = function (token, message) {
if (this._scanner.token() !== token) {
var expected = tokenToString(token);
var actual = tokenToString(this._scanner.token());
return this.fail(message || "Expected token '".concat(expected, "', received '").concat(actual, "' instead."), undefined);
}
this._scanner.scan();
};
Parser.prototype.fail = function (message, fallback) {
this._errors.push(message);
return fallback;
};
return Parser;
}());
function formatNavigation(navigation) {
switch (navigation) {
case Navigation.Exports:
return '.';
case Navigation.Members:
return '#';
case Navigation.Locals:
return '~';
default:
return '';
}
}
function isCharacterEscapeSequence(ch) {
return isSingleEscapeCharacter(ch) || isNonEscapeCharacter(ch);
}
function isSingleEscapeCharacter(ch) {
switch (ch) {
case "'":
case '"':
case '\\':
case 'b':
case 'f':
case 'n':
case 'r':
case 't':
case 'v':
return true;
default:
return false;
}
}
function isNonEscapeCharacter(ch) {
return !isEscapeCharacter(ch) && !isLineTerminator(ch);
}
function isEscapeCharacter(ch) {
switch (ch) {
case 'x':
case 'u':
return true;
default:
return isSingleEscapeCharacter(ch) || isDecimalDigit(ch);
}
}
function isLineTerminator(ch) {
switch (ch) {
case '\r':
case '\n':
// TODO: <LS>, <PS>
return true;
default:
return false;
}
}
function isDecimalDigit(ch) {
switch (ch) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
return true;
default:
return false;
}
}
function isHexDigit(ch) {
switch (ch) {
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
return true;
default:
return isDecimalDigit(ch);
}
}
function isPunctuator(ch) {
switch (ch) {
case '{':
case