- if (token.kind === 29 /* LessThanToken */ && token.parent.kind === 276 /* JsxExpression */) {
- return true;
- }
- //
{
- // |
- // } < /div>
- if (token && token.kind === 19 /* CloseBraceToken */ && token.parent.kind === 276 /* JsxExpression */) {
- return true;
- }
- //
|
- if (token.kind === 29 /* LessThanToken */ && token.parent.kind === 269 /* JsxClosingElement */) {
- return true;
- }
- return false;
- }
- ts.isInsideJsxElementOrAttribute = isInsideJsxElementOrAttribute;
- function isWhiteSpaceOnlyJsxText(node) {
- return ts.isJsxText(node) && node.containsOnlyTriviaWhiteSpaces;
- }
- function isInTemplateString(sourceFile, position) {
- var token = getTokenAtPosition(sourceFile, position);
- return ts.isTemplateLiteralKind(token.kind) && position > token.getStart(sourceFile);
- }
- ts.isInTemplateString = isInTemplateString;
- function isInJSXText(sourceFile, position) {
- var token = getTokenAtPosition(sourceFile, position);
- if (ts.isJsxText(token)) {
- return true;
- }
- if (token.kind === 18 /* OpenBraceToken */ && ts.isJsxExpression(token.parent) && ts.isJsxElement(token.parent.parent)) {
- return true;
- }
- if (token.kind === 29 /* LessThanToken */ && ts.isJsxOpeningLikeElement(token.parent) && ts.isJsxElement(token.parent.parent)) {
- return true;
- }
- return false;
- }
- ts.isInJSXText = isInJSXText;
- function findPrecedingMatchingToken(token, matchingTokenKind, sourceFile) {
- var tokenKind = token.kind;
- var remainingMatchingTokens = 0;
- while (true) {
- var preceding = findPrecedingToken(token.getFullStart(), sourceFile);
- if (!preceding) {
- return undefined;
- }
- token = preceding;
- if (token.kind === matchingTokenKind) {
- if (remainingMatchingTokens === 0) {
- return token;
- }
- remainingMatchingTokens--;
- }
- else if (token.kind === tokenKind) {
- remainingMatchingTokens++;
- }
- }
- }
- ts.findPrecedingMatchingToken = findPrecedingMatchingToken;
- function removeOptionality(type, isOptionalExpression, isOptionalChain) {
- return isOptionalExpression ? type.getNonNullableType() :
- isOptionalChain ? type.getNonOptionalType() :
- type;
- }
- ts.removeOptionality = removeOptionality;
- function isPossiblyTypeArgumentPosition(token, sourceFile, checker) {
- var info = getPossibleTypeArgumentsInfo(token, sourceFile);
- return info !== undefined && (ts.isPartOfTypeNode(info.called) ||
- getPossibleGenericSignatures(info.called, info.nTypeArguments, checker).length !== 0 ||
- isPossiblyTypeArgumentPosition(info.called, sourceFile, checker));
- }
- ts.isPossiblyTypeArgumentPosition = isPossiblyTypeArgumentPosition;
- function getPossibleGenericSignatures(called, typeArgumentCount, checker) {
- var type = checker.getTypeAtLocation(called);
- if (ts.isOptionalChain(called.parent)) {
- type = removeOptionality(type, ts.isOptionalChainRoot(called.parent), /*isOptionalChain*/ true);
- }
- var signatures = ts.isNewExpression(called.parent) ? type.getConstructSignatures() : type.getCallSignatures();
- return signatures.filter(function (candidate) { return !!candidate.typeParameters && candidate.typeParameters.length >= typeArgumentCount; });
- }
- ts.getPossibleGenericSignatures = getPossibleGenericSignatures;
- // Get info for an expression like `f <` that may be the start of type arguments.
- function getPossibleTypeArgumentsInfo(tokenIn, sourceFile) {
- var token = tokenIn;
- // This function determines if the node could be type argument position
- // Since during editing, when type argument list is not complete,
- // the tree could be of any shape depending on the tokens parsed before current node,
- // scanning of the previous identifier followed by "<" before current node would give us better result
- // Note that we also balance out the already provided type arguments, arrays, object literals while doing so
- var remainingLessThanTokens = 0;
- var nTypeArguments = 0;
- while (token) {
- switch (token.kind) {
- case 29 /* LessThanToken */:
- // Found the beginning of the generic argument expression
- token = findPrecedingToken(token.getFullStart(), sourceFile);
- if (token && token.kind === 28 /* QuestionDotToken */) {
- token = findPrecedingToken(token.getFullStart(), sourceFile);
- }
- if (!token || !ts.isIdentifier(token))
- return undefined;
- if (!remainingLessThanTokens) {
- return ts.isDeclarationName(token) ? undefined : { called: token, nTypeArguments: nTypeArguments };
- }
- remainingLessThanTokens--;
- break;
- case 49 /* GreaterThanGreaterThanGreaterThanToken */:
- remainingLessThanTokens = +3;
- break;
- case 48 /* GreaterThanGreaterThanToken */:
- remainingLessThanTokens = +2;
- break;
- case 31 /* GreaterThanToken */:
- remainingLessThanTokens++;
- break;
- case 19 /* CloseBraceToken */:
- // This can be object type, skip until we find the matching open brace token
- // Skip until the matching open brace token
- token = findPrecedingMatchingToken(token, 18 /* OpenBraceToken */, sourceFile);
- if (!token)
- return undefined;
- break;
- case 21 /* CloseParenToken */:
- // This can be object type, skip until we find the matching open brace token
- // Skip until the matching open brace token
- token = findPrecedingMatchingToken(token, 20 /* OpenParenToken */, sourceFile);
- if (!token)
- return undefined;
- break;
- case 23 /* CloseBracketToken */:
- // This can be object type, skip until we find the matching open brace token
- // Skip until the matching open brace token
- token = findPrecedingMatchingToken(token, 22 /* OpenBracketToken */, sourceFile);
- if (!token)
- return undefined;
- break;
- // Valid tokens in a type name. Skip.
- case 27 /* CommaToken */:
- nTypeArguments++;
- break;
- case 38 /* EqualsGreaterThanToken */:
- // falls through
- case 75 /* Identifier */:
- case 10 /* StringLiteral */:
- case 8 /* NumericLiteral */:
- case 9 /* BigIntLiteral */:
- case 106 /* TrueKeyword */:
- case 91 /* FalseKeyword */:
- // falls through
- case 108 /* TypeOfKeyword */:
- case 90 /* ExtendsKeyword */:
- case 134 /* KeyOfKeyword */:
- case 24 /* DotToken */:
- case 51 /* BarToken */:
- case 57 /* QuestionToken */:
- case 58 /* ColonToken */:
- break;
- default:
- if (ts.isTypeNode(token)) {
- break;
- }
- // Invalid token in type
- return undefined;
- }
- token = findPrecedingToken(token.getFullStart(), sourceFile);
- }
- return undefined;
- }
- ts.getPossibleTypeArgumentsInfo = getPossibleTypeArgumentsInfo;
- /**
- * Returns true if the cursor at position in sourceFile is within a comment.
- *
- * @param tokenAtPosition Must equal `getTokenAtPosition(sourceFile, position)
- * @param predicate Additional predicate to test on the comment range.
- */
- function isInComment(sourceFile, position, tokenAtPosition) {
- return ts.formatting.getRangeOfEnclosingComment(sourceFile, position, /*precedingToken*/ undefined, tokenAtPosition);
- }
- ts.isInComment = isInComment;
- function hasDocComment(sourceFile, position) {
- var token = getTokenAtPosition(sourceFile, position);
- return !!ts.findAncestor(token, ts.isJSDoc);
- }
- ts.hasDocComment = hasDocComment;
- function nodeHasTokens(n, sourceFile) {
- // If we have a token or node that has a non-zero width, it must have tokens.
- // Note: getWidth() does not take trivia into account.
- return n.kind === 1 /* EndOfFileToken */ ? !!n.jsDoc : n.getWidth(sourceFile) !== 0;
- }
- function getNodeModifiers(node) {
- var flags = ts.isDeclaration(node) ? ts.getCombinedModifierFlags(node) : 0 /* None */;
- var result = [];
- if (flags & 8 /* Private */)
- result.push("private" /* privateMemberModifier */);
- if (flags & 16 /* Protected */)
- result.push("protected" /* protectedMemberModifier */);
- if (flags & 4 /* Public */)
- result.push("public" /* publicMemberModifier */);
- if (flags & 32 /* Static */)
- result.push("static" /* staticModifier */);
- if (flags & 128 /* Abstract */)
- result.push("abstract" /* abstractModifier */);
- if (flags & 1 /* Export */)
- result.push("export" /* exportedModifier */);
- if (node.flags & 8388608 /* Ambient */)
- result.push("declare" /* ambientModifier */);
- if (node.kind === 259 /* ExportAssignment */)
- result.push("export" /* exportedModifier */);
- return result.length > 0 ? result.join(",") : "" /* none */;
- }
- ts.getNodeModifiers = getNodeModifiers;
- function getTypeArgumentOrTypeParameterList(node) {
- if (node.kind === 169 /* TypeReference */ || node.kind === 196 /* CallExpression */) {
- return node.typeArguments;
- }
- if (ts.isFunctionLike(node) || node.kind === 245 /* ClassDeclaration */ || node.kind === 246 /* InterfaceDeclaration */) {
- return node.typeParameters;
- }
- return undefined;
- }
- ts.getTypeArgumentOrTypeParameterList = getTypeArgumentOrTypeParameterList;
- function isComment(kind) {
- return kind === 2 /* SingleLineCommentTrivia */ || kind === 3 /* MultiLineCommentTrivia */;
- }
- ts.isComment = isComment;
- function isStringOrRegularExpressionOrTemplateLiteral(kind) {
- if (kind === 10 /* StringLiteral */
- || kind === 13 /* RegularExpressionLiteral */
- || ts.isTemplateLiteralKind(kind)) {
- return true;
- }
- return false;
- }
- ts.isStringOrRegularExpressionOrTemplateLiteral = isStringOrRegularExpressionOrTemplateLiteral;
- function isPunctuation(kind) {
- return 18 /* FirstPunctuation */ <= kind && kind <= 74 /* LastPunctuation */;
- }
- ts.isPunctuation = isPunctuation;
- function isInsideTemplateLiteral(node, position, sourceFile) {
- return ts.isTemplateLiteralKind(node.kind)
- && (node.getStart(sourceFile) < position && position < node.end) || (!!node.isUnterminated && position === node.end);
- }
- ts.isInsideTemplateLiteral = isInsideTemplateLiteral;
- function isAccessibilityModifier(kind) {
- switch (kind) {
- case 119 /* PublicKeyword */:
- case 117 /* PrivateKeyword */:
- case 118 /* ProtectedKeyword */:
- return true;
- }
- return false;
- }
- ts.isAccessibilityModifier = isAccessibilityModifier;
- function cloneCompilerOptions(options) {
- var result = ts.clone(options);
- ts.setConfigFileInOptions(result, options && options.configFile);
- return result;
- }
- ts.cloneCompilerOptions = cloneCompilerOptions;
- function isArrayLiteralOrObjectLiteralDestructuringPattern(node) {
- if (node.kind === 192 /* ArrayLiteralExpression */ ||
- node.kind === 193 /* ObjectLiteralExpression */) {
- // [a,b,c] from:
- // [a, b, c] = someExpression;
- if (node.parent.kind === 209 /* BinaryExpression */ &&
- node.parent.left === node &&
- node.parent.operatorToken.kind === 62 /* EqualsToken */) {
- return true;
- }
- // [a, b, c] from:
- // for([a, b, c] of expression)
- if (node.parent.kind === 232 /* ForOfStatement */ &&
- node.parent.initializer === node) {
- return true;
- }
- // [a, b, c] of
- // [x, [a, b, c] ] = someExpression
- // or
- // {x, a: {a, b, c} } = someExpression
- if (isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent.kind === 281 /* PropertyAssignment */ ? node.parent.parent : node.parent)) {
- return true;
- }
- }
- return false;
- }
- ts.isArrayLiteralOrObjectLiteralDestructuringPattern = isArrayLiteralOrObjectLiteralDestructuringPattern;
- function isInReferenceComment(sourceFile, position) {
- return isInReferenceCommentWorker(sourceFile, position, /*shouldBeReference*/ true);
- }
- ts.isInReferenceComment = isInReferenceComment;
- function isInNonReferenceComment(sourceFile, position) {
- return isInReferenceCommentWorker(sourceFile, position, /*shouldBeReference*/ false);
- }
- ts.isInNonReferenceComment = isInNonReferenceComment;
- function isInReferenceCommentWorker(sourceFile, position, shouldBeReference) {
- var range = isInComment(sourceFile, position, /*tokenAtPosition*/ undefined);
- return !!range && shouldBeReference === tripleSlashDirectivePrefixRegex.test(sourceFile.text.substring(range.pos, range.end));
- }
- function getReplacementSpanForContextToken(contextToken) {
- if (!contextToken)
- return undefined;
- switch (contextToken.kind) {
- case 10 /* StringLiteral */:
- case 14 /* NoSubstitutionTemplateLiteral */:
- return createTextSpanFromStringLiteralLikeContent(contextToken);
- default:
- return createTextSpanFromNode(contextToken);
- }
- }
- ts.getReplacementSpanForContextToken = getReplacementSpanForContextToken;
- function createTextSpanFromNode(node, sourceFile, endNode) {
- return ts.createTextSpanFromBounds(node.getStart(sourceFile), (endNode || node).getEnd());
- }
- ts.createTextSpanFromNode = createTextSpanFromNode;
- function createTextSpanFromStringLiteralLikeContent(node) {
- if (node.isUnterminated)
- return undefined;
- return ts.createTextSpanFromBounds(node.getStart() + 1, node.getEnd() - 1);
- }
- ts.createTextSpanFromStringLiteralLikeContent = createTextSpanFromStringLiteralLikeContent;
- function createTextRangeFromNode(node, sourceFile) {
- return ts.createRange(node.getStart(sourceFile), node.end);
- }
- ts.createTextRangeFromNode = createTextRangeFromNode;
- function createTextSpanFromRange(range) {
- return ts.createTextSpanFromBounds(range.pos, range.end);
- }
- ts.createTextSpanFromRange = createTextSpanFromRange;
- function createTextRangeFromSpan(span) {
- return ts.createRange(span.start, span.start + span.length);
- }
- ts.createTextRangeFromSpan = createTextRangeFromSpan;
- function createTextChangeFromStartLength(start, length, newText) {
- return createTextChange(ts.createTextSpan(start, length), newText);
- }
- ts.createTextChangeFromStartLength = createTextChangeFromStartLength;
- function createTextChange(span, newText) {
- return { span: span, newText: newText };
- }
- ts.createTextChange = createTextChange;
- ts.typeKeywords = [
- 125 /* AnyKeyword */,
- 124 /* AssertsKeyword */,
- 151 /* BigIntKeyword */,
- 128 /* BooleanKeyword */,
- 91 /* FalseKeyword */,
- 134 /* KeyOfKeyword */,
- 137 /* NeverKeyword */,
- 100 /* NullKeyword */,
- 140 /* NumberKeyword */,
- 141 /* ObjectKeyword */,
- 138 /* ReadonlyKeyword */,
- 143 /* StringKeyword */,
- 144 /* SymbolKeyword */,
- 106 /* TrueKeyword */,
- 110 /* VoidKeyword */,
- 146 /* UndefinedKeyword */,
- 147 /* UniqueKeyword */,
- 148 /* UnknownKeyword */,
- ];
- function isTypeKeyword(kind) {
- return ts.contains(ts.typeKeywords, kind);
- }
- ts.isTypeKeyword = isTypeKeyword;
- function isTypeKeywordToken(node) {
- return node.kind === 145 /* TypeKeyword */;
- }
- ts.isTypeKeywordToken = isTypeKeywordToken;
- /** True if the symbol is for an external module, as opposed to a namespace. */
- function isExternalModuleSymbol(moduleSymbol) {
- return !!(moduleSymbol.flags & 1536 /* Module */) && moduleSymbol.name.charCodeAt(0) === 34 /* doubleQuote */;
- }
- ts.isExternalModuleSymbol = isExternalModuleSymbol;
- function nodeSeenTracker() {
- var seen = [];
- return function (node) {
- var id = ts.getNodeId(node);
- return !seen[id] && (seen[id] = true);
- };
- }
- ts.nodeSeenTracker = nodeSeenTracker;
- function getSnapshotText(snap) {
- return snap.getText(0, snap.getLength());
- }
- ts.getSnapshotText = getSnapshotText;
- function repeatString(str, count) {
- var result = "";
- for (var i = 0; i < count; i++) {
- result += str;
- }
- return result;
- }
- ts.repeatString = repeatString;
- function skipConstraint(type) {
- return type.isTypeParameter() ? type.getConstraint() || type : type;
- }
- ts.skipConstraint = skipConstraint;
- function getNameFromPropertyName(name) {
- return name.kind === 154 /* ComputedPropertyName */
- // treat computed property names where expression is string/numeric literal as just string/numeric literal
- ? ts.isStringOrNumericLiteralLike(name.expression) ? name.expression.text : undefined
- : ts.isPrivateIdentifier(name) ? ts.idText(name) : ts.getTextOfIdentifierOrLiteral(name);
- }
- ts.getNameFromPropertyName = getNameFromPropertyName;
- function programContainsModules(program) {
- return program.getSourceFiles().some(function (s) { return !s.isDeclarationFile && !program.isSourceFileFromExternalLibrary(s) && !!(s.externalModuleIndicator || s.commonJsModuleIndicator); });
- }
- ts.programContainsModules = programContainsModules;
- function programContainsEs6Modules(program) {
- return program.getSourceFiles().some(function (s) { return !s.isDeclarationFile && !program.isSourceFileFromExternalLibrary(s) && !!s.externalModuleIndicator; });
- }
- ts.programContainsEs6Modules = programContainsEs6Modules;
- function compilerOptionsIndicateEs6Modules(compilerOptions) {
- return !!compilerOptions.module || compilerOptions.target >= 2 /* ES2015 */ || !!compilerOptions.noEmit;
- }
- ts.compilerOptionsIndicateEs6Modules = compilerOptionsIndicateEs6Modules;
- function createModuleSpecifierResolutionHost(program, host) {
- // Mix in `getProbableSymlinks` from Program when host doesn't have it
- // in order for non-Project hosts to have a symlinks cache.
- return {
- fileExists: function (fileName) { return program.fileExists(fileName); },
- getCurrentDirectory: function () { return host.getCurrentDirectory(); },
- readFile: ts.maybeBind(host, host.readFile),
- useCaseSensitiveFileNames: ts.maybeBind(host, host.useCaseSensitiveFileNames),
- getProbableSymlinks: ts.maybeBind(host, host.getProbableSymlinks) || (function () { return program.getProbableSymlinks(); }),
- getGlobalTypingsCacheLocation: ts.maybeBind(host, host.getGlobalTypingsCacheLocation),
- getSourceFiles: function () { return program.getSourceFiles(); },
- redirectTargetsMap: program.redirectTargetsMap,
- getProjectReferenceRedirect: function (fileName) { return program.getProjectReferenceRedirect(fileName); },
- isSourceOfProjectReferenceRedirect: function (fileName) { return program.isSourceOfProjectReferenceRedirect(fileName); },
- };
- }
- ts.createModuleSpecifierResolutionHost = createModuleSpecifierResolutionHost;
- function getModuleSpecifierResolverHost(program, host) {
- return __assign(__assign({}, createModuleSpecifierResolutionHost(program, host)), { getCommonSourceDirectory: function () { return program.getCommonSourceDirectory(); } });
- }
- ts.getModuleSpecifierResolverHost = getModuleSpecifierResolverHost;
- function makeImportIfNecessary(defaultImport, namedImports, moduleSpecifier, quotePreference) {
- return defaultImport || namedImports && namedImports.length ? makeImport(defaultImport, namedImports, moduleSpecifier, quotePreference) : undefined;
- }
- ts.makeImportIfNecessary = makeImportIfNecessary;
- function makeImport(defaultImport, namedImports, moduleSpecifier, quotePreference, isTypeOnly) {
- return ts.createImportDeclaration(
- /*decorators*/ undefined,
- /*modifiers*/ undefined, defaultImport || namedImports
- ? ts.createImportClause(defaultImport, namedImports && namedImports.length ? ts.createNamedImports(namedImports) : undefined, isTypeOnly)
- : undefined, typeof moduleSpecifier === "string" ? makeStringLiteral(moduleSpecifier, quotePreference) : moduleSpecifier);
- }
- ts.makeImport = makeImport;
- function makeStringLiteral(text, quotePreference) {
- return ts.createLiteral(text, quotePreference === 0 /* Single */);
- }
- ts.makeStringLiteral = makeStringLiteral;
- var QuotePreference;
- (function (QuotePreference) {
- QuotePreference[QuotePreference["Single"] = 0] = "Single";
- QuotePreference[QuotePreference["Double"] = 1] = "Double";
- })(QuotePreference = ts.QuotePreference || (ts.QuotePreference = {}));
- function quotePreferenceFromString(str, sourceFile) {
- return ts.isStringDoubleQuoted(str, sourceFile) ? 1 /* Double */ : 0 /* Single */;
- }
- ts.quotePreferenceFromString = quotePreferenceFromString;
- function getQuotePreference(sourceFile, preferences) {
- if (preferences.quotePreference && preferences.quotePreference !== "auto") {
- return preferences.quotePreference === "single" ? 0 /* Single */ : 1 /* Double */;
- }
- else {
- var firstModuleSpecifier = sourceFile.imports && ts.find(sourceFile.imports, ts.isStringLiteral);
- return firstModuleSpecifier ? quotePreferenceFromString(firstModuleSpecifier, sourceFile) : 1 /* Double */;
- }
- }
- ts.getQuotePreference = getQuotePreference;
- function getQuoteFromPreference(qp) {
- switch (qp) {
- case 0 /* Single */: return "'";
- case 1 /* Double */: return '"';
- default: return ts.Debug.assertNever(qp);
- }
- }
- ts.getQuoteFromPreference = getQuoteFromPreference;
- function symbolNameNoDefault(symbol) {
- var escaped = symbolEscapedNameNoDefault(symbol);
- return escaped === undefined ? undefined : ts.unescapeLeadingUnderscores(escaped);
- }
- ts.symbolNameNoDefault = symbolNameNoDefault;
- function symbolEscapedNameNoDefault(symbol) {
- if (symbol.escapedName !== "default" /* Default */) {
- return symbol.escapedName;
- }
- return ts.firstDefined(symbol.declarations, function (decl) {
- var name = ts.getNameOfDeclaration(decl);
- return name && name.kind === 75 /* Identifier */ ? name.escapedText : undefined;
- });
- }
- ts.symbolEscapedNameNoDefault = symbolEscapedNameNoDefault;
- function isObjectBindingElementWithoutPropertyName(bindingElement) {
- return ts.isBindingElement(bindingElement) &&
- ts.isObjectBindingPattern(bindingElement.parent) &&
- ts.isIdentifier(bindingElement.name) &&
- !bindingElement.propertyName;
- }
- ts.isObjectBindingElementWithoutPropertyName = isObjectBindingElementWithoutPropertyName;
- function getPropertySymbolFromBindingElement(checker, bindingElement) {
- var typeOfPattern = checker.getTypeAtLocation(bindingElement.parent);
- return typeOfPattern && checker.getPropertyOfType(typeOfPattern, bindingElement.name.text);
- }
- ts.getPropertySymbolFromBindingElement = getPropertySymbolFromBindingElement;
- /**
- * Find symbol of the given property-name and add the symbol to the given result array
- * @param symbol a symbol to start searching for the given propertyName
- * @param propertyName a name of property to search for
- * @param result an array of symbol of found property symbols
- * @param previousIterationSymbolsCache a cache of symbol from previous iterations of calling this function to prevent infinite revisiting of the same symbol.
- * The value of previousIterationSymbol is undefined when the function is first called.
- */
- function getPropertySymbolsFromBaseTypes(symbol, propertyName, checker, cb) {
- var seen = ts.createMap();
- return recur(symbol);
- function recur(symbol) {
- // Use `addToSeen` to ensure we don't infinitely recurse in this situation:
- // interface C extends C {
- // /*findRef*/propName: string;
- // }
- if (!(symbol.flags & (32 /* Class */ | 64 /* Interface */)) || !ts.addToSeen(seen, ts.getSymbolId(symbol)))
- return;
- return ts.firstDefined(symbol.declarations, function (declaration) { return ts.firstDefined(ts.getAllSuperTypeNodes(declaration), function (typeReference) {
- var type = checker.getTypeAtLocation(typeReference);
- var propertySymbol = type && type.symbol && checker.getPropertyOfType(type, propertyName);
- // Visit the typeReference as well to see if it directly or indirectly uses that property
- return type && propertySymbol && (ts.firstDefined(checker.getRootSymbols(propertySymbol), cb) || recur(type.symbol));
- }); });
- }
- }
- ts.getPropertySymbolsFromBaseTypes = getPropertySymbolsFromBaseTypes;
- function isMemberSymbolInBaseType(memberSymbol, checker) {
- return getPropertySymbolsFromBaseTypes(memberSymbol.parent, memberSymbol.name, checker, function (_) { return true; }) || false;
- }
- ts.isMemberSymbolInBaseType = isMemberSymbolInBaseType;
- function getParentNodeInSpan(node, file, span) {
- if (!node)
- return undefined;
- while (node.parent) {
- if (ts.isSourceFile(node.parent) || !spanContainsNode(span, node.parent, file)) {
- return node;
- }
- node = node.parent;
- }
- }
- ts.getParentNodeInSpan = getParentNodeInSpan;
- function spanContainsNode(span, node, file) {
- return ts.textSpanContainsPosition(span, node.getStart(file)) &&
- node.getEnd() <= ts.textSpanEnd(span);
- }
- function findModifier(node, kind) {
- return node.modifiers && ts.find(node.modifiers, function (m) { return m.kind === kind; });
- }
- ts.findModifier = findModifier;
- function insertImports(changes, sourceFile, imports, blankLineBetween) {
- var decl = ts.isArray(imports) ? imports[0] : imports;
- var importKindPredicate = decl.kind === 225 /* VariableStatement */ ? ts.isRequireVariableDeclarationStatement : ts.isAnyImportSyntax;
- var lastImportDeclaration = ts.findLast(sourceFile.statements, function (statement) { return importKindPredicate(statement); });
- if (lastImportDeclaration) {
- if (ts.isArray(imports)) {
- changes.insertNodesAfter(sourceFile, lastImportDeclaration, imports);
- }
- else {
- changes.insertNodeAfter(sourceFile, lastImportDeclaration, imports);
- }
- }
- else if (ts.isArray(imports)) {
- changes.insertNodesAtTopOfFile(sourceFile, imports, blankLineBetween);
- }
- else {
- changes.insertNodeAtTopOfFile(sourceFile, imports, blankLineBetween);
- }
- }
- ts.insertImports = insertImports;
- function getTypeKeywordOfTypeOnlyImport(importClause, sourceFile) {
- ts.Debug.assert(importClause.isTypeOnly);
- return ts.cast(importClause.getChildAt(0, sourceFile), isTypeKeywordToken);
- }
- ts.getTypeKeywordOfTypeOnlyImport = getTypeKeywordOfTypeOnlyImport;
- function textSpansEqual(a, b) {
- return !!a && !!b && a.start === b.start && a.length === b.length;
- }
- ts.textSpansEqual = textSpansEqual;
- function documentSpansEqual(a, b) {
- return a.fileName === b.fileName && textSpansEqual(a.textSpan, b.textSpan);
- }
- ts.documentSpansEqual = documentSpansEqual;
- /**
- * Iterates through 'array' by index and performs the callback on each element of array until the callback
- * returns a truthy value, then returns that value.
- * If no such value is found, the callback is applied to each element of array and undefined is returned.
- */
- function forEachUnique(array, callback) {
- if (array) {
- for (var i = 0; i < array.length; i++) {
- if (array.indexOf(array[i]) === i) {
- var result = callback(array[i], i);
- if (result) {
- return result;
- }
- }
- }
- }
- return undefined;
- }
- ts.forEachUnique = forEachUnique;
- // #endregion
- // Display-part writer helpers
- // #region
- function isFirstDeclarationOfSymbolParameter(symbol) {
- return symbol.declarations && symbol.declarations.length > 0 && symbol.declarations[0].kind === 156 /* Parameter */;
- }
- ts.isFirstDeclarationOfSymbolParameter = isFirstDeclarationOfSymbolParameter;
- var displayPartWriter = getDisplayPartWriter();
- function getDisplayPartWriter() {
- var absoluteMaximumLength = ts.defaultMaximumTruncationLength * 10; // A hard cutoff to avoid overloading the messaging channel in worst-case scenarios
- var displayParts;
- var lineStart;
- var indent;
- var length;
- resetWriter();
- var unknownWrite = function (text) { return writeKind(text, ts.SymbolDisplayPartKind.text); };
- return {
- displayParts: function () {
- var finalText = displayParts.length && displayParts[displayParts.length - 1].text;
- if (length > absoluteMaximumLength && finalText && finalText !== "...") {
- if (!ts.isWhiteSpaceLike(finalText.charCodeAt(finalText.length - 1))) {
- displayParts.push(displayPart(" ", ts.SymbolDisplayPartKind.space));
- }
- displayParts.push(displayPart("...", ts.SymbolDisplayPartKind.punctuation));
- }
- return displayParts;
- },
- writeKeyword: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.keyword); },
- writeOperator: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.operator); },
- writePunctuation: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.punctuation); },
- writeTrailingSemicolon: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.punctuation); },
- writeSpace: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.space); },
- writeStringLiteral: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.stringLiteral); },
- writeParameter: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.parameterName); },
- writeProperty: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.propertyName); },
- writeLiteral: function (text) { return writeKind(text, ts.SymbolDisplayPartKind.stringLiteral); },
- writeSymbol: writeSymbol,
- writeLine: writeLine,
- write: unknownWrite,
- writeComment: unknownWrite,
- getText: function () { return ""; },
- getTextPos: function () { return 0; },
- getColumn: function () { return 0; },
- getLine: function () { return 0; },
- isAtStartOfLine: function () { return false; },
- hasTrailingWhitespace: function () { return false; },
- hasTrailingComment: function () { return false; },
- rawWrite: ts.notImplemented,
- getIndent: function () { return indent; },
- increaseIndent: function () { indent++; },
- decreaseIndent: function () { indent--; },
- clear: resetWriter,
- trackSymbol: ts.noop,
- reportInaccessibleThisError: ts.noop,
- reportInaccessibleUniqueSymbolError: ts.noop,
- reportPrivateInBaseOfClassExpression: ts.noop,
- };
- function writeIndent() {
- if (length > absoluteMaximumLength)
- return;
- if (lineStart) {
- var indentString = ts.getIndentString(indent);
- if (indentString) {
- length += indentString.length;
- displayParts.push(displayPart(indentString, ts.SymbolDisplayPartKind.space));
- }
- lineStart = false;
- }
- }
- function writeKind(text, kind) {
- if (length > absoluteMaximumLength)
- return;
- writeIndent();
- length += text.length;
- displayParts.push(displayPart(text, kind));
- }
- function writeSymbol(text, symbol) {
- if (length > absoluteMaximumLength)
- return;
- writeIndent();
- length += text.length;
- displayParts.push(symbolPart(text, symbol));
- }
- function writeLine() {
- if (length > absoluteMaximumLength)
- return;
- length += 1;
- displayParts.push(lineBreakPart());
- lineStart = true;
- }
- function resetWriter() {
- displayParts = [];
- lineStart = true;
- indent = 0;
- length = 0;
- }
- }
- function symbolPart(text, symbol) {
- return displayPart(text, displayPartKind(symbol));
- function displayPartKind(symbol) {
- var flags = symbol.flags;
- if (flags & 3 /* Variable */) {
- return isFirstDeclarationOfSymbolParameter(symbol) ? ts.SymbolDisplayPartKind.parameterName : ts.SymbolDisplayPartKind.localName;
- }
- else if (flags & 4 /* Property */) {
- return ts.SymbolDisplayPartKind.propertyName;
- }
- else if (flags & 32768 /* GetAccessor */) {
- return ts.SymbolDisplayPartKind.propertyName;
- }
- else if (flags & 65536 /* SetAccessor */) {
- return ts.SymbolDisplayPartKind.propertyName;
- }
- else if (flags & 8 /* EnumMember */) {
- return ts.SymbolDisplayPartKind.enumMemberName;
- }
- else if (flags & 16 /* Function */) {
- return ts.SymbolDisplayPartKind.functionName;
- }
- else if (flags & 32 /* Class */) {
- return ts.SymbolDisplayPartKind.className;
- }
- else if (flags & 64 /* Interface */) {
- return ts.SymbolDisplayPartKind.interfaceName;
- }
- else if (flags & 384 /* Enum */) {
- return ts.SymbolDisplayPartKind.enumName;
- }
- else if (flags & 1536 /* Module */) {
- return ts.SymbolDisplayPartKind.moduleName;
- }
- else if (flags & 8192 /* Method */) {
- return ts.SymbolDisplayPartKind.methodName;
- }
- else if (flags & 262144 /* TypeParameter */) {
- return ts.SymbolDisplayPartKind.typeParameterName;
- }
- else if (flags & 524288 /* TypeAlias */) {
- return ts.SymbolDisplayPartKind.aliasName;
- }
- else if (flags & 2097152 /* Alias */) {
- return ts.SymbolDisplayPartKind.aliasName;
- }
- return ts.SymbolDisplayPartKind.text;
- }
- }
- ts.symbolPart = symbolPart;
- function displayPart(text, kind) {
- return { text: text, kind: ts.SymbolDisplayPartKind[kind] };
- }
- ts.displayPart = displayPart;
- function spacePart() {
- return displayPart(" ", ts.SymbolDisplayPartKind.space);
- }
- ts.spacePart = spacePart;
- function keywordPart(kind) {
- return displayPart(ts.tokenToString(kind), ts.SymbolDisplayPartKind.keyword);
- }
- ts.keywordPart = keywordPart;
- function punctuationPart(kind) {
- return displayPart(ts.tokenToString(kind), ts.SymbolDisplayPartKind.punctuation);
- }
- ts.punctuationPart = punctuationPart;
- function operatorPart(kind) {
- return displayPart(ts.tokenToString(kind), ts.SymbolDisplayPartKind.operator);
- }
- ts.operatorPart = operatorPart;
- function textOrKeywordPart(text) {
- var kind = ts.stringToToken(text);
- return kind === undefined
- ? textPart(text)
- : keywordPart(kind);
- }
- ts.textOrKeywordPart = textOrKeywordPart;
- function textPart(text) {
- return displayPart(text, ts.SymbolDisplayPartKind.text);
- }
- ts.textPart = textPart;
- var carriageReturnLineFeed = "\r\n";
- /**
- * The default is CRLF.
- */
- function getNewLineOrDefaultFromHost(host, formatSettings) {
- var _a;
- return (formatSettings === null || formatSettings === void 0 ? void 0 : formatSettings.newLineCharacter) || ((_a = host.getNewLine) === null || _a === void 0 ? void 0 : _a.call(host)) ||
- carriageReturnLineFeed;
- }
- ts.getNewLineOrDefaultFromHost = getNewLineOrDefaultFromHost;
- function lineBreakPart() {
- return displayPart("\n", ts.SymbolDisplayPartKind.lineBreak);
- }
- ts.lineBreakPart = lineBreakPart;
- function mapToDisplayParts(writeDisplayParts) {
- try {
- writeDisplayParts(displayPartWriter);
- return displayPartWriter.displayParts();
- }
- finally {
- displayPartWriter.clear();
- }
- }
- ts.mapToDisplayParts = mapToDisplayParts;
- function typeToDisplayParts(typechecker, type, enclosingDeclaration, flags) {
- if (flags === void 0) { flags = 0 /* None */; }
- return mapToDisplayParts(function (writer) {
- typechecker.writeType(type, enclosingDeclaration, flags | 1024 /* MultilineObjectLiterals */ | 16384 /* UseAliasDefinedOutsideCurrentScope */, writer);
- });
- }
- ts.typeToDisplayParts = typeToDisplayParts;
- function symbolToDisplayParts(typeChecker, symbol, enclosingDeclaration, meaning, flags) {
- if (flags === void 0) { flags = 0 /* None */; }
- return mapToDisplayParts(function (writer) {
- typeChecker.writeSymbol(symbol, enclosingDeclaration, meaning, flags | 8 /* UseAliasDefinedOutsideCurrentScope */, writer);
- });
- }
- ts.symbolToDisplayParts = symbolToDisplayParts;
- function signatureToDisplayParts(typechecker, signature, enclosingDeclaration, flags) {
- if (flags === void 0) { flags = 0 /* None */; }
- flags |= 16384 /* UseAliasDefinedOutsideCurrentScope */ | 1024 /* MultilineObjectLiterals */ | 32 /* WriteTypeArgumentsOfSignature */ | 8192 /* OmitParameterModifiers */;
- return mapToDisplayParts(function (writer) {
- typechecker.writeSignature(signature, enclosingDeclaration, flags, /*signatureKind*/ undefined, writer);
- });
- }
- ts.signatureToDisplayParts = signatureToDisplayParts;
- function isImportOrExportSpecifierName(location) {
- return !!location.parent && ts.isImportOrExportSpecifier(location.parent) && location.parent.propertyName === location;
- }
- ts.isImportOrExportSpecifierName = isImportOrExportSpecifierName;
- function scriptKindIs(fileName, host) {
- var scriptKinds = [];
- for (var _i = 2; _i < arguments.length; _i++) {
- scriptKinds[_i - 2] = arguments[_i];
- }
- var scriptKind = getScriptKind(fileName, host);
- return ts.some(scriptKinds, function (k) { return k === scriptKind; });
- }
- ts.scriptKindIs = scriptKindIs;
- function getScriptKind(fileName, host) {
- // First check to see if the script kind was specified by the host. Chances are the host
- // may override the default script kind for the file extension.
- return ts.ensureScriptKind(fileName, host && host.getScriptKind && host.getScriptKind(fileName));
- }
- ts.getScriptKind = getScriptKind;
- function getSymbolTarget(symbol, checker) {
- var next = symbol;
- while (isAliasSymbol(next) || (isTransientSymbol(next) && next.target)) {
- if (isTransientSymbol(next) && next.target) {
- next = next.target;
- }
- else {
- next = ts.skipAlias(next, checker);
- }
- }
- return next;
- }
- ts.getSymbolTarget = getSymbolTarget;
- function isTransientSymbol(symbol) {
- return (symbol.flags & 33554432 /* Transient */) !== 0;
- }
- function isAliasSymbol(symbol) {
- return (symbol.flags & 2097152 /* Alias */) !== 0;
- }
- function getUniqueSymbolId(symbol, checker) {
- return ts.getSymbolId(ts.skipAlias(symbol, checker));
- }
- ts.getUniqueSymbolId = getUniqueSymbolId;
- function getFirstNonSpaceCharacterPosition(text, position) {
- while (ts.isWhiteSpaceLike(text.charCodeAt(position))) {
- position += 1;
- }
- return position;
- }
- ts.getFirstNonSpaceCharacterPosition = getFirstNonSpaceCharacterPosition;
- function getPrecedingNonSpaceCharacterPosition(text, position) {
- while (position > -1 && ts.isWhiteSpaceSingleLine(text.charCodeAt(position))) {
- position -= 1;
- }
- return position + 1;
- }
- ts.getPrecedingNonSpaceCharacterPosition = getPrecedingNonSpaceCharacterPosition;
- /**
- * Creates a deep, memberwise clone of a node with no source map location.
- *
- * WARNING: This is an expensive operation and is only intended to be used in refactorings
- * and code fixes (because those are triggered by explicit user actions).
- */
- function getSynthesizedDeepClone(node, includeTrivia) {
- if (includeTrivia === void 0) { includeTrivia = true; }
- var clone = node && getSynthesizedDeepCloneWorker(node);
- if (clone && !includeTrivia)
- suppressLeadingAndTrailingTrivia(clone);
- return clone;
- }
- ts.getSynthesizedDeepClone = getSynthesizedDeepClone;
- function getSynthesizedDeepCloneWithRenames(node, includeTrivia, renameMap, checker, callback) {
- if (includeTrivia === void 0) { includeTrivia = true; }
- var clone;
- if (renameMap && checker && ts.isBindingElement(node) && ts.isIdentifier(node.name) && ts.isObjectBindingPattern(node.parent)) {
- var symbol = checker.getSymbolAtLocation(node.name);
- var renameInfo = symbol && renameMap.get(String(ts.getSymbolId(symbol)));
- if (renameInfo && renameInfo.text !== (node.name || node.propertyName).getText()) {
- clone = ts.setOriginalNode(ts.createBindingElement(node.dotDotDotToken, node.propertyName || node.name, renameInfo, node.initializer), node);
- }
- }
- else if (renameMap && checker && ts.isIdentifier(node)) {
- var symbol = checker.getSymbolAtLocation(node);
- var renameInfo = symbol && renameMap.get(String(ts.getSymbolId(symbol)));
- if (renameInfo) {
- clone = ts.setOriginalNode(ts.createIdentifier(renameInfo.text), node);
- }
- }
- if (!clone) {
- clone = getSynthesizedDeepCloneWorker(node, renameMap, checker, callback);
- }
- if (clone && !includeTrivia)
- suppressLeadingAndTrailingTrivia(clone);
- if (callback && clone)
- callback(node, clone);
- return clone;
- }
- ts.getSynthesizedDeepCloneWithRenames = getSynthesizedDeepCloneWithRenames;
- function getSynthesizedDeepCloneWorker(node, renameMap, checker, callback) {
- var visited = (renameMap || checker || callback) ?
- ts.visitEachChild(node, wrapper, ts.nullTransformationContext) :
- ts.visitEachChild(node, getSynthesizedDeepClone, ts.nullTransformationContext);
- if (visited === node) {
- // This only happens for leaf nodes - internal nodes always see their children change.
- var clone_1 = ts.getSynthesizedClone(node);
- if (ts.isStringLiteral(clone_1)) {
- clone_1.textSourceNode = node;
- }
- else if (ts.isNumericLiteral(clone_1)) {
- clone_1.numericLiteralFlags = node.numericLiteralFlags;
- }
- return ts.setTextRange(clone_1, node);
- }
- // PERF: As an optimization, rather than calling getSynthesizedClone, we'll update
- // the new node created by visitEachChild with the extra changes getSynthesizedClone
- // would have made.
- visited.parent = undefined;
- return visited;
- function wrapper(node) {
- return getSynthesizedDeepCloneWithRenames(node, /*includeTrivia*/ true, renameMap, checker, callback);
- }
- }
- function getSynthesizedDeepClones(nodes, includeTrivia) {
- if (includeTrivia === void 0) { includeTrivia = true; }
- return nodes && ts.createNodeArray(nodes.map(function (n) { return getSynthesizedDeepClone(n, includeTrivia); }), nodes.hasTrailingComma);
- }
- ts.getSynthesizedDeepClones = getSynthesizedDeepClones;
- /**
- * Sets EmitFlags to suppress leading and trailing trivia on the node.
- */
- function suppressLeadingAndTrailingTrivia(node) {
- suppressLeadingTrivia(node);
- suppressTrailingTrivia(node);
- }
- ts.suppressLeadingAndTrailingTrivia = suppressLeadingAndTrailingTrivia;
- /**
- * Sets EmitFlags to suppress leading trivia on the node.
- */
- function suppressLeadingTrivia(node) {
- addEmitFlagsRecursively(node, 512 /* NoLeadingComments */, getFirstChild);
- }
- ts.suppressLeadingTrivia = suppressLeadingTrivia;
- /**
- * Sets EmitFlags to suppress trailing trivia on the node.
- */
- function suppressTrailingTrivia(node) {
- addEmitFlagsRecursively(node, 1024 /* NoTrailingComments */, ts.getLastChild);
- }
- ts.suppressTrailingTrivia = suppressTrailingTrivia;
- function copyComments(sourceNode, targetNode) {
- var sourceFile = sourceNode.getSourceFile();
- var text = sourceFile.text;
- if (hasLeadingLineBreak(sourceNode, text)) {
- copyLeadingComments(sourceNode, targetNode, sourceFile);
- }
- else {
- copyTrailingAsLeadingComments(sourceNode, targetNode, sourceFile);
- }
- copyTrailingComments(sourceNode, targetNode, sourceFile);
- }
- ts.copyComments = copyComments;
- function hasLeadingLineBreak(node, text) {
- var start = node.getFullStart();
- var end = node.getStart();
- for (var i = start; i < end; i++) {
- if (text.charCodeAt(i) === 10 /* lineFeed */)
- return true;
- }
- return false;
- }
- function addEmitFlagsRecursively(node, flag, getChild) {
- ts.addEmitFlags(node, flag);
- var child = getChild(node);
- if (child)
- addEmitFlagsRecursively(child, flag, getChild);
- }
- function getFirstChild(node) {
- return node.forEachChild(function (child) { return child; });
- }
- function getUniqueName(baseName, sourceFile) {
- var nameText = baseName;
- for (var i = 1; !ts.isFileLevelUniqueName(sourceFile, nameText); i++) {
- nameText = baseName + "_" + i;
- }
- return nameText;
- }
- ts.getUniqueName = getUniqueName;
- /**
- * @return The index of the (only) reference to the extracted symbol. We want the cursor
- * to be on the reference, rather than the declaration, because it's closer to where the
- * user was before extracting it.
- */
- function getRenameLocation(edits, renameFilename, name, preferLastLocation) {
- var delta = 0;
- var lastPos = -1;
- for (var _i = 0, edits_1 = edits; _i < edits_1.length; _i++) {
- var _a = edits_1[_i], fileName = _a.fileName, textChanges_2 = _a.textChanges;
- ts.Debug.assert(fileName === renameFilename);
- for (var _b = 0, textChanges_1 = textChanges_2; _b < textChanges_1.length; _b++) {
- var change = textChanges_1[_b];
- var span = change.span, newText = change.newText;
- var index = indexInTextChange(newText, name);
- if (index !== -1) {
- lastPos = span.start + delta + index;
- // If the reference comes first, return immediately.
- if (!preferLastLocation) {
- return lastPos;
- }
- }
- delta += newText.length - span.length;
- }
- }
- // If the declaration comes first, return the position of the last occurrence.
- ts.Debug.assert(preferLastLocation);
- ts.Debug.assert(lastPos >= 0);
- return lastPos;
- }
- ts.getRenameLocation = getRenameLocation;
- function copyLeadingComments(sourceNode, targetNode, sourceFile, commentKind, hasTrailingNewLine) {
- ts.forEachLeadingCommentRange(sourceFile.text, sourceNode.pos, getAddCommentsFunction(targetNode, sourceFile, commentKind, hasTrailingNewLine, ts.addSyntheticLeadingComment));
- }
- ts.copyLeadingComments = copyLeadingComments;
- function copyTrailingComments(sourceNode, targetNode, sourceFile, commentKind, hasTrailingNewLine) {
- ts.forEachTrailingCommentRange(sourceFile.text, sourceNode.end, getAddCommentsFunction(targetNode, sourceFile, commentKind, hasTrailingNewLine, ts.addSyntheticTrailingComment));
- }
- ts.copyTrailingComments = copyTrailingComments;
- /**
- * This function copies the trailing comments for the token that comes before `sourceNode`, as leading comments of `targetNode`.
- * This is useful because sometimes a comment that refers to `sourceNode` will be a leading comment for `sourceNode`, according to the
- * notion of trivia ownership, and instead will be a trailing comment for the token before `sourceNode`, e.g.:
- * `function foo(\* not leading comment for a *\ a: string) {}`
- * The comment refers to `a` but belongs to the `(` token, but we might want to copy it.
- */
- function copyTrailingAsLeadingComments(sourceNode, targetNode, sourceFile, commentKind, hasTrailingNewLine) {
- ts.forEachTrailingCommentRange(sourceFile.text, sourceNode.pos, getAddCommentsFunction(targetNode, sourceFile, commentKind, hasTrailingNewLine, ts.addSyntheticLeadingComment));
- }
- ts.copyTrailingAsLeadingComments = copyTrailingAsLeadingComments;
- function getAddCommentsFunction(targetNode, sourceFile, commentKind, hasTrailingNewLine, cb) {
- return function (pos, end, kind, htnl) {
- if (kind === 3 /* MultiLineCommentTrivia */) {
- // Remove leading /*
- pos += 2;
- // Remove trailing */
- end -= 2;
- }
- else {
- // Remove leading //
- pos += 2;
- }
- cb(targetNode, commentKind || kind, sourceFile.text.slice(pos, end), hasTrailingNewLine !== undefined ? hasTrailingNewLine : htnl);
- };
- }
- function indexInTextChange(change, name) {
- if (ts.startsWith(change, name))
- return 0;
- // Add a " " to avoid references inside words
- var idx = change.indexOf(" " + name);
- if (idx === -1)
- idx = change.indexOf("." + name);
- if (idx === -1)
- idx = change.indexOf('"' + name);
- return idx === -1 ? -1 : idx + 1;
- }
- /* @internal */
- function needsParentheses(expression) {
- return ts.isBinaryExpression(expression) && expression.operatorToken.kind === 27 /* CommaToken */ || ts.isObjectLiteralExpression(expression);
- }
- ts.needsParentheses = needsParentheses;
- function getContextualTypeFromParent(node, checker) {
- var parent = node.parent;
- switch (parent.kind) {
- case 197 /* NewExpression */:
- return checker.getContextualType(parent);
- case 209 /* BinaryExpression */: {
- var _a = parent, left = _a.left, operatorToken = _a.operatorToken, right = _a.right;
- return isEqualityOperatorKind(operatorToken.kind)
- ? checker.getTypeAtLocation(node === right ? left : right)
- : checker.getContextualType(node);
- }
- case 277 /* CaseClause */:
- return parent.expression === node ? getSwitchedType(parent, checker) : undefined;
- default:
- return checker.getContextualType(node);
- }
- }
- ts.getContextualTypeFromParent = getContextualTypeFromParent;
- function quote(text, preferences) {
- // Editors can pass in undefined or empty string - we want to infer the preference in those cases.
- var quotePreference = preferences.quotePreference || "auto";
- var quoted = JSON.stringify(text);
- switch (quotePreference) {
- // TODO use getQuotePreference to infer the actual quote style.
- case "auto":
- case "double":
- return quoted;
- case "single":
- return "'" + ts.stripQuotes(quoted).replace("'", "\\'").replace('\\"', '"') + "'";
- default:
- return ts.Debug.assertNever(quotePreference);
- }
- }
- ts.quote = quote;
- function isEqualityOperatorKind(kind) {
- switch (kind) {
- case 36 /* EqualsEqualsEqualsToken */:
- case 34 /* EqualsEqualsToken */:
- case 37 /* ExclamationEqualsEqualsToken */:
- case 35 /* ExclamationEqualsToken */:
- return true;
- default:
- return false;
- }
- }
- ts.isEqualityOperatorKind = isEqualityOperatorKind;
- function isStringLiteralOrTemplate(node) {
- switch (node.kind) {
- case 10 /* StringLiteral */:
- case 14 /* NoSubstitutionTemplateLiteral */:
- case 211 /* TemplateExpression */:
- case 198 /* TaggedTemplateExpression */:
- return true;
- default:
- return false;
- }
- }
- ts.isStringLiteralOrTemplate = isStringLiteralOrTemplate;
- function hasIndexSignature(type) {
- return !!type.getStringIndexType() || !!type.getNumberIndexType();
- }
- ts.hasIndexSignature = hasIndexSignature;
- function getSwitchedType(caseClause, checker) {
- return checker.getTypeAtLocation(caseClause.parent.parent.expression);
- }
- ts.getSwitchedType = getSwitchedType;
- ts.ANONYMOUS = "anonymous function";
- function getTypeNodeIfAccessible(type, enclosingScope, program, host) {
- var checker = program.getTypeChecker();
- var typeIsAccessible = true;
- var notAccessible = function () { typeIsAccessible = false; };
- var res = checker.typeToTypeNode(type, enclosingScope, /*flags*/ undefined, {
- trackSymbol: function (symbol, declaration, meaning) {
- typeIsAccessible = typeIsAccessible && checker.isSymbolAccessible(symbol, declaration, meaning, /*shouldComputeAliasToMarkVisible*/ false).accessibility === 0 /* Accessible */;
- },
- reportInaccessibleThisError: notAccessible,
- reportPrivateInBaseOfClassExpression: notAccessible,
- reportInaccessibleUniqueSymbolError: notAccessible,
- moduleResolverHost: getModuleSpecifierResolverHost(program, host)
- });
- return typeIsAccessible ? res : undefined;
- }
- ts.getTypeNodeIfAccessible = getTypeNodeIfAccessible;
- function syntaxRequiresTrailingCommaOrSemicolonOrASI(kind) {
- return kind === 165 /* CallSignature */
- || kind === 166 /* ConstructSignature */
- || kind === 167 /* IndexSignature */
- || kind === 158 /* PropertySignature */
- || kind === 160 /* MethodSignature */;
- }
- ts.syntaxRequiresTrailingCommaOrSemicolonOrASI = syntaxRequiresTrailingCommaOrSemicolonOrASI;
- function syntaxRequiresTrailingFunctionBlockOrSemicolonOrASI(kind) {
- return kind === 244 /* FunctionDeclaration */
- || kind === 162 /* Constructor */
- || kind === 161 /* MethodDeclaration */
- || kind === 163 /* GetAccessor */
- || kind === 164 /* SetAccessor */;
- }
- ts.syntaxRequiresTrailingFunctionBlockOrSemicolonOrASI = syntaxRequiresTrailingFunctionBlockOrSemicolonOrASI;
- function syntaxRequiresTrailingModuleBlockOrSemicolonOrASI(kind) {
- return kind === 249 /* ModuleDeclaration */;
- }
- ts.syntaxRequiresTrailingModuleBlockOrSemicolonOrASI = syntaxRequiresTrailingModuleBlockOrSemicolonOrASI;
- function syntaxRequiresTrailingSemicolonOrASI(kind) {
- return kind === 225 /* VariableStatement */
- || kind === 226 /* ExpressionStatement */
- || kind === 228 /* DoStatement */
- || kind === 233 /* ContinueStatement */
- || kind === 234 /* BreakStatement */
- || kind === 235 /* ReturnStatement */
- || kind === 239 /* ThrowStatement */
- || kind === 241 /* DebuggerStatement */
- || kind === 159 /* PropertyDeclaration */
- || kind === 247 /* TypeAliasDeclaration */
- || kind === 254 /* ImportDeclaration */
- || kind === 253 /* ImportEqualsDeclaration */
- || kind === 260 /* ExportDeclaration */
- || kind === 252 /* NamespaceExportDeclaration */
- || kind === 259 /* ExportAssignment */;
- }
- ts.syntaxRequiresTrailingSemicolonOrASI = syntaxRequiresTrailingSemicolonOrASI;
- ts.syntaxMayBeASICandidate = ts.or(syntaxRequiresTrailingCommaOrSemicolonOrASI, syntaxRequiresTrailingFunctionBlockOrSemicolonOrASI, syntaxRequiresTrailingModuleBlockOrSemicolonOrASI, syntaxRequiresTrailingSemicolonOrASI);
- function nodeIsASICandidate(node, sourceFile) {
- var lastToken = node.getLastToken(sourceFile);
- if (lastToken && lastToken.kind === 26 /* SemicolonToken */) {
- return false;
- }
- if (syntaxRequiresTrailingCommaOrSemicolonOrASI(node.kind)) {
- if (lastToken && lastToken.kind === 27 /* CommaToken */) {
- return false;
- }
- }
- else if (syntaxRequiresTrailingModuleBlockOrSemicolonOrASI(node.kind)) {
- var lastChild = ts.last(node.getChildren(sourceFile));
- if (lastChild && ts.isModuleBlock(lastChild)) {
- return false;
- }
- }
- else if (syntaxRequiresTrailingFunctionBlockOrSemicolonOrASI(node.kind)) {
- var lastChild = ts.last(node.getChildren(sourceFile));
- if (lastChild && ts.isFunctionBlock(lastChild)) {
- return false;
- }
- }
- else if (!syntaxRequiresTrailingSemicolonOrASI(node.kind)) {
- return false;
- }
- // See comment in parser’s `parseDoStatement`
- if (node.kind === 228 /* DoStatement */) {
- return true;
- }
- var topNode = ts.findAncestor(node, function (ancestor) { return !ancestor.parent; });
- var nextToken = findNextToken(node, topNode, sourceFile);
- if (!nextToken || nextToken.kind === 19 /* CloseBraceToken */) {
- return true;
- }
- var startLine = sourceFile.getLineAndCharacterOfPosition(node.getEnd()).line;
- var endLine = sourceFile.getLineAndCharacterOfPosition(nextToken.getStart(sourceFile)).line;
- return startLine !== endLine;
- }
- function positionIsASICandidate(pos, context, sourceFile) {
- var contextAncestor = ts.findAncestor(context, function (ancestor) {
- if (ancestor.end !== pos) {
- return "quit";
- }
- return ts.syntaxMayBeASICandidate(ancestor.kind);
- });
- return !!contextAncestor && nodeIsASICandidate(contextAncestor, sourceFile);
- }
- ts.positionIsASICandidate = positionIsASICandidate;
- function probablyUsesSemicolons(sourceFile) {
- var withSemicolon = 0;
- var withoutSemicolon = 0;
- var nStatementsToObserve = 5;
- ts.forEachChild(sourceFile, function visit(node) {
- if (syntaxRequiresTrailingSemicolonOrASI(node.kind)) {
- var lastToken = node.getLastToken(sourceFile);
- if (lastToken && lastToken.kind === 26 /* SemicolonToken */) {
- withSemicolon++;
- }
- else {
- withoutSemicolon++;
- }
- }
- if (withSemicolon + withoutSemicolon >= nStatementsToObserve) {
- return true;
- }
- return ts.forEachChild(node, visit);
- });
- // One statement missing a semicolon isn’t sufficient evidence to say the user
- // doesn’t want semicolons, because they may not even be done writing that statement.
- if (withSemicolon === 0 && withoutSemicolon <= 1) {
- return true;
- }
- // If even 2/5 places have a semicolon, the user probably wants semicolons
- return withSemicolon / withoutSemicolon > 1 / nStatementsToObserve;
- }
- ts.probablyUsesSemicolons = probablyUsesSemicolons;
- function tryGetDirectories(host, directoryName) {
- return tryIOAndConsumeErrors(host, host.getDirectories, directoryName) || [];
- }
- ts.tryGetDirectories = tryGetDirectories;
- function tryReadDirectory(host, path, extensions, exclude, include) {
- return tryIOAndConsumeErrors(host, host.readDirectory, path, extensions, exclude, include) || ts.emptyArray;
- }
- ts.tryReadDirectory = tryReadDirectory;
- function tryFileExists(host, path) {
- return tryIOAndConsumeErrors(host, host.fileExists, path);
- }
- ts.tryFileExists = tryFileExists;
- function tryDirectoryExists(host, path) {
- return tryAndIgnoreErrors(function () { return ts.directoryProbablyExists(path, host); }) || false;
- }
- ts.tryDirectoryExists = tryDirectoryExists;
- function tryAndIgnoreErrors(cb) {
- try {
- return cb();
- }
- catch (_a) {
- return undefined;
- }
- }
- ts.tryAndIgnoreErrors = tryAndIgnoreErrors;
- function tryIOAndConsumeErrors(host, toApply) {
- var args = [];
- for (var _i = 2; _i < arguments.length; _i++) {
- args[_i - 2] = arguments[_i];
- }
- return tryAndIgnoreErrors(function () { return toApply && toApply.apply(host, args); });
- }
- ts.tryIOAndConsumeErrors = tryIOAndConsumeErrors;
- function findPackageJsons(startDirectory, host, stopDirectory) {
- var paths = [];
- ts.forEachAncestorDirectory(startDirectory, function (ancestor) {
- if (ancestor === stopDirectory) {
- return true;
- }
- var currentConfigPath = ts.combinePaths(ancestor, "package.json");
- if (tryFileExists(host, currentConfigPath)) {
- paths.push(currentConfigPath);
- }
- });
- return paths;
- }
- ts.findPackageJsons = findPackageJsons;
- function findPackageJson(directory, host) {
- var packageJson;
- ts.forEachAncestorDirectory(directory, function (ancestor) {
- if (ancestor === "node_modules")
- return true;
- packageJson = ts.findConfigFile(ancestor, function (f) { return tryFileExists(host, f); }, "package.json");
- if (packageJson) {
- return true; // break out
- }
- });
- return packageJson;
- }
- ts.findPackageJson = findPackageJson;
- function getPackageJsonsVisibleToFile(fileName, host) {
- if (!host.fileExists) {
- return [];
- }
- var packageJsons = [];
- ts.forEachAncestorDirectory(ts.getDirectoryPath(fileName), function (ancestor) {
- var packageJsonFileName = ts.combinePaths(ancestor, "package.json");
- if (host.fileExists(packageJsonFileName)) {
- var info = createPackageJsonInfo(packageJsonFileName, host);
- if (info) {
- packageJsons.push(info);
- }
- }
- });
- return packageJsons;
- }
- ts.getPackageJsonsVisibleToFile = getPackageJsonsVisibleToFile;
- function createPackageJsonInfo(fileName, host) {
- if (!host.readFile) {
- return undefined;
- }
- var dependencyKeys = ["dependencies", "devDependencies", "optionalDependencies", "peerDependencies"];
- var stringContent = host.readFile(fileName);
- if (!stringContent)
- return undefined;
- var content = tryParseJson(stringContent);
- if (!content)
- return false;
- var info = {};
- for (var _i = 0, dependencyKeys_1 = dependencyKeys; _i < dependencyKeys_1.length; _i++) {
- var key = dependencyKeys_1[_i];
- var dependencies = content[key];
- if (!dependencies) {
- continue;
- }
- var dependencyMap = ts.createMap();
- for (var packageName in dependencies) {
- dependencyMap.set(packageName, dependencies[packageName]);
- }
- info[key] = dependencyMap;
- }
- var dependencyGroups = [
- [1 /* Dependencies */, info.dependencies],
- [2 /* DevDependencies */, info.devDependencies],
- [8 /* OptionalDependencies */, info.optionalDependencies],
- [4 /* PeerDependencies */, info.peerDependencies],
- ];
- return __assign(__assign({}, info), { fileName: fileName,
- get: get,
- has: function (dependencyName, inGroups) {
- return !!get(dependencyName, inGroups);
- } });
- function get(dependencyName, inGroups) {
- if (inGroups === void 0) { inGroups = 15 /* All */; }
- for (var _i = 0, dependencyGroups_1 = dependencyGroups; _i < dependencyGroups_1.length; _i++) {
- var _a = dependencyGroups_1[_i], group_1 = _a[0], deps = _a[1];
- if (deps && (inGroups & group_1)) {
- var dep = deps.get(dependencyName);
- if (dep !== undefined) {
- return dep;
- }
- }
- }
- }
- }
- ts.createPackageJsonInfo = createPackageJsonInfo;
- function tryParseJson(text) {
- try {
- return JSON.parse(text);
- }
- catch (_a) {
- return undefined;
- }
- }
- function consumesNodeCoreModules(sourceFile) {
- return ts.some(sourceFile.imports, function (_a) {
- var text = _a.text;
- return ts.JsTyping.nodeCoreModules.has(text);
- });
- }
- ts.consumesNodeCoreModules = consumesNodeCoreModules;
- function isInsideNodeModules(fileOrDirectory) {
- return ts.contains(ts.getPathComponents(fileOrDirectory), "node_modules");
- }
- ts.isInsideNodeModules = isInsideNodeModules;
- function isDiagnosticWithLocation(diagnostic) {
- return diagnostic.file !== undefined && diagnostic.start !== undefined && diagnostic.length !== undefined;
- }
- ts.isDiagnosticWithLocation = isDiagnosticWithLocation;
- function findDiagnosticForNode(node, sortedFileDiagnostics) {
- var span = createTextSpanFromNode(node);
- var index = ts.binarySearchKey(sortedFileDiagnostics, span, ts.identity, ts.compareTextSpans);
- if (index >= 0) {
- var diagnostic = sortedFileDiagnostics[index];
- ts.Debug.assertEqual(diagnostic.file, node.getSourceFile(), "Diagnostics proided to 'findDiagnosticForNode' must be from a single SourceFile");
- return ts.cast(diagnostic, isDiagnosticWithLocation);
- }
- }
- ts.findDiagnosticForNode = findDiagnosticForNode;
- function getDiagnosticsWithinSpan(span, sortedFileDiagnostics) {
- var _a;
- var index = ts.binarySearchKey(sortedFileDiagnostics, span.start, function (diag) { return diag.start; }, ts.compareValues);
- if (index < 0) {
- index = ~index;
- }
- while (((_a = sortedFileDiagnostics[index - 1]) === null || _a === void 0 ? void 0 : _a.start) === span.start) {
- index--;
- }
- var result = [];
- var end = ts.textSpanEnd(span);
- while (true) {
- var diagnostic = ts.tryCast(sortedFileDiagnostics[index], isDiagnosticWithLocation);
- if (!diagnostic || diagnostic.start > end) {
- break;
- }
- if (ts.textSpanContainsTextSpan(span, diagnostic)) {
- result.push(diagnostic);
- }
- index++;
- }
- return result;
- }
- ts.getDiagnosticsWithinSpan = getDiagnosticsWithinSpan;
- /* @internal */
- function getRefactorContextSpan(_a) {
- var startPosition = _a.startPosition, endPosition = _a.endPosition;
- return ts.createTextSpanFromBounds(startPosition, endPosition === undefined ? startPosition : endPosition);
- }
- ts.getRefactorContextSpan = getRefactorContextSpan;
- function mapOneOrMany(valueOrArray, f, resultSelector) {
- if (resultSelector === void 0) { resultSelector = ts.identity; }
- return valueOrArray ? ts.isArray(valueOrArray) ? resultSelector(ts.map(valueOrArray, f)) : f(valueOrArray, 0) : undefined;
- }
- ts.mapOneOrMany = mapOneOrMany;
- /**
- * If the provided value is an array, the first element of the array is returned; otherwise, the provided value is returned instead.
- */
- function firstOrOnly(valueOrArray) {
- return ts.isArray(valueOrArray) ? ts.first(valueOrArray) : valueOrArray;
- }
- ts.firstOrOnly = firstOrOnly;
- function getNameForExportedSymbol(symbol, scriptTarget) {
- if (symbol.escapedName === "export=" /* ExportEquals */ || symbol.escapedName === "default" /* Default */) {
- // Name of "export default foo;" is "foo". Name of "export default 0" is the filename converted to camelCase.
- return ts.firstDefined(symbol.declarations, function (d) { return ts.isExportAssignment(d) && ts.isIdentifier(d.expression) ? d.expression.text : undefined; })
- || ts.codefix.moduleSymbolToValidIdentifier(ts.Debug.checkDefined(symbol.parent), scriptTarget);
- }
- return symbol.name;
- }
- ts.getNameForExportedSymbol = getNameForExportedSymbol;
- /**
- * Useful to check whether a string contains another string at a specific index
- * without allocating another string or traversing the entire contents of the outer string.
- *
- * This function is useful in place of either of the following:
- *
- * ```ts
- * // Allocates
- * haystack.substr(startIndex, needle.length) === needle
- *
- * // Full traversal
- * haystack.indexOf(needle, startIndex) === startIndex
- * ```
- *
- * @param haystack The string that potentially contains `needle`.
- * @param needle The string whose content might sit within `haystack`.
- * @param startIndex The index within `haystack` to start searching for `needle`.
- */
- function stringContainsAt(haystack, needle, startIndex) {
- var needleLength = needle.length;
- if (needleLength + startIndex > haystack.length) {
- return false;
- }
- for (var i = 0; i < needleLength; i++) {
- if (needle.charCodeAt(i) !== haystack.charCodeAt(i + startIndex))
- return false;
- }
- return true;
- }
- ts.stringContainsAt = stringContainsAt;
- function startsWithUnderscore(name) {
- return name.charCodeAt(0) === 95 /* _ */;
- }
- ts.startsWithUnderscore = startsWithUnderscore;
- function isGlobalDeclaration(declaration) {
- return !isNonGlobalDeclaration(declaration);
- }
- ts.isGlobalDeclaration = isGlobalDeclaration;
- function isNonGlobalDeclaration(declaration) {
- var sourceFile = declaration.getSourceFile();
- // If the file is not a module, the declaration is global
- if (!sourceFile.externalModuleIndicator && !sourceFile.commonJsModuleIndicator) {
- return false;
- }
- // If the file is a module written in TypeScript, it still might be in a `declare global` augmentation
- return ts.isInJSFile(declaration) || !ts.findAncestor(declaration, ts.isGlobalScopeAugmentation);
- }
- ts.isNonGlobalDeclaration = isNonGlobalDeclaration;
- // #endregion
-})(ts || (ts = {}));
-var ts;
-(function (ts) {
- /** The classifier is used for syntactic highlighting in editors via the TSServer */
- function createClassifier() {
- var scanner = ts.createScanner(99 /* Latest */, /*skipTrivia*/ false);
- function getClassificationsForLine(text, lexState, syntacticClassifierAbsent) {
- return convertClassificationsToResult(getEncodedLexicalClassifications(text, lexState, syntacticClassifierAbsent), text);
- }
- // If there is a syntactic classifier ('syntacticClassifierAbsent' is false),
- // we will be more conservative in order to avoid conflicting with the syntactic classifier.
- function getEncodedLexicalClassifications(text, lexState, syntacticClassifierAbsent) {
- var token = 0 /* Unknown */;
- var lastNonTriviaToken = 0 /* Unknown */;
- // Just a stack of TemplateHeads and OpenCurlyBraces, used to perform rudimentary (inexact)
- // classification on template strings. Because of the context free nature of templates,
- // the only precise way to classify a template portion would be by propagating the stack across
- // lines, just as we do with the end-of-line state. However, this is a burden for implementers,
- // and the behavior is entirely subsumed by the syntactic classifier anyway, so we instead
- // flatten any nesting when the template stack is non-empty and encode it in the end-of-line state.
- // Situations in which this fails are
- // 1) When template strings are nested across different lines:
- // `hello ${ `world
- // ` }`
- //
- // Where on the second line, you will get the closing of a template,
- // a closing curly, and a new template.
- //
- // 2) When substitution expressions have curly braces and the curly brace falls on the next line:
- // `hello ${ () => {
- // return "world" } } `
- //
- // Where on the second line, you will get the 'return' keyword,
- // a string literal, and a template end consisting of '} } `'.
- var templateStack = [];
- var _a = getPrefixFromLexState(lexState), prefix = _a.prefix, pushTemplate = _a.pushTemplate;
- text = prefix + text;
- var offset = prefix.length;
- if (pushTemplate) {
- templateStack.push(15 /* TemplateHead */);
- }
- scanner.setText(text);
- var endOfLineState = 0 /* None */;
- var spans = [];
- // We can run into an unfortunate interaction between the lexical and syntactic classifier
- // when the user is typing something generic. Consider the case where the user types:
- //
- // Foo
tokens. It's a weak heuristic, but should
- // work well enough in practice.
- var angleBracketStack = 0;
- do {
- token = scanner.scan();
- if (!ts.isTrivia(token)) {
- handleToken();
- lastNonTriviaToken = token;
- }
- var end = scanner.getTextPos();
- pushEncodedClassification(scanner.getTokenPos(), end, offset, classFromKind(token), spans);
- if (end >= text.length) {
- var end_1 = getNewEndOfLineState(scanner, token, ts.lastOrUndefined(templateStack));
- if (end_1 !== undefined) {
- endOfLineState = end_1;
- }
- }
- } while (token !== 1 /* EndOfFileToken */);
- function handleToken() {
- switch (token) {
- case 43 /* SlashToken */:
- case 67 /* SlashEqualsToken */:
- if (!noRegexTable[lastNonTriviaToken] && scanner.reScanSlashToken() === 13 /* RegularExpressionLiteral */) {
- token = 13 /* RegularExpressionLiteral */;
- }
- break;
- case 29 /* LessThanToken */:
- if (lastNonTriviaToken === 75 /* Identifier */) {
- // Could be the start of something generic. Keep track of that by bumping
- // up the current count of generic contexts we may be in.
- angleBracketStack++;
- }
- break;
- case 31 /* GreaterThanToken */:
- if (angleBracketStack > 0) {
- // If we think we're currently in something generic, then mark that that
- // generic entity is complete.
- angleBracketStack--;
- }
- break;
- case 125 /* AnyKeyword */:
- case 143 /* StringKeyword */:
- case 140 /* NumberKeyword */:
- case 128 /* BooleanKeyword */:
- case 144 /* SymbolKeyword */:
- if (angleBracketStack > 0 && !syntacticClassifierAbsent) {
- // If it looks like we're could be in something generic, don't classify this
- // as a keyword. We may just get overwritten by the syntactic classifier,
- // causing a noisy experience for the user.
- token = 75 /* Identifier */;
- }
- break;
- case 15 /* TemplateHead */:
- templateStack.push(token);
- break;
- case 18 /* OpenBraceToken */:
- // If we don't have anything on the template stack,
- // then we aren't trying to keep track of a previously scanned template head.
- if (templateStack.length > 0) {
- templateStack.push(token);
- }
- break;
- case 19 /* CloseBraceToken */:
- // If we don't have anything on the template stack,
- // then we aren't trying to keep track of a previously scanned template head.
- if (templateStack.length > 0) {
- var lastTemplateStackToken = ts.lastOrUndefined(templateStack);
- if (lastTemplateStackToken === 15 /* TemplateHead */) {
- token = scanner.reScanTemplateToken(/* isTaggedTemplate */ false);
- // Only pop on a TemplateTail; a TemplateMiddle indicates there is more for us.
- if (token === 17 /* TemplateTail */) {
- templateStack.pop();
- }
- else {
- ts.Debug.assertEqual(token, 16 /* TemplateMiddle */, "Should have been a template middle.");
- }
- }
- else {
- ts.Debug.assertEqual(lastTemplateStackToken, 18 /* OpenBraceToken */, "Should have been an open brace");
- templateStack.pop();
- }
- }
- break;
- default:
- if (!ts.isKeyword(token)) {
- break;
- }
- if (lastNonTriviaToken === 24 /* DotToken */) {
- token = 75 /* Identifier */;
- }
- else if (ts.isKeyword(lastNonTriviaToken) && ts.isKeyword(token) && !canFollow(lastNonTriviaToken, token)) {
- // We have two keywords in a row. Only treat the second as a keyword if
- // it's a sequence that could legally occur in the language. Otherwise
- // treat it as an identifier. This way, if someone writes "private var"
- // we recognize that 'var' is actually an identifier here.
- token = 75 /* Identifier */;
- }
- }
- }
- return { endOfLineState: endOfLineState, spans: spans };
- }
- return { getClassificationsForLine: getClassificationsForLine, getEncodedLexicalClassifications: getEncodedLexicalClassifications };
- }
- ts.createClassifier = createClassifier;
- /// We do not have a full parser support to know when we should parse a regex or not
- /// If we consider every slash token to be a regex, we could be missing cases like "1/2/3", where
- /// we have a series of divide operator. this list allows us to be more accurate by ruling out
- /// locations where a regexp cannot exist.
- var noRegexTable = ts.arrayToNumericMap([
- 75 /* Identifier */,
- 10 /* StringLiteral */,
- 8 /* NumericLiteral */,
- 9 /* BigIntLiteral */,
- 13 /* RegularExpressionLiteral */,
- 104 /* ThisKeyword */,
- 45 /* PlusPlusToken */,
- 46 /* MinusMinusToken */,
- 21 /* CloseParenToken */,
- 23 /* CloseBracketToken */,
- 19 /* CloseBraceToken */,
- 106 /* TrueKeyword */,
- 91 /* FalseKeyword */,
- ], function (token) { return token; }, function () { return true; });
- function getNewEndOfLineState(scanner, token, lastOnTemplateStack) {
- switch (token) {
- case 10 /* StringLiteral */: {
- // Check to see if we finished up on a multiline string literal.
- if (!scanner.isUnterminated())
- return undefined;
- var tokenText = scanner.getTokenText();
- var lastCharIndex = tokenText.length - 1;
- var numBackslashes = 0;
- while (tokenText.charCodeAt(lastCharIndex - numBackslashes) === 92 /* backslash */) {
- numBackslashes++;
- }
- // If we have an odd number of backslashes, then the multiline string is unclosed
- if ((numBackslashes & 1) === 0)
- return undefined;
- return tokenText.charCodeAt(0) === 34 /* doubleQuote */ ? 3 /* InDoubleQuoteStringLiteral */ : 2 /* InSingleQuoteStringLiteral */;
- }
- case 3 /* MultiLineCommentTrivia */:
- // Check to see if the multiline comment was unclosed.
- return scanner.isUnterminated() ? 1 /* InMultiLineCommentTrivia */ : undefined;
- default:
- if (ts.isTemplateLiteralKind(token)) {
- if (!scanner.isUnterminated()) {
- return undefined;
- }
- switch (token) {
- case 17 /* TemplateTail */:
- return 5 /* InTemplateMiddleOrTail */;
- case 14 /* NoSubstitutionTemplateLiteral */:
- return 4 /* InTemplateHeadOrNoSubstitutionTemplate */;
- default:
- return ts.Debug.fail("Only 'NoSubstitutionTemplateLiteral's and 'TemplateTail's can be unterminated; got SyntaxKind #" + token);
- }
- }
- return lastOnTemplateStack === 15 /* TemplateHead */ ? 6 /* InTemplateSubstitutionPosition */ : undefined;
- }
- }
- function pushEncodedClassification(start, end, offset, classification, result) {
- if (classification === 8 /* whiteSpace */) {
- // Don't bother with whitespace classifications. They're not needed.
- return;
- }
- if (start === 0 && offset > 0) {
- // We're classifying the first token, and this was a case where we prepended text.
- // We should consider the start of this token to be at the start of the original text.
- start += offset;
- }
- var length = end - start;
- if (length > 0) {
- // All our tokens are in relation to the augmented text. Move them back to be
- // relative to the original text.
- result.push(start - offset, length, classification);
- }
- }
- function convertClassificationsToResult(classifications, text) {
- var entries = [];
- var dense = classifications.spans;
- var lastEnd = 0;
- for (var i = 0; i < dense.length; i += 3) {
- var start = dense[i];
- var length_1 = dense[i + 1];
- var type = dense[i + 2];
- // Make a whitespace entry between the last item and this one.
- if (lastEnd >= 0) {
- var whitespaceLength_1 = start - lastEnd;
- if (whitespaceLength_1 > 0) {
- entries.push({ length: whitespaceLength_1, classification: ts.TokenClass.Whitespace });
- }
- }
- entries.push({ length: length_1, classification: convertClassification(type) });
- lastEnd = start + length_1;
- }
- var whitespaceLength = text.length - lastEnd;
- if (whitespaceLength > 0) {
- entries.push({ length: whitespaceLength, classification: ts.TokenClass.Whitespace });
- }
- return { entries: entries, finalLexState: classifications.endOfLineState };
- }
- function convertClassification(type) {
- switch (type) {
- case 1 /* comment */: return ts.TokenClass.Comment;
- case 3 /* keyword */: return ts.TokenClass.Keyword;
- case 4 /* numericLiteral */: return ts.TokenClass.NumberLiteral;
- case 25 /* bigintLiteral */: return ts.TokenClass.BigIntLiteral;
- case 5 /* operator */: return ts.TokenClass.Operator;
- case 6 /* stringLiteral */: return ts.TokenClass.StringLiteral;
- case 8 /* whiteSpace */: return ts.TokenClass.Whitespace;
- case 10 /* punctuation */: return ts.TokenClass.Punctuation;
- case 2 /* identifier */:
- case 11 /* className */:
- case 12 /* enumName */:
- case 13 /* interfaceName */:
- case 14 /* moduleName */:
- case 15 /* typeParameterName */:
- case 16 /* typeAliasName */:
- case 9 /* text */:
- case 17 /* parameterName */:
- return ts.TokenClass.Identifier;
- default:
- return undefined; // TODO: GH#18217 Debug.assertNever(type);
- }
- }
- /** Returns true if 'keyword2' can legally follow 'keyword1' in any language construct. */
- function canFollow(keyword1, keyword2) {
- if (!ts.isAccessibilityModifier(keyword1)) {
- // Assume any other keyword combination is legal.
- // This can be refined in the future if there are more cases we want the classifier to be better at.
- return true;
- }
- switch (keyword2) {
- case 131 /* GetKeyword */:
- case 142 /* SetKeyword */:
- case 129 /* ConstructorKeyword */:
- case 120 /* StaticKeyword */:
- return true; // Allow things like "public get", "public constructor" and "public static".
- default:
- return false; // Any other keyword following "public" is actually an identifier, not a real keyword.
- }
- }
- function getPrefixFromLexState(lexState) {
- // If we're in a string literal, then prepend: "\
- // (and a newline). That way when we lex we'll think we're still in a string literal.
- //
- // If we're in a multiline comment, then prepend: /*
- // (and a newline). That way when we lex we'll think we're still in a multiline comment.
- switch (lexState) {
- case 3 /* InDoubleQuoteStringLiteral */:
- return { prefix: "\"\\\n" };
- case 2 /* InSingleQuoteStringLiteral */:
- return { prefix: "'\\\n" };
- case 1 /* InMultiLineCommentTrivia */:
- return { prefix: "/*\n" };
- case 4 /* InTemplateHeadOrNoSubstitutionTemplate */:
- return { prefix: "`\n" };
- case 5 /* InTemplateMiddleOrTail */:
- return { prefix: "}\n", pushTemplate: true };
- case 6 /* InTemplateSubstitutionPosition */:
- return { prefix: "", pushTemplate: true };
- case 0 /* None */:
- return { prefix: "" };
- default:
- return ts.Debug.assertNever(lexState);
- }
- }
- function isBinaryExpressionOperatorToken(token) {
- switch (token) {
- case 41 /* AsteriskToken */:
- case 43 /* SlashToken */:
- case 44 /* PercentToken */:
- case 39 /* PlusToken */:
- case 40 /* MinusToken */:
- case 47 /* LessThanLessThanToken */:
- case 48 /* GreaterThanGreaterThanToken */:
- case 49 /* GreaterThanGreaterThanGreaterThanToken */:
- case 29 /* LessThanToken */:
- case 31 /* GreaterThanToken */:
- case 32 /* LessThanEqualsToken */:
- case 33 /* GreaterThanEqualsToken */:
- case 98 /* InstanceOfKeyword */:
- case 97 /* InKeyword */:
- case 123 /* AsKeyword */:
- case 34 /* EqualsEqualsToken */:
- case 35 /* ExclamationEqualsToken */:
- case 36 /* EqualsEqualsEqualsToken */:
- case 37 /* ExclamationEqualsEqualsToken */:
- case 50 /* AmpersandToken */:
- case 52 /* CaretToken */:
- case 51 /* BarToken */:
- case 55 /* AmpersandAmpersandToken */:
- case 56 /* BarBarToken */:
- case 73 /* BarEqualsToken */:
- case 72 /* AmpersandEqualsToken */:
- case 74 /* CaretEqualsToken */:
- case 69 /* LessThanLessThanEqualsToken */:
- case 70 /* GreaterThanGreaterThanEqualsToken */:
- case 71 /* GreaterThanGreaterThanGreaterThanEqualsToken */:
- case 63 /* PlusEqualsToken */:
- case 64 /* MinusEqualsToken */:
- case 65 /* AsteriskEqualsToken */:
- case 67 /* SlashEqualsToken */:
- case 68 /* PercentEqualsToken */:
- case 62 /* EqualsToken */:
- case 27 /* CommaToken */:
- case 60 /* QuestionQuestionToken */:
- return true;
- default:
- return false;
- }
- }
- function isPrefixUnaryExpressionOperatorToken(token) {
- switch (token) {
- case 39 /* PlusToken */:
- case 40 /* MinusToken */:
- case 54 /* TildeToken */:
- case 53 /* ExclamationToken */:
- case 45 /* PlusPlusToken */:
- case 46 /* MinusMinusToken */:
- return true;
- default:
- return false;
- }
- }
- function classFromKind(token) {
- if (ts.isKeyword(token)) {
- return 3 /* keyword */;
- }
- else if (isBinaryExpressionOperatorToken(token) || isPrefixUnaryExpressionOperatorToken(token)) {
- return 5 /* operator */;
- }
- else if (token >= 18 /* FirstPunctuation */ && token <= 74 /* LastPunctuation */) {
- return 10 /* punctuation */;
- }
- switch (token) {
- case 8 /* NumericLiteral */:
- return 4 /* numericLiteral */;
- case 9 /* BigIntLiteral */:
- return 25 /* bigintLiteral */;
- case 10 /* StringLiteral */:
- return 6 /* stringLiteral */;
- case 13 /* RegularExpressionLiteral */:
- return 7 /* regularExpressionLiteral */;
- case 7 /* ConflictMarkerTrivia */:
- case 3 /* MultiLineCommentTrivia */:
- case 2 /* SingleLineCommentTrivia */:
- return 1 /* comment */;
- case 5 /* WhitespaceTrivia */:
- case 4 /* NewLineTrivia */:
- return 8 /* whiteSpace */;
- case 75 /* Identifier */:
- default:
- if (ts.isTemplateLiteralKind(token)) {
- return 6 /* stringLiteral */;
- }
- return 2 /* identifier */;
- }
- }
- /* @internal */
- function getSemanticClassifications(typeChecker, cancellationToken, sourceFile, classifiableNames, span) {
- return convertClassificationsToSpans(getEncodedSemanticClassifications(typeChecker, cancellationToken, sourceFile, classifiableNames, span));
- }
- ts.getSemanticClassifications = getSemanticClassifications;
- function checkForClassificationCancellation(cancellationToken, kind) {
- // We don't want to actually call back into our host on every node to find out if we've
- // been canceled. That would be an enormous amount of chattyness, along with the all
- // the overhead of marshalling the data to/from the host. So instead we pick a few
- // reasonable node kinds to bother checking on. These node kinds represent high level
- // constructs that we would expect to see commonly, but just at a far less frequent
- // interval.
- //
- // For example, in checker.ts (around 750k) we only have around 600 of these constructs.
- // That means we're calling back into the host around every 1.2k of the file we process.
- // Lib.d.ts has similar numbers.
- switch (kind) {
- case 249 /* ModuleDeclaration */:
- case 245 /* ClassDeclaration */:
- case 246 /* InterfaceDeclaration */:
- case 244 /* FunctionDeclaration */:
- cancellationToken.throwIfCancellationRequested();
- }
- }
- /* @internal */
- function getEncodedSemanticClassifications(typeChecker, cancellationToken, sourceFile, classifiableNames, span) {
- var spans = [];
- sourceFile.forEachChild(function cb(node) {
- // Only walk into nodes that intersect the requested span.
- if (!node || !ts.textSpanIntersectsWith(span, node.pos, node.getFullWidth())) {
- return;
- }
- checkForClassificationCancellation(cancellationToken, node.kind);
- // Only bother calling into the typechecker if this is an identifier that
- // could possibly resolve to a type name. This makes classification run
- // in a third of the time it would normally take.
- if (ts.isIdentifier(node) && !ts.nodeIsMissing(node) && classifiableNames.has(node.escapedText)) {
- var symbol = typeChecker.getSymbolAtLocation(node);
- var type = symbol && classifySymbol(symbol, ts.getMeaningFromLocation(node), typeChecker);
- if (type) {
- pushClassification(node.getStart(sourceFile), node.getEnd(), type);
- }
- }
- node.forEachChild(cb);
- });
- return { spans: spans, endOfLineState: 0 /* None */ };
- function pushClassification(start, end, type) {
- var length = end - start;
- ts.Debug.assert(length > 0, "Classification had non-positive length of " + length);
- spans.push(start);
- spans.push(length);
- spans.push(type);
- }
- }
- ts.getEncodedSemanticClassifications = getEncodedSemanticClassifications;
- function classifySymbol(symbol, meaningAtPosition, checker) {
- var flags = symbol.getFlags();
- if ((flags & 2885600 /* Classifiable */) === 0 /* None */) {
- return undefined;
- }
- else if (flags & 32 /* Class */) {
- return 11 /* className */;
- }
- else if (flags & 384 /* Enum */) {
- return 12 /* enumName */;
- }
- else if (flags & 524288 /* TypeAlias */) {
- return 16 /* typeAliasName */;
- }
- else if (flags & 1536 /* Module */) {
- // Only classify a module as such if
- // - It appears in a namespace context.
- // - There exists a module declaration which actually impacts the value side.
- return meaningAtPosition & 4 /* Namespace */ || meaningAtPosition & 1 /* Value */ && hasValueSideModule(symbol) ? 14 /* moduleName */ : undefined;
- }
- else if (flags & 2097152 /* Alias */) {
- return classifySymbol(checker.getAliasedSymbol(symbol), meaningAtPosition, checker);
- }
- else if (meaningAtPosition & 2 /* Type */) {
- return flags & 64 /* Interface */ ? 13 /* interfaceName */ : flags & 262144 /* TypeParameter */ ? 15 /* typeParameterName */ : undefined;
- }
- else {
- return undefined;
- }
- }
- /** Returns true if there exists a module that introduces entities on the value side. */
- function hasValueSideModule(symbol) {
- return ts.some(symbol.declarations, function (declaration) {
- return ts.isModuleDeclaration(declaration) && ts.getModuleInstanceState(declaration) === 1 /* Instantiated */;
- });
- }
- function getClassificationTypeName(type) {
- switch (type) {
- case 1 /* comment */: return "comment" /* comment */;
- case 2 /* identifier */: return "identifier" /* identifier */;
- case 3 /* keyword */: return "keyword" /* keyword */;
- case 4 /* numericLiteral */: return "number" /* numericLiteral */;
- case 25 /* bigintLiteral */: return "bigint" /* bigintLiteral */;
- case 5 /* operator */: return "operator" /* operator */;
- case 6 /* stringLiteral */: return "string" /* stringLiteral */;
- case 8 /* whiteSpace */: return "whitespace" /* whiteSpace */;
- case 9 /* text */: return "text" /* text */;
- case 10 /* punctuation */: return "punctuation" /* punctuation */;
- case 11 /* className */: return "class name" /* className */;
- case 12 /* enumName */: return "enum name" /* enumName */;
- case 13 /* interfaceName */: return "interface name" /* interfaceName */;
- case 14 /* moduleName */: return "module name" /* moduleName */;
- case 15 /* typeParameterName */: return "type parameter name" /* typeParameterName */;
- case 16 /* typeAliasName */: return "type alias name" /* typeAliasName */;
- case 17 /* parameterName */: return "parameter name" /* parameterName */;
- case 18 /* docCommentTagName */: return "doc comment tag name" /* docCommentTagName */;
- case 19 /* jsxOpenTagName */: return "jsx open tag name" /* jsxOpenTagName */;
- case 20 /* jsxCloseTagName */: return "jsx close tag name" /* jsxCloseTagName */;
- case 21 /* jsxSelfClosingTagName */: return "jsx self closing tag name" /* jsxSelfClosingTagName */;
- case 22 /* jsxAttribute */: return "jsx attribute" /* jsxAttribute */;
- case 23 /* jsxText */: return "jsx text" /* jsxText */;
- case 24 /* jsxAttributeStringLiteralValue */: return "jsx attribute string literal value" /* jsxAttributeStringLiteralValue */;
- default: return undefined; // TODO: GH#18217 throw Debug.assertNever(type);
- }
- }
- function convertClassificationsToSpans(classifications) {
- ts.Debug.assert(classifications.spans.length % 3 === 0);
- var dense = classifications.spans;
- var result = [];
- for (var i = 0; i < dense.length; i += 3) {
- result.push({
- textSpan: ts.createTextSpan(dense[i], dense[i + 1]),
- classificationType: getClassificationTypeName(dense[i + 2])
- });
- }
- return result;
- }
- /* @internal */
- function getSyntacticClassifications(cancellationToken, sourceFile, span) {
- return convertClassificationsToSpans(getEncodedSyntacticClassifications(cancellationToken, sourceFile, span));
- }
- ts.getSyntacticClassifications = getSyntacticClassifications;
- /* @internal */
- function getEncodedSyntacticClassifications(cancellationToken, sourceFile, span) {
- var spanStart = span.start;
- var spanLength = span.length;
- // Make a scanner we can get trivia from.
- var triviaScanner = ts.createScanner(99 /* Latest */, /*skipTrivia*/ false, sourceFile.languageVariant, sourceFile.text);
- var mergeConflictScanner = ts.createScanner(99 /* Latest */, /*skipTrivia*/ false, sourceFile.languageVariant, sourceFile.text);
- var result = [];
- processElement(sourceFile);
- return { spans: result, endOfLineState: 0 /* None */ };
- function pushClassification(start, length, type) {
- result.push(start);
- result.push(length);
- result.push(type);
- }
- function classifyLeadingTriviaAndGetTokenStart(token) {
- triviaScanner.setTextPos(token.pos);
- while (true) {
- var start = triviaScanner.getTextPos();
- // only bother scanning if we have something that could be trivia.
- if (!ts.couldStartTrivia(sourceFile.text, start)) {
- return start;
- }
- var kind = triviaScanner.scan();
- var end = triviaScanner.getTextPos();
- var width = end - start;
- // The moment we get something that isn't trivia, then stop processing.
- if (!ts.isTrivia(kind)) {
- return start;
- }
- switch (kind) {
- case 4 /* NewLineTrivia */:
- case 5 /* WhitespaceTrivia */:
- // Don't bother with newlines/whitespace.
- continue;
- case 2 /* SingleLineCommentTrivia */:
- case 3 /* MultiLineCommentTrivia */:
- // Only bother with the trivia if it at least intersects the span of interest.
- classifyComment(token, kind, start, width);
- // Classifying a comment might cause us to reuse the trivia scanner
- // (because of jsdoc comments). So after we classify the comment make
- // sure we set the scanner position back to where it needs to be.
- triviaScanner.setTextPos(end);
- continue;
- case 7 /* ConflictMarkerTrivia */:
- var text = sourceFile.text;
- var ch = text.charCodeAt(start);
- // for the <<<<<<< and >>>>>>> markers, we just add them in as comments
- // in the classification stream.
- if (ch === 60 /* lessThan */ || ch === 62 /* greaterThan */) {
- pushClassification(start, width, 1 /* comment */);
- continue;
- }
- // for the ||||||| and ======== markers, add a comment for the first line,
- // and then lex all subsequent lines up until the end of the conflict marker.
- ts.Debug.assert(ch === 124 /* bar */ || ch === 61 /* equals */);
- classifyDisabledMergeCode(text, start, end);
- break;
- case 6 /* ShebangTrivia */:
- // TODO: Maybe we should classify these.
- break;
- default:
- ts.Debug.assertNever(kind);
- }
- }
- }
- function classifyComment(token, kind, start, width) {
- if (kind === 3 /* MultiLineCommentTrivia */) {
- // See if this is a doc comment. If so, we'll classify certain portions of it
- // specially.
- var docCommentAndDiagnostics = ts.parseIsolatedJSDocComment(sourceFile.text, start, width);
- if (docCommentAndDiagnostics && docCommentAndDiagnostics.jsDoc) {
- // TODO: This should be predicated on `token["kind"]` being compatible with `HasJSDoc["kind"]`
- docCommentAndDiagnostics.jsDoc.parent = token;
- classifyJSDocComment(docCommentAndDiagnostics.jsDoc);
- return;
- }
- }
- else if (kind === 2 /* SingleLineCommentTrivia */) {
- if (tryClassifyTripleSlashComment(start, width)) {
- return;
- }
- }
- // Simple comment. Just add as is.
- pushCommentRange(start, width);
- }
- function pushCommentRange(start, width) {
- pushClassification(start, width, 1 /* comment */);
- }
- function classifyJSDocComment(docComment) {
- var pos = docComment.pos;
- if (docComment.tags) {
- for (var _i = 0, _a = docComment.tags; _i < _a.length; _i++) {
- var tag = _a[_i];
- // As we walk through each tag, classify the portion of text from the end of
- // the last tag (or the start of the entire doc comment) as 'comment'.
- if (tag.pos !== pos) {
- pushCommentRange(pos, tag.pos - pos);
- }
- pushClassification(tag.pos, 1, 10 /* punctuation */); // "@"
- pushClassification(tag.tagName.pos, tag.tagName.end - tag.tagName.pos, 18 /* docCommentTagName */); // e.g. "param"
- pos = tag.tagName.end;
- switch (tag.kind) {
- case 317 /* JSDocParameterTag */:
- processJSDocParameterTag(tag);
- break;
- case 321 /* JSDocTemplateTag */:
- processJSDocTemplateTag(tag);
- pos = tag.end;
- break;
- case 320 /* JSDocTypeTag */:
- processElement(tag.typeExpression);
- pos = tag.end;
- break;
- case 318 /* JSDocReturnTag */:
- processElement(tag.typeExpression);
- pos = tag.end;
- break;
- }
- }
- }
- if (pos !== docComment.end) {
- pushCommentRange(pos, docComment.end - pos);
- }
- return;
- function processJSDocParameterTag(tag) {
- if (tag.isNameFirst) {
- pushCommentRange(pos, tag.name.pos - pos);
- pushClassification(tag.name.pos, tag.name.end - tag.name.pos, 17 /* parameterName */);
- pos = tag.name.end;
- }
- if (tag.typeExpression) {
- pushCommentRange(pos, tag.typeExpression.pos - pos);
- processElement(tag.typeExpression);
- pos = tag.typeExpression.end;
- }
- if (!tag.isNameFirst) {
- pushCommentRange(pos, tag.name.pos - pos);
- pushClassification(tag.name.pos, tag.name.end - tag.name.pos, 17 /* parameterName */);
- pos = tag.name.end;
- }
- }
- }
- function tryClassifyTripleSlashComment(start, width) {
- var tripleSlashXMLCommentRegEx = /^(\/\/\/\s*)(<)(?:(\S+)((?:[^/]|\/[^>])*)(\/>)?)?/im;
- var attributeRegex = /(\S+)(\s*)(=)(\s*)('[^']+'|"[^"]+")/img;
- var text = sourceFile.text.substr(start, width);
- var match = tripleSlashXMLCommentRegEx.exec(text);
- if (!match) {
- return false;
- }
- // Limiting classification to exactly the elements and attributes
- // defined in `ts.commentPragmas` would be excessive, but we can avoid
- // some obvious false positives (e.g. in XML-like doc comments) by
- // checking the element name.
- // eslint-disable-next-line no-in-operator
- if (!match[3] || !(match[3] in ts.commentPragmas)) {
- return false;
- }
- var pos = start;
- pushCommentRange(pos, match[1].length); // ///
- pos += match[1].length;
- pushClassification(pos, match[2].length, 10 /* punctuation */); // <
- pos += match[2].length;
- pushClassification(pos, match[3].length, 21 /* jsxSelfClosingTagName */); // element name
- pos += match[3].length;
- var attrText = match[4];
- var attrPos = pos;
- while (true) {
- var attrMatch = attributeRegex.exec(attrText);
- if (!attrMatch) {
- break;
- }
- var newAttrPos = pos + attrMatch.index;
- if (newAttrPos > attrPos) {
- pushCommentRange(attrPos, newAttrPos - attrPos);
- attrPos = newAttrPos;
- }
- pushClassification(attrPos, attrMatch[1].length, 22 /* jsxAttribute */); // attribute name
- attrPos += attrMatch[1].length;
- if (attrMatch[2].length) {
- pushCommentRange(attrPos, attrMatch[2].length); // whitespace
- attrPos += attrMatch[2].length;
- }
- pushClassification(attrPos, attrMatch[3].length, 5 /* operator */); // =
- attrPos += attrMatch[3].length;
- if (attrMatch[4].length) {
- pushCommentRange(attrPos, attrMatch[4].length); // whitespace
- attrPos += attrMatch[4].length;
- }
- pushClassification(attrPos, attrMatch[5].length, 24 /* jsxAttributeStringLiteralValue */); // attribute value
- attrPos += attrMatch[5].length;
- }
- pos += match[4].length;
- if (pos > attrPos) {
- pushCommentRange(attrPos, pos - attrPos);
- }
- if (match[5]) {
- pushClassification(pos, match[5].length, 10 /* punctuation */); // />
- pos += match[5].length;
- }
- var end = start + width;
- if (pos < end) {
- pushCommentRange(pos, end - pos);
- }
- return true;
- }
- function processJSDocTemplateTag(tag) {
- for (var _i = 0, _a = tag.getChildren(); _i < _a.length; _i++) {
- var child = _a[_i];
- processElement(child);
- }
- }
- function classifyDisabledMergeCode(text, start, end) {
- // Classify the line that the ||||||| or ======= marker is on as a comment.
- // Then just lex all further tokens and add them to the result.
- var i;
- for (i = start; i < end; i++) {
- if (ts.isLineBreak(text.charCodeAt(i))) {
- break;
- }
- }
- pushClassification(start, i - start, 1 /* comment */);
- mergeConflictScanner.setTextPos(i);
- while (mergeConflictScanner.getTextPos() < end) {
- classifyDisabledCodeToken();
- }
- }
- function classifyDisabledCodeToken() {
- var start = mergeConflictScanner.getTextPos();
- var tokenKind = mergeConflictScanner.scan();
- var end = mergeConflictScanner.getTextPos();
- var type = classifyTokenType(tokenKind);
- if (type) {
- pushClassification(start, end - start, type);
- }
- }
- /**
- * Returns true if node should be treated as classified and no further processing is required.
- * False will mean that node is not classified and traverse routine should recurse into node contents.
- */
- function tryClassifyNode(node) {
- if (ts.isJSDoc(node)) {
- return true;
- }
- if (ts.nodeIsMissing(node)) {
- return true;
- }
- var classifiedElementName = tryClassifyJsxElementName(node);
- if (!ts.isToken(node) && node.kind !== 11 /* JsxText */ && classifiedElementName === undefined) {
- return false;
- }
- var tokenStart = node.kind === 11 /* JsxText */ ? node.pos : classifyLeadingTriviaAndGetTokenStart(node);
- var tokenWidth = node.end - tokenStart;
- ts.Debug.assert(tokenWidth >= 0);
- if (tokenWidth > 0) {
- var type = classifiedElementName || classifyTokenType(node.kind, node);
- if (type) {
- pushClassification(tokenStart, tokenWidth, type);
- }
- }
- return true;
- }
- function tryClassifyJsxElementName(token) {
- switch (token.parent && token.parent.kind) {
- case 268 /* JsxOpeningElement */:
- if (token.parent.tagName === token) {
- return 19 /* jsxOpenTagName */;
- }
- break;
- case 269 /* JsxClosingElement */:
- if (token.parent.tagName === token) {
- return 20 /* jsxCloseTagName */;
- }
- break;
- case 267 /* JsxSelfClosingElement */:
- if (token.parent.tagName === token) {
- return 21 /* jsxSelfClosingTagName */;
- }
- break;
- case 273 /* JsxAttribute */:
- if (token.parent.name === token) {
- return 22 /* jsxAttribute */;
- }
- break;
- }
- return undefined;
- }
- // for accurate classification, the actual token should be passed in. however, for
- // cases like 'disabled merge code' classification, we just get the token kind and
- // classify based on that instead.
- function classifyTokenType(tokenKind, token) {
- if (ts.isKeyword(tokenKind)) {
- return 3 /* keyword */;
- }
- // Special case `<` and `>`: If they appear in a generic context they are punctuation,
- // not operators.
- if (tokenKind === 29 /* LessThanToken */ || tokenKind === 31 /* GreaterThanToken */) {
- // If the node owning the token has a type argument list or type parameter list, then
- // we can effectively assume that a '<' and '>' belong to those lists.
- if (token && ts.getTypeArgumentOrTypeParameterList(token.parent)) {
- return 10 /* punctuation */;
- }
- }
- if (ts.isPunctuation(tokenKind)) {
- if (token) {
- var parent = token.parent;
- if (tokenKind === 62 /* EqualsToken */) {
- // the '=' in a variable declaration is special cased here.
- if (parent.kind === 242 /* VariableDeclaration */ ||
- parent.kind === 159 /* PropertyDeclaration */ ||
- parent.kind === 156 /* Parameter */ ||
- parent.kind === 273 /* JsxAttribute */) {
- return 5 /* operator */;
- }
- }
- if (parent.kind === 209 /* BinaryExpression */ ||
- parent.kind === 207 /* PrefixUnaryExpression */ ||
- parent.kind === 208 /* PostfixUnaryExpression */ ||
- parent.kind === 210 /* ConditionalExpression */) {
- return 5 /* operator */;
- }
- }
- return 10 /* punctuation */;
- }
- else if (tokenKind === 8 /* NumericLiteral */) {
- return 4 /* numericLiteral */;
- }
- else if (tokenKind === 9 /* BigIntLiteral */) {
- return 25 /* bigintLiteral */;
- }
- else if (tokenKind === 10 /* StringLiteral */) {
- return token && token.parent.kind === 273 /* JsxAttribute */ ? 24 /* jsxAttributeStringLiteralValue */ : 6 /* stringLiteral */;
- }
- else if (tokenKind === 13 /* RegularExpressionLiteral */) {
- // TODO: we should get another classification type for these literals.
- return 6 /* stringLiteral */;
- }
- else if (ts.isTemplateLiteralKind(tokenKind)) {
- // TODO (drosen): we should *also* get another classification type for these literals.
- return 6 /* stringLiteral */;
- }
- else if (tokenKind === 11 /* JsxText */) {
- return 23 /* jsxText */;
- }
- else if (tokenKind === 75 /* Identifier */) {
- if (token) {
- switch (token.parent.kind) {
- case 245 /* ClassDeclaration */:
- if (token.parent.name === token) {
- return 11 /* className */;
- }
- return;
- case 155 /* TypeParameter */:
- if (token.parent.name === token) {
- return 15 /* typeParameterName */;
- }
- return;
- case 246 /* InterfaceDeclaration */:
- if (token.parent.name === token) {
- return 13 /* interfaceName */;
- }
- return;
- case 248 /* EnumDeclaration */:
- if (token.parent.name === token) {
- return 12 /* enumName */;
- }
- return;
- case 249 /* ModuleDeclaration */:
- if (token.parent.name === token) {
- return 14 /* moduleName */;
- }
- return;
- case 156 /* Parameter */:
- if (token.parent.name === token) {
- return ts.isThisIdentifier(token) ? 3 /* keyword */ : 17 /* parameterName */;
- }
- return;
- }
- }
- return 2 /* identifier */;
- }
- }
- function processElement(element) {
- if (!element) {
- return;
- }
- // Ignore nodes that don't intersect the original span to classify.
- if (ts.decodedTextSpanIntersectsWith(spanStart, spanLength, element.pos, element.getFullWidth())) {
- checkForClassificationCancellation(cancellationToken, element.kind);
- for (var _i = 0, _a = element.getChildren(sourceFile); _i < _a.length; _i++) {
- var child = _a[_i];
- if (!tryClassifyNode(child)) {
- // Recurse into our child nodes.
- processElement(child);
- }
- }
- }
- }
- }
- ts.getEncodedSyntacticClassifications = getEncodedSyntacticClassifications;
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var Completions;
- (function (Completions) {
- var StringCompletions;
- (function (StringCompletions) {
- function getStringLiteralCompletions(sourceFile, position, contextToken, checker, options, host, log, preferences) {
- if (ts.isInReferenceComment(sourceFile, position)) {
- var entries = getTripleSlashReferenceCompletion(sourceFile, position, options, host);
- return entries && convertPathCompletions(entries);
- }
- if (ts.isInString(sourceFile, position, contextToken)) {
- if (!contextToken || !ts.isStringLiteralLike(contextToken))
- return undefined;
- var entries = getStringLiteralCompletionEntries(sourceFile, contextToken, position, checker, options, host);
- return convertStringLiteralCompletions(entries, contextToken, sourceFile, checker, log, preferences);
- }
- }
- StringCompletions.getStringLiteralCompletions = getStringLiteralCompletions;
- function convertStringLiteralCompletions(completion, contextToken, sourceFile, checker, log, preferences) {
- if (completion === undefined) {
- return undefined;
- }
- switch (completion.kind) {
- case 0 /* Paths */:
- return convertPathCompletions(completion.paths);
- case 1 /* Properties */: {
- var entries = [];
- Completions.getCompletionEntriesFromSymbols(completion.symbols, entries, contextToken, sourceFile, sourceFile, checker, 99 /* ESNext */, log, 4 /* String */, preferences); // Target will not be used, so arbitrary
- return { isGlobalCompletion: false, isMemberCompletion: true, isNewIdentifierLocation: completion.hasIndexSignature, entries: entries };
- }
- case 2 /* Types */: {
- var entries = completion.types.map(function (type) { return ({
- name: type.value,
- kindModifiers: "" /* none */,
- kind: "string" /* string */,
- sortText: "0",
- replacementSpan: ts.getReplacementSpanForContextToken(contextToken)
- }); });
- return { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: completion.isNewIdentifier, entries: entries };
- }
- default:
- return ts.Debug.assertNever(completion);
- }
- }
- function getStringLiteralCompletionDetails(name, sourceFile, position, contextToken, checker, options, host, cancellationToken) {
- if (!contextToken || !ts.isStringLiteralLike(contextToken))
- return undefined;
- var completions = getStringLiteralCompletionEntries(sourceFile, contextToken, position, checker, options, host);
- return completions && stringLiteralCompletionDetails(name, contextToken, completions, sourceFile, checker, cancellationToken);
- }
- StringCompletions.getStringLiteralCompletionDetails = getStringLiteralCompletionDetails;
- function stringLiteralCompletionDetails(name, location, completion, sourceFile, checker, cancellationToken) {
- switch (completion.kind) {
- case 0 /* Paths */: {
- var match = ts.find(completion.paths, function (p) { return p.name === name; });
- return match && Completions.createCompletionDetails(name, kindModifiersFromExtension(match.extension), match.kind, [ts.textPart(name)]);
- }
- case 1 /* Properties */: {
- var match = ts.find(completion.symbols, function (s) { return s.name === name; });
- return match && Completions.createCompletionDetailsForSymbol(match, checker, sourceFile, location, cancellationToken);
- }
- case 2 /* Types */:
- return ts.find(completion.types, function (t) { return t.value === name; }) ? Completions.createCompletionDetails(name, "" /* none */, "type" /* typeElement */, [ts.textPart(name)]) : undefined;
- default:
- return ts.Debug.assertNever(completion);
- }
- }
- function convertPathCompletions(pathCompletions) {
- var isGlobalCompletion = false; // We don't want the editor to offer any other completions, such as snippets, inside a comment.
- var isNewIdentifierLocation = true; // The user may type in a path that doesn't yet exist, creating a "new identifier" with respect to the collection of identifiers the server is aware of.
- var entries = pathCompletions.map(function (_a) {
- var name = _a.name, kind = _a.kind, span = _a.span, extension = _a.extension;
- return ({ name: name, kind: kind, kindModifiers: kindModifiersFromExtension(extension), sortText: Completions.SortText.LocationPriority, replacementSpan: span });
- });
- return { isGlobalCompletion: isGlobalCompletion, isMemberCompletion: false, isNewIdentifierLocation: isNewIdentifierLocation, entries: entries };
- }
- function kindModifiersFromExtension(extension) {
- switch (extension) {
- case ".d.ts" /* Dts */: return ".d.ts" /* dtsModifier */;
- case ".js" /* Js */: return ".js" /* jsModifier */;
- case ".json" /* Json */: return ".json" /* jsonModifier */;
- case ".jsx" /* Jsx */: return ".jsx" /* jsxModifier */;
- case ".ts" /* Ts */: return ".ts" /* tsModifier */;
- case ".tsx" /* Tsx */: return ".tsx" /* tsxModifier */;
- case ".tsbuildinfo" /* TsBuildInfo */: return ts.Debug.fail("Extension " + ".tsbuildinfo" /* TsBuildInfo */ + " is unsupported.");
- case undefined: return "" /* none */;
- default:
- return ts.Debug.assertNever(extension);
- }
- }
- var StringLiteralCompletionKind;
- (function (StringLiteralCompletionKind) {
- StringLiteralCompletionKind[StringLiteralCompletionKind["Paths"] = 0] = "Paths";
- StringLiteralCompletionKind[StringLiteralCompletionKind["Properties"] = 1] = "Properties";
- StringLiteralCompletionKind[StringLiteralCompletionKind["Types"] = 2] = "Types";
- })(StringLiteralCompletionKind || (StringLiteralCompletionKind = {}));
- function getStringLiteralCompletionEntries(sourceFile, node, position, typeChecker, compilerOptions, host) {
- var parent = node.parent;
- switch (parent.kind) {
- case 187 /* LiteralType */:
- switch (parent.parent.kind) {
- case 169 /* TypeReference */:
- return { kind: 2 /* Types */, types: getStringLiteralTypes(typeChecker.getTypeArgumentConstraint(parent)), isNewIdentifier: false };
- case 185 /* IndexedAccessType */:
- // Get all apparent property names
- // i.e. interface Foo {
- // foo: string;
- // bar: string;
- // }
- // let x: Foo["/*completion position*/"]
- return stringLiteralCompletionsFromProperties(typeChecker.getTypeFromTypeNode(parent.parent.objectType));
- case 188 /* ImportType */:
- return { kind: 0 /* Paths */, paths: getStringLiteralCompletionsFromModuleNames(sourceFile, node, compilerOptions, host, typeChecker) };
- case 178 /* UnionType */: {
- if (!ts.isTypeReferenceNode(parent.parent.parent))
- return undefined;
- var alreadyUsedTypes_1 = getAlreadyUsedTypesInStringLiteralUnion(parent.parent, parent);
- var types = getStringLiteralTypes(typeChecker.getTypeArgumentConstraint(parent.parent)).filter(function (t) { return !ts.contains(alreadyUsedTypes_1, t.value); });
- return { kind: 2 /* Types */, types: types, isNewIdentifier: false };
- }
- default:
- return undefined;
- }
- case 281 /* PropertyAssignment */:
- if (ts.isObjectLiteralExpression(parent.parent) && parent.name === node) {
- // Get quoted name of properties of the object literal expression
- // i.e. interface ConfigFiles {
- // 'jspm:dev': string
- // }
- // let files: ConfigFiles = {
- // '/*completion position*/'
- // }
- //
- // function foo(c: ConfigFiles) {}
- // foo({
- // '/*completion position*/'
- // });
- return stringLiteralCompletionsFromProperties(typeChecker.getContextualType(parent.parent));
- }
- return fromContextualType();
- case 195 /* ElementAccessExpression */: {
- var _a = parent, expression = _a.expression, argumentExpression = _a.argumentExpression;
- if (node === argumentExpression) {
- // Get all names of properties on the expression
- // i.e. interface A {
- // 'prop1': string
- // }
- // let a: A;
- // a['/*completion position*/']
- return stringLiteralCompletionsFromProperties(typeChecker.getTypeAtLocation(expression));
- }
- return undefined;
- }
- case 196 /* CallExpression */:
- case 197 /* NewExpression */:
- if (!ts.isRequireCall(parent, /*checkArgumentIsStringLiteralLike*/ false) && !ts.isImportCall(parent)) {
- var argumentInfo = ts.SignatureHelp.getArgumentInfoForCompletions(node, position, sourceFile);
- // Get string literal completions from specialized signatures of the target
- // i.e. declare function f(a: 'A');
- // f("/*completion position*/")
- return argumentInfo ? getStringLiteralCompletionsFromSignature(argumentInfo, typeChecker) : fromContextualType();
- }
- // falls through (is `require("")` or `import("")`)
- case 254 /* ImportDeclaration */:
- case 260 /* ExportDeclaration */:
- case 265 /* ExternalModuleReference */:
- // Get all known external module names or complete a path to a module
- // i.e. import * as ns from "/*completion position*/";
- // var y = import("/*completion position*/");
- // import x = require("/*completion position*/");
- // var y = require("/*completion position*/");
- // export * from "/*completion position*/";
- return { kind: 0 /* Paths */, paths: getStringLiteralCompletionsFromModuleNames(sourceFile, node, compilerOptions, host, typeChecker) };
- default:
- return fromContextualType();
- }
- function fromContextualType() {
- // Get completion for string literal from string literal type
- // i.e. var x: "hi" | "hello" = "/*completion position*/"
- return { kind: 2 /* Types */, types: getStringLiteralTypes(ts.getContextualTypeFromParent(node, typeChecker)), isNewIdentifier: false };
- }
- }
- function getAlreadyUsedTypesInStringLiteralUnion(union, current) {
- return ts.mapDefined(union.types, function (type) {
- return type !== current && ts.isLiteralTypeNode(type) && ts.isStringLiteral(type.literal) ? type.literal.text : undefined;
- });
- }
- function getStringLiteralCompletionsFromSignature(argumentInfo, checker) {
- var isNewIdentifier = false;
- var uniques = ts.createMap();
- var candidates = [];
- checker.getResolvedSignature(argumentInfo.invocation, candidates, argumentInfo.argumentCount);
- var types = ts.flatMap(candidates, function (candidate) {
- if (!ts.signatureHasRestParameter(candidate) && argumentInfo.argumentCount > candidate.parameters.length)
- return;
- var type = checker.getParameterType(candidate, argumentInfo.argumentIndex);
- isNewIdentifier = isNewIdentifier || !!(type.flags & 4 /* String */);
- return getStringLiteralTypes(type, uniques);
- });
- return { kind: 2 /* Types */, types: types, isNewIdentifier: isNewIdentifier };
- }
- function stringLiteralCompletionsFromProperties(type) {
- return type && {
- kind: 1 /* Properties */,
- symbols: type.getApparentProperties().filter(function (prop) {
- return !ts.isPrivateIdentifierPropertyDeclaration(ts.isTransientSymbol(prop) && prop.syntheticOrigin ? prop.syntheticOrigin.valueDeclaration : prop.valueDeclaration);
- }),
- hasIndexSignature: ts.hasIndexSignature(type)
- };
- }
- function getStringLiteralTypes(type, uniques) {
- if (uniques === void 0) { uniques = ts.createMap(); }
- if (!type)
- return ts.emptyArray;
- type = ts.skipConstraint(type);
- return type.isUnion() ? ts.flatMap(type.types, function (t) { return getStringLiteralTypes(t, uniques); }) :
- type.isStringLiteral() && !(type.flags & 1024 /* EnumLiteral */) && ts.addToSeen(uniques, type.value) ? [type] : ts.emptyArray;
- }
- function nameAndKind(name, kind, extension) {
- return { name: name, kind: kind, extension: extension };
- }
- function directoryResult(name) {
- return nameAndKind(name, "directory" /* directory */, /*extension*/ undefined);
- }
- function addReplacementSpans(text, textStart, names) {
- var span = getDirectoryFragmentTextSpan(text, textStart);
- return names.map(function (_a) {
- var name = _a.name, kind = _a.kind, extension = _a.extension;
- return ({ name: name, kind: kind, extension: extension, span: span });
- });
- }
- function getStringLiteralCompletionsFromModuleNames(sourceFile, node, compilerOptions, host, typeChecker) {
- return addReplacementSpans(node.text, node.getStart(sourceFile) + 1, getStringLiteralCompletionsFromModuleNamesWorker(sourceFile, node, compilerOptions, host, typeChecker));
- }
- function getStringLiteralCompletionsFromModuleNamesWorker(sourceFile, node, compilerOptions, host, typeChecker) {
- var literalValue = ts.normalizeSlashes(node.text);
- var scriptPath = sourceFile.path;
- var scriptDirectory = ts.getDirectoryPath(scriptPath);
- return isPathRelativeToScript(literalValue) || !compilerOptions.baseUrl && (ts.isRootedDiskPath(literalValue) || ts.isUrl(literalValue))
- ? getCompletionEntriesForRelativeModules(literalValue, scriptDirectory, compilerOptions, host, scriptPath)
- : getCompletionEntriesForNonRelativeModules(literalValue, scriptDirectory, compilerOptions, host, typeChecker);
- }
- function getExtensionOptions(compilerOptions, includeExtensions) {
- if (includeExtensions === void 0) { includeExtensions = false; }
- return { extensions: getSupportedExtensionsForModuleResolution(compilerOptions), includeExtensions: includeExtensions };
- }
- function getCompletionEntriesForRelativeModules(literalValue, scriptDirectory, compilerOptions, host, scriptPath) {
- var extensionOptions = getExtensionOptions(compilerOptions);
- if (compilerOptions.rootDirs) {
- return getCompletionEntriesForDirectoryFragmentWithRootDirs(compilerOptions.rootDirs, literalValue, scriptDirectory, extensionOptions, compilerOptions, host, scriptPath);
- }
- else {
- return getCompletionEntriesForDirectoryFragment(literalValue, scriptDirectory, extensionOptions, host, scriptPath);
- }
- }
- function getSupportedExtensionsForModuleResolution(compilerOptions) {
- var extensions = ts.getSupportedExtensions(compilerOptions);
- return compilerOptions.resolveJsonModule && ts.getEmitModuleResolutionKind(compilerOptions) === ts.ModuleResolutionKind.NodeJs ?
- extensions.concat(".json" /* Json */) :
- extensions;
- }
- /**
- * Takes a script path and returns paths for all potential folders that could be merged with its
- * containing folder via the "rootDirs" compiler option
- */
- function getBaseDirectoriesFromRootDirs(rootDirs, basePath, scriptDirectory, ignoreCase) {
- // Make all paths absolute/normalized if they are not already
- rootDirs = rootDirs.map(function (rootDirectory) { return ts.normalizePath(ts.isRootedDiskPath(rootDirectory) ? rootDirectory : ts.combinePaths(basePath, rootDirectory)); });
- // Determine the path to the directory containing the script relative to the root directory it is contained within
- var relativeDirectory = ts.firstDefined(rootDirs, function (rootDirectory) {
- return ts.containsPath(rootDirectory, scriptDirectory, basePath, ignoreCase) ? scriptDirectory.substr(rootDirectory.length) : undefined;
- }); // TODO: GH#18217
- // Now find a path for each potential directory that is to be merged with the one containing the script
- return ts.deduplicate(__spreadArrays(rootDirs.map(function (rootDirectory) { return ts.combinePaths(rootDirectory, relativeDirectory); }), [scriptDirectory]), ts.equateStringsCaseSensitive, ts.compareStringsCaseSensitive);
- }
- function getCompletionEntriesForDirectoryFragmentWithRootDirs(rootDirs, fragment, scriptDirectory, extensionOptions, compilerOptions, host, exclude) {
- var basePath = compilerOptions.project || host.getCurrentDirectory();
- var ignoreCase = !(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames());
- var baseDirectories = getBaseDirectoriesFromRootDirs(rootDirs, basePath, scriptDirectory, ignoreCase);
- return ts.flatMap(baseDirectories, function (baseDirectory) { return getCompletionEntriesForDirectoryFragment(fragment, baseDirectory, extensionOptions, host, exclude); });
- }
- /**
- * Given a path ending at a directory, gets the completions for the path, and filters for those entries containing the basename.
- */
- function getCompletionEntriesForDirectoryFragment(fragment, scriptPath, _a, host, exclude, result) {
- var extensions = _a.extensions, includeExtensions = _a.includeExtensions;
- if (result === void 0) { result = []; }
- if (fragment === undefined) {
- fragment = "";
- }
- fragment = ts.normalizeSlashes(fragment);
- /**
- * Remove the basename from the path. Note that we don't use the basename to filter completions;
- * the client is responsible for refining completions.
- */
- if (!ts.hasTrailingDirectorySeparator(fragment)) {
- fragment = ts.getDirectoryPath(fragment);
- }
- if (fragment === "") {
- fragment = "." + ts.directorySeparator;
- }
- fragment = ts.ensureTrailingDirectorySeparator(fragment);
- // const absolutePath = normalizeAndPreserveTrailingSlash(isRootedDiskPath(fragment) ? fragment : combinePaths(scriptPath, fragment)); // TODO(rbuckton): should use resolvePaths
- var absolutePath = ts.resolvePath(scriptPath, fragment);
- var baseDirectory = ts.hasTrailingDirectorySeparator(absolutePath) ? absolutePath : ts.getDirectoryPath(absolutePath);
- var ignoreCase = !(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames());
- if (!ts.tryDirectoryExists(host, baseDirectory))
- return result;
- // Enumerate the available files if possible
- var files = ts.tryReadDirectory(host, baseDirectory, extensions, /*exclude*/ undefined, /*include*/ ["./*"]);
- if (files) {
- /**
- * Multiple file entries might map to the same truncated name once we remove extensions
- * (happens iff includeExtensions === false)so we use a set-like data structure. Eg:
- *
- * both foo.ts and foo.tsx become foo
- */
- var foundFiles = ts.createMap(); // maps file to its extension
- for (var _i = 0, files_1 = files; _i < files_1.length; _i++) {
- var filePath = files_1[_i];
- filePath = ts.normalizePath(filePath);
- if (exclude && ts.comparePaths(filePath, exclude, scriptPath, ignoreCase) === 0 /* EqualTo */) {
- continue;
- }
- var foundFileName = includeExtensions || ts.fileExtensionIs(filePath, ".json" /* Json */) ? ts.getBaseFileName(filePath) : ts.removeFileExtension(ts.getBaseFileName(filePath));
- foundFiles.set(foundFileName, ts.tryGetExtensionFromPath(filePath));
- }
- foundFiles.forEach(function (ext, foundFile) {
- result.push(nameAndKind(foundFile, "script" /* scriptElement */, ext));
- });
- }
- // If possible, get folder completion as well
- var directories = ts.tryGetDirectories(host, baseDirectory);
- if (directories) {
- for (var _b = 0, directories_1 = directories; _b < directories_1.length; _b++) {
- var directory = directories_1[_b];
- var directoryName = ts.getBaseFileName(ts.normalizePath(directory));
- if (directoryName !== "@types") {
- result.push(directoryResult(directoryName));
- }
- }
- }
- // check for a version redirect
- var packageJsonPath = ts.findPackageJson(baseDirectory, host);
- if (packageJsonPath) {
- var packageJson = ts.readJson(packageJsonPath, host);
- var typesVersions = packageJson.typesVersions;
- if (typeof typesVersions === "object") {
- var versionResult = ts.getPackageJsonTypesVersionsPaths(typesVersions);
- var versionPaths = versionResult && versionResult.paths;
- var rest = absolutePath.slice(ts.ensureTrailingDirectorySeparator(baseDirectory).length);
- if (versionPaths) {
- addCompletionEntriesFromPaths(result, rest, baseDirectory, extensions, versionPaths, host);
- }
- }
- }
- return result;
- }
- function addCompletionEntriesFromPaths(result, fragment, baseDirectory, fileExtensions, paths, host) {
- for (var path in paths) {
- if (!ts.hasProperty(paths, path))
- continue;
- var patterns = paths[path];
- if (patterns) {
- var _loop_1 = function (name, kind, extension) {
- // Path mappings may provide a duplicate way to get to something we've already added, so don't add again.
- if (!result.some(function (entry) { return entry.name === name; })) {
- result.push(nameAndKind(name, kind, extension));
- }
- };
- for (var _i = 0, _a = getCompletionsForPathMapping(path, patterns, fragment, baseDirectory, fileExtensions, host); _i < _a.length; _i++) {
- var _b = _a[_i], name = _b.name, kind = _b.kind, extension = _b.extension;
- _loop_1(name, kind, extension);
- }
- }
- }
- }
- /**
- * Check all of the declared modules and those in node modules. Possible sources of modules:
- * Modules that are found by the type checker
- * Modules found relative to "baseUrl" compliler options (including patterns from "paths" compiler option)
- * Modules from node_modules (i.e. those listed in package.json)
- * This includes all files that are found in node_modules/moduleName/ with acceptable file extensions
- */
- function getCompletionEntriesForNonRelativeModules(fragment, scriptPath, compilerOptions, host, typeChecker) {
- var baseUrl = compilerOptions.baseUrl, paths = compilerOptions.paths;
- var result = [];
- var extensionOptions = getExtensionOptions(compilerOptions);
- if (baseUrl) {
- var projectDir = compilerOptions.project || host.getCurrentDirectory();
- var absolute = ts.normalizePath(ts.combinePaths(projectDir, baseUrl));
- getCompletionEntriesForDirectoryFragment(fragment, absolute, extensionOptions, host, /*exclude*/ undefined, result);
- if (paths) {
- addCompletionEntriesFromPaths(result, fragment, absolute, extensionOptions.extensions, paths, host);
- }
- }
- var fragmentDirectory = getFragmentDirectory(fragment);
- for (var _i = 0, _a = getAmbientModuleCompletions(fragment, fragmentDirectory, typeChecker); _i < _a.length; _i++) {
- var ambientName = _a[_i];
- result.push(nameAndKind(ambientName, "external module name" /* externalModuleName */, /*extension*/ undefined));
- }
- getCompletionEntriesFromTypings(host, compilerOptions, scriptPath, fragmentDirectory, extensionOptions, result);
- if (ts.getEmitModuleResolutionKind(compilerOptions) === ts.ModuleResolutionKind.NodeJs) {
- // If looking for a global package name, don't just include everything in `node_modules` because that includes dependencies' own dependencies.
- // (But do if we didn't find anything, e.g. 'package.json' missing.)
- var foundGlobal = false;
- if (fragmentDirectory === undefined) {
- var _loop_2 = function (moduleName) {
- if (!result.some(function (entry) { return entry.name === moduleName; })) {
- foundGlobal = true;
- result.push(nameAndKind(moduleName, "external module name" /* externalModuleName */, /*extension*/ undefined));
- }
- };
- for (var _b = 0, _c = enumerateNodeModulesVisibleToScript(host, scriptPath); _b < _c.length; _b++) {
- var moduleName = _c[_b];
- _loop_2(moduleName);
- }
- }
- if (!foundGlobal) {
- ts.forEachAncestorDirectory(scriptPath, function (ancestor) {
- var nodeModules = ts.combinePaths(ancestor, "node_modules");
- if (ts.tryDirectoryExists(host, nodeModules)) {
- getCompletionEntriesForDirectoryFragment(fragment, nodeModules, extensionOptions, host, /*exclude*/ undefined, result);
- }
- });
- }
- }
- return result;
- }
- function getFragmentDirectory(fragment) {
- return containsSlash(fragment) ? ts.hasTrailingDirectorySeparator(fragment) ? fragment : ts.getDirectoryPath(fragment) : undefined;
- }
- function getCompletionsForPathMapping(path, patterns, fragment, baseUrl, fileExtensions, host) {
- if (!ts.endsWith(path, "*")) {
- // For a path mapping "foo": ["/x/y/z.ts"], add "foo" itself as a completion.
- return !ts.stringContains(path, "*") ? justPathMappingName(path) : ts.emptyArray;
- }
- var pathPrefix = path.slice(0, path.length - 1);
- var remainingFragment = ts.tryRemovePrefix(fragment, pathPrefix);
- return remainingFragment === undefined ? justPathMappingName(pathPrefix) : ts.flatMap(patterns, function (pattern) {
- return getModulesForPathsPattern(remainingFragment, baseUrl, pattern, fileExtensions, host);
- });
- function justPathMappingName(name) {
- return ts.startsWith(name, fragment) ? [directoryResult(name)] : ts.emptyArray;
- }
- }
- function getModulesForPathsPattern(fragment, baseUrl, pattern, fileExtensions, host) {
- if (!host.readDirectory) {
- return undefined;
- }
- var parsed = ts.hasZeroOrOneAsteriskCharacter(pattern) ? ts.tryParsePattern(pattern) : undefined;
- if (!parsed) {
- return undefined;
- }
- // The prefix has two effective parts: the directory path and the base component after the filepath that is not a
- // full directory component. For example: directory/path/of/prefix/base*
- var normalizedPrefix = ts.resolvePath(parsed.prefix);
- var normalizedPrefixDirectory = ts.hasTrailingDirectorySeparator(parsed.prefix) ? normalizedPrefix : ts.getDirectoryPath(normalizedPrefix);
- var normalizedPrefixBase = ts.hasTrailingDirectorySeparator(parsed.prefix) ? "" : ts.getBaseFileName(normalizedPrefix);
- var fragmentHasPath = containsSlash(fragment);
- var fragmentDirectory = fragmentHasPath ? ts.hasTrailingDirectorySeparator(fragment) ? fragment : ts.getDirectoryPath(fragment) : undefined;
- // Try and expand the prefix to include any path from the fragment so that we can limit the readDirectory call
- var expandedPrefixDirectory = fragmentHasPath ? ts.combinePaths(normalizedPrefixDirectory, normalizedPrefixBase + fragmentDirectory) : normalizedPrefixDirectory;
- var normalizedSuffix = ts.normalizePath(parsed.suffix);
- // Need to normalize after combining: If we combinePaths("a", "../b"), we want "b" and not "a/../b".
- var baseDirectory = ts.normalizePath(ts.combinePaths(baseUrl, expandedPrefixDirectory));
- var completePrefix = fragmentHasPath ? baseDirectory : ts.ensureTrailingDirectorySeparator(baseDirectory) + normalizedPrefixBase;
- // If we have a suffix, then we need to read the directory all the way down. We could create a glob
- // that encodes the suffix, but we would have to escape the character "?" which readDirectory
- // doesn't support. For now, this is safer but slower
- var includeGlob = normalizedSuffix ? "**/*" : "./*";
- var matches = ts.mapDefined(ts.tryReadDirectory(host, baseDirectory, fileExtensions, /*exclude*/ undefined, [includeGlob]), function (match) {
- var extension = ts.tryGetExtensionFromPath(match);
- var name = trimPrefixAndSuffix(match);
- return name === undefined ? undefined : nameAndKind(ts.removeFileExtension(name), "script" /* scriptElement */, extension);
- });
- var directories = ts.mapDefined(ts.tryGetDirectories(host, baseDirectory).map(function (d) { return ts.combinePaths(baseDirectory, d); }), function (dir) {
- var name = trimPrefixAndSuffix(dir);
- return name === undefined ? undefined : directoryResult(name);
- });
- return __spreadArrays(matches, directories);
- function trimPrefixAndSuffix(path) {
- var inner = withoutStartAndEnd(ts.normalizePath(path), completePrefix, normalizedSuffix);
- return inner === undefined ? undefined : removeLeadingDirectorySeparator(inner);
- }
- }
- function withoutStartAndEnd(s, start, end) {
- return ts.startsWith(s, start) && ts.endsWith(s, end) ? s.slice(start.length, s.length - end.length) : undefined;
- }
- function removeLeadingDirectorySeparator(path) {
- return path[0] === ts.directorySeparator ? path.slice(1) : path;
- }
- function getAmbientModuleCompletions(fragment, fragmentDirectory, checker) {
- // Get modules that the type checker picked up
- var ambientModules = checker.getAmbientModules().map(function (sym) { return ts.stripQuotes(sym.name); });
- var nonRelativeModuleNames = ambientModules.filter(function (moduleName) { return ts.startsWith(moduleName, fragment); });
- // Nested modules of the form "module-name/sub" need to be adjusted to only return the string
- // after the last '/' that appears in the fragment because that's where the replacement span
- // starts
- if (fragmentDirectory !== undefined) {
- var moduleNameWithSeparator_1 = ts.ensureTrailingDirectorySeparator(fragmentDirectory);
- return nonRelativeModuleNames.map(function (nonRelativeModuleName) { return ts.removePrefix(nonRelativeModuleName, moduleNameWithSeparator_1); });
- }
- return nonRelativeModuleNames;
- }
- function getTripleSlashReferenceCompletion(sourceFile, position, compilerOptions, host) {
- var token = ts.getTokenAtPosition(sourceFile, position);
- var commentRanges = ts.getLeadingCommentRanges(sourceFile.text, token.pos);
- var range = commentRanges && ts.find(commentRanges, function (commentRange) { return position >= commentRange.pos && position <= commentRange.end; });
- if (!range) {
- return undefined;
- }
- var text = sourceFile.text.slice(range.pos, position);
- var match = tripleSlashDirectiveFragmentRegex.exec(text);
- if (!match) {
- return undefined;
- }
- var prefix = match[1], kind = match[2], toComplete = match[3];
- var scriptPath = ts.getDirectoryPath(sourceFile.path);
- var names = kind === "path" ? getCompletionEntriesForDirectoryFragment(toComplete, scriptPath, getExtensionOptions(compilerOptions, /*includeExtensions*/ true), host, sourceFile.path)
- : kind === "types" ? getCompletionEntriesFromTypings(host, compilerOptions, scriptPath, getFragmentDirectory(toComplete), getExtensionOptions(compilerOptions))
- : ts.Debug.fail();
- return addReplacementSpans(toComplete, range.pos + prefix.length, names);
- }
- function getCompletionEntriesFromTypings(host, options, scriptPath, fragmentDirectory, extensionOptions, result) {
- if (result === void 0) { result = []; }
- // Check for typings specified in compiler options
- var seen = ts.createMap();
- var typeRoots = ts.tryAndIgnoreErrors(function () { return ts.getEffectiveTypeRoots(options, host); }) || ts.emptyArray;
- for (var _i = 0, typeRoots_1 = typeRoots; _i < typeRoots_1.length; _i++) {
- var root = typeRoots_1[_i];
- getCompletionEntriesFromDirectories(root);
- }
- // Also get all @types typings installed in visible node_modules directories
- for (var _a = 0, _b = ts.findPackageJsons(scriptPath, host); _a < _b.length; _a++) {
- var packageJson = _b[_a];
- var typesDir = ts.combinePaths(ts.getDirectoryPath(packageJson), "node_modules/@types");
- getCompletionEntriesFromDirectories(typesDir);
- }
- return result;
- function getCompletionEntriesFromDirectories(directory) {
- if (!ts.tryDirectoryExists(host, directory))
- return;
- for (var _i = 0, _a = ts.tryGetDirectories(host, directory); _i < _a.length; _i++) {
- var typeDirectoryName = _a[_i];
- var packageName = ts.unmangleScopedPackageName(typeDirectoryName);
- if (options.types && !ts.contains(options.types, packageName))
- continue;
- if (fragmentDirectory === undefined) {
- if (!seen.has(packageName)) {
- result.push(nameAndKind(packageName, "external module name" /* externalModuleName */, /*extension*/ undefined));
- seen.set(packageName, true);
- }
- }
- else {
- var baseDirectory = ts.combinePaths(directory, typeDirectoryName);
- var remainingFragment = ts.tryRemoveDirectoryPrefix(fragmentDirectory, packageName, ts.hostGetCanonicalFileName(host));
- if (remainingFragment !== undefined) {
- getCompletionEntriesForDirectoryFragment(remainingFragment, baseDirectory, extensionOptions, host, /*exclude*/ undefined, result);
- }
- }
- }
- }
- }
- function enumerateNodeModulesVisibleToScript(host, scriptPath) {
- if (!host.readFile || !host.fileExists)
- return ts.emptyArray;
- var result = [];
- for (var _i = 0, _a = ts.findPackageJsons(scriptPath, host); _i < _a.length; _i++) {
- var packageJson = _a[_i];
- var contents = ts.readJson(packageJson, host); // Cast to assert that readFile is defined
- // Provide completions for all non @types dependencies
- for (var _b = 0, nodeModulesDependencyKeys_1 = nodeModulesDependencyKeys; _b < nodeModulesDependencyKeys_1.length; _b++) {
- var key = nodeModulesDependencyKeys_1[_b];
- var dependencies = contents[key];
- if (!dependencies)
- continue;
- for (var dep in dependencies) {
- if (dependencies.hasOwnProperty(dep) && !ts.startsWith(dep, "@types/")) {
- result.push(dep);
- }
- }
- }
- }
- return result;
- }
- // Replace everything after the last directory separator that appears
- function getDirectoryFragmentTextSpan(text, textStart) {
- var index = Math.max(text.lastIndexOf(ts.directorySeparator), text.lastIndexOf("\\"));
- var offset = index !== -1 ? index + 1 : 0;
- // If the range is an identifier, span is unnecessary.
- var length = text.length - offset;
- return length === 0 || ts.isIdentifierText(text.substr(offset, length), 99 /* ESNext */) ? undefined : ts.createTextSpan(textStart + offset, length);
- }
- // Returns true if the path is explicitly relative to the script (i.e. relative to . or ..)
- function isPathRelativeToScript(path) {
- if (path && path.length >= 2 && path.charCodeAt(0) === 46 /* dot */) {
- var slashIndex = path.length >= 3 && path.charCodeAt(1) === 46 /* dot */ ? 2 : 1;
- var slashCharCode = path.charCodeAt(slashIndex);
- return slashCharCode === 47 /* slash */ || slashCharCode === 92 /* backslash */;
- }
- return false;
- }
- /**
- * Matches a triple slash reference directive with an incomplete string literal for its path. Used
- * to determine if the caret is currently within the string literal and capture the literal fragment
- * for completions.
- * For example, this matches
- *
- * /// /*1*/
- // The completion list at "1" will contain "div>" with type any
- // And at `