/*1*/>
- // The completion list at "1" will contain "div" with type any
- var tagName = location.parent.parent.openingElement.tagName;
- return { isGlobalCompletion: false, isMemberCompletion: true, isNewIdentifierLocation: false,
- entries: [{
- name: tagName.getFullText(),
- kind: "class" /* classElement */,
- kindModifiers: undefined,
- sortText: "0",
- }] };
- }
- var entries = [];
- if (ts.isSourceFileJavaScript(sourceFile)) {
- var uniqueNames = getCompletionEntriesFromSymbols(symbols, entries, location, sourceFile, typeChecker, compilerOptions.target, log, completionKind, includeInsertTextCompletions, propertyAccessToConvert, isJsxInitializer, recommendedCompletion, symbolToOriginInfoMap);
- getJavaScriptCompletionEntries(sourceFile, location.pos, uniqueNames, compilerOptions.target, entries);
- }
- else {
- if ((!symbols || symbols.length === 0) && keywordFilters === 0 /* None */) {
- return undefined;
- }
- getCompletionEntriesFromSymbols(symbols, entries, location, sourceFile, typeChecker, compilerOptions.target, log, completionKind, includeInsertTextCompletions, propertyAccessToConvert, isJsxInitializer, recommendedCompletion, symbolToOriginInfoMap);
- }
- // TODO add filter for keyword based on type/value/namespace and also location
- // Add all keywords if
- // - this is not a member completion list (all the keywords)
- // - other filters are enabled in required scenario so add those keywords
- var isMemberCompletion = isMemberCompletionKind(completionKind);
- if (keywordFilters !== 0 /* None */ || !isMemberCompletion) {
- ts.addRange(entries, getKeywordCompletions(keywordFilters));
- }
- return { isGlobalCompletion: isInSnippetScope, isMemberCompletion: isMemberCompletion, isNewIdentifierLocation: isNewIdentifierLocation, entries: entries };
- }
- function isMemberCompletionKind(kind) {
- switch (kind) {
- case 0 /* ObjectPropertyDeclaration */:
- case 3 /* MemberLike */:
- case 2 /* PropertyAccess */:
- return true;
- default:
- return false;
- }
- }
- function getJavaScriptCompletionEntries(sourceFile, position, uniqueNames, target, entries) {
- ts.getNameTable(sourceFile).forEach(function (pos, name) {
- // Skip identifiers produced only from the current location
- if (pos === position) {
- return;
- }
- var realName = ts.unescapeLeadingUnderscores(name);
- if (ts.addToSeen(uniqueNames, realName) && ts.isIdentifierText(realName, target) && !ts.isStringANonContextualKeyword(realName)) {
- entries.push({
- name: realName,
- kind: "warning" /* warning */,
- kindModifiers: "",
- sortText: "1"
- });
- }
- });
- }
- function createCompletionEntry(symbol, location, sourceFile, typeChecker, target, kind, origin, recommendedCompletion, propertyAccessToConvert, isJsxInitializer, includeInsertTextCompletions) {
- var info = getCompletionEntryDisplayNameForSymbol(symbol, target, origin, kind);
- if (!info) {
- return undefined;
- }
- var name = info.name, needsConvertPropertyAccess = info.needsConvertPropertyAccess;
- var insertText;
- var replacementSpan;
- if (includeInsertTextCompletions) {
- if (origin && origin.type === "this-type") {
- insertText = needsConvertPropertyAccess ? "this[" + quote(name) + "]" : "this." + name;
- }
- // We should only have needsConvertPropertyAccess if there's a property access to convert. But see #21790.
- // Somehow there was a global with a non-identifier name. Hopefully someone will complain about getting a "foo bar" global completion and provide a repro.
- else if (needsConvertPropertyAccess && propertyAccessToConvert) {
- insertText = "[" + quote(name) + "]";
- var dot = ts.findChildOfKind(propertyAccessToConvert, 23 /* DotToken */, sourceFile);
- // If the text after the '.' starts with this name, write over it. Else, add new text.
- var end = ts.startsWith(name, propertyAccessToConvert.name.text) ? propertyAccessToConvert.name.end : dot.end;
- replacementSpan = ts.createTextSpanFromBounds(dot.getStart(sourceFile), end);
- }
- if (isJsxInitializer) {
- if (insertText === undefined)
- insertText = name;
- insertText = "{" + insertText + "}";
- if (typeof isJsxInitializer !== "boolean") {
- replacementSpan = ts.createTextSpanFromNode(isJsxInitializer, sourceFile);
- }
- }
- }
- if (insertText !== undefined && !includeInsertTextCompletions) {
- return undefined;
- }
- // TODO(drosen): Right now we just permit *all* semantic meanings when calling
- // 'getSymbolKind' which is permissible given that it is backwards compatible; but
- // really we should consider passing the meaning for the node so that we don't report
- // that a suggestion for a value is an interface. We COULD also just do what
- // 'getSymbolModifiers' does, which is to use the first declaration.
- // Use a 'sortText' of 0' so that all symbol completion entries come before any other
- // entries (like JavaScript identifier entries).
- return {
- name: name,
- kind: ts.SymbolDisplay.getSymbolKind(typeChecker, symbol, location),
- kindModifiers: ts.SymbolDisplay.getSymbolModifiers(symbol),
- sortText: "0",
- source: getSourceFromOrigin(origin),
- hasAction: trueOrUndefined(!!origin && origin.type === "export"),
- isRecommended: trueOrUndefined(isRecommendedCompletionMatch(symbol, recommendedCompletion, typeChecker)),
- insertText: insertText,
- replacementSpan: replacementSpan,
- };
- }
- function quote(text) {
- // TODO: GH#20619 Use configured quote style
- return JSON.stringify(text);
- }
- function isRecommendedCompletionMatch(localSymbol, recommendedCompletion, checker) {
- return localSymbol === recommendedCompletion ||
- !!(localSymbol.flags & 1048576 /* ExportValue */) && checker.getExportSymbolOfSymbol(localSymbol) === recommendedCompletion;
- }
- function trueOrUndefined(b) {
- return b ? true : undefined;
- }
- function getSourceFromOrigin(origin) {
- return origin && origin.type === "export" ? ts.stripQuotes(origin.moduleSymbol.name) : undefined;
- }
- function getCompletionEntriesFromSymbols(symbols, entries, location, sourceFile, typeChecker, target, log, kind, includeInsertTextCompletions, propertyAccessToConvert, isJsxInitializer, recommendedCompletion, symbolToOriginInfoMap) {
- var start = ts.timestamp();
- // Tracks unique names.
- // We don't set this for global variables or completions from external module exports, because we can have multiple of those.
- // Based on the order we add things we will always see locals first, then globals, then module exports.
- // So adding a completion for a local will prevent us from adding completions for external module exports sharing the same name.
- var uniques = ts.createMap();
- for (var _i = 0, symbols_4 = symbols; _i < symbols_4.length; _i++) {
- var symbol = symbols_4[_i];
- var origin = symbolToOriginInfoMap ? symbolToOriginInfoMap[ts.getSymbolId(symbol)] : undefined;
- var entry = createCompletionEntry(symbol, location, sourceFile, typeChecker, target, kind, origin, recommendedCompletion, propertyAccessToConvert, isJsxInitializer, includeInsertTextCompletions);
- if (!entry) {
- continue;
- }
- var name = entry.name;
- if (uniques.has(name)) {
- continue;
- }
- // Latter case tests whether this is a global variable.
- if (!origin && !(symbol.parent === undefined && !ts.some(symbol.declarations, function (d) { return d.getSourceFile() === location.getSourceFile(); }))) {
- uniques.set(name, true);
- }
- entries.push(entry);
- }
- log("getCompletionsAtPosition: getCompletionEntriesFromSymbols: " + (ts.timestamp() - start));
- return uniques;
- }
- function getLabelCompletionAtPosition(node) {
- var entries = getLabelStatementCompletions(node);
- if (entries.length) {
- return { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, entries: entries };
- }
- }
- function getLabelStatementCompletions(node) {
- var entries = [];
- var uniques = ts.createMap();
- var current = node;
- while (current) {
- if (ts.isFunctionLike(current)) {
- break;
- }
- if (ts.isLabeledStatement(current)) {
- var name = current.label.text;
- if (!uniques.has(name)) {
- uniques.set(name, true);
- entries.push({
- name: name,
- kindModifiers: "" /* none */,
- kind: "label" /* label */,
- sortText: "0"
- });
- }
- }
- current = current.parent;
- }
- return entries;
- }
- 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) {
- switch (node.parent.kind) {
- case 177 /* LiteralType */:
- switch (node.parent.parent.kind) {
- case 161 /* TypeReference */:
- return { kind: 2 /* Types */, types: getStringLiteralTypes(typeChecker.getTypeArgumentConstraint(node.parent), typeChecker) };
- case 175 /* IndexedAccessType */:
- // Get all apparent property names
- // i.e. interface Foo {
- // foo: string;
- // bar: string;
- // }
- // let x: Foo["/*completion position*/"]
- return { kind: 1 /* Properties */, symbols: typeChecker.getTypeFromTypeNode(node.parent.parent.objectType).getApparentProperties() };
- default:
- return undefined;
- }
- case 268 /* PropertyAssignment */:
- if (ts.isObjectLiteralExpression(node.parent.parent) && node.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*/'
- // });
- var type = typeChecker.getContextualType(node.parent.parent);
- return type && { kind: 1 /* Properties */, symbols: type.getApparentProperties() };
- }
- return fromContextualType();
- case 184 /* ElementAccessExpression */: {
- var _a = node.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 { kind: 1 /* Properties */, symbols: typeChecker.getTypeAtLocation(expression).getApparentProperties() };
- }
- return undefined;
- }
- case 185 /* CallExpression */:
- case 186 /* NewExpression */:
- if (!ts.isRequireCall(node.parent, /*checkArgumentIsStringLiteral*/ false) && !ts.isImportCall(node.parent)) {
- var argumentInfo_1 = ts.SignatureHelp.getImmediatelyContainingArgumentInfo(node, position, sourceFile);
- // Get string literal completions from specialized signatures of the target
- // i.e. declare function f(a: 'A');
- // f("/*completion position*/")
- if (argumentInfo_1) {
- var candidates = [];
- typeChecker.getResolvedSignature(argumentInfo_1.invocation, candidates, argumentInfo_1.argumentCount);
- var uniques_1 = ts.createMap();
- return { kind: 2 /* Types */, types: ts.flatMap(candidates, function (candidate) { return getStringLiteralTypes(typeChecker.getParameterType(candidate, argumentInfo_1.argumentIndex), typeChecker, uniques_1); }) };
- }
- return fromContextualType();
- }
- // falls through (is `require("")` or `import("")`)
- case 242 /* ImportDeclaration */:
- case 248 /* ExportDeclaration */:
- case 252 /* 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: Completions.PathCompletions.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(getContextualTypeFromParent(node, typeChecker), typeChecker) };
- }
- }
- function getStringLiteralTypes(type, typeChecker, uniques) {
- if (uniques === void 0) { uniques = ts.createMap(); }
- if (type && type.flags & 32768 /* TypeParameter */) {
- type = type.getConstraint();
- }
- return type && type.flags & 131072 /* Union */
- ? ts.flatMap(type.types, function (t) { return getStringLiteralTypes(t, typeChecker, uniques); })
- : type && type.flags & 32 /* StringLiteral */ && !(type.flags & 256 /* EnumLiteral */) && ts.addToSeen(uniques, type.value)
- ? [type]
- : ts.emptyArray;
- }
- function getSymbolCompletionFromEntryId(typeChecker, log, compilerOptions, sourceFile, position, _a, allSourceFiles) {
- var name = _a.name, source = _a.source;
- var completionData = getCompletionData(typeChecker, log, sourceFile, position, allSourceFiles, { includeExternalModuleExports: true, includeInsertTextCompletions: true }, compilerOptions.target);
- if (!completionData) {
- return { type: "none" };
- }
- if (completionData.kind !== 0 /* Data */) {
- return { type: "request", request: completionData };
- }
- var symbols = completionData.symbols, location = completionData.location, completionKind = completionData.completionKind, symbolToOriginInfoMap = completionData.symbolToOriginInfoMap, previousToken = completionData.previousToken, isJsxInitializer = completionData.isJsxInitializer;
- // Find the symbol with the matching entry name.
- // We don't need to perform character checks here because we're only comparing the
- // name against 'entryName' (which is known to be good), not building a new
- // completion entry.
- return ts.firstDefined(symbols, function (symbol) {
- var origin = symbolToOriginInfoMap[ts.getSymbolId(symbol)];
- var info = getCompletionEntryDisplayNameForSymbol(symbol, compilerOptions.target, origin, completionKind);
- return info && info.name === name && getSourceFromOrigin(origin) === source ? { type: "symbol", symbol: symbol, location: location, symbolToOriginInfoMap: symbolToOriginInfoMap, previousToken: previousToken, isJsxInitializer: isJsxInitializer } : undefined;
- }) || { type: "none" };
- }
- function getSymbolName(symbol, origin, target) {
- return origin && origin.type === "export" && origin.isDefaultExport && symbol.escapedName === "default" /* Default */
- // Name of "export default foo;" is "foo". Name of "export default 0" is the filename converted to camelCase.
- ? ts.firstDefined(symbol.declarations, function (d) { return ts.isExportAssignment(d) && ts.isIdentifier(d.expression) ? d.expression.text : undefined; })
- || ts.codefix.moduleSymbolToValidIdentifier(origin.moduleSymbol, target)
- : symbol.name;
- }
- function getCompletionEntryDetails(program, log, compilerOptions, sourceFile, position, entryId, allSourceFiles, host, formatContext, getCanonicalFileName) {
- var typeChecker = program.getTypeChecker();
- var name = entryId.name;
- // Compute all the completion symbols again.
- var symbolCompletion = getSymbolCompletionFromEntryId(typeChecker, log, compilerOptions, sourceFile, position, entryId, allSourceFiles);
- switch (symbolCompletion.type) {
- case "request": {
- var request = symbolCompletion.request;
- switch (request.kind) {
- case 1 /* JsDocTagName */:
- return ts.JsDoc.getJSDocTagNameCompletionDetails(name);
- case 2 /* JsDocTag */:
- return ts.JsDoc.getJSDocTagCompletionDetails(name);
- case 3 /* JsDocParameterName */:
- return ts.JsDoc.getJSDocParameterNameCompletionDetails(name);
- default:
- return ts.Debug.assertNever(request);
- }
- }
- case "symbol": {
- var symbol = symbolCompletion.symbol, location = symbolCompletion.location, symbolToOriginInfoMap = symbolCompletion.symbolToOriginInfoMap, previousToken = symbolCompletion.previousToken;
- var _a = getCompletionEntryCodeActionsAndSourceDisplay(symbolToOriginInfoMap, symbol, program, typeChecker, host, compilerOptions, sourceFile, previousToken, formatContext, getCanonicalFileName, allSourceFiles), codeActions = _a.codeActions, sourceDisplay = _a.sourceDisplay;
- var kindModifiers = ts.SymbolDisplay.getSymbolModifiers(symbol);
- var _b = ts.SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker, symbol, sourceFile, location, location, 7 /* All */), displayParts = _b.displayParts, documentation = _b.documentation, symbolKind = _b.symbolKind, tags = _b.tags;
- return { name: name, kindModifiers: kindModifiers, kind: symbolKind, displayParts: displayParts, documentation: documentation, tags: tags, codeActions: codeActions, source: sourceDisplay };
- }
- case "none": {
- // Didn't find a symbol with this name. See if we can find a keyword instead.
- if (allKeywordsCompletions().some(function (c) { return c.name === name; })) {
- return {
- name: name,
- kind: "keyword" /* keyword */,
- kindModifiers: "" /* none */,
- displayParts: [ts.displayPart(name, ts.SymbolDisplayPartKind.keyword)],
- documentation: undefined,
- tags: undefined,
- codeActions: undefined,
- source: undefined,
- };
- }
- return undefined;
- }
- }
- }
- Completions.getCompletionEntryDetails = getCompletionEntryDetails;
- function getCompletionEntryCodeActionsAndSourceDisplay(symbolToOriginInfoMap, symbol, program, checker, host, compilerOptions, sourceFile, previousToken, formatContext, getCanonicalFileName, allSourceFiles) {
- var symbolOriginInfo = symbolToOriginInfoMap[ts.getSymbolId(symbol)];
- return symbolOriginInfo && symbolOriginInfo.type === "export"
- ? getCodeActionsAndSourceDisplayForImport(symbolOriginInfo, symbol, program, checker, host, compilerOptions, sourceFile, previousToken, formatContext, getCanonicalFileName, allSourceFiles)
- : { codeActions: undefined, sourceDisplay: undefined };
- }
- function getCodeActionsAndSourceDisplayForImport(symbolOriginInfo, symbol, program, checker, host, compilerOptions, sourceFile, previousToken, formatContext, getCanonicalFileName, allSourceFiles) {
- var moduleSymbol = symbolOriginInfo.moduleSymbol;
- var exportedSymbol = ts.skipAlias(symbol.exportSymbol || symbol, checker);
- var _a = ts.codefix.getImportCompletionAction(exportedSymbol, moduleSymbol, sourceFile, getSymbolName(symbol, symbolOriginInfo, compilerOptions.target), host, program, checker, compilerOptions, allSourceFiles, formatContext, getCanonicalFileName, previousToken), moduleSpecifier = _a.moduleSpecifier, codeAction = _a.codeAction;
- return { sourceDisplay: [ts.textPart(moduleSpecifier)], codeActions: [codeAction] };
- }
- function getCompletionEntrySymbol(typeChecker, log, compilerOptions, sourceFile, position, entryId, allSourceFiles) {
- var completion = getSymbolCompletionFromEntryId(typeChecker, log, compilerOptions, sourceFile, position, entryId, allSourceFiles);
- return completion.type === "symbol" ? completion.symbol : undefined;
- }
- Completions.getCompletionEntrySymbol = getCompletionEntrySymbol;
- var CompletionDataKind;
- (function (CompletionDataKind) {
- CompletionDataKind[CompletionDataKind["Data"] = 0] = "Data";
- CompletionDataKind[CompletionDataKind["JsDocTagName"] = 1] = "JsDocTagName";
- CompletionDataKind[CompletionDataKind["JsDocTag"] = 2] = "JsDocTag";
- CompletionDataKind[CompletionDataKind["JsDocParameterName"] = 3] = "JsDocParameterName";
- })(CompletionDataKind || (CompletionDataKind = {}));
- var CompletionKind;
- (function (CompletionKind) {
- CompletionKind[CompletionKind["ObjectPropertyDeclaration"] = 0] = "ObjectPropertyDeclaration";
- CompletionKind[CompletionKind["Global"] = 1] = "Global";
- CompletionKind[CompletionKind["PropertyAccess"] = 2] = "PropertyAccess";
- CompletionKind[CompletionKind["MemberLike"] = 3] = "MemberLike";
- CompletionKind[CompletionKind["String"] = 4] = "String";
- CompletionKind[CompletionKind["None"] = 5] = "None";
- })(CompletionKind || (CompletionKind = {}));
- function getRecommendedCompletion(currentToken, position, sourceFile, checker) {
- var ty = getContextualType(currentToken, position, sourceFile, checker);
- var symbol = ty && ty.symbol;
- // Don't include make a recommended completion for an abstract class
- return symbol && (symbol.flags & 384 /* Enum */ || symbol.flags & 32 /* Class */ && !ts.isAbstractConstructorSymbol(symbol))
- ? getFirstSymbolInChain(symbol, currentToken, checker)
- : undefined;
- }
- function getContextualType(currentToken, position, sourceFile, checker) {
- var parent = currentToken.parent;
- switch (currentToken.kind) {
- case 71 /* Identifier */:
- return getContextualTypeFromParent(currentToken, checker);
- case 58 /* EqualsToken */:
- switch (parent.kind) {
- case 230 /* VariableDeclaration */:
- return checker.getContextualType(parent.initializer);
- case 198 /* BinaryExpression */:
- return checker.getTypeAtLocation(parent.left);
- case 260 /* JsxAttribute */:
- return checker.getContextualTypeForJsxAttribute(parent);
- default:
- return undefined;
- }
- case 94 /* NewKeyword */:
- return checker.getContextualType(parent);
- case 73 /* CaseKeyword */:
- return getSwitchedType(ts.cast(parent, ts.isCaseClause), checker);
- case 17 /* OpenBraceToken */:
- return ts.isJsxExpression(parent) && parent.parent.kind !== 253 /* JsxElement */ ? checker.getContextualTypeForJsxAttribute(parent.parent) : undefined;
- default:
- var argInfo = ts.SignatureHelp.getImmediatelyContainingArgumentInfo(currentToken, position, sourceFile);
- return argInfo
- // At `,`, treat this as the next argument after the comma.
- ? checker.getContextualTypeForArgumentAtIndex(argInfo.invocation, argInfo.argumentIndex + (currentToken.kind === 26 /* CommaToken */ ? 1 : 0))
- : isEqualityOperatorKind(currentToken.kind) && ts.isBinaryExpression(parent) && isEqualityOperatorKind(parent.operatorToken.kind)
- // completion at `x ===/**/` should be for the right side
- ? checker.getTypeAtLocation(parent.left)
- : checker.getContextualType(currentToken);
- }
- }
- function getContextualTypeFromParent(node, checker) {
- var parent = node.parent;
- switch (parent.kind) {
- case 186 /* NewExpression */:
- return checker.getContextualType(parent);
- case 198 /* 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 264 /* CaseClause */:
- return parent.expression === node ? getSwitchedType(parent, checker) : undefined;
- default:
- return checker.getContextualType(node);
- }
- }
- function getSwitchedType(caseClause, checker) {
- return checker.getTypeAtLocation(caseClause.parent.parent.expression);
- }
- function getFirstSymbolInChain(symbol, enclosingDeclaration, checker) {
- var chain = checker.getAccessibleSymbolChain(symbol, enclosingDeclaration, /*meaning*/ 67108863 /* All */, /*useOnlyExternalAliasing*/ false);
- if (chain)
- return ts.first(chain);
- return symbol.parent && (isModuleSymbol(symbol.parent) ? symbol : getFirstSymbolInChain(symbol.parent, enclosingDeclaration, checker));
- }
- function isModuleSymbol(symbol) {
- return symbol.declarations.some(function (d) { return d.kind === 272 /* SourceFile */; });
- }
- function getCompletionData(typeChecker, log, sourceFile, position, allSourceFiles, options, target) {
- var start = ts.timestamp();
- var currentToken = ts.getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false); // TODO: GH#15853
- // We will check for jsdoc comments with insideComment and getJsDocTagAtPosition. (TODO: that seems rather inefficient to check the same thing so many times.)
- log("getCompletionData: Get current token: " + (ts.timestamp() - start));
- start = ts.timestamp();
- // Completion not allowed inside comments, bail out if this is the case
- var insideComment = ts.isInComment(sourceFile, position, currentToken);
- log("getCompletionData: Is inside comment: " + (ts.timestamp() - start));
- var insideJsDocTagTypeExpression = false;
- var isInSnippetScope = false;
- if (insideComment) {
- if (ts.hasDocComment(sourceFile, position)) {
- if (sourceFile.text.charCodeAt(position - 1) === 64 /* at */) {
- // The current position is next to the '@' sign, when no tag name being provided yet.
- // Provide a full list of tag names
- return { kind: 1 /* JsDocTagName */ };
- }
- else {
- // When completion is requested without "@", we will have check to make sure that
- // there are no comments prefix the request position. We will only allow "*" and space.
- // e.g
- // /** |c| /*
- //
- // /**
- // |c|
- // */
- //
- // /**
- // * |c|
- // */
- //
- // /**
- // * |c|
- // */
- var lineStart = ts.getLineStartPositionForPosition(position, sourceFile);
- if (!(sourceFile.text.substring(lineStart, position).match(/[^\*|\s|(/\*\*)]/))) {
- return { kind: 2 /* JsDocTag */ };
- }
- }
- }
- // Completion should work inside certain JsDoc tags. For example:
- // /** @type {number | string} */
- // Completion should work in the brackets
- var tag = getJsDocTagAtPosition(currentToken, position);
- if (tag) {
- if (tag.tagName.pos <= position && position <= tag.tagName.end) {
- return { kind: 1 /* JsDocTagName */ };
- }
- if (isTagWithTypeExpression(tag) && tag.typeExpression && tag.typeExpression.kind === 274 /* JSDocTypeExpression */) {
- currentToken = ts.getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ true);
- if (!currentToken ||
- (!ts.isDeclarationName(currentToken) &&
- (currentToken.parent.kind !== 292 /* JSDocPropertyTag */ ||
- currentToken.parent.name !== currentToken))) {
- // Use as type location if inside tag's type expression
- insideJsDocTagTypeExpression = isCurrentlyEditingNode(tag.typeExpression);
- }
- }
- if (ts.isJSDocParameterTag(tag) && (ts.nodeIsMissing(tag.name) || tag.name.pos <= position && position <= tag.name.end)) {
- return { kind: 3 /* JsDocParameterName */, tag: tag };
- }
- }
- if (!insideJsDocTagTypeExpression) {
- // Proceed if the current position is in jsDoc tag expression; otherwise it is a normal
- // comment or the plain text part of a jsDoc comment, so no completion should be available
- log("Returning an empty list because completion was inside a regular comment or plain text part of a JsDoc comment.");
- return undefined;
- }
- }
- start = ts.timestamp();
- var previousToken = ts.findPrecedingToken(position, sourceFile, /*startNode*/ undefined, insideJsDocTagTypeExpression);
- log("getCompletionData: Get previous token 1: " + (ts.timestamp() - start));
- // The decision to provide completion depends on the contextToken, which is determined through the previousToken.
- // Note: 'previousToken' (and thus 'contextToken') can be undefined if we are the beginning of the file
- var contextToken = previousToken;
- // Check if the caret is at the end of an identifier; this is a partial identifier that we want to complete: e.g. a.toS|
- // Skip this partial identifier and adjust the contextToken to the token that precedes it.
- if (contextToken && position <= contextToken.end && ts.isWord(contextToken.kind)) {
- var start_4 = ts.timestamp();
- contextToken = ts.findPrecedingToken(contextToken.getFullStart(), sourceFile, /*startNode*/ undefined, insideJsDocTagTypeExpression);
- log("getCompletionData: Get previous token 2: " + (ts.timestamp() - start_4));
- }
- // Find the node where completion is requested on.
- // Also determine whether we are trying to complete with members of that node
- // or attributes of a JSX tag.
- var node = currentToken;
- var propertyAccessToConvert;
- var isRightOfDot = false;
- var isRightOfOpenTag = false;
- var isStartingCloseTag = false;
- var isJsxInitializer = false;
- var location = ts.getTouchingPropertyName(sourceFile, position, insideJsDocTagTypeExpression); // TODO: GH#15853
- if (contextToken) {
- // Bail out if this is a known invalid completion location
- if (isCompletionListBlocker(contextToken)) {
- log("Returning an empty list because completion was requested in an invalid position.");
- return undefined;
- }
- var parent = contextToken.parent;
- if (contextToken.kind === 23 /* DotToken */) {
- isRightOfDot = true;
- switch (parent.kind) {
- case 183 /* PropertyAccessExpression */:
- propertyAccessToConvert = parent;
- node = propertyAccessToConvert.expression;
- break;
- case 145 /* QualifiedName */:
- node = parent.left;
- break;
- default:
- // There is nothing that precedes the dot, so this likely just a stray character
- // or leading into a '...' token. Just bail out instead.
- return undefined;
- }
- }
- else if (sourceFile.languageVariant === 1 /* JSX */) {
- //
- // If the tagname is a property access expression, we will then walk up to the top most of property access expression.
- // Then, try to get a JSX container and its associated attributes type.
- if (parent && parent.kind === 183 /* PropertyAccessExpression */) {
- contextToken = parent;
- parent = parent.parent;
- }
- // Fix location
- if (currentToken.parent === location) {
- switch (currentToken.kind) {
- case 29 /* GreaterThanToken */:
- if (currentToken.parent.kind === 253 /* JsxElement */ || currentToken.parent.kind === 255 /* JsxOpeningElement */) {
- location = currentToken;
- }
- break;
- case 41 /* SlashToken */:
- if (currentToken.parent.kind === 254 /* JsxSelfClosingElement */) {
- location = currentToken;
- }
- break;
- }
- }
- switch (parent.kind) {
- case 256 /* JsxClosingElement */:
- if (contextToken.kind === 41 /* SlashToken */) {
- isStartingCloseTag = true;
- location = contextToken;
- }
- break;
- case 198 /* BinaryExpression */:
- if (!(parent.left.flags & 32768 /* ThisNodeHasError */)) {
- // It has a left-hand side, so we're not in an opening JSX tag.
- break;
- }
- // falls through
- case 254 /* JsxSelfClosingElement */:
- case 253 /* JsxElement */:
- case 255 /* JsxOpeningElement */:
- if (contextToken.kind === 27 /* LessThanToken */) {
- isRightOfOpenTag = true;
- location = contextToken;
- }
- break;
- case 260 /* JsxAttribute */:
- switch (previousToken.kind) {
- case 58 /* EqualsToken */:
- isJsxInitializer = true;
- break;
- case 71 /* Identifier */:
- // For `
x$
- //
- // the cursor is outside of both the 'x' and the arrow function 'xyz => x',
- // so 'xyz' is not returned in our results.
- //
- // We define 'adjustedPosition' so that we may appropriately account for
- // being at the end of an identifier. The intention is that if requesting completion
- // at the end of an identifier, it should be effectively equivalent to requesting completion
- // anywhere inside/at the beginning of the identifier. So in the previous case, the
- // 'adjustedPosition' will work as if requesting completion in the following:
- //
- // xyz => $x
- //
- // If previousToken !== contextToken, then
- // - 'contextToken' was adjusted to the token prior to 'previousToken'
- // because we were at the end of an identifier.
- // - 'previousToken' is defined.
- var adjustedPosition = previousToken !== contextToken ?
- previousToken.getStart() :
- position;
- var scopeNode = getScopeNode(contextToken, adjustedPosition, sourceFile) || sourceFile;
- isInSnippetScope = isSnippetScope(scopeNode);
- var symbolMeanings = 67901928 /* Type */ | 67216319 /* Value */ | 1920 /* Namespace */ | 2097152 /* Alias */;
- symbols = ts.Debug.assertEachDefined(typeChecker.getSymbolsInScope(scopeNode, symbolMeanings), "getSymbolsInScope() should all be defined");
- // Need to insert 'this.' before properties of `this` type, so only do that if `includeInsertTextCompletions`
- if (options.includeInsertTextCompletions && scopeNode.kind !== 272 /* SourceFile */) {
- var thisType = typeChecker.tryGetThisTypeAt(scopeNode);
- if (thisType) {
- for (var _i = 0, _a = getPropertiesForCompletion(thisType, typeChecker, /*isForAccess*/ true); _i < _a.length; _i++) {
- var symbol = _a[_i];
- symbolToOriginInfoMap[ts.getSymbolId(symbol)] = { type: "this-type" };
- symbols.push(symbol);
- }
- }
- }
- // Don't suggest import completions for a commonjs-only module
- if (options.includeExternalModuleExports && !(sourceFile.commonJsModuleIndicator && !sourceFile.externalModuleIndicator)) {
- getSymbolsFromOtherSourceFileExports(symbols, previousToken && ts.isIdentifier(previousToken) ? previousToken.text : "", target);
- }
- filterGlobalCompletion(symbols);
- return true;
- }
- function isSnippetScope(scopeNode) {
- switch (scopeNode.kind) {
- case 272 /* SourceFile */:
- case 200 /* TemplateExpression */:
- case 263 /* JsxExpression */:
- case 211 /* Block */:
- return true;
- default:
- return ts.isStatement(scopeNode);
- }
- }
- function filterGlobalCompletion(symbols) {
- var isTypeOnlyCompletion = insideJsDocTagTypeExpression || !isContextTokenValueLocation(contextToken) && (ts.isPartOfTypeNode(location) || isContextTokenTypeLocation(contextToken));
- var allowTypes = isTypeOnlyCompletion || !isContextTokenValueLocation(contextToken) && ts.isPossiblyTypeArgumentPosition(contextToken, sourceFile);
- if (isTypeOnlyCompletion)
- keywordFilters = 4 /* TypeKeywords */;
- ts.filterMutate(symbols, function (symbol) {
- if (!ts.isSourceFile(location)) {
- // export = /**/ here we want to get all meanings, so any symbol is ok
- if (ts.isExportAssignment(location.parent)) {
- return true;
- }
- symbol = ts.skipAlias(symbol, typeChecker);
- // import m = /**/ <-- It can only access namespace (if typing import = x. this would get member symbols and not namespace)
- if (ts.isInRightSideOfInternalImportEqualsDeclaration(location)) {
- return !!(symbol.flags & 1920 /* Namespace */);
- }
- if (allowTypes) {
- // Its a type, but you can reach it by namespace.type as well
- var symbolAllowedAsType = symbolCanBeReferencedAtTypeLocation(symbol);
- if (symbolAllowedAsType || isTypeOnlyCompletion) {
- return symbolAllowedAsType;
- }
- }
- }
- // expressions are value space (which includes the value namespaces)
- return !!(ts.getCombinedLocalAndExportSymbolFlags(symbol) & 67216319 /* Value */);
- });
- }
- function isContextTokenValueLocation(contextToken) {
- return contextToken &&
- contextToken.kind === 103 /* TypeOfKeyword */ &&
- (contextToken.parent.kind === 164 /* TypeQuery */ || ts.isTypeOfExpression(contextToken.parent));
- }
- function isContextTokenTypeLocation(contextToken) {
- if (contextToken) {
- var parentKind = contextToken.parent.kind;
- switch (contextToken.kind) {
- case 56 /* ColonToken */:
- return parentKind === 151 /* PropertyDeclaration */ ||
- parentKind === 150 /* PropertySignature */ ||
- parentKind === 148 /* Parameter */ ||
- parentKind === 230 /* VariableDeclaration */ ||
- ts.isFunctionLikeKind(parentKind);
- case 58 /* EqualsToken */:
- return parentKind === 235 /* TypeAliasDeclaration */;
- case 118 /* AsKeyword */:
- return parentKind === 206 /* AsExpression */;
- }
- }
- return false;
- }
- function symbolCanBeReferencedAtTypeLocation(symbol) {
- symbol = symbol.exportSymbol || symbol;
- // This is an alias, follow what it aliases
- symbol = ts.skipAlias(symbol, typeChecker);
- if (symbol.flags & 67901928 /* Type */) {
- return true;
- }
- if (symbol.flags & 1536 /* Module */) {
- var exportedSymbols = typeChecker.getExportsOfModule(symbol);
- // If the exported symbols contains type,
- // symbol can be referenced at locations where type is allowed
- return ts.forEach(exportedSymbols, symbolCanBeReferencedAtTypeLocation);
- }
- }
- function getSymbolsFromOtherSourceFileExports(symbols, tokenText, target) {
- var tokenTextLowerCase = tokenText.toLowerCase();
- ts.codefix.forEachExternalModuleToImportFrom(typeChecker, sourceFile, allSourceFiles, function (moduleSymbol) {
- for (var _i = 0, _a = typeChecker.getExportsOfModule(moduleSymbol); _i < _a.length; _i++) {
- var symbol = _a[_i];
- // Don't add a completion for a re-export, only for the original.
- // The actual import fix might end up coming from a re-export -- we don't compute that until getting completion details.
- // This is just to avoid adding duplicate completion entries.
- //
- // If `symbol.parent !== ...`, this comes from an `export * from "foo"` re-export. Those don't create new symbols.
- // If `some(...)`, this comes from an `export { foo } from "foo"` re-export, which creates a new symbol (thus isn't caught by the first check).
- if (typeChecker.getMergedSymbol(symbol.parent) !== typeChecker.resolveExternalModuleSymbol(moduleSymbol)
- || ts.some(symbol.declarations, function (d) { return ts.isExportSpecifier(d) && !!d.parent.parent.moduleSpecifier; })) {
- continue;
- }
- var isDefaultExport = symbol.name === "default" /* Default */;
- if (isDefaultExport) {
- symbol = ts.getLocalSymbolForExportDefault(symbol) || symbol;
- }
- var origin = { type: "export", moduleSymbol: moduleSymbol, isDefaultExport: isDefaultExport };
- if (stringContainsCharactersInOrder(getSymbolName(symbol, origin, target).toLowerCase(), tokenTextLowerCase)) {
- symbols.push(symbol);
- symbolToOriginInfoMap[ts.getSymbolId(symbol)] = origin;
- }
- }
- });
- }
- /**
- * True if you could remove some characters in `a` to get `b`.
- * E.g., true for "abcdef" and "bdf".
- * But not true for "abcdef" and "dbf".
- */
- function stringContainsCharactersInOrder(str, characters) {
- if (characters.length === 0) {
- return true;
- }
- var characterIndex = 0;
- for (var strIndex = 0; strIndex < str.length; strIndex++) {
- if (str.charCodeAt(strIndex) === characters.charCodeAt(characterIndex)) {
- characterIndex++;
- if (characterIndex === characters.length) {
- return true;
- }
- }
- }
- // Did not find all characters
- return false;
- }
- /**
- * Finds the first node that "embraces" the position, so that one may
- * accurately aggregate locals from the closest containing scope.
- */
- function getScopeNode(initialToken, position, sourceFile) {
- var scope = initialToken;
- while (scope && !ts.positionBelongsToNode(scope, position, sourceFile)) {
- scope = scope.parent;
- }
- return scope;
- }
- function isCompletionListBlocker(contextToken) {
- var start = ts.timestamp();
- var result = isInStringOrRegularExpressionOrTemplateLiteral(contextToken) ||
- isSolelyIdentifierDefinitionLocation(contextToken) ||
- isDotOfNumericLiteral(contextToken) ||
- isInJsxText(contextToken);
- log("getCompletionsAtPosition: isCompletionListBlocker: " + (ts.timestamp() - start));
- return result;
- }
- function isInJsxText(contextToken) {
- if (contextToken.kind === 10 /* JsxText */) {
- return true;
- }
- if (contextToken.kind === 29 /* GreaterThanToken */ && contextToken.parent) {
- if (contextToken.parent.kind === 255 /* JsxOpeningElement */) {
- return true;
- }
- if (contextToken.parent.kind === 256 /* JsxClosingElement */ || contextToken.parent.kind === 254 /* JsxSelfClosingElement */) {
- return contextToken.parent.parent && contextToken.parent.parent.kind === 253 /* JsxElement */;
- }
- }
- return false;
- }
- function isNewIdentifierDefinitionLocation(previousToken) {
- if (previousToken) {
- var containingNodeKind = previousToken.parent.kind;
- switch (previousToken.kind) {
- case 26 /* CommaToken */:
- return containingNodeKind === 185 /* CallExpression */ // func( a, |
- || containingNodeKind === 154 /* Constructor */ // constructor( a, | /* public, protected, private keywords are allowed here, so show completion */
- || containingNodeKind === 186 /* NewExpression */ // new C(a, |
- || containingNodeKind === 181 /* ArrayLiteralExpression */ // [a, |
- || containingNodeKind === 198 /* BinaryExpression */ // const x = (a, |
- || containingNodeKind === 162 /* FunctionType */; // var x: (s: string, list|
- case 19 /* OpenParenToken */:
- return containingNodeKind === 185 /* CallExpression */ // func( |
- || containingNodeKind === 154 /* Constructor */ // constructor( |
- || containingNodeKind === 186 /* NewExpression */ // new C(a|
- || containingNodeKind === 189 /* ParenthesizedExpression */ // const x = (a|
- || containingNodeKind === 172 /* ParenthesizedType */; // function F(pred: (a| /* this can become an arrow function, where 'a' is the argument */
- case 21 /* OpenBracketToken */:
- return containingNodeKind === 181 /* ArrayLiteralExpression */ // [ |
- || containingNodeKind === 159 /* IndexSignature */ // [ | : string ]
- || containingNodeKind === 146 /* ComputedPropertyName */; // [ | /* this can become an index signature */
- case 129 /* ModuleKeyword */: // module |
- case 130 /* NamespaceKeyword */: // namespace |
- return true;
- case 23 /* DotToken */:
- return containingNodeKind === 237 /* ModuleDeclaration */; // module A.|
- case 17 /* OpenBraceToken */:
- return containingNodeKind === 233 /* ClassDeclaration */; // class A{ |
- case 58 /* EqualsToken */:
- return containingNodeKind === 230 /* VariableDeclaration */ // const x = a|
- || containingNodeKind === 198 /* BinaryExpression */; // x = a|
- case 14 /* TemplateHead */:
- return containingNodeKind === 200 /* TemplateExpression */; // `aa ${|
- case 15 /* TemplateMiddle */:
- return containingNodeKind === 209 /* TemplateSpan */; // `aa ${10} dd ${|
- case 114 /* PublicKeyword */:
- case 112 /* PrivateKeyword */:
- case 113 /* ProtectedKeyword */:
- return containingNodeKind === 151 /* PropertyDeclaration */; // class A{ public |
- }
- // Previous token may have been a keyword that was converted to an identifier.
- switch (previousToken.getText()) {
- case "public":
- case "protected":
- case "private":
- return true;
- }
- }
- return false;
- }
- function isInStringOrRegularExpressionOrTemplateLiteral(contextToken) {
- if (contextToken.kind === 9 /* StringLiteral */
- || contextToken.kind === 12 /* RegularExpressionLiteral */
- || ts.isTemplateLiteralKind(contextToken.kind)) {
- var start_5 = contextToken.getStart();
- var end = contextToken.getEnd();
- // To be "in" one of these literals, the position has to be:
- // 1. entirely within the token text.
- // 2. at the end position of an unterminated token.
- // 3. at the end of a regular expression (due to trailing flags like '/foo/g').
- if (start_5 < position && position < end) {
- return true;
- }
- if (position === end) {
- return !!contextToken.isUnterminated
- || contextToken.kind === 12 /* RegularExpressionLiteral */;
- }
- }
- return false;
- }
- /**
- * Aggregates relevant symbols for completion in object literals and object binding patterns.
- * Relevant symbols are stored in the captured 'symbols' variable.
- *
- * @returns true if 'symbols' was successfully populated; false otherwise.
- */
- function tryGetObjectLikeCompletionSymbols(objectLikeContainer) {
- // We're looking up possible property names from contextual/inferred/declared type.
- completionKind = 0 /* ObjectPropertyDeclaration */;
- var typeMembers;
- var existingMembers;
- if (objectLikeContainer.kind === 182 /* ObjectLiteralExpression */) {
- // We are completing on contextual types, but may also include properties
- // other than those within the declared type.
- isNewIdentifierLocation = true;
- var typeForObject = typeChecker.getContextualType(objectLikeContainer);
- if (!typeForObject)
- return false;
- typeMembers = getPropertiesForCompletion(typeForObject, typeChecker, /*isForAccess*/ false);
- existingMembers = objectLikeContainer.properties;
- }
- else {
- ts.Debug.assert(objectLikeContainer.kind === 178 /* ObjectBindingPattern */);
- // We are *only* completing on properties from the type being destructured.
- isNewIdentifierLocation = false;
- var rootDeclaration = ts.getRootDeclaration(objectLikeContainer.parent);
- if (!ts.isVariableLike(rootDeclaration))
- return ts.Debug.fail("Root declaration is not variable-like.");
- // We don't want to complete using the type acquired by the shape
- // of the binding pattern; we are only interested in types acquired
- // through type declaration or inference.
- // Also proceed if rootDeclaration is a parameter and if its containing function expression/arrow function is contextually typed -
- // type of parameter will flow in from the contextual type of the function
- var canGetType = ts.hasInitializer(rootDeclaration) || ts.hasType(rootDeclaration) || rootDeclaration.parent.parent.kind === 220 /* ForOfStatement */;
- if (!canGetType && rootDeclaration.kind === 148 /* Parameter */) {
- if (ts.isExpression(rootDeclaration.parent)) {
- canGetType = !!typeChecker.getContextualType(rootDeclaration.parent);
- }
- else if (rootDeclaration.parent.kind === 153 /* MethodDeclaration */ || rootDeclaration.parent.kind === 156 /* SetAccessor */) {
- canGetType = ts.isExpression(rootDeclaration.parent.parent) && !!typeChecker.getContextualType(rootDeclaration.parent.parent);
- }
- }
- if (canGetType) {
- var typeForObject = typeChecker.getTypeAtLocation(objectLikeContainer);
- if (!typeForObject)
- return false;
- // In a binding pattern, get only known properties. Everywhere else we will get all possible properties.
- typeMembers = typeChecker.getPropertiesOfType(typeForObject).filter(function (symbol) { return !(ts.getDeclarationModifierFlagsFromSymbol(symbol) & 24 /* NonPublicAccessibilityModifier */); });
- existingMembers = objectLikeContainer.elements;
- }
- }
- if (typeMembers && typeMembers.length > 0) {
- // Add filtered items to the completion list
- symbols = filterObjectMembersList(typeMembers, ts.Debug.assertDefined(existingMembers));
- }
- return true;
- }
- /**
- * Aggregates relevant symbols for completion in import clauses and export clauses
- * whose declarations have a module specifier; for instance, symbols will be aggregated for
- *
- * import { | } from "moduleName";
- * export { a as foo, | } from "moduleName";
- *
- * but not for
- *
- * export { | };
- *
- * Relevant symbols are stored in the captured 'symbols' variable.
- *
- * @returns true if 'symbols' was successfully populated; false otherwise.
- */
- function tryGetImportOrExportClauseCompletionSymbols(namedImportsOrExports) {
- var declarationKind = namedImportsOrExports.kind === 245 /* NamedImports */ ?
- 242 /* ImportDeclaration */ :
- 248 /* ExportDeclaration */;
- var importOrExportDeclaration = ts.getAncestor(namedImportsOrExports, declarationKind);
- var moduleSpecifier = importOrExportDeclaration.moduleSpecifier;
- if (!moduleSpecifier) {
- return false;
- }
- completionKind = 3 /* MemberLike */;
- isNewIdentifierLocation = false;
- var moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(moduleSpecifier);
- if (!moduleSpecifierSymbol) {
- symbols = ts.emptyArray;
- return true;
- }
- var exports = typeChecker.getExportsAndPropertiesOfModule(moduleSpecifierSymbol);
- symbols = filterNamedImportOrExportCompletionItems(exports, namedImportsOrExports.elements);
- return true;
- }
- /**
- * Aggregates relevant symbols for completion in class declaration
- * Relevant symbols are stored in the captured 'symbols' variable.
- */
- function getGetClassLikeCompletionSymbols(classLikeDeclaration) {
- // We're looking up possible property names from parent type.
- completionKind = 3 /* MemberLike */;
- // Declaring new property/method/accessor
- isNewIdentifierLocation = true;
- // Has keywords for class elements
- keywordFilters = 1 /* ClassElementKeywords */;
- var baseTypeNode = ts.getClassExtendsHeritageClauseElement(classLikeDeclaration);
- var implementsTypeNodes = ts.getClassImplementsHeritageClauseElements(classLikeDeclaration);
- if (baseTypeNode || implementsTypeNodes) {
- var classElement = contextToken.parent;
- var classElementModifierFlags = ts.isClassElement(classElement) && ts.getModifierFlags(classElement);
- // If this is context token is not something we are editing now, consider if this would lead to be modifier
- if (contextToken.kind === 71 /* Identifier */ && !isCurrentlyEditingNode(contextToken)) {
- switch (contextToken.getText()) {
- case "private":
- classElementModifierFlags = classElementModifierFlags | 8 /* Private */;
- break;
- case "static":
- classElementModifierFlags = classElementModifierFlags | 32 /* Static */;
- break;
- }
- }
- // No member list for private methods
- if (!(classElementModifierFlags & 8 /* Private */)) {
- var baseClassTypeToGetPropertiesFrom = void 0;
- if (baseTypeNode) {
- baseClassTypeToGetPropertiesFrom = typeChecker.getTypeAtLocation(baseTypeNode);
- if (classElementModifierFlags & 32 /* Static */) {
- // Use static class to get property symbols from
- baseClassTypeToGetPropertiesFrom = typeChecker.getTypeOfSymbolAtLocation(baseClassTypeToGetPropertiesFrom.symbol, classLikeDeclaration);
- }
- }
- var implementedInterfaceTypePropertySymbols = (classElementModifierFlags & 32 /* Static */) ?
- ts.emptyArray :
- ts.flatMap(implementsTypeNodes || ts.emptyArray, function (typeNode) { return typeChecker.getPropertiesOfType(typeChecker.getTypeAtLocation(typeNode)); });
- // List of property symbols of base type that are not private and already implemented
- symbols = filterClassMembersList(baseClassTypeToGetPropertiesFrom ?
- typeChecker.getPropertiesOfType(baseClassTypeToGetPropertiesFrom) :
- ts.emptyArray, implementedInterfaceTypePropertySymbols, classLikeDeclaration.members, classElementModifierFlags);
- }
- }
- }
- /**
- * Returns the immediate owning object literal or binding pattern of a context token,
- * on the condition that one exists and that the context implies completion should be given.
- */
- function tryGetObjectLikeCompletionContainer(contextToken) {
- if (contextToken) {
- switch (contextToken.kind) {
- case 17 /* OpenBraceToken */: // const x = { |
- case 26 /* CommaToken */: // const x = { a: 0, |
- var parent = contextToken.parent;
- if (ts.isObjectLiteralExpression(parent) || ts.isObjectBindingPattern(parent)) {
- return parent;
- }
- break;
- }
- }
- return undefined;
- }
- /**
- * Returns the containing list of named imports or exports of a context token,
- * on the condition that one exists and that the context implies completion should be given.
- */
- function tryGetNamedImportsOrExportsForCompletion(contextToken) {
- if (contextToken) {
- switch (contextToken.kind) {
- case 17 /* OpenBraceToken */: // import { |
- case 26 /* CommaToken */: // import { a as 0, |
- switch (contextToken.parent.kind) {
- case 245 /* NamedImports */:
- case 249 /* NamedExports */:
- return contextToken.parent;
- }
- }
- }
- return undefined;
- }
- function isFromClassElementDeclaration(node) {
- return node.parent && ts.isClassElement(node.parent) && ts.isClassLike(node.parent.parent);
- }
- function isParameterOfConstructorDeclaration(node) {
- return ts.isParameter(node) && ts.isConstructorDeclaration(node.parent);
- }
- function isConstructorParameterCompletion(node) {
- return node.parent &&
- isParameterOfConstructorDeclaration(node.parent) &&
- (isConstructorParameterCompletionKeyword(node.kind) || ts.isDeclarationName(node));
- }
- /**
- * Returns the immediate owning class declaration of a context token,
- * on the condition that one exists and that the context implies completion should be given.
- */
- function tryGetClassLikeCompletionContainer(contextToken) {
- if (contextToken) {
- switch (contextToken.kind) {
- case 17 /* OpenBraceToken */: // class c { |
- if (ts.isClassLike(contextToken.parent)) {
- return contextToken.parent;
- }
- break;
- // class c {getValue(): number, | }
- case 26 /* CommaToken */:
- if (ts.isClassLike(contextToken.parent)) {
- return contextToken.parent;
- }
- break;
- // class c {getValue(): number; | }
- case 25 /* SemicolonToken */:
- // class c { method() { } | }
- case 18 /* CloseBraceToken */:
- if (ts.isClassLike(location)) {
- return location;
- }
- // class c { method() { } b| }
- if (isFromClassElementDeclaration(location) &&
- location.parent.name === location) {
- return location.parent.parent;
- }
- break;
- default:
- if (isFromClassElementDeclaration(contextToken) &&
- (isClassMemberCompletionKeyword(contextToken.kind) ||
- isClassMemberCompletionKeywordText(contextToken.getText()))) {
- return contextToken.parent.parent;
- }
- }
- }
- // class c { method() { } | method2() { } }
- if (location && location.kind === 293 /* SyntaxList */ && ts.isClassLike(location.parent)) {
- return location.parent;
- }
- return undefined;
- }
- /**
- * Returns the immediate owning class declaration of a context token,
- * on the condition that one exists and that the context implies completion should be given.
- */
- function tryGetConstructorLikeCompletionContainer(contextToken) {
- if (contextToken) {
- switch (contextToken.kind) {
- case 19 /* OpenParenToken */:
- case 26 /* CommaToken */:
- return ts.isConstructorDeclaration(contextToken.parent) && contextToken.parent;
- default:
- if (isConstructorParameterCompletion(contextToken)) {
- return contextToken.parent.parent;
- }
- }
- }
- return undefined;
- }
- function tryGetFunctionLikeBodyCompletionContainer(contextToken) {
- if (contextToken) {
- var prev_1;
- var container = ts.findAncestor(contextToken.parent, function (node) {
- if (ts.isClassLike(node)) {
- return "quit";
- }
- if (ts.isFunctionLikeDeclaration(node) && prev_1 === node.body) {
- return true;
- }
- prev_1 = node;
- });
- return container && container;
- }
- }
- function tryGetContainingJsxElement(contextToken) {
- if (contextToken) {
- var parent = contextToken.parent;
- switch (contextToken.kind) {
- case 28 /* LessThanSlashToken */:
- case 41 /* SlashToken */:
- case 71 /* Identifier */:
- case 183 /* PropertyAccessExpression */:
- case 261 /* JsxAttributes */:
- case 260 /* JsxAttribute */:
- case 262 /* JsxSpreadAttribute */:
- if (parent && (parent.kind === 254 /* JsxSelfClosingElement */ || parent.kind === 255 /* JsxOpeningElement */)) {
- return parent;
- }
- else if (parent.kind === 260 /* JsxAttribute */) {
- // Currently we parse JsxOpeningLikeElement as:
- // JsxOpeningLikeElement
- // attributes: JsxAttributes
- // properties: NodeArray
- return parent.parent.parent;
- }
- break;
- // The context token is the closing } or " of an attribute, which means
- // its parent is a JsxExpression, whose parent is a JsxAttribute,
- // whose parent is a JsxOpeningLikeElement
- case 9 /* StringLiteral */:
- if (parent && ((parent.kind === 260 /* JsxAttribute */) || (parent.kind === 262 /* JsxSpreadAttribute */))) {
- // Currently we parse JsxOpeningLikeElement as:
- // JsxOpeningLikeElement
- // attributes: JsxAttributes
- // properties: NodeArray
- return parent.parent.parent;
- }
- break;
- case 18 /* CloseBraceToken */:
- if (parent &&
- parent.kind === 263 /* JsxExpression */ &&
- parent.parent && parent.parent.kind === 260 /* JsxAttribute */) {
- // Currently we parse JsxOpeningLikeElement as:
- // JsxOpeningLikeElement
- // attributes: JsxAttributes
- // properties: NodeArray
- // each JsxAttribute can have initializer as JsxExpression
- return parent.parent.parent.parent;
- }
- if (parent && parent.kind === 262 /* JsxSpreadAttribute */) {
- // Currently we parse JsxOpeningLikeElement as:
- // JsxOpeningLikeElement
- // attributes: JsxAttributes
- // properties: NodeArray
- return parent.parent.parent;
- }
- break;
- }
- }
- return undefined;
- }
- /**
- * @returns true if we are certain that the currently edited location must define a new location; false otherwise.
- */
- function isSolelyIdentifierDefinitionLocation(contextToken) {
- var containingNodeKind = contextToken.parent.kind;
- switch (contextToken.kind) {
- case 26 /* CommaToken */:
- return containingNodeKind === 230 /* VariableDeclaration */ ||
- containingNodeKind === 231 /* VariableDeclarationList */ ||
- containingNodeKind === 212 /* VariableStatement */ ||
- containingNodeKind === 236 /* EnumDeclaration */ || // enum a { foo, |
- isFunctionLikeButNotConstructor(containingNodeKind) ||
- containingNodeKind === 234 /* InterfaceDeclaration */ || // interface A= contextToken.pos);
- case 23 /* DotToken */:
- return containingNodeKind === 179 /* ArrayBindingPattern */; // var [.|
- case 56 /* ColonToken */:
- return containingNodeKind === 180 /* BindingElement */; // var {x :html|
- case 21 /* OpenBracketToken */:
- return containingNodeKind === 179 /* ArrayBindingPattern */; // var [x|
- case 19 /* OpenParenToken */:
- return containingNodeKind === 267 /* CatchClause */ ||
- isFunctionLikeButNotConstructor(containingNodeKind);
- case 17 /* OpenBraceToken */:
- return containingNodeKind === 236 /* EnumDeclaration */ || // enum a { |
- containingNodeKind === 234 /* InterfaceDeclaration */ || // interface a { |
- containingNodeKind === 165 /* TypeLiteral */; // const x : { |
- case 25 /* SemicolonToken */:
- return containingNodeKind === 150 /* PropertySignature */ &&
- contextToken.parent && contextToken.parent.parent &&
- (contextToken.parent.parent.kind === 234 /* InterfaceDeclaration */ || // interface a { f; |
- contextToken.parent.parent.kind === 165 /* TypeLiteral */); // const x : { a; |
- case 27 /* LessThanToken */:
- return containingNodeKind === 233 /* ClassDeclaration */ || // class A< |
- containingNodeKind === 203 /* ClassExpression */ || // var C = class D< |
- containingNodeKind === 234 /* InterfaceDeclaration */ || // interface A< |
- containingNodeKind === 235 /* TypeAliasDeclaration */ || // type List< |
- ts.isFunctionLikeKind(containingNodeKind);
- case 115 /* StaticKeyword */:
- return containingNodeKind === 151 /* PropertyDeclaration */ && !ts.isClassLike(contextToken.parent.parent);
- case 24 /* DotDotDotToken */:
- return containingNodeKind === 148 /* Parameter */ ||
- (contextToken.parent && contextToken.parent.parent &&
- contextToken.parent.parent.kind === 179 /* ArrayBindingPattern */); // var [...z|
- case 114 /* PublicKeyword */:
- case 112 /* PrivateKeyword */:
- case 113 /* ProtectedKeyword */:
- return containingNodeKind === 148 /* Parameter */ && !ts.isConstructorDeclaration(contextToken.parent.parent);
- case 118 /* AsKeyword */:
- return containingNodeKind === 246 /* ImportSpecifier */ ||
- containingNodeKind === 250 /* ExportSpecifier */ ||
- containingNodeKind === 244 /* NamespaceImport */;
- case 125 /* GetKeyword */:
- case 136 /* SetKeyword */:
- if (isFromClassElementDeclaration(contextToken)) {
- return false;
- }
- // falls through
- case 75 /* ClassKeyword */:
- case 83 /* EnumKeyword */:
- case 109 /* InterfaceKeyword */:
- case 89 /* FunctionKeyword */:
- case 104 /* VarKeyword */:
- case 91 /* ImportKeyword */:
- case 110 /* LetKeyword */:
- case 76 /* ConstKeyword */:
- case 116 /* YieldKeyword */:
- case 139 /* TypeKeyword */: // type htm|
- return true;
- }
- // If the previous token is keyword correspoding to class member completion keyword
- // there will be completion available here
- if (isClassMemberCompletionKeywordText(contextToken.getText()) &&
- isFromClassElementDeclaration(contextToken)) {
- return false;
- }
- if (isConstructorParameterCompletion(contextToken)) {
- // constructor parameter completion is available only if
- // - its modifier of the constructor parameter or
- // - its name of the parameter and not being edited
- // eg. constructor(a |<- this shouldnt show completion
- if (!ts.isIdentifier(contextToken) ||
- isConstructorParameterCompletionKeywordText(contextToken.getText()) ||
- isCurrentlyEditingNode(contextToken)) {
- return false;
- }
- }
- // Previous token may have been a keyword that was converted to an identifier.
- switch (contextToken.getText()) {
- case "abstract":
- case "async":
- case "class":
- case "const":
- case "declare":
- case "enum":
- case "function":
- case "interface":
- case "let":
- case "private":
- case "protected":
- case "public":
- case "static":
- case "var":
- case "yield":
- return true;
- }
- return ts.isDeclarationName(contextToken)
- && !ts.isJsxAttribute(contextToken.parent)
- // Don't block completions if we're in `class C /**/`, because we're *past* the end of the identifier and might want to complete `extends`.
- // If `contextToken !== previousToken`, this is `class C ex/**/`.
- && !(ts.isClassLike(contextToken.parent) && (contextToken !== previousToken || position > previousToken.end));
- }
- function isFunctionLikeButNotConstructor(kind) {
- return ts.isFunctionLikeKind(kind) && kind !== 154 /* Constructor */;
- }
- function isDotOfNumericLiteral(contextToken) {
- if (contextToken.kind === 8 /* NumericLiteral */) {
- var text = contextToken.getFullText();
- return text.charAt(text.length - 1) === ".";
- }
- return false;
- }
- /**
- * Filters out completion suggestions for named imports or exports.
- *
- * @param exportsOfModule The list of symbols which a module exposes.
- * @param namedImportsOrExports The list of existing import/export specifiers in the import/export clause.
- *
- * @returns Symbols to be suggested at an import/export clause, barring those whose named imports/exports
- * do not occur at the current position and have not otherwise been typed.
- */
- function filterNamedImportOrExportCompletionItems(exportsOfModule, namedImportsOrExports) {
- var existingImportsOrExports = ts.createUnderscoreEscapedMap();
- for (var _i = 0, namedImportsOrExports_1 = namedImportsOrExports; _i < namedImportsOrExports_1.length; _i++) {
- var element = namedImportsOrExports_1[_i];
- // If this is the current item we are editing right now, do not filter it out
- if (isCurrentlyEditingNode(element)) {
- continue;
- }
- var name = element.propertyName || element.name;
- existingImportsOrExports.set(name.escapedText, true);
- }
- return exportsOfModule.filter(function (e) { return e.escapedName !== "default" /* Default */ && !existingImportsOrExports.get(e.escapedName); });
- }
- /**
- * Filters out completion suggestions for named imports or exports.
- *
- * @returns Symbols to be suggested in an object binding pattern or object literal expression, barring those whose declarations
- * do not occur at the current position and have not otherwise been typed.
- */
- function filterObjectMembersList(contextualMemberSymbols, existingMembers) {
- if (existingMembers.length === 0) {
- return contextualMemberSymbols;
- }
- var existingMemberNames = ts.createUnderscoreEscapedMap();
- for (var _i = 0, existingMembers_1 = existingMembers; _i < existingMembers_1.length; _i++) {
- var m = existingMembers_1[_i];
- // Ignore omitted expressions for missing members
- if (m.kind !== 268 /* PropertyAssignment */ &&
- m.kind !== 269 /* ShorthandPropertyAssignment */ &&
- m.kind !== 180 /* BindingElement */ &&
- m.kind !== 153 /* MethodDeclaration */ &&
- m.kind !== 155 /* GetAccessor */ &&
- m.kind !== 156 /* SetAccessor */) {
- continue;
- }
- // If this is the current item we are editing right now, do not filter it out
- if (isCurrentlyEditingNode(m)) {
- continue;
- }
- var existingName = void 0;
- if (m.kind === 180 /* BindingElement */ && m.propertyName) {
- // include only identifiers in completion list
- if (m.propertyName.kind === 71 /* Identifier */) {
- existingName = m.propertyName.escapedText;
- }
- }
- else {
- // TODO: Account for computed property name
- // NOTE: if one only performs this step when m.name is an identifier,
- // things like '__proto__' are not filtered out.
- var name = ts.getNameOfDeclaration(m);
- existingName = ts.isPropertyNameLiteral(name) ? ts.getEscapedTextOfIdentifierOrLiteral(name) : undefined;
- }
- existingMemberNames.set(existingName, true);
- }
- return contextualMemberSymbols.filter(function (m) { return !existingMemberNames.get(m.escapedName); });
- }
- /**
- * Filters out completion suggestions for class elements.
- *
- * @returns Symbols to be suggested in an class element depending on existing memebers and symbol flags
- */
- function filterClassMembersList(baseSymbols, implementingTypeSymbols, existingMembers, currentClassElementModifierFlags) {
- var existingMemberNames = ts.createUnderscoreEscapedMap();
- for (var _i = 0, existingMembers_2 = existingMembers; _i < existingMembers_2.length; _i++) {
- var m = existingMembers_2[_i];
- // Ignore omitted expressions for missing members
- if (m.kind !== 151 /* PropertyDeclaration */ &&
- m.kind !== 153 /* MethodDeclaration */ &&
- m.kind !== 155 /* GetAccessor */ &&
- m.kind !== 156 /* SetAccessor */) {
- continue;
- }
- // If this is the current item we are editing right now, do not filter it out
- if (isCurrentlyEditingNode(m)) {
- continue;
- }
- // Dont filter member even if the name matches if it is declared private in the list
- if (ts.hasModifier(m, 8 /* Private */)) {
- continue;
- }
- // do not filter it out if the static presence doesnt match
- var mIsStatic = ts.hasModifier(m, 32 /* Static */);
- var currentElementIsStatic = !!(currentClassElementModifierFlags & 32 /* Static */);
- if ((mIsStatic && !currentElementIsStatic) ||
- (!mIsStatic && currentElementIsStatic)) {
- continue;
- }
- var existingName = ts.getPropertyNameForPropertyNameNode(m.name);
- if (existingName) {
- existingMemberNames.set(existingName, true);
- }
- }
- var result = [];
- addPropertySymbols(baseSymbols, 8 /* Private */);
- addPropertySymbols(implementingTypeSymbols, 24 /* NonPublicAccessibilityModifier */);
- return result;
- function addPropertySymbols(properties, inValidModifierFlags) {
- for (var _i = 0, properties_12 = properties; _i < properties_12.length; _i++) {
- var property = properties_12[_i];
- if (isValidProperty(property, inValidModifierFlags)) {
- result.push(property);
- }
- }
- }
- function isValidProperty(propertySymbol, inValidModifierFlags) {
- return !existingMemberNames.get(propertySymbol.escapedName) &&
- propertySymbol.getDeclarations() &&
- !(ts.getDeclarationModifierFlagsFromSymbol(propertySymbol) & inValidModifierFlags);
- }
- }
- /**
- * Filters out completion suggestions from 'symbols' according to existing JSX attributes.
- *
- * @returns Symbols to be suggested in a JSX element, barring those whose attributes
- * do not occur at the current position and have not otherwise been typed.
- */
- function filterJsxAttributes(symbols, attributes) {
- var seenNames = ts.createUnderscoreEscapedMap();
- for (var _i = 0, attributes_1 = attributes; _i < attributes_1.length; _i++) {
- var attr = attributes_1[_i];
- // If this is the current item we are editing right now, do not filter it out
- if (isCurrentlyEditingNode(attr)) {
- continue;
- }
- if (attr.kind === 260 /* JsxAttribute */) {
- seenNames.set(attr.name.escapedText, true);
- }
- }
- return symbols.filter(function (a) { return !seenNames.get(a.escapedName); });
- }
- function isCurrentlyEditingNode(node) {
- return node.getStart() <= position && position <= node.getEnd();
- }
- }
- function getCompletionEntryDisplayNameForSymbol(symbol, target, origin, kind) {
- var name = getSymbolName(symbol, origin, target);
- if (name === undefined
- // If the symbol is external module, don't show it in the completion list
- // (i.e declare module "http" { const x; } | // <= request completion here, "http" should not be there)
- || symbol.flags & 1536 /* Module */ && ts.startsWithQuote(name)
- // If the symbol is the internal name of an ES symbol, it is not a valid entry. Internal names for ES symbols start with "__@"
- || ts.isKnownSymbol(symbol)) {
- return undefined;
- }
- var validIdentiferResult = { name: name, needsConvertPropertyAccess: false };
- if (ts.isIdentifierText(name, target))
- return validIdentiferResult;
- switch (kind) {
- case 3 /* MemberLike */:
- return undefined;
- case 0 /* ObjectPropertyDeclaration */:
- // TODO: GH#18169
- return { name: JSON.stringify(name), needsConvertPropertyAccess: false };
- case 2 /* PropertyAccess */:
- case 1 /* Global */: // For a 'this.' completion it will be in a global context, but may have a non-identifier name.
- // Don't add a completion for a name starting with a space. See https://github.com/Microsoft/TypeScript/pull/20547
- return name.charCodeAt(0) === 32 /* space */ ? undefined : { name: name, needsConvertPropertyAccess: true };
- case 5 /* None */:
- case 4 /* String */:
- return validIdentiferResult;
- default:
- ts.Debug.assertNever(kind);
- }
- }
- // A cache of completion entries for keywords, these do not change between sessions
- var _keywordCompletions = [];
- var allKeywordsCompletions = ts.memoize(function () {
- var res = [];
- for (var i = 72 /* FirstKeyword */; i <= 144 /* LastKeyword */; i++) {
- res.push({
- name: ts.tokenToString(i),
- kind: "keyword" /* keyword */,
- kindModifiers: "" /* none */,
- sortText: "0"
- });
- }
- return res;
- });
- function getKeywordCompletions(keywordFilter) {
- return _keywordCompletions[keywordFilter] || (_keywordCompletions[keywordFilter] = allKeywordsCompletions().filter(function (entry) {
- var kind = ts.stringToToken(entry.name);
- switch (keywordFilter) {
- case 0 /* None */:
- // "undefined" is a global variable, so don't need a keyword completion for it.
- return kind !== 140 /* UndefinedKeyword */;
- case 1 /* ClassElementKeywords */:
- return isClassMemberCompletionKeyword(kind);
- case 2 /* ConstructorParameterKeywords */:
- return isConstructorParameterCompletionKeyword(kind);
- case 3 /* FunctionLikeBodyKeywords */:
- return isFunctionLikeBodyCompletionKeyword(kind);
- case 4 /* TypeKeywords */:
- return ts.isTypeKeyword(kind);
- default:
- return ts.Debug.assertNever(keywordFilter);
- }
- }));
- }
- function isClassMemberCompletionKeyword(kind) {
- switch (kind) {
- case 114 /* PublicKeyword */:
- case 113 /* ProtectedKeyword */:
- case 112 /* PrivateKeyword */:
- case 117 /* AbstractKeyword */:
- case 115 /* StaticKeyword */:
- case 123 /* ConstructorKeyword */:
- case 132 /* ReadonlyKeyword */:
- case 125 /* GetKeyword */:
- case 136 /* SetKeyword */:
- case 120 /* AsyncKeyword */:
- return true;
- }
- }
- function isClassMemberCompletionKeywordText(text) {
- return isClassMemberCompletionKeyword(ts.stringToToken(text));
- }
- function isConstructorParameterCompletionKeyword(kind) {
- switch (kind) {
- case 114 /* PublicKeyword */:
- case 112 /* PrivateKeyword */:
- case 113 /* ProtectedKeyword */:
- case 132 /* ReadonlyKeyword */:
- return true;
- }
- }
- function isConstructorParameterCompletionKeywordText(text) {
- return isConstructorParameterCompletionKeyword(ts.stringToToken(text));
- }
- function isFunctionLikeBodyCompletionKeyword(kind) {
- switch (kind) {
- case 114 /* PublicKeyword */:
- case 112 /* PrivateKeyword */:
- case 113 /* ProtectedKeyword */:
- case 132 /* ReadonlyKeyword */:
- case 123 /* ConstructorKeyword */:
- case 115 /* StaticKeyword */:
- case 117 /* AbstractKeyword */:
- case 125 /* GetKeyword */:
- case 136 /* SetKeyword */:
- case 140 /* UndefinedKeyword */:
- return false;
- }
- return true;
- }
- function isEqualityOperatorKind(kind) {
- switch (kind) {
- case 34 /* EqualsEqualsEqualsToken */:
- case 32 /* EqualsEqualsToken */:
- case 35 /* ExclamationEqualsEqualsToken */:
- case 33 /* ExclamationEqualsToken */:
- return true;
- default:
- return false;
- }
- }
- /** Get the corresponding JSDocTag node if the position is in a jsDoc comment */
- function getJsDocTagAtPosition(node, position) {
- var jsDoc = getJsDocHavingNode(node).jsDoc;
- if (!jsDoc)
- return undefined;
- for (var _i = 0, jsDoc_1 = jsDoc; _i < jsDoc_1.length; _i++) {
- var _a = jsDoc_1[_i], pos = _a.pos, end = _a.end, tags = _a.tags;
- if (!tags || position < pos || position > end)
- continue;
- for (var i = tags.length - 1; i >= 0; i--) {
- var tag = tags[i];
- if (position >= tag.pos) {
- return tag;
- }
- }
- }
- }
- function getJsDocHavingNode(node) {
- if (!ts.isToken(node))
- return node;
- switch (node.kind) {
- case 104 /* VarKeyword */:
- case 110 /* LetKeyword */:
- case 76 /* ConstKeyword */:
- // if the current token is var, let or const, skip the VariableDeclarationList
- return node.parent.parent;
- default:
- return node.parent;
- }
- }
- /**
- * Gets all properties on a type, but if that type is a union of several types,
- * excludes array-like types or callable/constructable types.
- */
- function getPropertiesForCompletion(type, checker, isForAccess) {
- if (!(type.flags & 131072 /* Union */)) {
- return ts.Debug.assertEachDefined(type.getApparentProperties(), "getApparentProperties() should all be defined");
- }
- var types = type.types;
- // If we're providing completions for an object literal, skip primitive, array-like, or callable types since those shouldn't be implemented by object literals.
- var filteredTypes = isForAccess ? types : types.filter(function (memberType) {
- return !(memberType.flags & 16382 /* Primitive */ || checker.isArrayLikeType(memberType) || ts.typeHasCallOrConstructSignatures(memberType, checker));
- });
- return ts.Debug.assertEachDefined(checker.getAllPossiblePropertiesOfTypes(filteredTypes), "getAllPossiblePropertiesOfTypes() should all be defined");
- }
- })(Completions = ts.Completions || (ts.Completions = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var DocumentHighlights;
- (function (DocumentHighlights) {
- function getDocumentHighlights(program, cancellationToken, sourceFile, position, sourceFilesToSearch) {
- var node = ts.getTouchingWord(sourceFile, position, /*includeJsDocComment*/ true);
- if (node.parent && (ts.isJsxOpeningElement(node.parent) && node.parent.tagName === node || ts.isJsxClosingElement(node.parent))) {
- // For a JSX element, just highlight the matching tag, not all references.
- var _a = node.parent.parent, openingElement = _a.openingElement, closingElement = _a.closingElement;
- var highlightSpans = [openingElement, closingElement].map(function (_a) {
- var tagName = _a.tagName;
- return getHighlightSpanForNode(tagName, sourceFile);
- });
- return [{ fileName: sourceFile.fileName, highlightSpans: highlightSpans }];
- }
- return getSemanticDocumentHighlights(position, node, program, cancellationToken, sourceFilesToSearch) || getSyntacticDocumentHighlights(node, sourceFile);
- }
- DocumentHighlights.getDocumentHighlights = getDocumentHighlights;
- function getHighlightSpanForNode(node, sourceFile) {
- return {
- fileName: sourceFile.fileName,
- textSpan: ts.createTextSpanFromNode(node, sourceFile),
- kind: "none" /* none */
- };
- }
- function getSemanticDocumentHighlights(position, node, program, cancellationToken, sourceFilesToSearch) {
- var referenceEntries = ts.FindAllReferences.getReferenceEntriesForNode(position, node, program, sourceFilesToSearch, cancellationToken);
- if (!referenceEntries)
- return undefined;
- var map = ts.arrayToMultiMap(referenceEntries.map(ts.FindAllReferences.toHighlightSpan), function (e) { return e.fileName; }, function (e) { return e.span; });
- return ts.arrayFrom(map.entries(), function (_a) {
- var fileName = _a[0], highlightSpans = _a[1];
- return ({ fileName: fileName, highlightSpans: highlightSpans });
- });
- }
- function getSyntacticDocumentHighlights(node, sourceFile) {
- var highlightSpans = getHighlightSpans(node, sourceFile);
- return highlightSpans && [{ fileName: sourceFile.fileName, highlightSpans: highlightSpans }];
- }
- function getHighlightSpans(node, sourceFile) {
- switch (node.kind) {
- case 90 /* IfKeyword */:
- case 82 /* ElseKeyword */:
- return ts.isIfStatement(node.parent) ? getIfElseOccurrences(node.parent, sourceFile) : undefined;
- case 96 /* ReturnKeyword */:
- return useParent(node.parent, ts.isReturnStatement, getReturnOccurrences);
- case 100 /* ThrowKeyword */:
- return useParent(node.parent, ts.isThrowStatement, getThrowOccurrences);
- case 102 /* TryKeyword */:
- case 74 /* CatchKeyword */:
- case 87 /* FinallyKeyword */:
- var tryStatement = node.kind === 74 /* CatchKeyword */ ? node.parent.parent : node.parent;
- return useParent(tryStatement, ts.isTryStatement, getTryCatchFinallyOccurrences);
- case 98 /* SwitchKeyword */:
- return useParent(node.parent, ts.isSwitchStatement, getSwitchCaseDefaultOccurrences);
- case 73 /* CaseKeyword */:
- case 79 /* DefaultKeyword */:
- return useParent(node.parent.parent.parent, ts.isSwitchStatement, getSwitchCaseDefaultOccurrences);
- case 72 /* BreakKeyword */:
- case 77 /* ContinueKeyword */:
- return useParent(node.parent, ts.isBreakOrContinueStatement, getBreakOrContinueStatementOccurrences);
- case 88 /* ForKeyword */:
- case 106 /* WhileKeyword */:
- case 81 /* DoKeyword */:
- return useParent(node.parent, function (n) { return ts.isIterationStatement(n, /*lookInLabeledStatements*/ true); }, getLoopBreakContinueOccurrences);
- case 123 /* ConstructorKeyword */:
- return getFromAllDeclarations(ts.isConstructorDeclaration, [123 /* ConstructorKeyword */]);
- case 125 /* GetKeyword */:
- case 136 /* SetKeyword */:
- return getFromAllDeclarations(ts.isAccessor, [125 /* GetKeyword */, 136 /* SetKeyword */]);
- default:
- return ts.isModifierKind(node.kind) && (ts.isDeclaration(node.parent) || ts.isVariableStatement(node.parent))
- ? highlightSpans(getModifierOccurrences(node.kind, node.parent))
- : undefined;
- }
- function getFromAllDeclarations(nodeTest, keywords) {
- return useParent(node.parent, nodeTest, function (decl) { return ts.mapDefined(decl.symbol.declarations, function (d) {
- return nodeTest(d) ? ts.find(d.getChildren(sourceFile), function (c) { return ts.contains(keywords, c.kind); }) : undefined;
- }); });
- }
- function useParent(node, nodeTest, getNodes) {
- return nodeTest(node) ? highlightSpans(getNodes(node, sourceFile)) : undefined;
- }
- function highlightSpans(nodes) {
- return nodes && nodes.map(function (node) { return getHighlightSpanForNode(node, sourceFile); });
- }
- }
- /**
- * Aggregates all throw-statements within this node *without* crossing
- * into function boundaries and try-blocks with catch-clauses.
- */
- function aggregateOwnedThrowStatements(node) {
- if (ts.isThrowStatement(node)) {
- return [node];
- }
- else if (ts.isTryStatement(node)) {
- // Exceptions thrown within a try block lacking a catch clause are "owned" in the current context.
- return ts.concatenate(node.catchClause ? aggregateOwnedThrowStatements(node.catchClause) : node.tryBlock && aggregateOwnedThrowStatements(node.tryBlock), aggregateOwnedThrowStatements(node.finallyBlock));
- }
- // Do not cross function boundaries.
- return ts.isFunctionLike(node) ? undefined : flatMapChildren(node, aggregateOwnedThrowStatements);
- }
- /**
- * For lack of a better name, this function takes a throw statement and returns the
- * nearest ancestor that is a try-block (whose try statement has a catch clause),
- * function-block, or source file.
- */
- function getThrowStatementOwner(throwStatement) {
- var child = throwStatement;
- while (child.parent) {
- var parent = child.parent;
- if (ts.isFunctionBlock(parent) || parent.kind === 272 /* SourceFile */) {
- return parent;
- }
- // A throw-statement is only owned by a try-statement if the try-statement has
- // a catch clause, and if the throw-statement occurs within the try block.
- if (ts.isTryStatement(parent) && parent.tryBlock === child && parent.catchClause) {
- return child;
- }
- child = parent;
- }
- return undefined;
- }
- function aggregateAllBreakAndContinueStatements(node) {
- return ts.isBreakOrContinueStatement(node) ? [node] : ts.isFunctionLike(node) ? undefined : flatMapChildren(node, aggregateAllBreakAndContinueStatements);
- }
- function flatMapChildren(node, cb) {
- var result = [];
- node.forEachChild(function (child) {
- var value = cb(child);
- if (value !== undefined) {
- result.push.apply(result, ts.toArray(value));
- }
- });
- return result;
- }
- function ownsBreakOrContinueStatement(owner, statement) {
- var actualOwner = getBreakOrContinueOwner(statement);
- return actualOwner && actualOwner === owner;
- }
- function getBreakOrContinueOwner(statement) {
- return ts.findAncestor(statement, function (node) {
- switch (node.kind) {
- case 225 /* SwitchStatement */:
- if (statement.kind === 221 /* ContinueStatement */) {
- return false;
- }
- // falls through
- case 218 /* ForStatement */:
- case 219 /* ForInStatement */:
- case 220 /* ForOfStatement */:
- case 217 /* WhileStatement */:
- case 216 /* DoStatement */:
- return !statement.label || isLabeledBy(node, statement.label.escapedText);
- default:
- // Don't cross function boundaries.
- // TODO: GH#20090
- return (ts.isFunctionLike(node) && "quit");
- }
- });
- }
- function getModifierOccurrences(modifier, declaration) {
- var modifierFlag = ts.modifierToFlag(modifier);
- return ts.mapDefined(getNodesToSearchForModifier(declaration, modifierFlag), function (node) {
- if (ts.getModifierFlags(node) & modifierFlag) {
- var mod = ts.find(node.modifiers, function (m) { return m.kind === modifier; });
- ts.Debug.assert(!!mod);
- return mod;
- }
- });
- }
- function getNodesToSearchForModifier(declaration, modifierFlag) {
- // Types of node whose children might have modifiers.
- var container = declaration.parent;
- switch (container.kind) {
- case 238 /* ModuleBlock */:
- case 272 /* SourceFile */:
- case 211 /* Block */:
- case 264 /* CaseClause */:
- case 265 /* DefaultClause */:
- // Container is either a class declaration or the declaration is a classDeclaration
- if (modifierFlag & 128 /* Abstract */ && ts.isClassDeclaration(declaration)) {
- return declaration.members.concat([declaration]);
- }
- else {
- return container.statements;
- }
- case 154 /* Constructor */:
- case 153 /* MethodDeclaration */:
- case 232 /* FunctionDeclaration */: {
- return container.parameters.concat((ts.isClassLike(container.parent) ? container.parent.members : []));
- }
- case 233 /* ClassDeclaration */:
- case 203 /* ClassExpression */:
- var nodes = container.members;
- // If we're an accessibility modifier, we're in an instance member and should search
- // the constructor's parameter list for instance members as well.
- if (modifierFlag & 28 /* AccessibilityModifier */) {
- var constructor = ts.find(container.members, ts.isConstructorDeclaration);
- if (constructor) {
- return nodes.concat(constructor.parameters);
- }
- }
- else if (modifierFlag & 128 /* Abstract */) {
- return nodes.concat([container]);
- }
- return nodes;
- default:
- ts.Debug.assertNever(container, "Invalid container kind.");
- }
- }
- function pushKeywordIf(keywordList, token) {
- var expected = [];
- for (var _i = 2; _i < arguments.length; _i++) {
- expected[_i - 2] = arguments[_i];
- }
- if (token && ts.contains(expected, token.kind)) {
- keywordList.push(token);
- return true;
- }
- return false;
- }
- function getLoopBreakContinueOccurrences(loopNode) {
- var keywords = [];
- if (pushKeywordIf(keywords, loopNode.getFirstToken(), 88 /* ForKeyword */, 106 /* WhileKeyword */, 81 /* DoKeyword */)) {
- // If we succeeded and got a do-while loop, then start looking for a 'while' keyword.
- if (loopNode.kind === 216 /* DoStatement */) {
- var loopTokens = loopNode.getChildren();
- for (var i = loopTokens.length - 1; i >= 0; i--) {
- if (pushKeywordIf(keywords, loopTokens[i], 106 /* WhileKeyword */)) {
- break;
- }
- }
- }
- }
- ts.forEach(aggregateAllBreakAndContinueStatements(loopNode.statement), function (statement) {
- if (ownsBreakOrContinueStatement(loopNode, statement)) {
- pushKeywordIf(keywords, statement.getFirstToken(), 72 /* BreakKeyword */, 77 /* ContinueKeyword */);
- }
- });
- return keywords;
- }
- function getBreakOrContinueStatementOccurrences(breakOrContinueStatement) {
- var owner = getBreakOrContinueOwner(breakOrContinueStatement);
- if (owner) {
- switch (owner.kind) {
- case 218 /* ForStatement */:
- case 219 /* ForInStatement */:
- case 220 /* ForOfStatement */:
- case 216 /* DoStatement */:
- case 217 /* WhileStatement */:
- return getLoopBreakContinueOccurrences(owner);
- case 225 /* SwitchStatement */:
- return getSwitchCaseDefaultOccurrences(owner);
- }
- }
- return undefined;
- }
- function getSwitchCaseDefaultOccurrences(switchStatement) {
- var keywords = [];
- pushKeywordIf(keywords, switchStatement.getFirstToken(), 98 /* SwitchKeyword */);
- // Go through each clause in the switch statement, collecting the 'case'/'default' keywords.
- ts.forEach(switchStatement.caseBlock.clauses, function (clause) {
- pushKeywordIf(keywords, clause.getFirstToken(), 73 /* CaseKeyword */, 79 /* DefaultKeyword */);
- ts.forEach(aggregateAllBreakAndContinueStatements(clause), function (statement) {
- if (ownsBreakOrContinueStatement(switchStatement, statement)) {
- pushKeywordIf(keywords, statement.getFirstToken(), 72 /* BreakKeyword */);
- }
- });
- });
- return keywords;
- }
- function getTryCatchFinallyOccurrences(tryStatement, sourceFile) {
- var keywords = [];
- pushKeywordIf(keywords, tryStatement.getFirstToken(), 102 /* TryKeyword */);
- if (tryStatement.catchClause) {
- pushKeywordIf(keywords, tryStatement.catchClause.getFirstToken(), 74 /* CatchKeyword */);
- }
- if (tryStatement.finallyBlock) {
- var finallyKeyword = ts.findChildOfKind(tryStatement, 87 /* FinallyKeyword */, sourceFile);
- pushKeywordIf(keywords, finallyKeyword, 87 /* FinallyKeyword */);
- }
- return keywords;
- }
- function getThrowOccurrences(throwStatement, sourceFile) {
- var owner = getThrowStatementOwner(throwStatement);
- if (!owner) {
- return undefined;
- }
- var keywords = [];
- ts.forEach(aggregateOwnedThrowStatements(owner), function (throwStatement) {
- keywords.push(ts.findChildOfKind(throwStatement, 100 /* ThrowKeyword */, sourceFile));
- });
- // If the "owner" is a function, then we equate 'return' and 'throw' statements in their
- // ability to "jump out" of the function, and include occurrences for both.
- if (ts.isFunctionBlock(owner)) {
- ts.forEachReturnStatement(owner, function (returnStatement) {
- keywords.push(ts.findChildOfKind(returnStatement, 96 /* ReturnKeyword */, sourceFile));
- });
- }
- return keywords;
- }
- function getReturnOccurrences(returnStatement, sourceFile) {
- var func = ts.getContainingFunction(returnStatement);
- if (!func) {
- return undefined;
- }
- var keywords = [];
- ts.forEachReturnStatement(ts.cast(func.body, ts.isBlock), function (returnStatement) {
- keywords.push(ts.findChildOfKind(returnStatement, 96 /* ReturnKeyword */, sourceFile));
- });
- // Include 'throw' statements that do not occur within a try block.
- ts.forEach(aggregateOwnedThrowStatements(func.body), function (throwStatement) {
- keywords.push(ts.findChildOfKind(throwStatement, 100 /* ThrowKeyword */, sourceFile));
- });
- return keywords;
- }
- function getIfElseOccurrences(ifStatement, sourceFile) {
- var keywords = getIfElseKeywords(ifStatement, sourceFile);
- var result = [];
- // We'd like to highlight else/ifs together if they are only separated by whitespace
- // (i.e. the keywords are separated by no comments, no newlines).
- for (var i = 0; i < keywords.length; i++) {
- if (keywords[i].kind === 82 /* ElseKeyword */ && i < keywords.length - 1) {
- var elseKeyword = keywords[i];
- var ifKeyword = keywords[i + 1]; // this *should* always be an 'if' keyword.
- var shouldCombineElseAndIf = true;
- // Avoid recalculating getStart() by iterating backwards.
- for (var j = ifKeyword.getStart(sourceFile) - 1; j >= elseKeyword.end; j--) {
- if (!ts.isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(j))) {
- shouldCombineElseAndIf = false;
- break;
- }
- }
- if (shouldCombineElseAndIf) {
- result.push({
- fileName: sourceFile.fileName,
- textSpan: ts.createTextSpanFromBounds(elseKeyword.getStart(), ifKeyword.end),
- kind: "reference" /* reference */
- });
- i++; // skip the next keyword
- continue;
- }
- }
- // Ordinary case: just highlight the keyword.
- result.push(getHighlightSpanForNode(keywords[i], sourceFile));
- }
- return result;
- }
- function getIfElseKeywords(ifStatement, sourceFile) {
- var keywords = [];
- // Traverse upwards through all parent if-statements linked by their else-branches.
- while (ts.isIfStatement(ifStatement.parent) && ifStatement.parent.elseStatement === ifStatement) {
- ifStatement = ifStatement.parent;
- }
- // Now traverse back down through the else branches, aggregating if/else keywords of if-statements.
- while (true) {
- var children = ifStatement.getChildren(sourceFile);
- pushKeywordIf(keywords, children[0], 90 /* IfKeyword */);
- // Generally the 'else' keyword is second-to-last, so we traverse backwards.
- for (var i = children.length - 1; i >= 0; i--) {
- if (pushKeywordIf(keywords, children[i], 82 /* ElseKeyword */)) {
- break;
- }
- }
- if (!ifStatement.elseStatement || !ts.isIfStatement(ifStatement.elseStatement)) {
- break;
- }
- ifStatement = ifStatement.elseStatement;
- }
- return keywords;
- }
- /**
- * Whether or not a 'node' is preceded by a label of the given string.
- * Note: 'node' cannot be a SourceFile.
- */
- function isLabeledBy(node, labelName) {
- return !!ts.findAncestor(node.parent, function (owner) { return !ts.isLabeledStatement(owner) ? "quit" : owner.label.escapedText === labelName; });
- }
- })(DocumentHighlights = ts.DocumentHighlights || (ts.DocumentHighlights = {}));
-})(ts || (ts = {}));
-var ts;
-(function (ts) {
- function createDocumentRegistry(useCaseSensitiveFileNames, currentDirectory) {
- if (currentDirectory === void 0) { currentDirectory = ""; }
- // Maps from compiler setting target (ES3, ES5, etc.) to all the cached documents we have
- // for those settings.
- var buckets = ts.createMap();
- var getCanonicalFileName = ts.createGetCanonicalFileName(!!useCaseSensitiveFileNames);
- function getKeyForCompilationSettings(settings) {
- return "_" + settings.target + "|" + settings.module + "|" + settings.noResolve + "|" + settings.jsx + "|" + settings.allowJs + "|" + settings.baseUrl + "|" + JSON.stringify(settings.typeRoots) + "|" + JSON.stringify(settings.rootDirs) + "|" + JSON.stringify(settings.paths);
- }
- function getBucketForCompilationSettings(key, createIfMissing) {
- var bucket = buckets.get(key);
- if (!bucket && createIfMissing) {
- buckets.set(key, bucket = ts.createMap());
- }
- return bucket;
- }
- function reportStats() {
- var bucketInfoArray = ts.arrayFrom(buckets.keys()).filter(function (name) { return name && name.charAt(0) === "_"; }).map(function (name) {
- var entries = buckets.get(name);
- var sourceFiles = [];
- entries.forEach(function (entry, name) {
- sourceFiles.push({
- name: name,
- refCount: entry.languageServiceRefCount,
- references: entry.owners.slice(0)
- });
- });
- sourceFiles.sort(function (x, y) { return y.refCount - x.refCount; });
- return {
- bucket: name,
- sourceFiles: sourceFiles
- };
- });
- return JSON.stringify(bucketInfoArray, undefined, 2);
- }
- function acquireDocument(fileName, compilationSettings, scriptSnapshot, version, scriptKind) {
- var path = ts.toPath(fileName, currentDirectory, getCanonicalFileName);
- var key = getKeyForCompilationSettings(compilationSettings);
- return acquireDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind);
- }
- function acquireDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind) {
- return acquireOrUpdateDocument(fileName, path, compilationSettings, key, scriptSnapshot, version, /*acquiring*/ true, scriptKind);
- }
- function updateDocument(fileName, compilationSettings, scriptSnapshot, version, scriptKind) {
- var path = ts.toPath(fileName, currentDirectory, getCanonicalFileName);
- var key = getKeyForCompilationSettings(compilationSettings);
- return updateDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind);
- }
- function updateDocumentWithKey(fileName, path, compilationSettings, key, scriptSnapshot, version, scriptKind) {
- return acquireOrUpdateDocument(fileName, path, compilationSettings, key, scriptSnapshot, version, /*acquiring*/ false, scriptKind);
- }
- function acquireOrUpdateDocument(fileName, path, compilationSettings, key, scriptSnapshot, version, acquiring, scriptKind) {
- var bucket = getBucketForCompilationSettings(key, /*createIfMissing*/ true);
- var entry = bucket.get(path);
- if (!entry) {
- // Have never seen this file with these settings. Create a new source file for it.
- var sourceFile = ts.createLanguageServiceSourceFile(fileName, scriptSnapshot, compilationSettings.target, version, /*setNodeParents*/ false, scriptKind);
- entry = {
- sourceFile: sourceFile,
- languageServiceRefCount: 1,
- owners: []
- };
- bucket.set(path, entry);
- }
- else {
- // We have an entry for this file. However, it may be for a different version of
- // the script snapshot. If so, update it appropriately. Otherwise, we can just
- // return it as is.
- if (entry.sourceFile.version !== version) {
- entry.sourceFile = ts.updateLanguageServiceSourceFile(entry.sourceFile, scriptSnapshot, version, scriptSnapshot.getChangeRange(entry.sourceFile.scriptSnapshot));
- }
- // If we're acquiring, then this is the first time this LS is asking for this document.
- // Increase our ref count so we know there's another LS using the document. If we're
- // not acquiring, then that means the LS is 'updating' the file instead, and that means
- // it has already acquired the document previously. As such, we do not need to increase
- // the ref count.
- if (acquiring) {
- entry.languageServiceRefCount++;
- }
- }
- return entry.sourceFile;
- }
- function releaseDocument(fileName, compilationSettings) {
- var path = ts.toPath(fileName, currentDirectory, getCanonicalFileName);
- var key = getKeyForCompilationSettings(compilationSettings);
- return releaseDocumentWithKey(path, key);
- }
- function releaseDocumentWithKey(path, key) {
- var bucket = getBucketForCompilationSettings(key, /*createIfMissing*/ false);
- ts.Debug.assert(bucket !== undefined);
- var entry = bucket.get(path);
- entry.languageServiceRefCount--;
- ts.Debug.assert(entry.languageServiceRefCount >= 0);
- if (entry.languageServiceRefCount === 0) {
- bucket.delete(path);
- }
- }
- return {
- acquireDocument: acquireDocument,
- acquireDocumentWithKey: acquireDocumentWithKey,
- updateDocument: updateDocument,
- updateDocumentWithKey: updateDocumentWithKey,
- releaseDocument: releaseDocument,
- releaseDocumentWithKey: releaseDocumentWithKey,
- reportStats: reportStats,
- getKeyForCompilationSettings: getKeyForCompilationSettings
- };
- }
- ts.createDocumentRegistry = createDocumentRegistry;
-})(ts || (ts = {}));
-/* Code for finding imports of an exported symbol. Used only by FindAllReferences. */
-/* @internal */
-var ts;
-(function (ts) {
- var FindAllReferences;
- (function (FindAllReferences) {
- /** Creates the imports map and returns an ImportTracker that uses it. Call this lazily to avoid calling `getDirectImportsMap` unnecessarily. */
- function createImportTracker(sourceFiles, checker, cancellationToken) {
- var allDirectImports = getDirectImportsMap(sourceFiles, checker, cancellationToken);
- return function (exportSymbol, exportInfo, isForRename) {
- var _a = getImportersForExport(sourceFiles, allDirectImports, exportInfo, checker, cancellationToken), directImports = _a.directImports, indirectUsers = _a.indirectUsers;
- return __assign({ indirectUsers: indirectUsers }, getSearchesFromDirectImports(directImports, exportSymbol, exportInfo.exportKind, checker, isForRename));
- };
- }
- FindAllReferences.createImportTracker = createImportTracker;
- var ExportKind;
- (function (ExportKind) {
- ExportKind[ExportKind["Named"] = 0] = "Named";
- ExportKind[ExportKind["Default"] = 1] = "Default";
- ExportKind[ExportKind["ExportEquals"] = 2] = "ExportEquals";
- })(ExportKind = FindAllReferences.ExportKind || (FindAllReferences.ExportKind = {}));
- var ImportExport;
- (function (ImportExport) {
- ImportExport[ImportExport["Import"] = 0] = "Import";
- ImportExport[ImportExport["Export"] = 1] = "Export";
- })(ImportExport = FindAllReferences.ImportExport || (FindAllReferences.ImportExport = {}));
- /** Returns import statements that directly reference the exporting module, and a list of files that may access the module through a namespace. */
- function getImportersForExport(sourceFiles, allDirectImports, _a, checker, cancellationToken) {
- var exportingModuleSymbol = _a.exportingModuleSymbol, exportKind = _a.exportKind;
- var markSeenDirectImport = ts.nodeSeenTracker();
- var markSeenIndirectUser = ts.nodeSeenTracker();
- var directImports = [];
- var isAvailableThroughGlobal = !!exportingModuleSymbol.globalExports;
- var indirectUserDeclarations = isAvailableThroughGlobal ? undefined : [];
- handleDirectImports(exportingModuleSymbol);
- return { directImports: directImports, indirectUsers: getIndirectUsers() };
- function getIndirectUsers() {
- if (isAvailableThroughGlobal) {
- // It has `export as namespace`, so anything could potentially use it.
- return sourceFiles;
- }
- // Module augmentations may use this module's exports without importing it.
- for (var _i = 0, _a = exportingModuleSymbol.declarations; _i < _a.length; _i++) {
- var decl = _a[_i];
- if (ts.isExternalModuleAugmentation(decl)) {
- addIndirectUser(decl);
- }
- }
- // This may return duplicates (if there are multiple module declarations in a single source file, all importing the same thing as a namespace), but `State.markSearchedSymbol` will handle that.
- return indirectUserDeclarations.map(ts.getSourceFileOfNode);
- }
- function handleDirectImports(exportingModuleSymbol) {
- var theseDirectImports = getDirectImports(exportingModuleSymbol);
- if (theseDirectImports) {
- for (var _i = 0, theseDirectImports_1 = theseDirectImports; _i < theseDirectImports_1.length; _i++) {
- var direct = theseDirectImports_1[_i];
- if (!markSeenDirectImport(direct)) {
- continue;
- }
- cancellationToken.throwIfCancellationRequested();
- switch (direct.kind) {
- case 185 /* CallExpression */:
- if (!isAvailableThroughGlobal) {
- var parent = direct.parent;
- if (exportKind === 2 /* ExportEquals */ && parent.kind === 230 /* VariableDeclaration */) {
- var name = parent.name;
- if (name.kind === 71 /* Identifier */) {
- directImports.push(name);
- break;
- }
- }
- // Don't support re-exporting 'require()' calls, so just add a single indirect user.
- addIndirectUser(direct.getSourceFile());
- }
- break;
- case 241 /* ImportEqualsDeclaration */:
- handleNamespaceImport(direct, direct.name, ts.hasModifier(direct, 1 /* Export */));
- break;
- case 242 /* ImportDeclaration */:
- var namedBindings = direct.importClause && direct.importClause.namedBindings;
- if (namedBindings && namedBindings.kind === 244 /* NamespaceImport */) {
- handleNamespaceImport(direct, namedBindings.name);
- }
- else if (ts.isDefaultImport(direct)) {
- var sourceFileLike = getSourceFileLikeForImportDeclaration(direct);
- if (!isAvailableThroughGlobal) {
- addIndirectUser(sourceFileLike); // Add a check for indirect uses to handle synthetic default imports
- }
- directImports.push(direct);
- }
- else {
- directImports.push(direct);
- }
- break;
- case 248 /* ExportDeclaration */:
- if (!direct.exportClause) {
- // This is `export * from "foo"`, so imports of this module may import the export too.
- handleDirectImports(getContainingModuleSymbol(direct, checker));
- }
- else {
- // This is `export { foo } from "foo"` and creates an alias symbol, so recursive search will get handle re-exports.
- directImports.push(direct);
- }
- break;
- }
- }
- }
- }
- function handleNamespaceImport(importDeclaration, name, isReExport) {
- if (exportKind === 2 /* ExportEquals */) {
- // This is a direct import, not import-as-namespace.
- directImports.push(importDeclaration);
- }
- else if (!isAvailableThroughGlobal) {
- var sourceFileLike = getSourceFileLikeForImportDeclaration(importDeclaration);
- ts.Debug.assert(sourceFileLike.kind === 272 /* SourceFile */ || sourceFileLike.kind === 237 /* ModuleDeclaration */);
- if (isReExport || findNamespaceReExports(sourceFileLike, name, checker)) {
- addIndirectUsers(sourceFileLike);
- }
- else {
- addIndirectUser(sourceFileLike);
- }
- }
- }
- function addIndirectUser(sourceFileLike) {
- ts.Debug.assert(!isAvailableThroughGlobal);
- var isNew = markSeenIndirectUser(sourceFileLike);
- if (isNew) {
- indirectUserDeclarations.push(sourceFileLike);
- }
- return isNew;
- }
- /** Adds a module and all of its transitive dependencies as possible indirect users. */
- function addIndirectUsers(sourceFileLike) {
- if (!addIndirectUser(sourceFileLike)) {
- return;
- }
- var moduleSymbol = checker.getMergedSymbol(sourceFileLike.symbol);
- ts.Debug.assert(!!(moduleSymbol.flags & 1536 /* Module */));
- var directImports = getDirectImports(moduleSymbol);
- if (directImports) {
- for (var _i = 0, directImports_1 = directImports; _i < directImports_1.length; _i++) {
- var directImport = directImports_1[_i];
- addIndirectUsers(getSourceFileLikeForImportDeclaration(directImport));
- }
- }
- }
- function getDirectImports(moduleSymbol) {
- return allDirectImports.get(ts.getSymbolId(moduleSymbol).toString());
- }
- }
- /**
- * Given the set of direct imports of a module, we need to find which ones import the particular exported symbol.
- * The returned `importSearches` will result in the entire source file being searched.
- * But re-exports will be placed in 'singleReferences' since they cannot be locally referenced.
- */
- function getSearchesFromDirectImports(directImports, exportSymbol, exportKind, checker, isForRename) {
- var importSearches = [];
- var singleReferences = [];
- function addSearch(location, symbol) {
- importSearches.push([location, symbol]);
- }
- if (directImports) {
- for (var _i = 0, directImports_2 = directImports; _i < directImports_2.length; _i++) {
- var decl = directImports_2[_i];
- handleImport(decl);
- }
- }
- return { importSearches: importSearches, singleReferences: singleReferences };
- function handleImport(decl) {
- if (decl.kind === 241 /* ImportEqualsDeclaration */) {
- if (isExternalModuleImportEquals(decl)) {
- handleNamespaceImportLike(decl.name);
- }
- return;
- }
- if (decl.kind === 71 /* Identifier */) {
- handleNamespaceImportLike(decl);
- return;
- }
- // Ignore if there's a grammar error
- if (decl.moduleSpecifier.kind !== 9 /* StringLiteral */) {
- return;
- }
- if (decl.kind === 248 /* ExportDeclaration */) {
- searchForNamedImport(decl.exportClause);
- return;
- }
- var importClause = decl.importClause;
- if (!importClause) {
- return;
- }
- var namedBindings = importClause.namedBindings;
- if (namedBindings && namedBindings.kind === 244 /* NamespaceImport */) {
- handleNamespaceImportLike(namedBindings.name);
- return;
- }
- if (exportKind === 0 /* Named */) {
- searchForNamedImport(namedBindings);
- }
- else {
- // `export =` might be imported by a default import if `--allowSyntheticDefaultImports` is on, so this handles both ExportKind.Default and ExportKind.ExportEquals
- var name = importClause.name;
- // If a default import has the same name as the default export, allow to rename it.
- // Given `import f` and `export default function f`, we will rename both, but for `import g` we will rename just that.
- if (name && (!isForRename || name.escapedText === symbolName(exportSymbol))) {
- var defaultImportAlias = checker.getSymbolAtLocation(name);
- addSearch(name, defaultImportAlias);
- }
- // 'default' might be accessed as a named import `{ default as foo }`.
- if (!isForRename && exportKind === 1 /* Default */) {
- searchForNamedImport(namedBindings);
- }
- }
- }
- /**
- * `import x = require("./x") or `import * as x from "./x"`.
- * An `export =` may be imported by this syntax, so it may be a direct import.
- * If it's not a direct import, it will be in `indirectUsers`, so we don't have to do anything here.
- */
- function handleNamespaceImportLike(importName) {
- // Don't rename an import that already has a different name than the export.
- if (exportKind === 2 /* ExportEquals */ && (!isForRename || isNameMatch(importName.escapedText))) {
- addSearch(importName, checker.getSymbolAtLocation(importName));
- }
- }
- function searchForNamedImport(namedBindings) {
- if (!namedBindings) {
- return;
- }
- for (var _i = 0, _a = namedBindings.elements; _i < _a.length; _i++) {
- var element = _a[_i];
- var name = element.name, propertyName = element.propertyName;
- if (!isNameMatch((propertyName || name).escapedText)) {
- continue;
- }
- if (propertyName) {
- // This is `import { foo as bar } from "./a"` or `export { foo as bar } from "./a"`. `foo` isn't a local in the file, so just add it as a single reference.
- singleReferences.push(propertyName);
- if (!isForRename) { // If renaming `foo`, don't touch `bar`, just `foo`.
- // Search locally for `bar`.
- addSearch(name, checker.getSymbolAtLocation(name));
- }
- }
- else {
- var localSymbol = element.kind === 250 /* ExportSpecifier */ && element.propertyName
- ? checker.getExportSpecifierLocalTargetSymbol(element) // For re-exporting under a different name, we want to get the re-exported symbol.
- : checker.getSymbolAtLocation(name);
- addSearch(name, localSymbol);
- }
- }
- }
- function isNameMatch(name) {
- // Use name of "default" even in `export =` case because we may have allowSyntheticDefaultImports
- return name === exportSymbol.escapedName || exportKind !== 0 /* Named */ && name === "default" /* Default */;
- }
- }
- /** Returns 'true' is the namespace 'name' is re-exported from this module, and 'false' if it is only used locally. */
- function findNamespaceReExports(sourceFileLike, name, checker) {
- var namespaceImportSymbol = checker.getSymbolAtLocation(name);
- return forEachPossibleImportOrExportStatement(sourceFileLike, function (statement) {
- if (statement.kind !== 248 /* ExportDeclaration */)
- return;
- var _a = statement, exportClause = _a.exportClause, moduleSpecifier = _a.moduleSpecifier;
- if (moduleSpecifier || !exportClause)
- return;
- for (var _i = 0, _b = exportClause.elements; _i < _b.length; _i++) {
- var element = _b[_i];
- if (checker.getExportSpecifierLocalTargetSymbol(element) === namespaceImportSymbol) {
- return true;
- }
- }
- });
- }
- function findModuleReferences(program, sourceFiles, searchModuleSymbol) {
- var refs = [];
- var checker = program.getTypeChecker();
- for (var _i = 0, sourceFiles_4 = sourceFiles; _i < sourceFiles_4.length; _i++) {
- var referencingFile = sourceFiles_4[_i];
- var searchSourceFile = searchModuleSymbol.valueDeclaration;
- if (searchSourceFile.kind === 272 /* SourceFile */) {
- for (var _a = 0, _b = referencingFile.referencedFiles; _a < _b.length; _a++) {
- var ref = _b[_a];
- if (program.getSourceFileFromReference(referencingFile, ref) === searchSourceFile) {
- refs.push({ kind: "reference", referencingFile: referencingFile, ref: ref });
- }
- }
- for (var _c = 0, _d = referencingFile.typeReferenceDirectives; _c < _d.length; _c++) {
- var ref = _d[_c];
- var referenced = program.getResolvedTypeReferenceDirectives().get(ref.fileName);
- if (referenced !== undefined && referenced.resolvedFileName === searchSourceFile.fileName) {
- refs.push({ kind: "reference", referencingFile: referencingFile, ref: ref });
- }
- }
- }
- forEachImport(referencingFile, function (_importDecl, moduleSpecifier) {
- var moduleSymbol = checker.getSymbolAtLocation(moduleSpecifier);
- if (moduleSymbol === searchModuleSymbol) {
- refs.push({ kind: "import", literal: moduleSpecifier });
- }
- });
- }
- return refs;
- }
- FindAllReferences.findModuleReferences = findModuleReferences;
- /** Returns a map from a module symbol Id to all import statements that directly reference the module. */
- function getDirectImportsMap(sourceFiles, checker, cancellationToken) {
- var map = ts.createMap();
- for (var _i = 0, sourceFiles_5 = sourceFiles; _i < sourceFiles_5.length; _i++) {
- var sourceFile = sourceFiles_5[_i];
- cancellationToken.throwIfCancellationRequested();
- forEachImport(sourceFile, function (importDecl, moduleSpecifier) {
- var moduleSymbol = checker.getSymbolAtLocation(moduleSpecifier);
- if (moduleSymbol) {
- var id = ts.getSymbolId(moduleSymbol).toString();
- var imports = map.get(id);
- if (!imports) {
- map.set(id, imports = []);
- }
- imports.push(importDecl);
- }
- });
- }
- return map;
- }
- /** Iterates over all statements at the top level or in module declarations. Returns the first truthy result. */
- function forEachPossibleImportOrExportStatement(sourceFileLike, action) {
- return ts.forEach(sourceFileLike.kind === 272 /* SourceFile */ ? sourceFileLike.statements : sourceFileLike.body.statements, function (statement) {
- return action(statement) || (isAmbientModuleDeclaration(statement) && ts.forEach(statement.body && statement.body.statements, action));
- });
- }
- /** Calls `action` for each import, re-export, or require() in a file. */
- function forEachImport(sourceFile, action) {
- if (sourceFile.externalModuleIndicator || sourceFile.imports !== undefined) {
- for (var _i = 0, _a = sourceFile.imports; _i < _a.length; _i++) {
- var moduleSpecifier = _a[_i];
- action(importerFromModuleSpecifier(moduleSpecifier), moduleSpecifier);
- }
- }
- else {
- forEachPossibleImportOrExportStatement(sourceFile, function (statement) {
- switch (statement.kind) {
- case 248 /* ExportDeclaration */:
- case 242 /* ImportDeclaration */: {
- var decl = statement;
- if (decl.moduleSpecifier && decl.moduleSpecifier.kind === 9 /* StringLiteral */) {
- action(decl, decl.moduleSpecifier);
- }
- break;
- }
- case 241 /* ImportEqualsDeclaration */: {
- var decl = statement;
- var moduleReference = decl.moduleReference;
- if (moduleReference.kind === 252 /* ExternalModuleReference */ &&
- moduleReference.expression.kind === 9 /* StringLiteral */) {
- action(decl, moduleReference.expression);
- }
- break;
- }
- }
- });
- }
- }
- function importerFromModuleSpecifier(moduleSpecifier) {
- var decl = moduleSpecifier.parent;
- switch (decl.kind) {
- case 185 /* CallExpression */:
- case 242 /* ImportDeclaration */:
- case 248 /* ExportDeclaration */:
- return decl;
- case 252 /* ExternalModuleReference */:
- return decl.parent;
- default:
- ts.Debug.fail("Unexpected module specifier parent: " + decl.kind);
- }
- }
- /**
- * Given a local reference, we might notice that it's an import/export and recursively search for references of that.
- * If at an import, look locally for the symbol it imports.
- * If an an export, look for all imports of it.
- * This doesn't handle export specifiers; that is done in `getReferencesAtExportSpecifier`.
- * @param comingFromExport If we are doing a search for all exports, don't bother looking backwards for the imported symbol, since that's the reason we're here.
- */
- function getImportOrExportSymbol(node, symbol, checker, comingFromExport) {
- return comingFromExport ? getExport() : getExport() || getImport();
- function getExport() {
- var parent = node.parent;
- if (symbol.exportSymbol) {
- if (parent.kind === 183 /* PropertyAccessExpression */) {
- // When accessing an export of a JS module, there's no alias. The symbol will still be flagged as an export even though we're at the use.
- // So check that we are at the declaration.
- return symbol.declarations.some(function (d) { return d === parent; }) && ts.isBinaryExpression(parent.parent)
- ? getSpecialPropertyExport(parent.parent, /*useLhsSymbol*/ false)
- : undefined;
- }
- else {
- return exportInfo(symbol.exportSymbol, getExportKindForDeclaration(parent));
- }
- }
- else {
- var exportNode = getExportNode(parent, node);
- if (exportNode && ts.hasModifier(exportNode, 1 /* Export */)) {
- if (ts.isImportEqualsDeclaration(exportNode) && exportNode.moduleReference === node) {
- // We're at `Y` in `export import X = Y`. This is not the exported symbol, the left-hand-side is. So treat this as an import statement.
- if (comingFromExport) {
- return undefined;
- }
- var lhsSymbol = checker.getSymbolAtLocation(exportNode.name);
- return { kind: 0 /* Import */, symbol: lhsSymbol, isNamedImport: false };
- }
- else {
- return exportInfo(symbol, getExportKindForDeclaration(exportNode));
- }
- }
- // If we are in `export = a;` or `export default a;`, `parent` is the export assignment.
- else if (ts.isExportAssignment(parent)) {
- return getExportAssignmentExport(parent);
- }
- // If we are in `export = class A {};` (or `export = class A {};`) at `A`, `parent.parent` is the export assignment.
- else if (ts.isExportAssignment(parent.parent)) {
- return getExportAssignmentExport(parent.parent);
- }
- // Similar for `module.exports =` and `exports.A =`.
- else if (ts.isBinaryExpression(parent)) {
- return getSpecialPropertyExport(parent, /*useLhsSymbol*/ true);
- }
- else if (ts.isBinaryExpression(parent.parent)) {
- return getSpecialPropertyExport(parent.parent, /*useLhsSymbol*/ true);
- }
- }
- function getExportAssignmentExport(ex) {
- // Get the symbol for the `export =` node; its parent is the module it's the export of.
- var exportingModuleSymbol = ts.Debug.assertDefined(ex.symbol.parent, "Expected export symbol to have a parent");
- var exportKind = ex.isExportEquals ? 2 /* ExportEquals */ : 1 /* Default */;
- return { kind: 1 /* Export */, symbol: symbol, exportInfo: { exportingModuleSymbol: exportingModuleSymbol, exportKind: exportKind } };
- }
- function getSpecialPropertyExport(node, useLhsSymbol) {
- var kind;
- switch (ts.getSpecialPropertyAssignmentKind(node)) {
- case 1 /* ExportsProperty */:
- kind = 0 /* Named */;
- break;
- case 2 /* ModuleExports */:
- kind = 2 /* ExportEquals */;
- break;
- default:
- return undefined;
- }
- var sym = useLhsSymbol ? checker.getSymbolAtLocation(ts.cast(node.left, ts.isPropertyAccessExpression).name) : symbol;
- // Better detection for GH#20803
- if (sym && !(checker.getMergedSymbol(sym.parent).flags & 1536 /* Module */)) {
- ts.Debug.fail("Special property assignment kind does not have a module as its parent. Assignment is " + ts.Debug.showSymbol(sym) + ", parent is " + ts.Debug.showSymbol(sym.parent));
- }
- return sym && exportInfo(sym, kind);
- }
- }
- function getImport() {
- var isImport = isNodeImport(node);
- if (!isImport)
- return undefined;
- // A symbol being imported is always an alias. So get what that aliases to find the local symbol.
- var importedSymbol = checker.getImmediateAliasedSymbol(symbol);
- if (!importedSymbol)
- return undefined;
- // Search on the local symbol in the exporting module, not the exported symbol.
- importedSymbol = skipExportSpecifierSymbol(importedSymbol, checker);
- // Similarly, skip past the symbol for 'export ='
- if (importedSymbol.escapedName === "export=") {
- importedSymbol = getExportEqualsLocalSymbol(importedSymbol, checker);
- }
- // If the import has a different name than the export, do not continue searching.
- // If `importedName` is undefined, do continue searching as the export is anonymous.
- // (All imports returned from this function will be ignored anyway if we are in rename and this is a not a named export.)
- var importedName = symbolName(importedSymbol);
- if (importedName === undefined || importedName === "default" /* Default */ || importedName === symbol.escapedName) {
- return __assign({ kind: 0 /* Import */, symbol: importedSymbol }, isImport);
- }
- }
- function exportInfo(symbol, kind) {
- var exportInfo = getExportInfo(symbol, kind, checker);
- return exportInfo && { kind: 1 /* Export */, symbol: symbol, exportInfo: exportInfo };
- }
- // Not meant for use with export specifiers or export assignment.
- function getExportKindForDeclaration(node) {
- return ts.hasModifier(node, 512 /* Default */) ? 1 /* Default */ : 0 /* Named */;
- }
- }
- FindAllReferences.getImportOrExportSymbol = getImportOrExportSymbol;
- function getExportEqualsLocalSymbol(importedSymbol, checker) {
- if (importedSymbol.flags & 2097152 /* Alias */) {
- return ts.Debug.assertDefined(checker.getImmediateAliasedSymbol(importedSymbol));
- }
- var decl = importedSymbol.valueDeclaration;
- if (ts.isExportAssignment(decl)) { // `export = class {}`
- return ts.Debug.assertDefined(decl.expression.symbol);
- }
- else if (ts.isBinaryExpression(decl)) { // `module.exports = class {}`
- return ts.Debug.assertDefined(decl.right.symbol);
- }
- return ts.Debug.fail();
- }
- // If a reference is a class expression, the exported node would be its parent.
- // If a reference is a variable declaration, the exported node would be the variable statement.
- function getExportNode(parent, node) {
- if (parent.kind === 230 /* VariableDeclaration */) {
- var p = parent;
- return p.name !== node ? undefined :
- p.parent.kind === 267 /* CatchClause */ ? undefined : p.parent.parent.kind === 212 /* VariableStatement */ ? p.parent.parent : undefined;
- }
- else {
- return parent;
- }
- }
- function isNodeImport(node) {
- var parent = node.parent;
- switch (parent.kind) {
- case 241 /* ImportEqualsDeclaration */:
- return parent.name === node && isExternalModuleImportEquals(parent)
- ? { isNamedImport: false }
- : undefined;
- case 246 /* ImportSpecifier */:
- // For a rename import `{ foo as bar }`, don't search for the imported symbol. Just find local uses of `bar`.
- return parent.propertyName ? undefined : { isNamedImport: true };
- case 243 /* ImportClause */:
- case 244 /* NamespaceImport */:
- ts.Debug.assert(parent.name === node);
- return { isNamedImport: false };
- default:
- return undefined;
- }
- }
- function getExportInfo(exportSymbol, exportKind, checker) {
- var moduleSymbol = exportSymbol.parent;
- if (!moduleSymbol)
- return undefined; // This can happen if an `export` is not at the top-level (which is a compile error).
- var exportingModuleSymbol = checker.getMergedSymbol(moduleSymbol); // Need to get merged symbol in case there's an augmentation.
- // `export` may appear in a namespace. In that case, just rely on global search.
- return ts.isExternalModuleSymbol(exportingModuleSymbol) ? { exportingModuleSymbol: exportingModuleSymbol, exportKind: exportKind } : undefined;
- }
- FindAllReferences.getExportInfo = getExportInfo;
- function symbolName(symbol) {
- if (symbol.escapedName !== "default" /* Default */) {
- return symbol.escapedName;
- }
- return ts.forEach(symbol.declarations, function (decl) {
- var name = ts.getNameOfDeclaration(decl);
- return name && name.kind === 71 /* Identifier */ && name.escapedText;
- });
- }
- /** If at an export specifier, go to the symbol it refers to. */
- function skipExportSpecifierSymbol(symbol, checker) {
- // For `export { foo } from './bar", there's nothing to skip, because it does not create a new alias. But `export { foo } does.
- if (symbol.declarations) {
- for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) {
- var declaration = _a[_i];
- if (ts.isExportSpecifier(declaration) && !declaration.propertyName && !declaration.parent.parent.moduleSpecifier) {
- return checker.getExportSpecifierLocalTargetSymbol(declaration);
- }
- }
- }
- return symbol;
- }
- function getContainingModuleSymbol(importer, checker) {
- return checker.getMergedSymbol(getSourceFileLikeForImportDeclaration(importer).symbol);
- }
- function getSourceFileLikeForImportDeclaration(node) {
- if (node.kind === 185 /* CallExpression */) {
- return node.getSourceFile();
- }
- var parent = node.parent;
- if (parent.kind === 272 /* SourceFile */) {
- return parent;
- }
- ts.Debug.assert(parent.kind === 238 /* ModuleBlock */);
- return ts.cast(parent.parent, isAmbientModuleDeclaration);
- }
- function isAmbientModuleDeclaration(node) {
- return node.kind === 237 /* ModuleDeclaration */ && node.name.kind === 9 /* StringLiteral */;
- }
- function isExternalModuleImportEquals(_a) {
- var moduleReference = _a.moduleReference;
- return moduleReference.kind === 252 /* ExternalModuleReference */ && moduleReference.expression.kind === 9 /* StringLiteral */;
- }
- })(FindAllReferences = ts.FindAllReferences || (ts.FindAllReferences = {}));
-})(ts || (ts = {}));
-///
-/* @internal */
-var ts;
-(function (ts) {
- var FindAllReferences;
- (function (FindAllReferences) {
- function nodeEntry(node, isInString) {
- return { type: "node", node: node, isInString: isInString };
- }
- FindAllReferences.nodeEntry = nodeEntry;
- function findReferencedSymbols(program, cancellationToken, sourceFiles, sourceFile, position) {
- var node = ts.getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ true);
- var referencedSymbols = FindAllReferences.Core.getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, /*options*/ {});
- var checker = program.getTypeChecker();
- return !referencedSymbols || !referencedSymbols.length ? undefined : ts.mapDefined(referencedSymbols, function (_a) {
- var definition = _a.definition, references = _a.references;
- // Only include referenced symbols that have a valid definition.
- return definition && { definition: definitionToReferencedSymbolDefinitionInfo(definition, checker, node), references: references.map(toReferenceEntry) };
- });
- }
- FindAllReferences.findReferencedSymbols = findReferencedSymbols;
- function getImplementationsAtPosition(program, cancellationToken, sourceFiles, sourceFile, position) {
- // A node in a JSDoc comment can't have an implementation anyway.
- var node = ts.getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ false);
- var referenceEntries = getImplementationReferenceEntries(program, cancellationToken, sourceFiles, node, position);
- var checker = program.getTypeChecker();
- return ts.map(referenceEntries, function (entry) { return toImplementationLocation(entry, checker); });
- }
- FindAllReferences.getImplementationsAtPosition = getImplementationsAtPosition;
- function getImplementationReferenceEntries(program, cancellationToken, sourceFiles, node, position) {
- if (node.kind === 272 /* SourceFile */) {
- return undefined;
- }
- var checker = program.getTypeChecker();
- // If invoked directly on a shorthand property assignment, then return
- // the declaration of the symbol being assigned (not the symbol being assigned to).
- if (node.parent.kind === 269 /* ShorthandPropertyAssignment */) {
- var result_4 = [];
- FindAllReferences.Core.getReferenceEntriesForShorthandPropertyAssignment(node, checker, function (node) { return result_4.push(nodeEntry(node)); });
- return result_4;
- }
- else if (node.kind === 97 /* SuperKeyword */ || ts.isSuperProperty(node.parent)) {
- // References to and accesses on the super keyword only have one possible implementation, so no
- // need to "Find all References"
- var symbol = checker.getSymbolAtLocation(node);
- return symbol.valueDeclaration && [nodeEntry(symbol.valueDeclaration)];
- }
- else {
- // Perform "Find all References" and retrieve only those that are implementations
- return getReferenceEntriesForNode(position, node, program, sourceFiles, cancellationToken, { implementations: true });
- }
- }
- function findReferencedEntries(program, cancellationToken, sourceFiles, sourceFile, position, options) {
- var node = ts.getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ true);
- return ts.map(flattenEntries(FindAllReferences.Core.getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, options)), toReferenceEntry);
- }
- FindAllReferences.findReferencedEntries = findReferencedEntries;
- function getReferenceEntriesForNode(position, node, program, sourceFiles, cancellationToken, options) {
- if (options === void 0) { options = {}; }
- return flattenEntries(FindAllReferences.Core.getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, options));
- }
- FindAllReferences.getReferenceEntriesForNode = getReferenceEntriesForNode;
- function flattenEntries(referenceSymbols) {
- return referenceSymbols && ts.flatMap(referenceSymbols, function (r) { return r.references; });
- }
- function definitionToReferencedSymbolDefinitionInfo(def, checker, originalNode) {
- var info = (function () {
- switch (def.type) {
- case "symbol": {
- var symbol = def.symbol;
- var _a = getDefinitionKindAndDisplayParts(symbol, checker, originalNode), displayParts_1 = _a.displayParts, kind_1 = _a.kind;
- var name_4 = displayParts_1.map(function (p) { return p.text; }).join("");
- return { node: symbol.declarations ? ts.getNameOfDeclaration(ts.first(symbol.declarations)) || ts.first(symbol.declarations) : originalNode, name: name_4, kind: kind_1, displayParts: displayParts_1 };
- }
- case "label": {
- var node_3 = def.node;
- return { node: node_3, name: node_3.text, kind: "label" /* label */, displayParts: [ts.displayPart(node_3.text, ts.SymbolDisplayPartKind.text)] };
- }
- case "keyword": {
- var node_4 = def.node;
- var name_5 = ts.tokenToString(node_4.kind);
- return { node: node_4, name: name_5, kind: "keyword" /* keyword */, displayParts: [{ text: name_5, kind: "keyword" /* keyword */ }] };
- }
- case "this": {
- var node_5 = def.node;
- var symbol = checker.getSymbolAtLocation(node_5);
- var displayParts_2 = symbol && ts.SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(checker, symbol, node_5.getSourceFile(), ts.getContainerNode(node_5), node_5).displayParts;
- return { node: node_5, name: "this", kind: "var" /* variableElement */, displayParts: displayParts_2 };
- }
- case "string": {
- var node_6 = def.node;
- return { node: node_6, name: node_6.text, kind: "var" /* variableElement */, displayParts: [ts.displayPart(ts.getTextOfNode(node_6), ts.SymbolDisplayPartKind.stringLiteral)] };
- }
- default:
- return ts.Debug.assertNever(def);
- }
- })();
- var node = info.node, name = info.name, kind = info.kind, displayParts = info.displayParts;
- var sourceFile = node.getSourceFile();
- return {
- containerKind: "" /* unknown */,
- containerName: "",
- fileName: sourceFile.fileName,
- kind: kind,
- name: name,
- textSpan: ts.createTextSpanFromNode(node, sourceFile),
- displayParts: displayParts
- };
- }
- function getDefinitionKindAndDisplayParts(symbol, checker, node) {
- var meaning = FindAllReferences.Core.getIntersectingMeaningFromDeclarations(node, symbol);
- var enclosingDeclaration = ts.firstOrUndefined(symbol.declarations) || node;
- var _a = ts.SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(checker, symbol, enclosingDeclaration.getSourceFile(), enclosingDeclaration, enclosingDeclaration, meaning), displayParts = _a.displayParts, symbolKind = _a.symbolKind;
- return { displayParts: displayParts, kind: symbolKind };
- }
- function toReferenceEntry(entry) {
- if (entry.type === "span") {
- return { textSpan: entry.textSpan, fileName: entry.fileName, isWriteAccess: false, isDefinition: false };
- }
- var node = entry.node, isInString = entry.isInString;
- return {
- fileName: node.getSourceFile().fileName,
- textSpan: getTextSpan(node),
- isWriteAccess: isWriteAccessForReference(node),
- isDefinition: node.kind === 79 /* DefaultKeyword */
- || ts.isAnyDeclarationName(node)
- || ts.isLiteralComputedPropertyDeclarationName(node),
- isInString: isInString
- };
- }
- function toImplementationLocation(entry, checker) {
- if (entry.type === "node") {
- var node = entry.node;
- return __assign({ textSpan: getTextSpan(node), fileName: node.getSourceFile().fileName }, implementationKindDisplayParts(node, checker));
- }
- else {
- var textSpan = entry.textSpan, fileName = entry.fileName;
- return { textSpan: textSpan, fileName: fileName, kind: "" /* unknown */, displayParts: [] };
- }
- }
- function implementationKindDisplayParts(node, checker) {
- var symbol = checker.getSymbolAtLocation(ts.isDeclaration(node) && node.name ? node.name : node);
- if (symbol) {
- return getDefinitionKindAndDisplayParts(symbol, checker, node);
- }
- else if (node.kind === 182 /* ObjectLiteralExpression */) {
- return {
- kind: "interface" /* interfaceElement */,
- displayParts: [ts.punctuationPart(19 /* OpenParenToken */), ts.textPart("object literal"), ts.punctuationPart(20 /* CloseParenToken */)]
- };
- }
- else if (node.kind === 203 /* ClassExpression */) {
- return {
- kind: "local class" /* localClassElement */,
- displayParts: [ts.punctuationPart(19 /* OpenParenToken */), ts.textPart("anonymous local class"), ts.punctuationPart(20 /* CloseParenToken */)]
- };
- }
- else {
- return { kind: ts.getNodeKind(node), displayParts: [] };
- }
- }
- function toHighlightSpan(entry) {
- if (entry.type === "span") {
- var fileName_1 = entry.fileName, textSpan = entry.textSpan;
- return { fileName: fileName_1, span: { textSpan: textSpan, kind: "reference" /* reference */ } };
- }
- var node = entry.node, isInString = entry.isInString;
- var fileName = entry.node.getSourceFile().fileName;
- var writeAccess = isWriteAccessForReference(node);
- var span = {
- textSpan: getTextSpan(node),
- kind: writeAccess ? "writtenReference" /* writtenReference */ : "reference" /* reference */,
- isInString: isInString
- };
- return { fileName: fileName, span: span };
- }
- FindAllReferences.toHighlightSpan = toHighlightSpan;
- function getTextSpan(node) {
- var start = node.getStart();
- var end = node.getEnd();
- if (node.kind === 9 /* StringLiteral */) {
- start += 1;
- end -= 1;
- }
- return ts.createTextSpanFromBounds(start, end);
- }
- /** A node is considered a writeAccess iff it is a name of a declaration or a target of an assignment */
- function isWriteAccessForReference(node) {
- return node.kind === 79 /* DefaultKeyword */ || ts.isAnyDeclarationName(node) || ts.isWriteAccess(node);
- }
- })(FindAllReferences = ts.FindAllReferences || (ts.FindAllReferences = {}));
-})(ts || (ts = {}));
-/** Encapsulates the core find-all-references algorithm. */
-/* @internal */
-(function (ts) {
- var FindAllReferences;
- (function (FindAllReferences) {
- var Core;
- (function (Core) {
- /** Core find-all-references algorithm. Handles special cases before delegating to `getReferencedSymbolsForSymbol`. */
- function getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, options) {
- if (options === void 0) { options = {}; }
- if (ts.isSourceFile(node)) {
- var reference = ts.GoToDefinition.getReferenceAtPosition(node, position, program);
- return reference && getReferencedSymbolsForModule(program, program.getTypeChecker().getMergedSymbol(reference.file.symbol), sourceFiles);
- }
- if (!options.implementations) {
- var special = getReferencedSymbolsSpecial(node, sourceFiles, cancellationToken);
- if (special) {
- return special;
- }
- }
- var checker = program.getTypeChecker();
- var symbol = checker.getSymbolAtLocation(node);
- // Could not find a symbol e.g. unknown identifier
- if (!symbol) {
- // String literal might be a property (and thus have a symbol), so do this here rather than in getReferencedSymbolsSpecial.
- return !options.implementations && ts.isStringLiteral(node) ? getReferencesForStringLiteral(node, sourceFiles, cancellationToken) : undefined;
- }
- if (symbol.flags & 1536 /* Module */ && isModuleReferenceLocation(node)) {
- return getReferencedSymbolsForModule(program, symbol, sourceFiles);
- }
- return getReferencedSymbolsForSymbol(symbol, node, sourceFiles, checker, cancellationToken, options);
- }
- Core.getReferencedSymbolsForNode = getReferencedSymbolsForNode;
- function isModuleReferenceLocation(node) {
- if (!ts.isStringLiteralLike(node)) {
- return false;
- }
- switch (node.parent.kind) {
- case 237 /* ModuleDeclaration */:
- case 252 /* ExternalModuleReference */:
- case 242 /* ImportDeclaration */:
- case 248 /* ExportDeclaration */:
- return true;
- case 185 /* CallExpression */:
- return ts.isRequireCall(node.parent, /*checkArgumentIsStringLiteral*/ false) || ts.isImportCall(node.parent);
- default:
- return false;
- }
- }
- function getReferencedSymbolsForModule(program, symbol, sourceFiles) {
- ts.Debug.assert(!!symbol.valueDeclaration);
- var references = FindAllReferences.findModuleReferences(program, sourceFiles, symbol).map(function (reference) {
- if (reference.kind === "import") {
- return { type: "node", node: reference.literal };
- }
- else {
- return {
- type: "span",
- fileName: reference.referencingFile.fileName,
- textSpan: ts.createTextSpanFromRange(reference.ref),
- };
- }
- });
- for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) {
- var decl = _a[_i];
- switch (decl.kind) {
- case 272 /* SourceFile */:
- // Don't include the source file itself. (This may not be ideal behavior, but awkward to include an entire file as a reference.)
- break;
- case 237 /* ModuleDeclaration */:
- references.push({ type: "node", node: decl.name });
- break;
- default:
- ts.Debug.fail("Expected a module symbol to be declared by a SourceFile or ModuleDeclaration.");
- }
- }
- return [{ definition: { type: "symbol", symbol: symbol }, references: references }];
- }
- /** getReferencedSymbols for special node kinds. */
- function getReferencedSymbolsSpecial(node, sourceFiles, cancellationToken) {
- if (ts.isTypeKeyword(node.kind)) {
- return getAllReferencesForKeyword(sourceFiles, node.kind, cancellationToken);
- }
- // Labels
- if (ts.isJumpStatementTarget(node)) {
- var labelDefinition = ts.getTargetLabel(node.parent, node.text);
- // if we have a label definition, look within its statement for references, if not, then
- // the label is undefined and we have no results..
- return labelDefinition && getLabelReferencesInNode(labelDefinition.parent, labelDefinition);
- }
- else if (ts.isLabelOfLabeledStatement(node)) {
- // it is a label definition and not a target, search within the parent labeledStatement
- return getLabelReferencesInNode(node.parent, node);
- }
- if (ts.isThis(node)) {
- return getReferencesForThisKeyword(node, sourceFiles, cancellationToken);
- }
- if (node.kind === 97 /* SuperKeyword */) {
- return getReferencesForSuperKeyword(node);
- }
- return undefined;
- }
- /** Core find-all-references algorithm for a normal symbol. */
- function getReferencedSymbolsForSymbol(symbol, node, sourceFiles, checker, cancellationToken, options) {
- symbol = skipPastExportOrImportSpecifierOrUnion(symbol, node, checker) || symbol;
- // Compute the meaning from the location and the symbol it references
- var searchMeaning = getIntersectingMeaningFromDeclarations(node, symbol);
- var result = [];
- var state = new State(sourceFiles, getSpecialSearchKind(node), checker, cancellationToken, searchMeaning, options, result);
- if (node.kind === 79 /* DefaultKeyword */) {
- addReference(node, symbol, state);
- searchForImportsOfExport(node, symbol, { exportingModuleSymbol: ts.Debug.assertDefined(symbol.parent, "Expected export symbol to have a parent"), exportKind: 1 /* Default */ }, state);
- }
- else {
- var search = state.createSearch(node, symbol, /*comingFrom*/ undefined, { allSearchSymbols: populateSearchSymbolSet(symbol, node, checker, options.implementations) });
- // Try to get the smallest valid scope that we can limit our search to;
- // otherwise we'll need to search globally (i.e. include each file).
- var scope = getSymbolScope(symbol);
- if (scope) {
- getReferencesInContainer(scope, scope.getSourceFile(), search, state);
- }
- else {
- // Global search
- for (var _i = 0, _a = state.sourceFiles; _i < _a.length; _i++) {
- var sourceFile = _a[_i];
- state.cancellationToken.throwIfCancellationRequested();
- searchForName(sourceFile, search, state);
- }
- }
- }
- return result;
- }
- function getSpecialSearchKind(node) {
- switch (node.kind) {
- case 123 /* ConstructorKeyword */:
- return 1 /* Constructor */;
- case 71 /* Identifier */:
- if (ts.isClassLike(node.parent)) {
- ts.Debug.assert(node.parent.name === node);
- return 2 /* Class */;
- }
- // falls through
- default:
- return 0 /* None */;
- }
- }
- /** Handle a few special cases relating to export/import specifiers. */
- function skipPastExportOrImportSpecifierOrUnion(symbol, node, checker) {
- var parent = node.parent;
- if (ts.isExportSpecifier(parent)) {
- return getLocalSymbolForExportSpecifier(node, symbol, parent, checker);
- }
- if (ts.isImportSpecifier(parent) && parent.propertyName === node) {
- // We're at `foo` in `import { foo as bar }`. Probably intended to find all refs on the original, not just on the import.
- return checker.getImmediateAliasedSymbol(symbol);
- }
- // If the symbol is declared as part of a declaration like `{ type: "a" } | { type: "b" }`, use the property on the union type to get more references.
- return ts.firstDefined(symbol.declarations, function (decl) {
- if (!decl.parent) {
- // Assertions for GH#21814. We should be handling SourceFile symbols in `getReferencedSymbolsForModule` instead of getting here.
- ts.Debug.assert(decl.kind === 272 /* SourceFile */);
- ts.Debug.fail("Unexpected symbol at " + ts.Debug.showSyntaxKind(node) + ": " + ts.Debug.showSymbol(symbol));
- }
- return ts.isTypeLiteralNode(decl.parent) && ts.isUnionTypeNode(decl.parent.parent)
- ? checker.getPropertyOfType(checker.getTypeFromTypeNode(decl.parent.parent), symbol.name)
- : undefined;
- });
- }
- var SpecialSearchKind;
- (function (SpecialSearchKind) {
- SpecialSearchKind[SpecialSearchKind["None"] = 0] = "None";
- SpecialSearchKind[SpecialSearchKind["Constructor"] = 1] = "Constructor";
- SpecialSearchKind[SpecialSearchKind["Class"] = 2] = "Class";
- })(SpecialSearchKind || (SpecialSearchKind = {}));
- /**
- * Holds all state needed for the finding references.
- * Unlike `Search`, there is only one `State`.
- */
- var State = /** @class */ (function () {
- function State(sourceFiles,
- /** True if we're searching for constructor references. */
- specialSearchKind, checker, cancellationToken, searchMeaning, options, result) {
- this.sourceFiles = sourceFiles;
- this.specialSearchKind = specialSearchKind;
- this.checker = checker;
- this.cancellationToken = cancellationToken;
- this.searchMeaning = searchMeaning;
- this.options = options;
- this.result = result;
- /** Cache for `explicitlyinheritsFrom`. */
- this.inheritsFromCache = ts.createMap();
- /**
- * Type nodes can contain multiple references to the same type. For example:
- * let x: Foo & (Foo & Bar) = ...
- * Because we are returning the implementation locations and not the identifier locations,
- * duplicate entries would be returned here as each of the type references is part of
- * the same implementation. For that reason, check before we add a new entry.
- */
- this.markSeenContainingTypeReference = ts.nodeSeenTracker();
- /**
- * It's possible that we will encounter the right side of `export { foo as bar } from "x";` more than once.
- * For example:
- * // b.ts
- * export { foo as bar } from "./a";
- * import { bar } from "./b";
- *
- * Normally at `foo as bar` we directly add `foo` and do not locally search for it (since it doesn't declare a local).
- * But another reference to it may appear in the same source file.
- * See `tests/cases/fourslash/transitiveExportImports3.ts`.
- */
- this.markSeenReExportRHS = ts.nodeSeenTracker();
- this.symbolIdToReferences = [];
- // Source file ID → symbol ID → Whether the symbol has been searched for in the source file.
- this.sourceFileToSeenSymbols = [];
- this.includedSourceFiles = ts.arrayToSet(sourceFiles, function (s) { return s.fileName; });
- }
- State.prototype.includesSourceFile = function (sourceFile) {
- return this.includedSourceFiles.has(sourceFile.fileName);
- };
- /** Gets every place to look for references of an exported symbols. See `ImportsResult` in `importTracker.ts` for more documentation. */
- State.prototype.getImportSearches = function (exportSymbol, exportInfo) {
- if (!this.importTracker)
- this.importTracker = FindAllReferences.createImportTracker(this.sourceFiles, this.checker, this.cancellationToken);
- return this.importTracker(exportSymbol, exportInfo, this.options.isForRename);
- };
- /** @param allSearchSymbols set of additinal symbols for use by `includes`. */
- State.prototype.createSearch = function (location, symbol, comingFrom, searchOptions) {
- if (searchOptions === void 0) { searchOptions = {}; }
- // Note: if this is an external module symbol, the name doesn't include quotes.
- // Note: getLocalSymbolForExportDefault handles `export default class C {}`, but not `export default C` or `export { C as default }`.
- // The other two forms seem to be handled downstream (e.g. in `skipPastExportOrImportSpecifier`), so special-casing the first form
- // here appears to be intentional).
- var _a = searchOptions.text, text = _a === void 0 ? ts.stripQuotes(ts.unescapeLeadingUnderscores((ts.getLocalSymbolForExportDefault(symbol) || symbol).escapedName)) : _a, allSearchSymbols = searchOptions.allSearchSymbols;
- var escapedText = ts.escapeLeadingUnderscores(text);
- var parents = this.options.implementations && getParentSymbolsOfPropertyAccess(location, symbol, this.checker);
- return {
- symbol: symbol, comingFrom: comingFrom, text: text, escapedText: escapedText, parents: parents,
- includes: function (referenceSymbol) { return allSearchSymbols ? ts.contains(allSearchSymbols, referenceSymbol) : referenceSymbol === symbol; },
- };
- };
- /**
- * Callback to add references for a particular searched symbol.
- * This initializes a reference group, so only call this if you will add at least one reference.
- */
- State.prototype.referenceAdder = function (searchSymbol) {
- var symbolId = ts.getSymbolId(searchSymbol);
- var references = this.symbolIdToReferences[symbolId];
- if (!references) {
- references = this.symbolIdToReferences[symbolId] = [];
- this.result.push({ definition: { type: "symbol", symbol: searchSymbol }, references: references });
- }
- return function (node) { return references.push(FindAllReferences.nodeEntry(node)); };
- };
- /** Add a reference with no associated definition. */
- State.prototype.addStringOrCommentReference = function (fileName, textSpan) {
- this.result.push({
- definition: undefined,
- references: [{ type: "span", fileName: fileName, textSpan: textSpan }]
- });
- };
- /** Returns `true` the first time we search for a symbol in a file and `false` afterwards. */
- State.prototype.markSearchedSymbol = function (sourceFile, symbol) {
- var sourceId = ts.getNodeId(sourceFile);
- var symbolId = ts.getSymbolId(symbol);
- var seenSymbols = this.sourceFileToSeenSymbols[sourceId] || (this.sourceFileToSeenSymbols[sourceId] = []);
- return !seenSymbols[symbolId] && (seenSymbols[symbolId] = true);
- };
- return State;
- }());
- /** Search for all imports of a given exported symbol using `State.getImportSearches`. */
- function searchForImportsOfExport(exportLocation, exportSymbol, exportInfo, state) {
- var _a = state.getImportSearches(exportSymbol, exportInfo), importSearches = _a.importSearches, singleReferences = _a.singleReferences, indirectUsers = _a.indirectUsers;
- // For `import { foo as bar }` just add the reference to `foo`, and don't otherwise search in the file.
- if (singleReferences.length) {
- var addRef = state.referenceAdder(exportSymbol);
- for (var _i = 0, singleReferences_1 = singleReferences; _i < singleReferences_1.length; _i++) {
- var singleRef = singleReferences_1[_i];
- addRef(singleRef);
- }
- }
- // For each import, find all references to that import in its source file.
- for (var _b = 0, importSearches_1 = importSearches; _b < importSearches_1.length; _b++) {
- var _c = importSearches_1[_b], importLocation = _c[0], importSymbol = _c[1];
- getReferencesInSourceFile(importLocation.getSourceFile(), state.createSearch(importLocation, importSymbol, 1 /* Export */), state);
- }
- if (indirectUsers.length) {
- var indirectSearch = void 0;
- switch (exportInfo.exportKind) {
- case 0 /* Named */:
- indirectSearch = state.createSearch(exportLocation, exportSymbol, 1 /* Export */);
- break;
- case 1 /* Default */:
- // Search for a property access to '.default'. This can't be renamed.
- indirectSearch = state.options.isForRename ? undefined : state.createSearch(exportLocation, exportSymbol, 1 /* Export */, { text: "default" });
- break;
- case 2 /* ExportEquals */:
- break;
- }
- if (indirectSearch) {
- for (var _d = 0, indirectUsers_1 = indirectUsers; _d < indirectUsers_1.length; _d++) {
- var indirectUser = indirectUsers_1[_d];
- searchForName(indirectUser, indirectSearch, state);
- }
- }
- }
- }
- // Go to the symbol we imported from and find references for it.
- function searchForImportedSymbol(symbol, state) {
- for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) {
- var declaration = _a[_i];
- var exportingFile = declaration.getSourceFile();
- if (state.includesSourceFile(exportingFile)) {
- getReferencesInSourceFile(exportingFile, state.createSearch(declaration, symbol, 0 /* Import */), state);
- }
- }
- }
- /** Search for all occurences of an identifier in a source file (and filter out the ones that match). */
- function searchForName(sourceFile, search, state) {
- if (ts.getNameTable(sourceFile).get(search.escapedText) !== undefined) {
- getReferencesInSourceFile(sourceFile, search, state);
- }
- }
- function getPropertySymbolOfDestructuringAssignment(location, checker) {
- return ts.isArrayLiteralOrObjectLiteralDestructuringPattern(location.parent.parent) &&
- checker.getPropertySymbolOfDestructuringAssignment(location);
- }
- function getObjectBindingElementWithoutPropertyName(symbol) {
- var bindingElement = ts.getDeclarationOfKind(symbol, 180 /* BindingElement */);
- if (bindingElement &&
- bindingElement.parent.kind === 178 /* ObjectBindingPattern */ &&
- !bindingElement.propertyName) {
- return bindingElement;
- }
- }
- function getPropertySymbolOfObjectBindingPatternWithoutPropertyName(symbol, checker) {
- var bindingElement = getObjectBindingElementWithoutPropertyName(symbol);
- if (!bindingElement)
- return undefined;
- var typeOfPattern = checker.getTypeAtLocation(bindingElement.parent);
- var propSymbol = typeOfPattern && checker.getPropertyOfType(typeOfPattern, bindingElement.name.text);
- if (propSymbol && propSymbol.flags & 98304 /* Accessor */) {
- // See GH#16922
- ts.Debug.assert(!!(propSymbol.flags & 33554432 /* Transient */));
- return propSymbol.target;
- }
- return propSymbol;
- }
- /**
- * Determines the smallest scope in which a symbol may have named references.
- * Note that not every construct has been accounted for. This function can
- * probably be improved.
- *
- * @returns undefined if the scope cannot be determined, implying that
- * a reference to a symbol can occur anywhere.
- */
- function getSymbolScope(symbol) {
- // If this is the symbol of a named function expression or named class expression,
- // then named references are limited to its own scope.
- var declarations = symbol.declarations, flags = symbol.flags, parent = symbol.parent, valueDeclaration = symbol.valueDeclaration;
- if (valueDeclaration && (valueDeclaration.kind === 190 /* FunctionExpression */ || valueDeclaration.kind === 203 /* ClassExpression */)) {
- return valueDeclaration;
- }
- if (!declarations) {
- return undefined;
- }
- // If this is private property or method, the scope is the containing class
- if (flags & (4 /* Property */ | 8192 /* Method */)) {
- var privateDeclaration = ts.find(declarations, function (d) { return ts.hasModifier(d, 8 /* Private */); });
- if (privateDeclaration) {
- return ts.getAncestor(privateDeclaration, 233 /* ClassDeclaration */);
- }
- // Else this is a public property and could be accessed from anywhere.
- return undefined;
- }
- // If symbol is of object binding pattern element without property name we would want to
- // look for property too and that could be anywhere
- if (getObjectBindingElementWithoutPropertyName(symbol)) {
- return undefined;
- }
- /*
- If the symbol has a parent, it's globally visible unless:
- - It's a private property (handled above).
- - It's a type parameter.
- - The parent is an external module: then we should only search in the module (and recurse on the export later).
- - But if the parent has `export as namespace`, the symbol is globally visible through that namespace.
- */
- var exposedByParent = parent && !(symbol.flags & 262144 /* TypeParameter */);
- if (exposedByParent && !((parent.flags & 1536 /* Module */) && ts.isExternalModuleSymbol(parent) && !parent.globalExports)) {
- return undefined;
- }
- var scope;
- for (var _i = 0, declarations_9 = declarations; _i < declarations_9.length; _i++) {
- var declaration = declarations_9[_i];
- var container = ts.getContainerNode(declaration);
- if (scope && scope !== container) {
- // Different declarations have different containers, bail out
- return undefined;
- }
- if (!container || container.kind === 272 /* SourceFile */ && !ts.isExternalOrCommonJsModule(container)) {
- // This is a global variable and not an external module, any declaration defined
- // within this scope is visible outside the file
- return undefined;
- }
- // The search scope is the container node
- scope = container;
- }
- // If symbol.parent, this means we are in an export of an external module. (Otherwise we would have returned `undefined` above.)
- // For an export of a module, we may be in a declaration file, and it may be accessed elsewhere. E.g.:
- // declare module "a" { export type T = number; }
- // declare module "b" { import { T } from "a"; export const x: T; }
- // So we must search the whole source file. (Because we will mark the source file as seen, we we won't return to it when searching for imports.)
- return exposedByParent ? scope.getSourceFile() : scope;
- }
- /** Used as a quick check for whether a symbol is used at all in a file (besides its definition). */
- function isSymbolReferencedInFile(definition, checker, sourceFile) {
- var symbol = checker.getSymbolAtLocation(definition);
- if (!symbol)
- return true; // Be lenient with invalid code.
- return getPossibleSymbolReferencePositions(sourceFile, symbol.name).some(function (position) {
- var token = ts.tryCast(ts.getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ true), ts.isIdentifier);
- return token && token !== definition && token.escapedText === definition.escapedText && checker.getSymbolAtLocation(token) === symbol;
- });
- }
- Core.isSymbolReferencedInFile = isSymbolReferencedInFile;
- function getPossibleSymbolReferencePositions(sourceFile, symbolName, container) {
- if (container === void 0) { container = sourceFile; }
- var positions = [];
- /// TODO: Cache symbol existence for files to save text search
- // Also, need to make this work for unicode escapes.
- // Be resilient in the face of a symbol with no name or zero length name
- if (!symbolName || !symbolName.length) {
- return positions;
- }
- var text = sourceFile.text;
- var sourceLength = text.length;
- var symbolNameLength = symbolName.length;
- var position = text.indexOf(symbolName, container.pos);
- while (position >= 0) {
- // If we are past the end, stop looking
- if (position > container.end)
- break;
- // We found a match. Make sure it's not part of a larger word (i.e. the char
- // before and after it have to be a non-identifier char).
- var endPosition = position + symbolNameLength;
- if ((position === 0 || !ts.isIdentifierPart(text.charCodeAt(position - 1), 6 /* Latest */)) &&
- (endPosition === sourceLength || !ts.isIdentifierPart(text.charCodeAt(endPosition), 6 /* Latest */))) {
- // Found a real match. Keep searching.
- positions.push(position);
- }
- position = text.indexOf(symbolName, position + symbolNameLength + 1);
- }
- return positions;
- }
- function getLabelReferencesInNode(container, targetLabel) {
- var sourceFile = container.getSourceFile();
- var labelName = targetLabel.text;
- var references = ts.mapDefined(getPossibleSymbolReferencePositions(sourceFile, labelName, container), function (position) {
- var node = ts.getTouchingWord(sourceFile, position, /*includeJsDocComment*/ false);
- // Only pick labels that are either the target label, or have a target that is the target label
- return node && (node === targetLabel || (ts.isJumpStatementTarget(node) && ts.getTargetLabel(node, labelName) === targetLabel)) ? FindAllReferences.nodeEntry(node) : undefined;
- });
- return [{ definition: { type: "label", node: targetLabel }, references: references }];
- }
- function isValidReferencePosition(node, searchSymbolName) {
- // Compare the length so we filter out strict superstrings of the symbol we are looking for
- switch (node.kind) {
- case 71 /* Identifier */:
- return node.text.length === searchSymbolName.length;
- case 9 /* StringLiteral */:
- return (ts.isLiteralNameOfPropertyDeclarationOrIndexAccess(node) || isNameOfExternalModuleImportOrDeclaration(node)) &&
- node.text.length === searchSymbolName.length;
- case 8 /* NumericLiteral */:
- return ts.isLiteralNameOfPropertyDeclarationOrIndexAccess(node) && node.text.length === searchSymbolName.length;
- case 79 /* DefaultKeyword */:
- return "default".length === searchSymbolName.length;
- default:
- return false;
- }
- }
- function getAllReferencesForKeyword(sourceFiles, keywordKind, cancellationToken) {
- var references = ts.flatMap(sourceFiles, function (sourceFile) {
- cancellationToken.throwIfCancellationRequested();
- return ts.mapDefined(getPossibleSymbolReferencePositions(sourceFile, ts.tokenToString(keywordKind), sourceFile), function (position) {
- var referenceLocation = ts.getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ true);
- return referenceLocation.kind === keywordKind ? FindAllReferences.nodeEntry(referenceLocation) : undefined;
- });
- });
- return references.length ? [{ definition: { type: "keyword", node: references[0].node }, references: references }] : undefined;
- }
- function getReferencesInSourceFile(sourceFile, search, state) {
- state.cancellationToken.throwIfCancellationRequested();
- return getReferencesInContainer(sourceFile, sourceFile, search, state);
- }
- /**
- * Search within node "container" for references for a search value, where the search value is defined as a
- * tuple of(searchSymbol, searchText, searchLocation, and searchMeaning).
- * searchLocation: a node where the search value
- */
- function getReferencesInContainer(container, sourceFile, search, state) {
- if (!state.markSearchedSymbol(sourceFile, search.symbol)) {
- return;
- }
- for (var _i = 0, _a = getPossibleSymbolReferencePositions(sourceFile, search.text, container); _i < _a.length; _i++) {
- var position = _a[_i];
- getReferencesAtLocation(sourceFile, position, search, state);
- }
- }
- function getReferencesAtLocation(sourceFile, position, search, state) {
- var referenceLocation = ts.getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ true);
- if (!isValidReferencePosition(referenceLocation, search.text)) {
- // This wasn't the start of a token. Check to see if it might be a
- // match in a comment or string if that's what the caller is asking
- // for.
- if (!state.options.implementations && (state.options.findInStrings && ts.isInString(sourceFile, position) || state.options.findInComments && ts.isInNonReferenceComment(sourceFile, position))) {
- // In the case where we're looking inside comments/strings, we don't have
- // an actual definition. So just use 'undefined' here. Features like
- // 'Rename' won't care (as they ignore the definitions), and features like
- // 'FindReferences' will just filter out these results.
- state.addStringOrCommentReference(sourceFile.fileName, ts.createTextSpan(position, search.text.length));
- }
- return;
- }
- if (!(ts.getMeaningFromLocation(referenceLocation) & state.searchMeaning)) {
- return;
- }
- var referenceSymbol = state.checker.getSymbolAtLocation(referenceLocation);
- if (!referenceSymbol) {
- return;
- }
- var parent = referenceLocation.parent;
- if (ts.isImportSpecifier(parent) && parent.propertyName === referenceLocation) {
- // This is added through `singleReferences` in ImportsResult. If we happen to see it again, don't add it again.
- return;
- }
- if (ts.isExportSpecifier(parent)) {
- ts.Debug.assert(referenceLocation.kind === 71 /* Identifier */);
- getReferencesAtExportSpecifier(referenceLocation, referenceSymbol, parent, search, state);
- return;
- }
- var relatedSymbol = getRelatedSymbol(search, referenceSymbol, referenceLocation, state);
- if (!relatedSymbol) {
- getReferenceForShorthandProperty(referenceSymbol, search, state);
- return;
- }
- switch (state.specialSearchKind) {
- case 0 /* None */:
- addReference(referenceLocation, relatedSymbol, state);
- break;
- case 1 /* Constructor */:
- addConstructorReferences(referenceLocation, sourceFile, search, state);
- break;
- case 2 /* Class */:
- addClassStaticThisReferences(referenceLocation, search, state);
- break;
- default:
- ts.Debug.assertNever(state.specialSearchKind);
- }
- getImportOrExportReferences(referenceLocation, referenceSymbol, search, state);
- }
- function getReferencesAtExportSpecifier(referenceLocation, referenceSymbol, exportSpecifier, search, state) {
- var parent = exportSpecifier.parent, propertyName = exportSpecifier.propertyName, name = exportSpecifier.name;
- var exportDeclaration = parent.parent;
- var localSymbol = getLocalSymbolForExportSpecifier(referenceLocation, referenceSymbol, exportSpecifier, state.checker);
- if (!search.includes(localSymbol)) {
- return;
- }
- if (!propertyName) {
- addRef();
- }
- else if (referenceLocation === propertyName) {
- // For `export { foo as bar } from "baz"`, "`foo`" will be added from the singleReferences for import searches of the original export.
- // For `export { foo as bar };`, where `foo` is a local, so add it now.
- if (!exportDeclaration.moduleSpecifier) {
- addRef();
- }
- if (!state.options.isForRename && state.markSeenReExportRHS(name)) {
- addReference(name, referenceSymbol, state);
- }
- }
- else {
- if (state.markSeenReExportRHS(referenceLocation)) {
- addRef();
- }
- }
- // For `export { foo as bar }`, rename `foo`, but not `bar`.
- if (!(referenceLocation === propertyName && state.options.isForRename)) {
- var exportKind = referenceLocation.originalKeywordKind === 79 /* DefaultKeyword */ ? 1 /* Default */ : 0 /* Named */;
- var exportInfo = FindAllReferences.getExportInfo(referenceSymbol, exportKind, state.checker);
- ts.Debug.assert(!!exportInfo);
- searchForImportsOfExport(referenceLocation, referenceSymbol, exportInfo, state);
- }
- // At `export { x } from "foo"`, also search for the imported symbol `"foo".x`.
- if (search.comingFrom !== 1 /* Export */ && exportDeclaration.moduleSpecifier && !propertyName) {
- var imported = state.checker.getExportSpecifierLocalTargetSymbol(exportSpecifier);
- if (imported)
- searchForImportedSymbol(imported, state);
- }
- function addRef() {
- addReference(referenceLocation, localSymbol, state);
- }
- }
- function getLocalSymbolForExportSpecifier(referenceLocation, referenceSymbol, exportSpecifier, checker) {
- return isExportSpecifierAlias(referenceLocation, exportSpecifier) && checker.getExportSpecifierLocalTargetSymbol(exportSpecifier) || referenceSymbol;
- }
- function isExportSpecifierAlias(referenceLocation, exportSpecifier) {
- var parent = exportSpecifier.parent, propertyName = exportSpecifier.propertyName, name = exportSpecifier.name;
- ts.Debug.assert(propertyName === referenceLocation || name === referenceLocation);
- if (propertyName) {
- // Given `export { foo as bar } [from "someModule"]`: It's an alias at `foo`, but at `bar` it's a new symbol.
- return propertyName === referenceLocation;
- }
- else {
- // `export { foo } from "foo"` is a re-export.
- // `export { foo };` is not a re-export, it creates an alias for the local variable `foo`.
- return !parent.parent.moduleSpecifier;
- }
- }
- function getImportOrExportReferences(referenceLocation, referenceSymbol, search, state) {
- var importOrExport = FindAllReferences.getImportOrExportSymbol(referenceLocation, referenceSymbol, state.checker, search.comingFrom === 1 /* Export */);
- if (!importOrExport)
- return;
- var symbol = importOrExport.symbol;
- if (importOrExport.kind === 0 /* Import */) {
- if (!state.options.isForRename || importOrExport.isNamedImport) {
- searchForImportedSymbol(symbol, state);
- }
- }
- else {
- // We don't check for `state.isForRename`, even for default exports, because importers that previously matched the export name should be updated to continue matching.
- searchForImportsOfExport(referenceLocation, symbol, importOrExport.exportInfo, state);
- }
- }
- function getReferenceForShorthandProperty(_a, search, state) {
- var flags = _a.flags, valueDeclaration = _a.valueDeclaration;
- var shorthandValueSymbol = state.checker.getShorthandAssignmentValueSymbol(valueDeclaration);
- /*
- * Because in short-hand property assignment, an identifier which stored as name of the short-hand property assignment
- * has two meanings: property name and property value. Therefore when we do findAllReference at the position where
- * an identifier is declared, the language service should return the position of the variable declaration as well as
- * the position in short-hand property assignment excluding property accessing. However, if we do findAllReference at the
- * position of property accessing, the referenceEntry of such position will be handled in the first case.
- */
- if (!(flags & 33554432 /* Transient */) && search.includes(shorthandValueSymbol)) {
- addReference(ts.getNameOfDeclaration(valueDeclaration), shorthandValueSymbol, state);
- }
- }
- function addReference(referenceLocation, relatedSymbol, state) {
- var addRef = state.referenceAdder(relatedSymbol);
- if (state.options.implementations) {
- addImplementationReferences(referenceLocation, addRef, state);
- }
- else {
- addRef(referenceLocation);
- }
- }
- /** Adds references when a constructor is used with `new this()` in its own class and `super()` calls in subclasses. */
- function addConstructorReferences(referenceLocation, sourceFile, search, state) {
- if (ts.isNewExpressionTarget(referenceLocation)) {
- addReference(referenceLocation, search.symbol, state);
- }
- var pusher = function () { return state.referenceAdder(search.symbol); };
- if (ts.isClassLike(referenceLocation.parent)) {
- ts.Debug.assert(referenceLocation.kind === 79 /* DefaultKeyword */ || referenceLocation.parent.name === referenceLocation);
- // This is the class declaration containing the constructor.
- findOwnConstructorReferences(search.symbol, sourceFile, pusher());
- }
- else {
- // If this class appears in `extends C`, then the extending class' "super" calls are references.
- var classExtending = tryGetClassByExtendingIdentifier(referenceLocation);
- if (classExtending) {
- findSuperConstructorAccesses(classExtending, pusher());
- }
- }
- }
- function addClassStaticThisReferences(referenceLocation, search, state) {
- addReference(referenceLocation, search.symbol, state);
- if (!state.options.isForRename && ts.isClassLike(referenceLocation.parent)) {
- ts.Debug.assert(referenceLocation.parent.name === referenceLocation);
- // This is the class declaration.
- addStaticThisReferences(referenceLocation.parent, state.referenceAdder(search.symbol));
- }
- }
- function addStaticThisReferences(classLike, pusher) {
- for (var _i = 0, _a = classLike.members; _i < _a.length; _i++) {
- var member = _a[_i];
- if (!(ts.isMethodOrAccessor(member) && ts.hasModifier(member, 32 /* Static */))) {
- continue;
- }
- member.body.forEachChild(function cb(node) {
- if (node.kind === 99 /* ThisKeyword */) {
- pusher(node);
- }
- else if (!ts.isFunctionLike(node)) {
- node.forEachChild(cb);
- }
- });
- }
- }
- function getPropertyAccessExpressionFromRightHandSide(node) {
- return ts.isRightSideOfPropertyAccess(node) && node.parent;
- }
- /**
- * `classSymbol` is the class where the constructor was defined.
- * Reference the constructor and all calls to `new this()`.
- */
- function findOwnConstructorReferences(classSymbol, sourceFile, addNode) {
- for (var _i = 0, _a = classSymbol.members.get("__constructor" /* Constructor */).declarations; _i < _a.length; _i++) {
- var decl = _a[_i];
- var ctrKeyword = ts.findChildOfKind(decl, 123 /* ConstructorKeyword */, sourceFile);
- ts.Debug.assert(decl.kind === 154 /* Constructor */ && !!ctrKeyword);
- addNode(ctrKeyword);
- }
- classSymbol.exports.forEach(function (member) {
- var decl = member.valueDeclaration;
- if (decl && decl.kind === 153 /* MethodDeclaration */) {
- var body = decl.body;
- if (body) {
- forEachDescendantOfKind(body, 99 /* ThisKeyword */, function (thisKeyword) {
- if (ts.isNewExpressionTarget(thisKeyword)) {
- addNode(thisKeyword);
- }
- });
- }
- }
- });
- }
- /** Find references to `super` in the constructor of an extending class. */
- function findSuperConstructorAccesses(cls, addNode) {
- var symbol = cls.symbol;
- var ctr = symbol.members.get("__constructor" /* Constructor */);
- if (!ctr) {
- return;
- }
- for (var _i = 0, _a = ctr.declarations; _i < _a.length; _i++) {
- var decl = _a[_i];
- ts.Debug.assert(decl.kind === 154 /* Constructor */);
- var body = decl.body;
- if (body) {
- forEachDescendantOfKind(body, 97 /* SuperKeyword */, function (node) {
- if (ts.isCallExpressionTarget(node)) {
- addNode(node);
- }
- });
- }
- }
- }
- function addImplementationReferences(refNode, addReference, state) {
- // Check if we found a function/propertyAssignment/method with an implementation or initializer
- if (ts.isDeclarationName(refNode) && isImplementation(refNode.parent)) {
- addReference(refNode.parent);
- return;
- }
- if (refNode.kind !== 71 /* Identifier */) {
- return;
- }
- if (refNode.parent.kind === 269 /* ShorthandPropertyAssignment */) {
- // Go ahead and dereference the shorthand assignment by going to its definition
- getReferenceEntriesForShorthandPropertyAssignment(refNode, state.checker, addReference);
- }
- // Check if the node is within an extends or implements clause
- var containingClass = getContainingClassIfInHeritageClause(refNode);
- if (containingClass) {
- addReference(containingClass);
- return;
- }
- // If we got a type reference, try and see if the reference applies to any expressions that can implement an interface
- var containingTypeReference = getContainingTypeReference(refNode);
- if (containingTypeReference && state.markSeenContainingTypeReference(containingTypeReference)) {
- var parent = containingTypeReference.parent;
- if (ts.hasType(parent) && parent.type === containingTypeReference && ts.hasInitializer(parent) && isImplementationExpression(parent.initializer)) {
- addReference(parent.initializer);
- }
- else if (ts.isFunctionLike(parent) && parent.type === containingTypeReference && parent.body) {
- var body = parent.body;
- if (body.kind === 211 /* Block */) {
- ts.forEachReturnStatement(body, function (returnStatement) {
- if (returnStatement.expression && isImplementationExpression(returnStatement.expression)) {
- addReference(returnStatement.expression);
- }
- });
- }
- else if (isImplementationExpression(body)) {
- addReference(body);
- }
- }
- else if (ts.isAssertionExpression(parent) && isImplementationExpression(parent.expression)) {
- addReference(parent.expression);
- }
- }
- }
- function getSymbolsForClassAndInterfaceComponents(type, result) {
- if (result === void 0) { result = []; }
- for (var _i = 0, _a = type.types; _i < _a.length; _i++) {
- var componentType = _a[_i];
- if (componentType.symbol && componentType.symbol.getFlags() & (32 /* Class */ | 64 /* Interface */)) {
- result.push(componentType.symbol);
- }
- if (componentType.getFlags() & 393216 /* UnionOrIntersection */) {
- getSymbolsForClassAndInterfaceComponents(componentType, result);
- }
- }
- return result;
- }
- function getContainingTypeReference(node) {
- var topLevelTypeReference;
- while (node) {
- if (ts.isTypeNode(node)) {
- topLevelTypeReference = node;
- }
- node = node.parent;
- }
- return topLevelTypeReference;
- }
- function getContainingClassIfInHeritageClause(node) {
- if (node && node.parent) {
- if (node.kind === 205 /* ExpressionWithTypeArguments */
- && node.parent.kind === 266 /* HeritageClause */
- && ts.isClassLike(node.parent.parent)) {
- return node.parent.parent;
- }
- else if (node.kind === 71 /* Identifier */ || node.kind === 183 /* PropertyAccessExpression */) {
- return getContainingClassIfInHeritageClause(node.parent);
- }
- }
- return undefined;
- }
- /**
- * Returns true if this is an expression that can be considered an implementation
- */
- function isImplementationExpression(node) {
- switch (node.kind) {
- case 189 /* ParenthesizedExpression */:
- return isImplementationExpression(node.expression);
- case 191 /* ArrowFunction */:
- case 190 /* FunctionExpression */:
- case 182 /* ObjectLiteralExpression */:
- case 203 /* ClassExpression */:
- case 181 /* ArrayLiteralExpression */:
- return true;
- default:
- return false;
- }
- }
- /**
- * Determines if the parent symbol occurs somewhere in the child's ancestry. If the parent symbol
- * is an interface, determines if some ancestor of the child symbol extends or inherits from it.
- * Also takes in a cache of previous results which makes this slightly more efficient and is
- * necessary to avoid potential loops like so:
- * class A extends B { }
- * class B extends A { }
- *
- * We traverse the AST rather than using the type checker because users are typically only interested
- * in explicit implementations of an interface/class when calling "Go to Implementation". Sibling
- * implementations of types that share a common ancestor with the type whose implementation we are
- * searching for need to be filtered out of the results. The type checker doesn't let us make the
- * distinction between structurally compatible implementations and explicit implementations, so we
- * must use the AST.
- *
- * @param child A class or interface Symbol
- * @param parent Another class or interface Symbol
- * @param cachedResults A map of symbol id pairs (i.e. "child,parent") to booleans indicating previous results
- */
- function explicitlyInheritsFrom(child, parent, cachedResults, checker) {
- var parentIsInterface = parent.getFlags() & 64 /* Interface */;
- return searchHierarchy(child);
- function searchHierarchy(symbol) {
- if (symbol === parent) {
- return true;
- }
- var key = ts.getSymbolId(symbol) + "," + ts.getSymbolId(parent);
- var cached = cachedResults.get(key);
- if (cached !== undefined) {
- return cached;
- }
- // Set the key so that we don't infinitely recurse
- cachedResults.set(key, false);
- var inherits = ts.forEach(symbol.getDeclarations(), function (declaration) {
- if (ts.isClassLike(declaration)) {
- if (parentIsInterface) {
- var interfaceReferences = ts.getClassImplementsHeritageClauseElements(declaration);
- if (interfaceReferences) {
- for (var _i = 0, interfaceReferences_1 = interfaceReferences; _i < interfaceReferences_1.length; _i++) {
- var typeReference = interfaceReferences_1[_i];
- if (searchTypeReference(typeReference)) {
- return true;
- }
- }
- }
- }
- return searchTypeReference(ts.getClassExtendsHeritageClauseElement(declaration));
- }
- else if (declaration.kind === 234 /* InterfaceDeclaration */) {
- if (parentIsInterface) {
- return ts.forEach(ts.getInterfaceBaseTypeNodes(declaration), searchTypeReference);
- }
- }
- return false;
- });
- cachedResults.set(key, inherits);
- return inherits;
- }
- function searchTypeReference(typeReference) {
- if (typeReference) {
- var type = checker.getTypeAtLocation(typeReference);
- if (type && type.symbol) {
- return searchHierarchy(type.symbol);
- }
- }
- return false;
- }
- }
- function getReferencesForSuperKeyword(superKeyword) {
- var searchSpaceNode = ts.getSuperContainer(superKeyword, /*stopOnFunctions*/ false);
- if (!searchSpaceNode) {
- return undefined;
- }
- // Whether 'super' occurs in a static context within a class.
- var staticFlag = 32 /* Static */;
- switch (searchSpaceNode.kind) {
- case 151 /* PropertyDeclaration */:
- case 150 /* PropertySignature */:
- case 153 /* MethodDeclaration */:
- case 152 /* MethodSignature */:
- case 154 /* Constructor */:
- case 155 /* GetAccessor */:
- case 156 /* SetAccessor */:
- staticFlag &= ts.getModifierFlags(searchSpaceNode);
- searchSpaceNode = searchSpaceNode.parent; // re-assign to be the owning class
- break;
- default:
- return undefined;
- }
- var sourceFile = searchSpaceNode.getSourceFile();
- var references = ts.mapDefined(getPossibleSymbolReferencePositions(sourceFile, "super", searchSpaceNode), function (position) {
- var node = ts.getTouchingWord(sourceFile, position, /*includeJsDocComment*/ false);
- if (!node || node.kind !== 97 /* SuperKeyword */) {
- return;
- }
- var container = ts.getSuperContainer(node, /*stopOnFunctions*/ false);
- // If we have a 'super' container, we must have an enclosing class.
- // Now make sure the owning class is the same as the search-space
- // and has the same static qualifier as the original 'super's owner.
- return container && (32 /* Static */ & ts.getModifierFlags(container)) === staticFlag && container.parent.symbol === searchSpaceNode.symbol ? FindAllReferences.nodeEntry(node) : undefined;
- });
- return [{ definition: { type: "symbol", symbol: searchSpaceNode.symbol }, references: references }];
- }
- function getReferencesForThisKeyword(thisOrSuperKeyword, sourceFiles, cancellationToken) {
- var searchSpaceNode = ts.getThisContainer(thisOrSuperKeyword, /* includeArrowFunctions */ false);
- // Whether 'this' occurs in a static context within a class.
- var staticFlag = 32 /* Static */;
- switch (searchSpaceNode.kind) {
- case 153 /* MethodDeclaration */:
- case 152 /* MethodSignature */:
- if (ts.isObjectLiteralMethod(searchSpaceNode)) {
- break;
- }
- // falls through
- case 151 /* PropertyDeclaration */:
- case 150 /* PropertySignature */:
- case 154 /* Constructor */:
- case 155 /* GetAccessor */:
- case 156 /* SetAccessor */:
- staticFlag &= ts.getModifierFlags(searchSpaceNode);
- searchSpaceNode = searchSpaceNode.parent; // re-assign to be the owning class
- break;
- case 272 /* SourceFile */:
- if (ts.isExternalModule(searchSpaceNode)) {
- return undefined;
- }
- // falls through
- case 232 /* FunctionDeclaration */:
- case 190 /* FunctionExpression */:
- break;
- // Computed properties in classes are not handled here because references to this are illegal,
- // so there is no point finding references to them.
- default:
- return undefined;
- }
- var references = [];
- for (var _i = 0, _a = searchSpaceNode.kind === 272 /* SourceFile */ ? sourceFiles : [searchSpaceNode.getSourceFile()]; _i < _a.length; _i++) {
- var sourceFile = _a[_i];
- cancellationToken.throwIfCancellationRequested();
- var positions = getPossibleSymbolReferencePositions(sourceFile, "this", ts.isSourceFile(searchSpaceNode) ? sourceFile : searchSpaceNode);
- getThisReferencesInFile(sourceFile, searchSpaceNode.kind === 272 /* SourceFile */ ? sourceFile : searchSpaceNode, positions, staticFlag, references);
- }
- return [{
- definition: { type: "this", node: thisOrSuperKeyword },
- references: references
- }];
- }
- function getThisReferencesInFile(sourceFile, searchSpaceNode, possiblePositions, staticFlag, result) {
- ts.forEach(possiblePositions, function (position) {
- var node = ts.getTouchingWord(sourceFile, position, /*includeJsDocComment*/ false);
- if (!node || !ts.isThis(node)) {
- return;
- }
- var container = ts.getThisContainer(node, /* includeArrowFunctions */ false);
- switch (searchSpaceNode.kind) {
- case 190 /* FunctionExpression */:
- case 232 /* FunctionDeclaration */:
- if (searchSpaceNode.symbol === container.symbol) {
- result.push(FindAllReferences.nodeEntry(node));
- }
- break;
- case 153 /* MethodDeclaration */:
- case 152 /* MethodSignature */:
- if (ts.isObjectLiteralMethod(searchSpaceNode) && searchSpaceNode.symbol === container.symbol) {
- result.push(FindAllReferences.nodeEntry(node));
- }
- break;
- case 203 /* ClassExpression */:
- case 233 /* ClassDeclaration */:
- // Make sure the container belongs to the same class
- // and has the appropriate static modifier from the original container.
- if (container.parent && searchSpaceNode.symbol === container.parent.symbol && (ts.getModifierFlags(container) & 32 /* Static */) === staticFlag) {
- result.push(FindAllReferences.nodeEntry(node));
- }
- break;
- case 272 /* SourceFile */:
- if (container.kind === 272 /* SourceFile */ && !ts.isExternalModule(container)) {
- result.push(FindAllReferences.nodeEntry(node));
- }
- break;
- }
- });
- }
- function getReferencesForStringLiteral(node, sourceFiles, cancellationToken) {
- var references = ts.flatMap(sourceFiles, function (sourceFile) {
- cancellationToken.throwIfCancellationRequested();
- return ts.mapDefined(getPossibleSymbolReferencePositions(sourceFile, node.text), function (position) {
- var ref = ts.tryCast(ts.getTouchingWord(sourceFile, position, /*includeJsDocComment*/ false), ts.isStringLiteral);
- return ref && ref.text === node.text ? FindAllReferences.nodeEntry(ref, /*isInString*/ true) : undefined;
- });
- });
- return [{
- definition: { type: "string", node: node },
- references: references
- }];
- }
- // For certain symbol kinds, we need to include other symbols in the search set.
- // This is not needed when searching for re-exports.
- function populateSearchSymbolSet(symbol, location, checker, implementations) {
- // The search set contains at least the current symbol
- var result = [];
- var containingObjectLiteralElement = ts.getContainingObjectLiteralElement(location);
- if (containingObjectLiteralElement) {
- // If the location is name of property symbol from object literal destructuring pattern
- // Search the property symbol
- // for ( { property: p2 } of elems) { }
- if (containingObjectLiteralElement.kind !== 269 /* ShorthandPropertyAssignment */) {
- var propertySymbol = getPropertySymbolOfDestructuringAssignment(location, checker);
- if (propertySymbol) {
- result.push(propertySymbol);
- }
- }
- // If the location is in a context sensitive location (i.e. in an object literal) try
- // to get a contextual type for it, and add the property symbol from the contextual
- // type to the search set
- for (var _i = 0, _a = getPropertySymbolsFromContextualType(containingObjectLiteralElement, checker); _i < _a.length; _i++) {
- var contextualSymbol = _a[_i];
- addRootSymbols(contextualSymbol);
- }
- /* Because in short-hand property assignment, location has two meaning : property name and as value of the property
- * When we do findAllReference at the position of the short-hand property assignment, we would want to have references to position of
- * property name and variable declaration of the identifier.
- * Like in below example, when querying for all references for an identifier 'name', of the property assignment, the language service
- * should show both 'name' in 'obj' and 'name' in variable declaration
- * const name = "Foo";
- * const obj = { name };
- * In order to do that, we will populate the search set with the value symbol of the identifier as a value of the property assignment
- * so that when matching with potential reference symbol, both symbols from property declaration and variable declaration
- * will be included correctly.
- */
- var shorthandValueSymbol = checker.getShorthandAssignmentValueSymbol(location.parent);
- if (shorthandValueSymbol) {
- result.push(shorthandValueSymbol);
- }
- }
- // If the symbol.valueDeclaration is a property parameter declaration,
- // we should include both parameter declaration symbol and property declaration symbol
- // Parameter Declaration symbol is only visible within function scope, so the symbol is stored in constructor.locals.
- // Property Declaration symbol is a member of the class, so the symbol is stored in its class Declaration.symbol.members
- ts.addRange(result, getParameterPropertySymbols(symbol, checker));
- // If this is symbol of binding element without propertyName declaration in Object binding pattern
- // Include the property in the search
- var bindingElementPropertySymbol = getPropertySymbolOfObjectBindingPatternWithoutPropertyName(symbol, checker);
- if (bindingElementPropertySymbol) {
- result.push(bindingElementPropertySymbol);
- addRootSymbols(bindingElementPropertySymbol);
- }
- addRootSymbols(symbol);
- return result;
- function addRootSymbols(sym) {
- // If this is a union property, add all the symbols from all its source symbols in all unioned types.
- // If the symbol is an instantiation from a another symbol (e.g. widened symbol) , add the root the list
- for (var _i = 0, _a = checker.getRootSymbols(sym); _i < _a.length; _i++) {
- var rootSymbol = _a[_i];
- result.push(rootSymbol);
- // Add symbol of properties/methods of the same name in base classes and implemented interfaces definitions
- if (!implementations && rootSymbol.parent && rootSymbol.parent.flags & (32 /* Class */ | 64 /* Interface */)) {
- getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.name, result, /*previousIterationSymbolsCache*/ ts.createSymbolTable(), checker);
- }
- }
- }
- }
- function getParameterPropertySymbols(symbol, checker) {
- return symbol.valueDeclaration && ts.isParameter(symbol.valueDeclaration) && ts.isParameterPropertyDeclaration(symbol.valueDeclaration)
- ? checker.getSymbolsOfParameterPropertyDeclaration(symbol.valueDeclaration, symbol.name)
- : undefined;
- }
- /**
- * 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, result, previousIterationSymbolsCache, checker) {
- if (!symbol) {
- return;
- }
- // If the current symbol is the same as the previous-iteration symbol, we can just return the symbol that has already been visited
- // This is particularly important for the following cases, so that we do not infinitely visit the same symbol.
- // For example:
- // interface C extends C {
- // /*findRef*/propName: string;
- // }
- // The first time getPropertySymbolsFromBaseTypes is called when finding-all-references at propName,
- // the symbol argument will be the symbol of an interface "C" and previousIterationSymbol is undefined,
- // the function will add any found symbol of the property-name, then its sub-routine will call
- // getPropertySymbolsFromBaseTypes again to walk up any base types to prevent revisiting already
- // visited symbol, interface "C", the sub-routine will pass the current symbol as previousIterationSymbol.
- if (previousIterationSymbolsCache.has(symbol.escapedName)) {
- return;
- }
- if (symbol.flags & (32 /* Class */ | 64 /* Interface */)) {
- ts.forEach(symbol.getDeclarations(), function (declaration) {
- if (ts.isClassLike(declaration)) {
- getPropertySymbolFromTypeReference(ts.getClassExtendsHeritageClauseElement(declaration));
- ts.forEach(ts.getClassImplementsHeritageClauseElements(declaration), getPropertySymbolFromTypeReference);
- }
- else if (declaration.kind === 234 /* InterfaceDeclaration */) {
- ts.forEach(ts.getInterfaceBaseTypeNodes(declaration), getPropertySymbolFromTypeReference);
- }
- });
- }
- return;
- function getPropertySymbolFromTypeReference(typeReference) {
- if (typeReference) {
- var type = checker.getTypeAtLocation(typeReference);
- if (type) {
- var propertySymbol = checker.getPropertyOfType(type, propertyName);
- if (propertySymbol) {
- result.push.apply(result, checker.getRootSymbols(propertySymbol));
- }
- // Visit the typeReference as well to see if it directly or indirectly use that property
- previousIterationSymbolsCache.set(symbol.escapedName, symbol);
- getPropertySymbolsFromBaseTypes(type.symbol, propertyName, result, previousIterationSymbolsCache, checker);
- }
- }
- }
- }
- function getRelatedSymbol(search, referenceSymbol, referenceLocation, state) {
- var checker = state.checker;
- if (search.includes(referenceSymbol)) {
- return referenceSymbol;
- }
- if (referenceSymbol.flags & 1 /* FunctionScopedVariable */) {
- ts.Debug.assert(!(referenceSymbol.flags & 4 /* Property */));
- var paramProps = getParameterPropertySymbols(referenceSymbol, checker);
- if (paramProps) {
- return getRelatedSymbol(search, ts.find(paramProps, function (x) { return !!(x.flags & 4 /* Property */); }), referenceLocation, state);
- }
- }
- // If the reference location is in an object literal, try to get the contextual type for the
- // object literal, lookup the property symbol in the contextual type, and use this symbol to
- // compare to our searchSymbol
- var containingObjectLiteralElement = ts.getContainingObjectLiteralElement(referenceLocation);
- if (containingObjectLiteralElement) {
- var contextualSymbol = ts.firstDefined(getPropertySymbolsFromContextualType(containingObjectLiteralElement, checker), findRootSymbol);
- if (contextualSymbol) {
- return contextualSymbol;
- }
- // If the reference location is the name of property from object literal destructuring pattern
- // Get the property symbol from the object literal's type and look if thats the search symbol
- // In below eg. get 'property' from type of elems iterating type
- // for ( { property: p2 } of elems) { }
- var propertySymbol = getPropertySymbolOfDestructuringAssignment(referenceLocation, checker);
- if (propertySymbol && search.includes(propertySymbol)) {
- return propertySymbol;
- }
- }
- // If the reference location is the binding element and doesn't have property name
- // then include the binding element in the related symbols
- // let { a } : { a };
- var bindingElementPropertySymbol = getPropertySymbolOfObjectBindingPatternWithoutPropertyName(referenceSymbol, checker);
- if (bindingElementPropertySymbol) {
- var fromBindingElement = findRootSymbol(bindingElementPropertySymbol);
- if (fromBindingElement)
- return fromBindingElement;
- }
- return findRootSymbol(referenceSymbol);
- function findRootSymbol(sym) {
- // Unwrap symbols to get to the root (e.g. transient symbols as a result of widening)
- // Or a union property, use its underlying unioned symbols
- return ts.firstDefined(checker.getRootSymbols(sym), function (rootSymbol) {
- // if it is in the list, then we are done
- if (search.includes(rootSymbol)) {
- return rootSymbol;
- }
- // Finally, try all properties with the same name in any type the containing type extended or implemented, and
- // see if any is in the list. If we were passed a parent symbol, only include types that are subtypes of the
- // parent symbol
- if (rootSymbol.parent && rootSymbol.parent.flags & (32 /* Class */ | 64 /* Interface */)) {
- // Parents will only be defined if implementations is true
- if (search.parents && !ts.some(search.parents, function (parent) { return explicitlyInheritsFrom(rootSymbol.parent, parent, state.inheritsFromCache, checker); })) {
- return undefined;
- }
- var result = [];
- getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.name, result, /*previousIterationSymbolsCache*/ ts.createSymbolTable(), checker);
- return ts.find(result, search.includes);
- }
- return undefined;
- });
- }
- }
- function getNameFromObjectLiteralElement(node) {
- if (node.name.kind === 146 /* ComputedPropertyName */) {
- var nameExpression = node.name.expression;
- // treat computed property names where expression is string/numeric literal as just string/numeric literal
- if (ts.isStringOrNumericLiteral(nameExpression)) {
- return nameExpression.text;
- }
- return undefined;
- }
- return ts.getTextOfIdentifierOrLiteral(node.name);
- }
- /** Gets all symbols for one property. Does not get symbols for every property. */
- function getPropertySymbolsFromContextualType(node, checker) {
- var contextualType = checker.getContextualType(node.parent);
- var name = getNameFromObjectLiteralElement(node);
- var symbol = contextualType && name && contextualType.getProperty(name);
- return symbol ? [symbol] :
- contextualType && contextualType.flags & 131072 /* Union */ ? ts.mapDefined(contextualType.types, function (t) { return t.getProperty(name); }) : ts.emptyArray;
- }
- /**
- * Given an initial searchMeaning, extracted from a location, widen the search scope based on the declarations
- * of the corresponding symbol. e.g. if we are searching for "Foo" in value position, but "Foo" references a class
- * then we need to widen the search to include type positions as well.
- * On the contrary, if we are searching for "Bar" in type position and we trace bar to an interface, and an uninstantiated
- * module, we want to keep the search limited to only types, as the two declarations (interface and uninstantiated module)
- * do not intersect in any of the three spaces.
- */
- function getIntersectingMeaningFromDeclarations(node, symbol) {
- var meaning = ts.getMeaningFromLocation(node);
- var declarations = symbol.declarations;
- if (declarations) {
- var lastIterationMeaning = void 0;
- do {
- // The result is order-sensitive, for instance if initialMeaning === Namespace, and declarations = [class, instantiated module]
- // we need to consider both as they initialMeaning intersects with the module in the namespace space, and the module
- // intersects with the class in the value space.
- // To achieve that we will keep iterating until the result stabilizes.
- // Remember the last meaning
- lastIterationMeaning = meaning;
- for (var _i = 0, declarations_10 = declarations; _i < declarations_10.length; _i++) {
- var declaration = declarations_10[_i];
- var declarationMeaning = ts.getMeaningFromDeclaration(declaration);
- if (declarationMeaning & meaning) {
- meaning |= declarationMeaning;
- }
- }
- } while (meaning !== lastIterationMeaning);
- }
- return meaning;
- }
- Core.getIntersectingMeaningFromDeclarations = getIntersectingMeaningFromDeclarations;
- function isImplementation(node) {
- if (!node) {
- return false;
- }
- else if (ts.isVariableLike(node) && ts.hasInitializer(node)) {
- return true;
- }
- else if (node.kind === 230 /* VariableDeclaration */) {
- var parentStatement = getParentStatementOfVariableDeclaration(node);
- return parentStatement && ts.hasModifier(parentStatement, 2 /* Ambient */);
- }
- else if (ts.isFunctionLike(node)) {
- return !!node.body || ts.hasModifier(node, 2 /* Ambient */);
- }
- else {
- switch (node.kind) {
- case 233 /* ClassDeclaration */:
- case 203 /* ClassExpression */:
- case 236 /* EnumDeclaration */:
- case 237 /* ModuleDeclaration */:
- return true;
- }
- }
- return false;
- }
- function getParentStatementOfVariableDeclaration(node) {
- if (node.parent && node.parent.parent && node.parent.parent.kind === 212 /* VariableStatement */) {
- ts.Debug.assert(node.parent.kind === 231 /* VariableDeclarationList */);
- return node.parent.parent;
- }
- }
- function getReferenceEntriesForShorthandPropertyAssignment(node, checker, addReference) {
- var refSymbol = checker.getSymbolAtLocation(node);
- var shorthandSymbol = checker.getShorthandAssignmentValueSymbol(refSymbol.valueDeclaration);
- if (shorthandSymbol) {
- for (var _i = 0, _a = shorthandSymbol.getDeclarations(); _i < _a.length; _i++) {
- var declaration = _a[_i];
- if (ts.getMeaningFromDeclaration(declaration) & 1 /* Value */) {
- addReference(declaration);
- }
- }
- }
- }
- Core.getReferenceEntriesForShorthandPropertyAssignment = getReferenceEntriesForShorthandPropertyAssignment;
- function forEachDescendantOfKind(node, kind, action) {
- ts.forEachChild(node, function (child) {
- if (child.kind === kind) {
- action(child);
- }
- forEachDescendantOfKind(child, kind, action);
- });
- }
- /** Get `C` given `N` if `N` is in the position `class C extends N` or `class C extends foo.N` where `N` is an identifier. */
- function tryGetClassByExtendingIdentifier(node) {
- return ts.tryGetClassExtendingExpressionWithTypeArguments(ts.climbPastPropertyAccess(node).parent);
- }
- function isNameOfExternalModuleImportOrDeclaration(node) {
- if (node.kind === 9 /* StringLiteral */) {
- return ts.isNameOfModuleDeclaration(node) || ts.isExpressionOfExternalModuleImportEqualsDeclaration(node);
- }
- return false;
- }
- /**
- * If we are just looking for implementations and this is a property access expression, we need to get the
- * symbol of the local type of the symbol the property is being accessed on. This is because our search
- * symbol may have a different parent symbol if the local type's symbol does not declare the property
- * being accessed (i.e. it is declared in some parent class or interface)
- */
- function getParentSymbolsOfPropertyAccess(location, symbol, checker) {
- var propertyAccessExpression = getPropertyAccessExpressionFromRightHandSide(location);
- if (!propertyAccessExpression) {
- return undefined;
- }
- var localParentType = checker.getTypeAtLocation(propertyAccessExpression.expression);
- if (!localParentType) {
- return undefined;
- }
- if (localParentType.symbol && localParentType.symbol.flags & (32 /* Class */ | 64 /* Interface */) && localParentType.symbol !== symbol.parent) {
- return [localParentType.symbol];
- }
- else if (localParentType.flags & 393216 /* UnionOrIntersection */) {
- return getSymbolsForClassAndInterfaceComponents(localParentType);
- }
- }
- })(Core = FindAllReferences.Core || (FindAllReferences.Core = {}));
- })(FindAllReferences = ts.FindAllReferences || (ts.FindAllReferences = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var GoToDefinition;
- (function (GoToDefinition) {
- function getDefinitionAtPosition(program, sourceFile, position) {
- var reference = getReferenceAtPosition(sourceFile, position, program);
- if (reference) {
- return [getDefinitionInfoForFileReference(reference.fileName, reference.file.fileName)];
- }
- var node = ts.getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ true);
- if (node === sourceFile) {
- return undefined;
- }
- // Labels
- if (ts.isJumpStatementTarget(node)) {
- var label = ts.getTargetLabel(node.parent, node.text);
- return label ? [createDefinitionInfoFromName(label, "label" /* label */, node.text, /*containerName*/ undefined)] : undefined;
- }
- var typeChecker = program.getTypeChecker();
- var calledDeclaration = tryGetSignatureDeclaration(typeChecker, node);
- if (calledDeclaration) {
- return [createDefinitionFromSignatureDeclaration(typeChecker, calledDeclaration)];
- }
- var symbol = typeChecker.getSymbolAtLocation(node);
- // Could not find a symbol e.g. node is string or number keyword,
- // or the symbol was an internal symbol and does not have a declaration e.g. undefined symbol
- if (!symbol) {
- return undefined;
- }
- // If this is an alias, and the request came at the declaration location
- // get the aliased symbol instead. This allows for goto def on an import e.g.
- // import {A, B} from "mod";
- // to jump to the implementation directly.
- if (symbol.flags & 2097152 /* Alias */ && shouldSkipAlias(node, symbol.declarations[0])) {
- var aliased = typeChecker.getAliasedSymbol(symbol);
- if (aliased.declarations) {
- symbol = aliased;
- }
- }
- // Because name in short-hand property assignment has two different meanings: property name and property value,
- // using go-to-definition at such position should go to the variable declaration of the property value rather than
- // go to the declaration of the property name (in this case stay at the same position). However, if go-to-definition
- // is performed at the location of property access, we would like to go to definition of the property in the short-hand
- // assignment. This case and others are handled by the following code.
- if (node.parent.kind === 269 /* ShorthandPropertyAssignment */) {
- var shorthandSymbol = typeChecker.getShorthandAssignmentValueSymbol(symbol.valueDeclaration);
- if (!shorthandSymbol) {
- return [];
- }
- var shorthandDeclarations = shorthandSymbol.getDeclarations();
- var shorthandSymbolKind_1 = ts.SymbolDisplay.getSymbolKind(typeChecker, shorthandSymbol, node);
- var shorthandSymbolName_1 = typeChecker.symbolToString(shorthandSymbol);
- var shorthandContainerName_1 = typeChecker.symbolToString(symbol.parent, node);
- return ts.map(shorthandDeclarations, function (declaration) { return createDefinitionInfo(declaration, shorthandSymbolKind_1, shorthandSymbolName_1, shorthandContainerName_1); });
- }
- // If the node is the name of a BindingElement within an ObjectBindingPattern instead of just returning the
- // declaration the symbol (which is itself), we should try to get to the original type of the ObjectBindingPattern
- // and return the property declaration for the referenced property.
- // For example:
- // import('./foo').then(({ b/*goto*/ar }) => undefined); => should get use to the declaration in file "./foo"
- //
- // function bar(onfulfilled: (value: T) => void) { //....}
- // interface Test {
- // pr/*destination*/op1: number
- // }
- // bar(({pr/*goto*/op1})=>{});
- if (ts.isPropertyName(node) && ts.isBindingElement(node.parent) && ts.isObjectBindingPattern(node.parent.parent) &&
- (node === (node.parent.propertyName || node.parent.name))) {
- var type = typeChecker.getTypeAtLocation(node.parent.parent);
- if (type) {
- var propSymbols = ts.getPropertySymbolsFromType(type, node);
- if (propSymbols) {
- return ts.flatMap(propSymbols, function (propSymbol) { return getDefinitionFromSymbol(typeChecker, propSymbol, node); });
- }
- }
- }
- // If the current location we want to find its definition is in an object literal, try to get the contextual type for the
- // object literal, lookup the property symbol in the contextual type, and use this for goto-definition.
- // For example
- // interface Props{
- // /*first*/prop1: number
- // prop2: boolean
- // }
- // function Foo(arg: Props) {}
- // Foo( { pr/*1*/op1: 10, prop2: true })
- var element = ts.getContainingObjectLiteralElement(node);
- if (element && typeChecker.getContextualType(element.parent)) {
- return ts.flatMap(ts.getPropertySymbolsFromContextualType(typeChecker, element), function (propertySymbol) {
- return getDefinitionFromSymbol(typeChecker, propertySymbol, node);
- });
- }
- return getDefinitionFromSymbol(typeChecker, symbol, node);
- }
- GoToDefinition.getDefinitionAtPosition = getDefinitionAtPosition;
- function getReferenceAtPosition(sourceFile, position, program) {
- var referencePath = findReferenceInPosition(sourceFile.referencedFiles, position);
- if (referencePath) {
- var file = ts.tryResolveScriptReference(program, sourceFile, referencePath);
- return file && { fileName: referencePath.fileName, file: file };
- }
- var typeReferenceDirective = findReferenceInPosition(sourceFile.typeReferenceDirectives, position);
- if (typeReferenceDirective) {
- var reference = program.getResolvedTypeReferenceDirectives().get(typeReferenceDirective.fileName);
- var file = reference && program.getSourceFile(reference.resolvedFileName);
- return file && { fileName: typeReferenceDirective.fileName, file: file };
- }
- return undefined;
- }
- GoToDefinition.getReferenceAtPosition = getReferenceAtPosition;
- /// Goto type
- function getTypeDefinitionAtPosition(typeChecker, sourceFile, position) {
- var node = ts.getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ true);
- if (node === sourceFile) {
- return undefined;
- }
- var symbol = typeChecker.getSymbolAtLocation(node);
- var type = symbol && typeChecker.getTypeOfSymbolAtLocation(symbol, node);
- if (!type) {
- return undefined;
- }
- if (type.flags & 131072 /* Union */ && !(type.flags & 16 /* Enum */)) {
- return ts.flatMap(type.types, function (t) { return t.symbol && getDefinitionFromSymbol(typeChecker, t.symbol, node); });
- }
- return type.symbol && getDefinitionFromSymbol(typeChecker, type.symbol, node);
- }
- GoToDefinition.getTypeDefinitionAtPosition = getTypeDefinitionAtPosition;
- function getDefinitionAndBoundSpan(program, sourceFile, position) {
- var definitions = getDefinitionAtPosition(program, sourceFile, position);
- if (!definitions || definitions.length === 0) {
- return undefined;
- }
- // Check if position is on triple slash reference.
- var comment = findReferenceInPosition(sourceFile.referencedFiles, position) || findReferenceInPosition(sourceFile.typeReferenceDirectives, position);
- if (comment) {
- return { definitions: definitions, textSpan: ts.createTextSpanFromRange(comment) };
- }
- var node = ts.getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ true);
- var textSpan = ts.createTextSpan(node.getStart(), node.getWidth());
- return { definitions: definitions, textSpan: textSpan };
- }
- GoToDefinition.getDefinitionAndBoundSpan = getDefinitionAndBoundSpan;
- // Go to the original declaration for cases:
- //
- // (1) when the aliased symbol was declared in the location(parent).
- // (2) when the aliased symbol is originating from an import.
- //
- function shouldSkipAlias(node, declaration) {
- if (node.kind !== 71 /* Identifier */) {
- return false;
- }
- if (node.parent === declaration) {
- return true;
- }
- switch (declaration.kind) {
- case 243 /* ImportClause */:
- case 241 /* ImportEqualsDeclaration */:
- return true;
- case 246 /* ImportSpecifier */:
- return declaration.parent.kind === 245 /* NamedImports */;
- default:
- return false;
- }
- }
- function getDefinitionFromSymbol(typeChecker, symbol, node) {
- var _a = getSymbolInfo(typeChecker, symbol, node), symbolName = _a.symbolName, symbolKind = _a.symbolKind, containerName = _a.containerName;
- return getConstructSignatureDefinition() || getCallSignatureDefinition() || ts.map(symbol.declarations, function (declaration) { return createDefinitionInfo(declaration, symbolKind, symbolName, containerName); });
- function getConstructSignatureDefinition() {
- // Applicable only if we are in a new expression, or we are on a constructor declaration
- // and in either case the symbol has a construct signature definition, i.e. class
- if (symbol.flags & 32 /* Class */ && (ts.isNewExpressionTarget(node) || node.kind === 123 /* ConstructorKeyword */)) {
- var cls = ts.find(symbol.declarations, ts.isClassLike) || ts.Debug.fail("Expected declaration to have at least one class-like declaration");
- return getSignatureDefinition(cls.members, /*selectConstructors*/ true);
- }
- }
- function getCallSignatureDefinition() {
- return ts.isCallExpressionTarget(node) || ts.isNewExpressionTarget(node) || ts.isNameOfFunctionDeclaration(node)
- ? getSignatureDefinition(symbol.declarations, /*selectConstructors*/ false)
- : undefined;
- }
- function getSignatureDefinition(signatureDeclarations, selectConstructors) {
- if (!signatureDeclarations) {
- return undefined;
- }
- var declarations = signatureDeclarations.filter(selectConstructors ? ts.isConstructorDeclaration : isSignatureDeclaration);
- return declarations.length
- ? [createDefinitionInfo(ts.find(declarations, function (d) { return !!d.body; }) || ts.last(declarations), symbolKind, symbolName, containerName)]
- : undefined;
- }
- }
- function isSignatureDeclaration(node) {
- switch (node.kind) {
- case 154 /* Constructor */:
- case 158 /* ConstructSignature */:
- case 232 /* FunctionDeclaration */:
- case 153 /* MethodDeclaration */:
- case 152 /* MethodSignature */:
- return true;
- default:
- return false;
- }
- }
- /** Creates a DefinitionInfo from a Declaration, using the declaration's name if possible. */
- function createDefinitionInfo(node, symbolKind, symbolName, containerName) {
- return createDefinitionInfoFromName(ts.getNameOfDeclaration(node) || node, symbolKind, symbolName, containerName);
- }
- /** Creates a DefinitionInfo directly from the name of a declaration. */
- function createDefinitionInfoFromName(name, symbolKind, symbolName, containerName) {
- var sourceFile = name.getSourceFile();
- return {
- fileName: sourceFile.fileName,
- textSpan: ts.createTextSpanFromNode(name, sourceFile),
- kind: symbolKind,
- name: symbolName,
- containerKind: undefined,
- containerName: containerName
- };
- }
- function getSymbolInfo(typeChecker, symbol, node) {
- return {
- symbolName: typeChecker.symbolToString(symbol),
- symbolKind: ts.SymbolDisplay.getSymbolKind(typeChecker, symbol, node),
- containerName: symbol.parent ? typeChecker.symbolToString(symbol.parent, node) : ""
- };
- }
- function createDefinitionFromSignatureDeclaration(typeChecker, decl) {
- var _a = getSymbolInfo(typeChecker, decl.symbol, decl), symbolName = _a.symbolName, symbolKind = _a.symbolKind, containerName = _a.containerName;
- return createDefinitionInfo(decl, symbolKind, symbolName, containerName);
- }
- function findReferenceInPosition(refs, pos) {
- for (var _i = 0, refs_1 = refs; _i < refs_1.length; _i++) {
- var ref = refs_1[_i];
- if (ref.pos <= pos && pos <= ref.end) {
- return ref;
- }
- }
- return undefined;
- }
- GoToDefinition.findReferenceInPosition = findReferenceInPosition;
- function getDefinitionInfoForFileReference(name, targetFileName) {
- return {
- fileName: targetFileName,
- textSpan: ts.createTextSpanFromBounds(0, 0),
- kind: "script" /* scriptElement */,
- name: name,
- containerName: undefined,
- containerKind: undefined
- };
- }
- /** Returns a CallLikeExpression where `node` is the target being invoked. */
- function getAncestorCallLikeExpression(node) {
- var target = climbPastManyPropertyAccesses(node);
- var callLike = target.parent;
- return callLike && ts.isCallLikeExpression(callLike) && ts.getInvokedExpression(callLike) === target && callLike;
- }
- function climbPastManyPropertyAccesses(node) {
- return ts.isRightSideOfPropertyAccess(node) ? climbPastManyPropertyAccesses(node.parent) : node;
- }
- function tryGetSignatureDeclaration(typeChecker, node) {
- var callLike = getAncestorCallLikeExpression(node);
- var signature = callLike && typeChecker.getResolvedSignature(callLike);
- if (signature) {
- var decl = signature.declaration;
- if (decl && isSignatureDeclaration(decl)) {
- return decl;
- }
- }
- // Don't go to a function type, go to the value having that type.
- return undefined;
- }
- })(GoToDefinition = ts.GoToDefinition || (ts.GoToDefinition = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var JsDoc;
- (function (JsDoc) {
- var jsDocTagNames = [
- "augments",
- "author",
- "argument",
- "borrows",
- "class",
- "constant",
- "constructor",
- "constructs",
- "default",
- "deprecated",
- "description",
- "event",
- "example",
- "extends",
- "field",
- "fileOverview",
- "function",
- "ignore",
- "inheritDoc",
- "inner",
- "lends",
- "link",
- "memberOf",
- "method",
- "name",
- "namespace",
- "param",
- "private",
- "prop",
- "property",
- "public",
- "requires",
- "returns",
- "see",
- "since",
- "static",
- "template",
- "throws",
- "type",
- "typedef",
- "version"
- ];
- var jsDocTagNameCompletionEntries;
- var jsDocTagCompletionEntries;
- function getJsDocCommentsFromDeclarations(declarations) {
- // Only collect doc comments from duplicate declarations once:
- // In case of a union property there might be same declaration multiple times
- // which only varies in type parameter
- // Eg. const a: Array | Array; a.length
- // The property length will have two declarations of property length coming
- // from Array - Array and Array
- var documentationComment = [];
- forEachUnique(declarations, function (declaration) {
- for (var _i = 0, _a = getCommentHavingNodes(declaration); _i < _a.length; _i++) {
- var comment = _a[_i].comment;
- if (comment === undefined)
- continue;
- if (documentationComment.length) {
- documentationComment.push(ts.lineBreakPart());
- }
- documentationComment.push(ts.textPart(comment));
- }
- });
- return documentationComment;
- }
- JsDoc.getJsDocCommentsFromDeclarations = getJsDocCommentsFromDeclarations;
- function getCommentHavingNodes(declaration) {
- switch (declaration.kind) {
- case 292 /* JSDocPropertyTag */:
- return [declaration];
- case 291 /* JSDocTypedefTag */:
- return [declaration.parent];
- default:
- return ts.getJSDocCommentsAndTags(declaration);
- }
- }
- function getJsDocTagsFromDeclarations(declarations) {
- // Only collect doc comments from duplicate declarations once.
- var tags = [];
- forEachUnique(declarations, function (declaration) {
- for (var _i = 0, _a = ts.getJSDocTags(declaration); _i < _a.length; _i++) {
- var tag = _a[_i];
- tags.push({ name: tag.tagName.text, text: getCommentText(tag) });
- }
- });
- return tags;
- }
- JsDoc.getJsDocTagsFromDeclarations = getJsDocTagsFromDeclarations;
- function getCommentText(tag) {
- var comment = tag.comment;
- switch (tag.kind) {
- case 285 /* JSDocAugmentsTag */:
- return withNode(tag.class);
- case 290 /* JSDocTemplateTag */:
- return withList(tag.typeParameters);
- case 289 /* JSDocTypeTag */:
- return withNode(tag.typeExpression);
- case 291 /* JSDocTypedefTag */:
- case 292 /* JSDocPropertyTag */:
- case 287 /* JSDocParameterTag */:
- var name = tag.name;
- return name ? withNode(name) : comment;
- default:
- return comment;
- }
- function withNode(node) {
- return addComment(node.getText());
- }
- function withList(list) {
- return addComment(list.map(function (x) { return x.getText(); }).join(", "));
- }
- function addComment(s) {
- return comment === undefined ? s : s + " " + comment;
- }
- }
- /**
- * 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;
- }
- function getJSDocTagNameCompletions() {
- return jsDocTagNameCompletionEntries || (jsDocTagNameCompletionEntries = ts.map(jsDocTagNames, function (tagName) {
- return {
- name: tagName,
- kind: "keyword" /* keyword */,
- kindModifiers: "",
- sortText: "0",
- };
- }));
- }
- JsDoc.getJSDocTagNameCompletions = getJSDocTagNameCompletions;
- JsDoc.getJSDocTagNameCompletionDetails = getJSDocTagCompletionDetails;
- function getJSDocTagCompletions() {
- return jsDocTagCompletionEntries || (jsDocTagCompletionEntries = ts.map(jsDocTagNames, function (tagName) {
- return {
- name: "@" + tagName,
- kind: "keyword" /* keyword */,
- kindModifiers: "",
- sortText: "0"
- };
- }));
- }
- JsDoc.getJSDocTagCompletions = getJSDocTagCompletions;
- function getJSDocTagCompletionDetails(name) {
- return {
- name: name,
- kind: "" /* unknown */,
- kindModifiers: "",
- displayParts: [ts.textPart(name)],
- documentation: ts.emptyArray,
- tags: ts.emptyArray,
- codeActions: undefined,
- };
- }
- JsDoc.getJSDocTagCompletionDetails = getJSDocTagCompletionDetails;
- function getJSDocParameterNameCompletions(tag) {
- if (!ts.isIdentifier(tag.name)) {
- return ts.emptyArray;
- }
- var nameThusFar = tag.name.text;
- var jsdoc = tag.parent;
- var fn = jsdoc.parent;
- if (!ts.isFunctionLike(fn))
- return [];
- return ts.mapDefined(fn.parameters, function (param) {
- if (!ts.isIdentifier(param.name))
- return undefined;
- var name = param.name.text;
- if (jsdoc.tags.some(function (t) { return t !== tag && ts.isJSDocParameterTag(t) && ts.isIdentifier(t.name) && t.name.escapedText === name; })
- || nameThusFar !== undefined && !ts.startsWith(name, nameThusFar)) {
- return undefined;
- }
- return { name: name, kind: "parameter" /* parameterElement */, kindModifiers: "", sortText: "0" };
- });
- }
- JsDoc.getJSDocParameterNameCompletions = getJSDocParameterNameCompletions;
- function getJSDocParameterNameCompletionDetails(name) {
- return {
- name: name,
- kind: "parameter" /* parameterElement */,
- kindModifiers: "",
- displayParts: [ts.textPart(name)],
- documentation: ts.emptyArray,
- tags: ts.emptyArray,
- codeActions: undefined,
- };
- }
- JsDoc.getJSDocParameterNameCompletionDetails = getJSDocParameterNameCompletionDetails;
- /**
- * Checks if position points to a valid position to add JSDoc comments, and if so,
- * returns the appropriate template. Otherwise returns an empty string.
- * Valid positions are
- * - outside of comments, statements, and expressions, and
- * - preceding a:
- * - function/constructor/method declaration
- * - class declarations
- * - variable statements
- * - namespace declarations
- * - interface declarations
- * - method signatures
- * - type alias declarations
- *
- * Hosts should ideally check that:
- * - The line is all whitespace up to 'position' before performing the insertion.
- * - If the keystroke sequence "/\*\*" induced the call, we also check that the next
- * non-whitespace character is '*', which (approximately) indicates whether we added
- * the second '*' to complete an existing (JSDoc) comment.
- * @param fileName The file in which to perform the check.
- * @param position The (character-indexed) position in the file where the check should
- * be performed.
- */
- function getDocCommentTemplateAtPosition(newLine, sourceFile, position) {
- // Check if in a context where we don't want to perform any insertion
- if (ts.isInString(sourceFile, position) || ts.isInComment(sourceFile, position) || ts.hasDocComment(sourceFile, position)) {
- return undefined;
- }
- var tokenAtPos = ts.getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false);
- var tokenStart = tokenAtPos.getStart();
- if (!tokenAtPos || tokenStart < position) {
- return undefined;
- }
- var commentOwnerInfo = getCommentOwnerInfo(tokenAtPos);
- if (!commentOwnerInfo) {
- return undefined;
- }
- var commentOwner = commentOwnerInfo.commentOwner, parameters = commentOwnerInfo.parameters;
- if (commentOwner.getStart() < position) {
- return undefined;
- }
- if (!parameters || parameters.length === 0) {
- // if there are no parameters, just complete to a single line JSDoc comment
- var singleLineResult = "/** */";
- return { newText: singleLineResult, caretOffset: 3 };
- }
- var posLineAndChar = sourceFile.getLineAndCharacterOfPosition(position);
- var lineStart = sourceFile.getLineStarts()[posLineAndChar.line];
- // replace non-whitespace characters in prefix with spaces.
- var indentationStr = sourceFile.text.substr(lineStart, posLineAndChar.character).replace(/\S/i, function () { return " "; });
- var isJavaScriptFile = ts.hasJavaScriptFileExtension(sourceFile.fileName);
- var docParams = "";
- for (var i = 0; i < parameters.length; i++) {
- var currentName = parameters[i].name;
- var paramName = currentName.kind === 71 /* Identifier */ ? currentName.escapedText : "param" + i;
- if (isJavaScriptFile) {
- docParams += indentationStr + " * @param {any} " + paramName + newLine;
- }
- else {
- docParams += indentationStr + " * @param " + paramName + newLine;
- }
- }
- // A doc comment consists of the following
- // * The opening comment line
- // * the first line (without a param) for the object's untagged info (this is also where the caret ends up)
- // * the '@param'-tagged lines
- // * TODO: other tags.
- // * the closing comment line
- // * if the caret was directly in front of the object, then we add an extra line and indentation.
- var preamble = "/**" + newLine +
- indentationStr + " * ";
- var result = preamble + newLine +
- docParams +
- indentationStr + " */" +
- (tokenStart === position ? newLine + indentationStr : "");
- return { newText: result, caretOffset: preamble.length };
- }
- JsDoc.getDocCommentTemplateAtPosition = getDocCommentTemplateAtPosition;
- function getCommentOwnerInfo(tokenAtPos) {
- for (var commentOwner = tokenAtPos; commentOwner; commentOwner = commentOwner.parent) {
- switch (commentOwner.kind) {
- case 232 /* FunctionDeclaration */:
- case 153 /* MethodDeclaration */:
- case 154 /* Constructor */:
- case 152 /* MethodSignature */:
- var parameters = commentOwner.parameters;
- return { commentOwner: commentOwner, parameters: parameters };
- case 233 /* ClassDeclaration */:
- case 234 /* InterfaceDeclaration */:
- case 150 /* PropertySignature */:
- case 236 /* EnumDeclaration */:
- case 271 /* EnumMember */:
- case 235 /* TypeAliasDeclaration */:
- return { commentOwner: commentOwner };
- case 212 /* VariableStatement */: {
- var varStatement = commentOwner;
- var varDeclarations = varStatement.declarationList.declarations;
- var parameters_1 = varDeclarations.length === 1 && varDeclarations[0].initializer
- ? getParametersFromRightHandSideOfAssignment(varDeclarations[0].initializer)
- : undefined;
- return { commentOwner: commentOwner, parameters: parameters_1 };
- }
- case 272 /* SourceFile */:
- return undefined;
- case 237 /* ModuleDeclaration */:
- // If in walking up the tree, we hit a a nested namespace declaration,
- // then we must be somewhere within a dotted namespace name; however we don't
- // want to give back a JSDoc template for the 'b' or 'c' in 'namespace a.b.c { }'.
- return commentOwner.parent.kind === 237 /* ModuleDeclaration */ ? undefined : { commentOwner: commentOwner };
- case 198 /* BinaryExpression */: {
- var be = commentOwner;
- if (ts.getSpecialPropertyAssignmentKind(be) === 0 /* None */) {
- return undefined;
- }
- var parameters_2 = ts.isFunctionLike(be.right) ? be.right.parameters : ts.emptyArray;
- return { commentOwner: commentOwner, parameters: parameters_2 };
- }
- }
- }
- }
- /**
- * Digs into an an initializer or RHS operand of an assignment operation
- * to get the parameters of an apt signature corresponding to a
- * function expression or a class expression.
- *
- * @param rightHandSide the expression which may contain an appropriate set of parameters
- * @returns the parameters of a signature found on the RHS if one exists; otherwise 'emptyArray'.
- */
- function getParametersFromRightHandSideOfAssignment(rightHandSide) {
- while (rightHandSide.kind === 189 /* ParenthesizedExpression */) {
- rightHandSide = rightHandSide.expression;
- }
- switch (rightHandSide.kind) {
- case 190 /* FunctionExpression */:
- case 191 /* ArrowFunction */:
- return rightHandSide.parameters;
- case 203 /* ClassExpression */:
- for (var _i = 0, _a = rightHandSide.members; _i < _a.length; _i++) {
- var member = _a[_i];
- if (member.kind === 154 /* Constructor */) {
- return member.parameters;
- }
- }
- break;
- }
- return ts.emptyArray;
- }
- })(JsDoc = ts.JsDoc || (ts.JsDoc = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- function stringToInt(str) {
- var n = parseInt(str, 10);
- if (isNaN(n)) {
- throw new Error("Error in parseInt(" + JSON.stringify(str) + ")");
- }
- return n;
- }
- var isPrereleaseRegex = /^(.*)-next.\d+/;
- var prereleaseSemverRegex = /^(\d+)\.(\d+)\.0-next.(\d+)$/;
- var semverRegex = /^(\d+)\.(\d+)\.(\d+)$/;
- var Semver = /** @class */ (function () {
- function Semver(major, minor, patch,
- /**
- * If true, this is `major.minor.0-next.patch`.
- * If false, this is `major.minor.patch`.
- */
- isPrerelease) {
- this.major = major;
- this.minor = minor;
- this.patch = patch;
- this.isPrerelease = isPrerelease;
- }
- Semver.parse = function (semver) {
- var isPrerelease = isPrereleaseRegex.test(semver);
- var result = Semver.tryParse(semver, isPrerelease);
- if (!result) {
- throw new Error("Unexpected semver: " + semver + " (isPrerelease: " + isPrerelease + ")");
- }
- return result;
- };
- Semver.fromRaw = function (_a) {
- var major = _a.major, minor = _a.minor, patch = _a.patch, isPrerelease = _a.isPrerelease;
- return new Semver(major, minor, patch, isPrerelease);
- };
- // This must parse the output of `versionString`.
- Semver.tryParse = function (semver, isPrerelease) {
- // Per the semver spec :
- // "A normal version number MUST take the form X.Y.Z where X, Y, and Z are non-negative integers, and MUST NOT contain leading zeroes."
- var rgx = isPrerelease ? prereleaseSemverRegex : semverRegex;
- var match = rgx.exec(semver);
- return match ? new Semver(stringToInt(match[1]), stringToInt(match[2]), stringToInt(match[3]), isPrerelease) : undefined;
- };
- Object.defineProperty(Semver.prototype, "versionString", {
- get: function () {
- return this.isPrerelease ? this.major + "." + this.minor + ".0-next." + this.patch : this.major + "." + this.minor + "." + this.patch;
- },
- enumerable: true,
- configurable: true
- });
- Semver.prototype.equals = function (sem) {
- return this.major === sem.major && this.minor === sem.minor && this.patch === sem.patch && this.isPrerelease === sem.isPrerelease;
- };
- Semver.prototype.greaterThan = function (sem) {
- return this.major > sem.major || this.major === sem.major
- && (this.minor > sem.minor || this.minor === sem.minor
- && (!this.isPrerelease && sem.isPrerelease || this.isPrerelease === sem.isPrerelease
- && this.patch > sem.patch));
- };
- return Semver;
- }());
- ts.Semver = Semver;
-})(ts || (ts = {}));
-// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0.
-// See LICENSE.txt in the project root for complete license information.
-///
-///
-///
-///
-/* @internal */
-var ts;
-(function (ts) {
- var JsTyping;
- (function (JsTyping) {
- /* @internal */
- function isTypingUpToDate(cachedTyping, availableTypingVersions) {
- var availableVersion = ts.Semver.parse(ts.getProperty(availableTypingVersions, "ts" + ts.versionMajorMinor) || ts.getProperty(availableTypingVersions, "latest"));
- return !availableVersion.greaterThan(cachedTyping.version);
- }
- JsTyping.isTypingUpToDate = isTypingUpToDate;
- /* @internal */
- JsTyping.nodeCoreModuleList = [
- "buffer", "querystring", "events", "http", "cluster",
- "zlib", "os", "https", "punycode", "repl", "readline",
- "vm", "child_process", "url", "dns", "net",
- "dgram", "fs", "path", "string_decoder", "tls",
- "crypto", "stream", "util", "assert", "tty", "domain",
- "constants", "process", "v8", "timers", "console"
- ];
- var nodeCoreModules = ts.arrayToSet(JsTyping.nodeCoreModuleList);
- function loadSafeList(host, safeListPath) {
- var result = ts.readConfigFile(safeListPath, function (path) { return host.readFile(path); });
- return ts.createMapFromTemplate(result.config);
- }
- JsTyping.loadSafeList = loadSafeList;
- function loadTypesMap(host, typesMapPath) {
- var result = ts.readConfigFile(typesMapPath, function (path) { return host.readFile(path); });
- if (result.config) {
- return ts.createMapFromTemplate(result.config.simpleMap);
- }
- return undefined;
- }
- JsTyping.loadTypesMap = loadTypesMap;
- /**
- * @param host is the object providing I/O related operations.
- * @param fileNames are the file names that belong to the same project
- * @param projectRootPath is the path to the project root directory
- * @param safeListPath is the path used to retrieve the safe list
- * @param packageNameToTypingLocation is the map of package names to their cached typing locations and installed versions
- * @param typeAcquisition is used to customize the typing acquisition process
- * @param compilerOptions are used as a source for typing inference
- */
- function discoverTypings(host, log, fileNames, projectRootPath, safeList, packageNameToTypingLocation, typeAcquisition, unresolvedImports, typesRegistry) {
- if (!typeAcquisition || !typeAcquisition.enable) {
- return { cachedTypingPaths: [], newTypingNames: [], filesToWatch: [] };
- }
- // A typing name to typing file path mapping
- var inferredTypings = ts.createMap();
- // Only infer typings for .js and .jsx files
- fileNames = ts.mapDefined(fileNames, function (fileName) {
- var path = ts.normalizePath(fileName);
- if (ts.hasJavaScriptFileExtension(path)) {
- return path;
- }
- });
- var filesToWatch = [];
- if (typeAcquisition.include)
- addInferredTypings(typeAcquisition.include, "Explicitly included types");
- var exclude = typeAcquisition.exclude || [];
- // Directories to search for package.json, bower.json and other typing information
- var possibleSearchDirs = ts.arrayToSet(fileNames, ts.getDirectoryPath);
- possibleSearchDirs.set(projectRootPath, true);
- possibleSearchDirs.forEach(function (_true, searchDir) {
- var packageJsonPath = ts.combinePaths(searchDir, "package.json");
- getTypingNamesFromJson(packageJsonPath, filesToWatch);
- var bowerJsonPath = ts.combinePaths(searchDir, "bower.json");
- getTypingNamesFromJson(bowerJsonPath, filesToWatch);
- var bowerComponentsPath = ts.combinePaths(searchDir, "bower_components");
- getTypingNamesFromPackagesFolder(bowerComponentsPath, filesToWatch);
- var nodeModulesPath = ts.combinePaths(searchDir, "node_modules");
- getTypingNamesFromPackagesFolder(nodeModulesPath, filesToWatch);
- });
- getTypingNamesFromSourceFileNames(fileNames);
- // add typings for unresolved imports
- if (unresolvedImports) {
- var module = ts.deduplicate(unresolvedImports.map(function (moduleId) { return nodeCoreModules.has(moduleId) ? "node" : moduleId; }), ts.equateStringsCaseSensitive, ts.compareStringsCaseSensitive);
- addInferredTypings(module, "Inferred typings from unresolved imports");
- }
- // Add the cached typing locations for inferred typings that are already installed
- packageNameToTypingLocation.forEach(function (typing, name) {
- if (inferredTypings.has(name) && inferredTypings.get(name) === undefined && isTypingUpToDate(typing, typesRegistry.get(name))) {
- inferredTypings.set(name, typing.typingLocation);
- }
- });
- // Remove typings that the user has added to the exclude list
- for (var _i = 0, exclude_1 = exclude; _i < exclude_1.length; _i++) {
- var excludeTypingName = exclude_1[_i];
- var didDelete = inferredTypings.delete(excludeTypingName);
- if (didDelete && log)
- log("Typing for " + excludeTypingName + " is in exclude list, will be ignored.");
- }
- var newTypingNames = [];
- var cachedTypingPaths = [];
- inferredTypings.forEach(function (inferred, typing) {
- if (inferred !== undefined) {
- cachedTypingPaths.push(inferred);
- }
- else {
- newTypingNames.push(typing);
- }
- });
- var result = { cachedTypingPaths: cachedTypingPaths, newTypingNames: newTypingNames, filesToWatch: filesToWatch };
- if (log)
- log("Result: " + JSON.stringify(result));
- return result;
- function addInferredTyping(typingName) {
- if (!inferredTypings.has(typingName)) {
- inferredTypings.set(typingName, undefined);
- }
- }
- function addInferredTypings(typingNames, message) {
- if (log)
- log(message + ": " + JSON.stringify(typingNames));
- ts.forEach(typingNames, addInferredTyping);
- }
- /**
- * Get the typing info from common package manager json files like package.json or bower.json
- */
- function getTypingNamesFromJson(jsonPath, filesToWatch) {
- if (!host.fileExists(jsonPath)) {
- return;
- }
- filesToWatch.push(jsonPath);
- var jsonConfig = ts.readConfigFile(jsonPath, function (path) { return host.readFile(path); }).config;
- var jsonTypingNames = ts.flatMap([jsonConfig.dependencies, jsonConfig.devDependencies, jsonConfig.optionalDependencies, jsonConfig.peerDependencies], ts.getOwnKeys);
- addInferredTypings(jsonTypingNames, "Typing names in '" + jsonPath + "' dependencies");
- }
- /**
- * Infer typing names from given file names. For example, the file name "jquery-min.2.3.4.js"
- * should be inferred to the 'jquery' typing name; and "angular-route.1.2.3.js" should be inferred
- * to the 'angular-route' typing name.
- * @param fileNames are the names for source files in the project
- */
- function getTypingNamesFromSourceFileNames(fileNames) {
- var fromFileNames = ts.mapDefined(fileNames, function (j) {
- if (!ts.hasJavaScriptFileExtension(j))
- return undefined;
- var inferredTypingName = ts.removeFileExtension(ts.getBaseFileName(j.toLowerCase()));
- var cleanedTypingName = ts.removeMinAndVersionNumbers(inferredTypingName);
- return safeList.get(cleanedTypingName);
- });
- if (fromFileNames.length) {
- addInferredTypings(fromFileNames, "Inferred typings from file names");
- }
- var hasJsxFile = ts.some(fileNames, function (f) { return ts.fileExtensionIs(f, ".jsx" /* Jsx */); });
- if (hasJsxFile) {
- if (log)
- log("Inferred 'react' typings due to presence of '.jsx' extension");
- addInferredTyping("react");
- }
- }
- /**
- * Infer typing names from packages folder (ex: node_module, bower_components)
- * @param packagesFolderPath is the path to the packages folder
- */
- function getTypingNamesFromPackagesFolder(packagesFolderPath, filesToWatch) {
- filesToWatch.push(packagesFolderPath);
- // Todo: add support for ModuleResolutionHost too
- if (!host.directoryExists(packagesFolderPath)) {
- return;
- }
- // depth of 2, so we access `node_modules/foo` but not `node_modules/foo/bar`
- var fileNames = host.readDirectory(packagesFolderPath, [".json" /* Json */], /*excludes*/ undefined, /*includes*/ undefined, /*depth*/ 2);
- if (log)
- log("Searching for typing names in " + packagesFolderPath + "; all files: " + JSON.stringify(fileNames));
- var packageNames = [];
- for (var _i = 0, fileNames_1 = fileNames; _i < fileNames_1.length; _i++) {
- var fileName = fileNames_1[_i];
- var normalizedFileName = ts.normalizePath(fileName);
- var baseFileName = ts.getBaseFileName(normalizedFileName);
- if (baseFileName !== "package.json" && baseFileName !== "bower.json") {
- continue;
- }
- var result_5 = ts.readConfigFile(normalizedFileName, function (path) { return host.readFile(path); });
- var packageJson = result_5.config;
- // npm 3's package.json contains a "_requiredBy" field
- // we should include all the top level module names for npm 2, and only module names whose
- // "_requiredBy" field starts with "#" or equals "/" for npm 3.
- if (baseFileName === "package.json" && packageJson._requiredBy &&
- ts.filter(packageJson._requiredBy, function (r) { return r[0] === "#" || r === "/"; }).length === 0) {
- continue;
- }
- // If the package has its own d.ts typings, those will take precedence. Otherwise the package name will be used
- // to download d.ts files from DefinitelyTyped
- if (!packageJson.name) {
- continue;
- }
- var ownTypes = packageJson.types || packageJson.typings;
- if (ownTypes) {
- var absolutePath = ts.getNormalizedAbsolutePath(ownTypes, ts.getDirectoryPath(normalizedFileName));
- if (log)
- log(" Package '" + packageJson.name + "' provides its own types.");
- inferredTypings.set(packageJson.name, absolutePath);
- }
- else {
- packageNames.push(packageJson.name);
- }
- }
- addInferredTypings(packageNames, " Found package names");
- }
- }
- JsTyping.discoverTypings = discoverTypings;
- var PackageNameValidationResult;
- (function (PackageNameValidationResult) {
- PackageNameValidationResult[PackageNameValidationResult["Ok"] = 0] = "Ok";
- PackageNameValidationResult[PackageNameValidationResult["ScopedPackagesNotSupported"] = 1] = "ScopedPackagesNotSupported";
- PackageNameValidationResult[PackageNameValidationResult["EmptyName"] = 2] = "EmptyName";
- PackageNameValidationResult[PackageNameValidationResult["NameTooLong"] = 3] = "NameTooLong";
- PackageNameValidationResult[PackageNameValidationResult["NameStartsWithDot"] = 4] = "NameStartsWithDot";
- PackageNameValidationResult[PackageNameValidationResult["NameStartsWithUnderscore"] = 5] = "NameStartsWithUnderscore";
- PackageNameValidationResult[PackageNameValidationResult["NameContainsNonURISafeCharacters"] = 6] = "NameContainsNonURISafeCharacters";
- })(PackageNameValidationResult = JsTyping.PackageNameValidationResult || (JsTyping.PackageNameValidationResult = {}));
- var maxPackageNameLength = 214;
- /**
- * Validates package name using rules defined at https://docs.npmjs.com/files/package.json
- */
- function validatePackageName(packageName) {
- if (!packageName) {
- return 2 /* EmptyName */;
- }
- if (packageName.length > maxPackageNameLength) {
- return 3 /* NameTooLong */;
- }
- if (packageName.charCodeAt(0) === 46 /* dot */) {
- return 4 /* NameStartsWithDot */;
- }
- if (packageName.charCodeAt(0) === 95 /* _ */) {
- return 5 /* NameStartsWithUnderscore */;
- }
- // check if name is scope package like: starts with @ and has one '/' in the middle
- // scoped packages are not currently supported
- // TODO: when support will be added we'll need to split and check both scope and package name
- if (/^@[^/]+\/[^/]+$/.test(packageName)) {
- return 1 /* ScopedPackagesNotSupported */;
- }
- if (encodeURIComponent(packageName) !== packageName) {
- return 6 /* NameContainsNonURISafeCharacters */;
- }
- return 0 /* Ok */;
- }
- JsTyping.validatePackageName = validatePackageName;
- function renderPackageNameValidationFailure(result, typing) {
- switch (result) {
- case 2 /* EmptyName */:
- return "Package name '" + typing + "' cannot be empty";
- case 3 /* NameTooLong */:
- return "Package name '" + typing + "' should be less than " + maxPackageNameLength + " characters";
- case 4 /* NameStartsWithDot */:
- return "Package name '" + typing + "' cannot start with '.'";
- case 5 /* NameStartsWithUnderscore */:
- return "Package name '" + typing + "' cannot start with '_'";
- case 1 /* ScopedPackagesNotSupported */:
- return "Package '" + typing + "' is scoped and currently is not supported";
- case 6 /* NameContainsNonURISafeCharacters */:
- return "Package name '" + typing + "' contains non URI safe characters";
- case 0 /* Ok */:
- return ts.Debug.fail(); // Shouldn't have called this.
- default:
- ts.Debug.assertNever(result);
- }
- }
- JsTyping.renderPackageNameValidationFailure = renderPackageNameValidationFailure;
- })(JsTyping = ts.JsTyping || (ts.JsTyping = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var NavigateTo;
- (function (NavigateTo) {
- function getNavigateToItems(sourceFiles, checker, cancellationToken, searchValue, maxResultCount, excludeDtsFiles) {
- var patternMatcher = ts.createPatternMatcher(searchValue);
- var rawItems = [];
- var _loop_8 = function (sourceFile) {
- cancellationToken.throwIfCancellationRequested();
- if (excludeDtsFiles && ts.fileExtensionIs(sourceFile.fileName, ".d.ts" /* Dts */)) {
- return "continue";
- }
- ts.forEachEntry(sourceFile.getNamedDeclarations(), function (declarations, name) {
- getItemsFromNamedDeclaration(patternMatcher, name, declarations, checker, sourceFile.fileName, rawItems);
- });
- };
- // Search the declarations in all files and output matched NavigateToItem into array of NavigateToItem[]
- for (var _i = 0, sourceFiles_6 = sourceFiles; _i < sourceFiles_6.length; _i++) {
- var sourceFile = sourceFiles_6[_i];
- _loop_8(sourceFile);
- }
- rawItems.sort(compareNavigateToItems);
- if (maxResultCount !== undefined) {
- rawItems = rawItems.slice(0, maxResultCount);
- }
- return rawItems.map(createNavigateToItem);
- }
- NavigateTo.getNavigateToItems = getNavigateToItems;
- function getItemsFromNamedDeclaration(patternMatcher, name, declarations, checker, fileName, rawItems) {
- // First do a quick check to see if the name of the declaration matches the
- // last portion of the (possibly) dotted name they're searching for.
- var matches = patternMatcher.getMatchesForLastSegmentOfPattern(name);
- if (!matches) {
- return; // continue to next named declarations
- }
- for (var _i = 0, declarations_11 = declarations; _i < declarations_11.length; _i++) {
- var declaration = declarations_11[_i];
- if (!shouldKeepItem(declaration, checker)) {
- continue;
- }
- // It was a match! If the pattern has dots in it, then also see if the
- // declaration container matches as well.
- var containerMatches = matches;
- if (patternMatcher.patternContainsDots) {
- containerMatches = patternMatcher.getMatches(getContainers(declaration), name);
- if (!containerMatches) {
- continue;
- }
- }
- var matchKind = bestMatchKind(containerMatches);
- var isCaseSensitive = allMatchesAreCaseSensitive(containerMatches);
- rawItems.push({ name: name, fileName: fileName, matchKind: matchKind, isCaseSensitive: isCaseSensitive, declaration: declaration });
- }
- }
- function shouldKeepItem(declaration, checker) {
- switch (declaration.kind) {
- case 243 /* ImportClause */:
- case 246 /* ImportSpecifier */:
- case 241 /* ImportEqualsDeclaration */:
- var importer = checker.getSymbolAtLocation(declaration.name);
- var imported = checker.getAliasedSymbol(importer);
- return importer.escapedName !== imported.escapedName;
- default:
- return true;
- }
- }
- function allMatchesAreCaseSensitive(matches) {
- ts.Debug.assert(matches.length > 0);
- // This is a case sensitive match, only if all the submatches were case sensitive.
- for (var _i = 0, matches_1 = matches; _i < matches_1.length; _i++) {
- var match = matches_1[_i];
- if (!match.isCaseSensitive) {
- return false;
- }
- }
- return true;
- }
- function tryAddSingleDeclarationName(declaration, containers) {
- var name = ts.getNameOfDeclaration(declaration);
- if (name && ts.isPropertyNameLiteral(name)) {
- containers.unshift(ts.getTextOfIdentifierOrLiteral(name));
- return true;
- }
- else if (name && name.kind === 146 /* ComputedPropertyName */) {
- return tryAddComputedPropertyName(name.expression, containers, /*includeLastPortion*/ true);
- }
- else {
- // Don't know how to add this.
- return false;
- }
- }
- // Only added the names of computed properties if they're simple dotted expressions, like:
- //
- // [X.Y.Z]() { }
- function tryAddComputedPropertyName(expression, containers, includeLastPortion) {
- if (ts.isPropertyNameLiteral(expression)) {
- var text = ts.getTextOfIdentifierOrLiteral(expression);
- if (includeLastPortion) {
- containers.unshift(text);
- }
- return true;
- }
- if (ts.isPropertyAccessExpression(expression)) {
- if (includeLastPortion) {
- containers.unshift(expression.name.text);
- }
- return tryAddComputedPropertyName(expression.expression, containers, /*includeLastPortion*/ true);
- }
- return false;
- }
- function getContainers(declaration) {
- var containers = [];
- // First, if we started with a computed property name, then add all but the last
- // portion into the container array.
- var name = ts.getNameOfDeclaration(declaration);
- if (name.kind === 146 /* ComputedPropertyName */) {
- if (!tryAddComputedPropertyName(name.expression, containers, /*includeLastPortion*/ false)) {
- return undefined;
- }
- }
- // Now, walk up our containers, adding all their names to the container array.
- declaration = ts.getContainerNode(declaration);
- while (declaration) {
- if (!tryAddSingleDeclarationName(declaration, containers)) {
- return undefined;
- }
- declaration = ts.getContainerNode(declaration);
- }
- return containers;
- }
- function bestMatchKind(matches) {
- ts.Debug.assert(matches.length > 0);
- var bestMatchKind = ts.PatternMatchKind.camelCase;
- for (var _i = 0, matches_2 = matches; _i < matches_2.length; _i++) {
- var match = matches_2[_i];
- var kind = match.kind;
- if (kind < bestMatchKind) {
- bestMatchKind = kind;
- }
- }
- return bestMatchKind;
- }
- function compareNavigateToItems(i1, i2) {
- // TODO(cyrusn): get the gamut of comparisons that VS already uses here.
- return ts.compareValues(i1.matchKind, i2.matchKind)
- || ts.compareStringsCaseSensitiveUI(i1.name, i2.name);
- }
- function createNavigateToItem(rawItem) {
- var declaration = rawItem.declaration;
- var container = ts.getContainerNode(declaration);
- var containerName = container && ts.getNameOfDeclaration(container);
- return {
- name: rawItem.name,
- kind: ts.getNodeKind(declaration),
- kindModifiers: ts.getNodeModifiers(declaration),
- matchKind: ts.PatternMatchKind[rawItem.matchKind],
- isCaseSensitive: rawItem.isCaseSensitive,
- fileName: rawItem.fileName,
- textSpan: ts.createTextSpanFromNode(declaration),
- // TODO(jfreeman): What should be the containerName when the container has a computed name?
- containerName: containerName ? containerName.text : "",
- containerKind: containerName ? ts.getNodeKind(container) : "" /* unknown */
- };
- }
- })(NavigateTo = ts.NavigateTo || (ts.NavigateTo = {}));
-})(ts || (ts = {}));
-///
-/* @internal */
-var ts;
-(function (ts) {
- var NavigationBar;
- (function (NavigationBar) {
- /**
- * Matches all whitespace characters in a string. Eg:
- *
- * "app.
- *
- * onactivated"
- *
- * matches because of the newline, whereas
- *
- * "app.onactivated"
- *
- * does not match.
- */
- var whiteSpaceRegex = /\s+/g;
- // Keep sourceFile handy so we don't have to search for it every time we need to call `getText`.
- var curCancellationToken;
- var curSourceFile;
- /**
- * For performance, we keep navigation bar parents on a stack rather than passing them through each recursion.
- * `parent` is the current parent and is *not* stored in parentsStack.
- * `startNode` sets a new parent and `endNode` returns to the previous parent.
- */
- var parentsStack = [];
- var parent;
- // NavigationBarItem requires an array, but will not mutate it, so just give it this for performance.
- var emptyChildItemArray = [];
- function getNavigationBarItems(sourceFile, cancellationToken) {
- curCancellationToken = cancellationToken;
- curSourceFile = sourceFile;
- try {
- return ts.map(topLevelItems(rootNavigationBarNode(sourceFile)), convertToTopLevelItem);
- }
- finally {
- reset();
- }
- }
- NavigationBar.getNavigationBarItems = getNavigationBarItems;
- function getNavigationTree(sourceFile, cancellationToken) {
- curCancellationToken = cancellationToken;
- curSourceFile = sourceFile;
- try {
- return convertToTree(rootNavigationBarNode(sourceFile));
- }
- finally {
- reset();
- }
- }
- NavigationBar.getNavigationTree = getNavigationTree;
- function reset() {
- curSourceFile = undefined;
- curCancellationToken = undefined;
- parentsStack = [];
- parent = undefined;
- emptyChildItemArray = [];
- }
- function nodeText(node) {
- return node.getText(curSourceFile);
- }
- function navigationBarNodeKind(n) {
- return n.node.kind;
- }
- function pushChild(parent, child) {
- if (parent.children) {
- parent.children.push(child);
- }
- else {
- parent.children = [child];
- }
- }
- function rootNavigationBarNode(sourceFile) {
- ts.Debug.assert(!parentsStack.length);
- var root = { node: sourceFile, additionalNodes: undefined, parent: undefined, children: undefined, indent: 0 };
- parent = root;
- for (var _i = 0, _a = sourceFile.statements; _i < _a.length; _i++) {
- var statement = _a[_i];
- addChildrenRecursively(statement);
- }
- endNode();
- ts.Debug.assert(!parent && !parentsStack.length);
- return root;
- }
- function addLeafNode(node) {
- pushChild(parent, emptyNavigationBarNode(node));
- }
- function emptyNavigationBarNode(node) {
- return {
- node: node,
- additionalNodes: undefined,
- parent: parent,
- children: undefined,
- indent: parent.indent + 1
- };
- }
- /**
- * Add a new level of NavigationBarNodes.
- * This pushes to the stack, so you must call `endNode` when you are done adding to this node.
- */
- function startNode(node) {
- var navNode = emptyNavigationBarNode(node);
- pushChild(parent, navNode);
- // Save the old parent
- parentsStack.push(parent);
- parent = navNode;
- }
- /** Call after calling `startNode` and adding children to it. */
- function endNode() {
- if (parent.children) {
- mergeChildren(parent.children);
- sortChildren(parent.children);
- }
- parent = parentsStack.pop();
- }
- function addNodeWithRecursiveChild(node, child) {
- startNode(node);
- addChildrenRecursively(child);
- endNode();
- }
- /** Look for navigation bar items in node's subtree, adding them to the current `parent`. */
- function addChildrenRecursively(node) {
- curCancellationToken.throwIfCancellationRequested();
- if (!node || ts.isToken(node)) {
- return;
- }
- switch (node.kind) {
- case 154 /* Constructor */:
- // Get parameter properties, and treat them as being on the *same* level as the constructor, not under it.
- var ctr = node;
- addNodeWithRecursiveChild(ctr, ctr.body);
- // Parameter properties are children of the class, not the constructor.
- for (var _i = 0, _a = ctr.parameters; _i < _a.length; _i++) {
- var param = _a[_i];
- if (ts.isParameterPropertyDeclaration(param)) {
- addLeafNode(param);
- }
- }
- break;
- case 153 /* MethodDeclaration */:
- case 155 /* GetAccessor */:
- case 156 /* SetAccessor */:
- case 152 /* MethodSignature */:
- if (!ts.hasDynamicName(node)) {
- addNodeWithRecursiveChild(node, node.body);
- }
- break;
- case 151 /* PropertyDeclaration */:
- case 150 /* PropertySignature */:
- if (!ts.hasDynamicName(node)) {
- addLeafNode(node);
- }
- break;
- case 243 /* ImportClause */:
- var importClause = node;
- // Handle default import case e.g.:
- // import d from "mod";
- if (importClause.name) {
- addLeafNode(importClause);
- }
- // Handle named bindings in imports e.g.:
- // import * as NS from "mod";
- // import {a, b as B} from "mod";
- var namedBindings = importClause.namedBindings;
- if (namedBindings) {
- if (namedBindings.kind === 244 /* NamespaceImport */) {
- addLeafNode(namedBindings);
- }
- else {
- for (var _b = 0, _c = namedBindings.elements; _b < _c.length; _b++) {
- var element = _c[_b];
- addLeafNode(element);
- }
- }
- }
- break;
- case 180 /* BindingElement */:
- case 230 /* VariableDeclaration */:
- var _d = node, name = _d.name, initializer = _d.initializer;
- if (ts.isBindingPattern(name)) {
- addChildrenRecursively(name);
- }
- else if (initializer && isFunctionOrClassExpression(initializer)) {
- if (initializer.name) {
- // Don't add a node for the VariableDeclaration, just for the initializer.
- addChildrenRecursively(initializer);
- }
- else {
- // Add a node for the VariableDeclaration, but not for the initializer.
- startNode(node);
- ts.forEachChild(initializer, addChildrenRecursively);
- endNode();
- }
- }
- else {
- addNodeWithRecursiveChild(node, initializer);
- }
- break;
- case 191 /* ArrowFunction */:
- case 232 /* FunctionDeclaration */:
- case 190 /* FunctionExpression */:
- addNodeWithRecursiveChild(node, node.body);
- break;
- case 236 /* EnumDeclaration */:
- startNode(node);
- for (var _e = 0, _f = node.members; _e < _f.length; _e++) {
- var member = _f[_e];
- if (!isComputedProperty(member)) {
- addLeafNode(member);
- }
- }
- endNode();
- break;
- case 233 /* ClassDeclaration */:
- case 203 /* ClassExpression */:
- case 234 /* InterfaceDeclaration */:
- startNode(node);
- for (var _g = 0, _h = node.members; _g < _h.length; _g++) {
- var member = _h[_g];
- addChildrenRecursively(member);
- }
- endNode();
- break;
- case 237 /* ModuleDeclaration */:
- addNodeWithRecursiveChild(node, getInteriorModule(node).body);
- break;
- case 250 /* ExportSpecifier */:
- case 241 /* ImportEqualsDeclaration */:
- case 159 /* IndexSignature */:
- case 157 /* CallSignature */:
- case 158 /* ConstructSignature */:
- case 235 /* TypeAliasDeclaration */:
- addLeafNode(node);
- break;
- case 198 /* BinaryExpression */: {
- var special = ts.getSpecialPropertyAssignmentKind(node);
- switch (special) {
- case 1 /* ExportsProperty */:
- case 2 /* ModuleExports */:
- case 3 /* PrototypeProperty */:
- case 6 /* Prototype */:
- addNodeWithRecursiveChild(node, node.right);
- break;
- case 4 /* ThisProperty */:
- case 5 /* Property */:
- case 0 /* None */:
- break;
- default:
- ts.Debug.assertNever(special);
- }
- }
- // falls through
- default:
- if (ts.hasJSDocNodes(node)) {
- ts.forEach(node.jsDoc, function (jsDoc) {
- ts.forEach(jsDoc.tags, function (tag) {
- if (tag.kind === 291 /* JSDocTypedefTag */) {
- addLeafNode(tag);
- }
- });
- });
- }
- ts.forEachChild(node, addChildrenRecursively);
- }
- }
- /** Merge declarations of the same kind. */
- function mergeChildren(children) {
- var nameToItems = ts.createMap();
- ts.filterMutate(children, function (child) {
- var declName = ts.getNameOfDeclaration(child.node);
- var name = declName && nodeText(declName);
- if (!name) {
- // Anonymous items are never merged.
- return true;
- }
- var itemsWithSameName = nameToItems.get(name);
- if (!itemsWithSameName) {
- nameToItems.set(name, child);
- return true;
- }
- if (itemsWithSameName instanceof Array) {
- for (var _i = 0, itemsWithSameName_1 = itemsWithSameName; _i < itemsWithSameName_1.length; _i++) {
- var itemWithSameName = itemsWithSameName_1[_i];
- if (tryMerge(itemWithSameName, child)) {
- return false;
- }
- }
- itemsWithSameName.push(child);
- return true;
- }
- else {
- var itemWithSameName = itemsWithSameName;
- if (tryMerge(itemWithSameName, child)) {
- return false;
- }
- nameToItems.set(name, [itemWithSameName, child]);
- return true;
- }
- });
- }
- function tryMerge(a, b) {
- if (shouldReallyMerge(a.node, b.node)) {
- merge(a, b);
- return true;
- }
- return false;
- }
- /** a and b have the same name, but they may not be mergeable. */
- function shouldReallyMerge(a, b) {
- if (a.kind !== b.kind) {
- return false;
- }
- switch (a.kind) {
- case 151 /* PropertyDeclaration */:
- case 153 /* MethodDeclaration */:
- case 155 /* GetAccessor */:
- case 156 /* SetAccessor */:
- return ts.hasModifier(a, 32 /* Static */) === ts.hasModifier(b, 32 /* Static */);
- case 237 /* ModuleDeclaration */:
- return areSameModule(a, b);
- default:
- return true;
- }
- }
- // We use 1 NavNode to represent 'A.B.C', but there are multiple source nodes.
- // Only merge module nodes that have the same chain. Don't merge 'A.B.C' with 'A'!
- function areSameModule(a, b) {
- return a.body.kind === b.body.kind && (a.body.kind !== 237 /* ModuleDeclaration */ || areSameModule(a.body, b.body));
- }
- /** Merge source into target. Source should be thrown away after this is called. */
- function merge(target, source) {
- target.additionalNodes = target.additionalNodes || [];
- target.additionalNodes.push(source.node);
- if (source.additionalNodes) {
- (_a = target.additionalNodes).push.apply(_a, source.additionalNodes);
- }
- target.children = ts.concatenate(target.children, source.children);
- if (target.children) {
- mergeChildren(target.children);
- sortChildren(target.children);
- }
- var _a;
- }
- /** Recursively ensure that each NavNode's children are in sorted order. */
- function sortChildren(children) {
- children.sort(compareChildren);
- }
- function compareChildren(child1, child2) {
- return ts.compareStringsCaseSensitiveUI(tryGetName(child1.node), tryGetName(child2.node))
- || ts.compareValues(navigationBarNodeKind(child1), navigationBarNodeKind(child2));
- }
- /**
- * This differs from getItemName because this is just used for sorting.
- * We only sort nodes by name that have a more-or-less "direct" name, as opposed to `new()` and the like.
- * So `new()` can still come before an `aardvark` method.
- */
- function tryGetName(node) {
- if (node.kind === 237 /* ModuleDeclaration */) {
- return getModuleName(node);
- }
- var declName = ts.getNameOfDeclaration(node);
- if (declName) {
- return ts.unescapeLeadingUnderscores(ts.getPropertyNameForPropertyNameNode(declName));
- }
- switch (node.kind) {
- case 190 /* FunctionExpression */:
- case 191 /* ArrowFunction */:
- case 203 /* ClassExpression */:
- return getFunctionOrClassName(node);
- case 291 /* JSDocTypedefTag */:
- return getJSDocTypedefTagName(node);
- default:
- return undefined;
- }
- }
- function getItemName(node) {
- if (node.kind === 237 /* ModuleDeclaration */) {
- return getModuleName(node);
- }
- var name = ts.getNameOfDeclaration(node);
- if (name) {
- var text = nodeText(name);
- if (text.length > 0) {
- return text;
- }
- }
- switch (node.kind) {
- case 272 /* SourceFile */:
- var sourceFile = node;
- return ts.isExternalModule(sourceFile)
- ? "\"" + ts.escapeString(ts.getBaseFileName(ts.removeFileExtension(ts.normalizePath(sourceFile.fileName)))) + "\""
- : "";
- case 191 /* ArrowFunction */:
- case 232 /* FunctionDeclaration */:
- case 190 /* FunctionExpression */:
- case 233 /* ClassDeclaration */:
- case 203 /* ClassExpression */:
- if (ts.getModifierFlags(node) & 512 /* Default */) {
- return "default";
- }
- // We may get a string with newlines or other whitespace in the case of an object dereference
- // (eg: "app\n.onactivated"), so we should remove the whitespace for readabiltiy in the
- // navigation bar.
- return getFunctionOrClassName(node);
- case 154 /* Constructor */:
- return "constructor";
- case 158 /* ConstructSignature */:
- return "new()";
- case 157 /* CallSignature */:
- return "()";
- case 159 /* IndexSignature */:
- return "[]";
- case 291 /* JSDocTypedefTag */:
- return getJSDocTypedefTagName(node);
- default:
- return "";
- }
- }
- function getJSDocTypedefTagName(node) {
- if (node.name) {
- return node.name.text;
- }
- else {
- var parentNode = node.parent && node.parent.parent;
- if (parentNode && parentNode.kind === 212 /* VariableStatement */) {
- if (parentNode.declarationList.declarations.length > 0) {
- var nameIdentifier = parentNode.declarationList.declarations[0].name;
- if (nameIdentifier.kind === 71 /* Identifier */) {
- return nameIdentifier.text;
- }
- }
- }
- return "";
- }
- }
- /** Flattens the NavNode tree to a list, keeping only the top-level items. */
- function topLevelItems(root) {
- var topLevel = [];
- function recur(item) {
- if (isTopLevel(item)) {
- topLevel.push(item);
- if (item.children) {
- for (var _i = 0, _a = item.children; _i < _a.length; _i++) {
- var child = _a[_i];
- recur(child);
- }
- }
- }
- }
- recur(root);
- return topLevel;
- function isTopLevel(item) {
- switch (navigationBarNodeKind(item)) {
- case 233 /* ClassDeclaration */:
- case 203 /* ClassExpression */:
- case 236 /* EnumDeclaration */:
- case 234 /* InterfaceDeclaration */:
- case 237 /* ModuleDeclaration */:
- case 272 /* SourceFile */:
- case 235 /* TypeAliasDeclaration */:
- case 291 /* JSDocTypedefTag */:
- return true;
- case 154 /* Constructor */:
- case 153 /* MethodDeclaration */:
- case 155 /* GetAccessor */:
- case 156 /* SetAccessor */:
- case 230 /* VariableDeclaration */:
- return hasSomeImportantChild(item);
- case 191 /* ArrowFunction */:
- case 232 /* FunctionDeclaration */:
- case 190 /* FunctionExpression */:
- return isTopLevelFunctionDeclaration(item);
- default:
- return false;
- }
- function isTopLevelFunctionDeclaration(item) {
- if (!item.node.body) {
- return false;
- }
- switch (navigationBarNodeKind(item.parent)) {
- case 238 /* ModuleBlock */:
- case 272 /* SourceFile */:
- case 153 /* MethodDeclaration */:
- case 154 /* Constructor */:
- return true;
- default:
- return hasSomeImportantChild(item);
- }
- }
- function hasSomeImportantChild(item) {
- return ts.forEach(item.children, function (child) {
- var childKind = navigationBarNodeKind(child);
- return childKind !== 230 /* VariableDeclaration */ && childKind !== 180 /* BindingElement */;
- });
- }
- }
- }
- function convertToTree(n) {
- return {
- text: getItemName(n.node),
- kind: ts.getNodeKind(n.node),
- kindModifiers: getModifiers(n.node),
- spans: getSpans(n),
- childItems: ts.map(n.children, convertToTree)
- };
- }
- function convertToTopLevelItem(n) {
- return {
- text: getItemName(n.node),
- kind: ts.getNodeKind(n.node),
- kindModifiers: getModifiers(n.node),
- spans: getSpans(n),
- childItems: ts.map(n.children, convertToChildItem) || emptyChildItemArray,
- indent: n.indent,
- bolded: false,
- grayed: false
- };
- function convertToChildItem(n) {
- return {
- text: getItemName(n.node),
- kind: ts.getNodeKind(n.node),
- kindModifiers: ts.getNodeModifiers(n.node),
- spans: getSpans(n),
- childItems: emptyChildItemArray,
- indent: 0,
- bolded: false,
- grayed: false
- };
- }
- }
- function getSpans(n) {
- var spans = [getNodeSpan(n.node)];
- if (n.additionalNodes) {
- for (var _i = 0, _a = n.additionalNodes; _i < _a.length; _i++) {
- var node = _a[_i];
- spans.push(getNodeSpan(node));
- }
- }
- return spans;
- }
- function getModuleName(moduleDeclaration) {
- // We want to maintain quotation marks.
- if (ts.isAmbientModule(moduleDeclaration)) {
- return ts.getTextOfNode(moduleDeclaration.name);
- }
- // Otherwise, we need to aggregate each identifier to build up the qualified name.
- var result = [];
- result.push(ts.getTextOfIdentifierOrLiteral(moduleDeclaration.name));
- while (moduleDeclaration.body && moduleDeclaration.body.kind === 237 /* ModuleDeclaration */) {
- moduleDeclaration = moduleDeclaration.body;
- result.push(ts.getTextOfIdentifierOrLiteral(moduleDeclaration.name));
- }
- return result.join(".");
- }
- /**
- * For 'module A.B.C', we want to get the node for 'C'.
- * We store 'A' as associated with a NavNode, and use getModuleName to traverse down again.
- */
- function getInteriorModule(decl) {
- return decl.body.kind === 237 /* ModuleDeclaration */ ? getInteriorModule(decl.body) : decl;
- }
- function isComputedProperty(member) {
- return !member.name || member.name.kind === 146 /* ComputedPropertyName */;
- }
- function getNodeSpan(node) {
- return node.kind === 272 /* SourceFile */ ? ts.createTextSpanFromRange(node) : ts.createTextSpanFromNode(node, curSourceFile);
- }
- function getModifiers(node) {
- if (node.parent && node.parent.kind === 230 /* VariableDeclaration */) {
- node = node.parent;
- }
- return ts.getNodeModifiers(node);
- }
- function getFunctionOrClassName(node) {
- if (node.name && ts.getFullWidth(node.name) > 0) {
- return ts.declarationNameToString(node.name);
- }
- // See if it is a var initializer. If so, use the var name.
- else if (node.parent.kind === 230 /* VariableDeclaration */) {
- return ts.declarationNameToString(node.parent.name);
- }
- // See if it is of the form " = function(){...}". If so, use the text from the left-hand side.
- else if (node.parent.kind === 198 /* BinaryExpression */ &&
- node.parent.operatorToken.kind === 58 /* EqualsToken */) {
- return nodeText(node.parent.left).replace(whiteSpaceRegex, "");
- }
- // See if it is a property assignment, and if so use the property name
- else if (node.parent.kind === 268 /* PropertyAssignment */ && node.parent.name) {
- return nodeText(node.parent.name);
- }
- // Default exports are named "default"
- else if (ts.getModifierFlags(node) & 512 /* Default */) {
- return "default";
- }
- else {
- return ts.isClassLike(node) ? "" : "";
- }
- }
- function isFunctionOrClassExpression(node) {
- switch (node.kind) {
- case 191 /* ArrowFunction */:
- case 190 /* FunctionExpression */:
- case 203 /* ClassExpression */:
- return true;
- default:
- return false;
- }
- }
- })(NavigationBar = ts.NavigationBar || (ts.NavigationBar = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var OrganizeImports;
- (function (OrganizeImports) {
- /**
- * Organize imports by:
- * 1) Removing unused imports
- * 2) Coalescing imports from the same module
- * 3) Sorting imports
- */
- function organizeImports(sourceFile, formatContext, host, program) {
- var changeTracker = ts.textChanges.ChangeTracker.fromContext({ host: host, formatContext: formatContext });
- // All of the old ImportDeclarations in the file, in syntactic order.
- var topLevelImportDecls = sourceFile.statements.filter(ts.isImportDeclaration);
- organizeImportsWorker(topLevelImportDecls);
- for (var _i = 0, _a = sourceFile.statements.filter(ts.isAmbientModule); _i < _a.length; _i++) {
- var ambientModule = _a[_i];
- var ambientModuleBody = getModuleBlock(ambientModule);
- var ambientModuleImportDecls = ambientModuleBody.statements.filter(ts.isImportDeclaration);
- organizeImportsWorker(ambientModuleImportDecls);
- }
- return changeTracker.getChanges();
- function organizeImportsWorker(oldImportDecls) {
- if (ts.length(oldImportDecls) === 0) {
- return;
- }
- // Special case: normally, we'd expect leading and trailing trivia to follow each import
- // around as it's sorted. However, we do not want this to happen for leading trivia
- // on the first import because it is probably the header comment for the file.
- // Consider: we could do a more careful check that this trivia is actually a header,
- // but the consequences of being wrong are very minor.
- ts.suppressLeadingTrivia(oldImportDecls[0]);
- var oldImportGroups = ts.group(oldImportDecls, function (importDecl) { return getExternalModuleName(importDecl.moduleSpecifier); });
- var sortedImportGroups = ts.stableSort(oldImportGroups, function (group1, group2) { return compareModuleSpecifiers(group1[0].moduleSpecifier, group2[0].moduleSpecifier); });
- var newImportDecls = ts.flatMap(sortedImportGroups, function (importGroup) {
- return getExternalModuleName(importGroup[0].moduleSpecifier)
- ? coalesceImports(removeUnusedImports(importGroup, sourceFile, program))
- : importGroup;
- });
- // Delete or replace the first import.
- if (newImportDecls.length === 0) {
- changeTracker.deleteNode(sourceFile, oldImportDecls[0], {
- useNonAdjustedStartPosition: true,
- useNonAdjustedEndPosition: false,
- });
- }
- else {
- // Note: Delete the surrounding trivia because it will have been retained in newImportDecls.
- changeTracker.replaceNodeWithNodes(sourceFile, oldImportDecls[0], newImportDecls, {
- useNonAdjustedStartPosition: true,
- useNonAdjustedEndPosition: false,
- suffix: ts.getNewLineOrDefaultFromHost(host, formatContext.options),
- });
- }
- // Delete any subsequent imports.
- for (var i = 1; i < oldImportDecls.length; i++) {
- changeTracker.deleteNode(sourceFile, oldImportDecls[i]);
- }
- }
- }
- OrganizeImports.organizeImports = organizeImports;
- function getModuleBlock(moduleDecl) {
- var body = moduleDecl.body;
- return body && !ts.isIdentifier(body) && (ts.isModuleBlock(body) ? body : getModuleBlock(body));
- }
- function removeUnusedImports(oldImports, sourceFile, program) {
- var typeChecker = program.getTypeChecker();
- var jsxNamespace = typeChecker.getJsxNamespace();
- var jsxContext = sourceFile.languageVariant === 1 /* JSX */ && program.getCompilerOptions().jsx;
- var usedImports = [];
- for (var _i = 0, oldImports_1 = oldImports; _i < oldImports_1.length; _i++) {
- var importDecl = oldImports_1[_i];
- var importClause = importDecl.importClause;
- if (!importClause) {
- // Imports without import clauses are assumed to be included for their side effects and are not removed.
- usedImports.push(importDecl);
- continue;
- }
- var name = importClause.name, namedBindings = importClause.namedBindings;
- // Default import
- if (name && !isDeclarationUsed(name)) {
- name = undefined;
- }
- if (namedBindings) {
- if (ts.isNamespaceImport(namedBindings)) {
- // Namespace import
- if (!isDeclarationUsed(namedBindings.name)) {
- namedBindings = undefined;
- }
- }
- else {
- // List of named imports
- var newElements = namedBindings.elements.filter(function (e) { return isDeclarationUsed(e.name); });
- if (newElements.length < namedBindings.elements.length) {
- namedBindings = newElements.length
- ? ts.updateNamedImports(namedBindings, newElements)
- : undefined;
- }
- }
- }
- if (name || namedBindings) {
- usedImports.push(updateImportDeclarationAndClause(importDecl, name, namedBindings));
- }
- }
- return usedImports;
- function isDeclarationUsed(identifier) {
- // The JSX factory symbol is always used.
- return jsxContext && (identifier.text === jsxNamespace) || ts.FindAllReferences.Core.isSymbolReferencedInFile(identifier, typeChecker, sourceFile);
- }
- }
- function getExternalModuleName(specifier) {
- return ts.isStringLiteral(specifier) || ts.isNoSubstitutionTemplateLiteral(specifier)
- ? specifier.text
- : undefined;
- }
- /* @internal */ // Internal for testing
- /**
- * @param importGroup a list of ImportDeclarations, all with the same module name.
- */
- function coalesceImports(importGroup) {
- if (importGroup.length === 0) {
- return importGroup;
- }
- var _a = getCategorizedImports(importGroup), importWithoutClause = _a.importWithoutClause, defaultImports = _a.defaultImports, namespaceImports = _a.namespaceImports, namedImports = _a.namedImports;
- var coalescedImports = [];
- if (importWithoutClause) {
- coalescedImports.push(importWithoutClause);
- }
- // Normally, we don't combine default and namespace imports, but it would be silly to
- // produce two import declarations in this special case.
- if (defaultImports.length === 1 && namespaceImports.length === 1 && namedImports.length === 0) {
- // Add the namespace import to the existing default ImportDeclaration.
- var defaultImport = defaultImports[0];
- coalescedImports.push(updateImportDeclarationAndClause(defaultImport, defaultImport.importClause.name, namespaceImports[0].importClause.namedBindings));
- return coalescedImports;
- }
- var sortedNamespaceImports = ts.stableSort(namespaceImports, function (i1, i2) {
- return compareIdentifiers(i1.importClause.namedBindings.name, i2.importClause.namedBindings.name);
- });
- for (var _i = 0, sortedNamespaceImports_1 = sortedNamespaceImports; _i < sortedNamespaceImports_1.length; _i++) {
- var namespaceImport = sortedNamespaceImports_1[_i];
- // Drop the name, if any
- coalescedImports.push(updateImportDeclarationAndClause(namespaceImport, /*name*/ undefined, namespaceImport.importClause.namedBindings));
- }
- if (defaultImports.length === 0 && namedImports.length === 0) {
- return coalescedImports;
- }
- var newDefaultImport;
- var newImportSpecifiers = [];
- if (defaultImports.length === 1) {
- newDefaultImport = defaultImports[0].importClause.name;
- }
- else {
- for (var _b = 0, defaultImports_1 = defaultImports; _b < defaultImports_1.length; _b++) {
- var defaultImport = defaultImports_1[_b];
- newImportSpecifiers.push(ts.createImportSpecifier(ts.createIdentifier("default"), defaultImport.importClause.name));
- }
- }
- newImportSpecifiers.push.apply(newImportSpecifiers, ts.flatMap(namedImports, function (i) { return i.importClause.namedBindings.elements; }));
- var sortedImportSpecifiers = ts.stableSort(newImportSpecifiers, function (s1, s2) {
- return compareIdentifiers(s1.propertyName || s1.name, s2.propertyName || s2.name) ||
- compareIdentifiers(s1.name, s2.name);
- });
- var importDecl = defaultImports.length > 0
- ? defaultImports[0]
- : namedImports[0];
- var newNamedImports = sortedImportSpecifiers.length === 0
- ? undefined
- : namedImports.length === 0
- ? ts.createNamedImports(sortedImportSpecifiers)
- : ts.updateNamedImports(namedImports[0].importClause.namedBindings, sortedImportSpecifiers);
- coalescedImports.push(updateImportDeclarationAndClause(importDecl, newDefaultImport, newNamedImports));
- return coalescedImports;
- /*
- * Returns entire import declarations because they may already have been rewritten and
- * may lack parent pointers. The desired parts can easily be recovered based on the
- * categorization.
- *
- * NB: There may be overlap between `defaultImports` and `namespaceImports`/`namedImports`.
- */
- function getCategorizedImports(importGroup) {
- var importWithoutClause;
- var defaultImports = [];
- var namespaceImports = [];
- var namedImports = [];
- for (var _i = 0, importGroup_1 = importGroup; _i < importGroup_1.length; _i++) {
- var importDeclaration = importGroup_1[_i];
- if (importDeclaration.importClause === undefined) {
- // Only the first such import is interesting - the others are redundant.
- // Note: Unfortunately, we will lose trivia that was on this node.
- importWithoutClause = importWithoutClause || importDeclaration;
- continue;
- }
- var _a = importDeclaration.importClause, name = _a.name, namedBindings = _a.namedBindings;
- if (name) {
- defaultImports.push(importDeclaration);
- }
- if (namedBindings) {
- if (ts.isNamespaceImport(namedBindings)) {
- namespaceImports.push(importDeclaration);
- }
- else {
- namedImports.push(importDeclaration);
- }
- }
- }
- return {
- importWithoutClause: importWithoutClause,
- defaultImports: defaultImports,
- namespaceImports: namespaceImports,
- namedImports: namedImports,
- };
- }
- function compareIdentifiers(s1, s2) {
- return ts.compareStringsCaseSensitive(s1.text, s2.text);
- }
- }
- OrganizeImports.coalesceImports = coalesceImports;
- function updateImportDeclarationAndClause(importDeclaration, name, namedBindings) {
- return ts.updateImportDeclaration(importDeclaration, importDeclaration.decorators, importDeclaration.modifiers, ts.updateImportClause(importDeclaration.importClause, name, namedBindings), importDeclaration.moduleSpecifier);
- }
- /* internal */ // Exported for testing
- function compareModuleSpecifiers(m1, m2) {
- var name1 = getExternalModuleName(m1);
- var name2 = getExternalModuleName(m2);
- return ts.compareBooleans(name1 === undefined, name2 === undefined) ||
- ts.compareBooleans(ts.isExternalModuleNameRelative(name1), ts.isExternalModuleNameRelative(name2)) ||
- ts.compareStringsCaseSensitive(name1, name2);
- }
- OrganizeImports.compareModuleSpecifiers = compareModuleSpecifiers;
- })(OrganizeImports = ts.OrganizeImports || (ts.OrganizeImports = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var OutliningElementsCollector;
- (function (OutliningElementsCollector) {
- function collectElements(sourceFile, cancellationToken) {
- var res = [];
- addNodeOutliningSpans(sourceFile, cancellationToken, res);
- addRegionOutliningSpans(sourceFile, res);
- return res.sort(function (span1, span2) { return span1.textSpan.start - span2.textSpan.start; });
- }
- OutliningElementsCollector.collectElements = collectElements;
- function addNodeOutliningSpans(sourceFile, cancellationToken, out) {
- var depthRemaining = 40;
- sourceFile.forEachChild(function walk(n) {
- if (depthRemaining === 0)
- return;
- cancellationToken.throwIfCancellationRequested();
- if (ts.isDeclaration(n)) {
- addOutliningForLeadingCommentsForNode(n, sourceFile, cancellationToken, out);
- }
- var span = getOutliningSpanForNode(n, sourceFile);
- if (span)
- out.push(span);
- depthRemaining--;
- n.forEachChild(walk);
- depthRemaining++;
- });
- }
- function addRegionOutliningSpans(sourceFile, out) {
- var regions = [];
- var lineStarts = sourceFile.getLineStarts();
- for (var i = 0; i < lineStarts.length; i++) {
- var currentLineStart = lineStarts[i];
- var lineEnd = i + 1 === lineStarts.length ? sourceFile.getEnd() : lineStarts[i + 1] - 1;
- var lineText = sourceFile.text.substring(currentLineStart, lineEnd);
- var result = lineText.match(/^\s*\/\/\s*#(end)?region(?:\s+(.*))?(?:\r)?$/);
- if (!result || ts.isInComment(sourceFile, currentLineStart)) {
- continue;
- }
- if (!result[1]) {
- var span_12 = ts.createTextSpanFromBounds(sourceFile.text.indexOf("//", currentLineStart), lineEnd);
- regions.push(createOutliningSpan(span_12, span_12, /*autoCollapse*/ false, result[2] || "#region"));
- }
- else {
- var region = regions.pop();
- if (region) {
- region.textSpan.length = lineEnd - region.textSpan.start;
- region.hintSpan.length = lineEnd - region.textSpan.start;
- out.push(region);
- }
- }
- }
- }
- function addOutliningForLeadingCommentsForNode(n, sourceFile, cancellationToken, out) {
- var comments = ts.getLeadingCommentRangesOfNode(n, sourceFile);
- if (!comments)
- return;
- var firstSingleLineCommentStart = -1;
- var lastSingleLineCommentEnd = -1;
- var singleLineCommentCount = 0;
- for (var _i = 0, comments_3 = comments; _i < comments_3.length; _i++) {
- var _a = comments_3[_i], kind = _a.kind, pos = _a.pos, end = _a.end;
- cancellationToken.throwIfCancellationRequested();
- switch (kind) {
- case 2 /* SingleLineCommentTrivia */:
- // For single line comments, combine consecutive ones (2 or more) into
- // a single span from the start of the first till the end of the last
- if (singleLineCommentCount === 0) {
- firstSingleLineCommentStart = pos;
- }
- lastSingleLineCommentEnd = end;
- singleLineCommentCount++;
- break;
- case 3 /* MultiLineCommentTrivia */:
- combineAndAddMultipleSingleLineComments();
- out.push(createOutliningSpanFromBounds(pos, end));
- singleLineCommentCount = 0;
- break;
- default:
- ts.Debug.assertNever(kind);
- }
- }
- combineAndAddMultipleSingleLineComments();
- function combineAndAddMultipleSingleLineComments() {
- // Only outline spans of two or more consecutive single line comments
- if (singleLineCommentCount > 1) {
- out.push(createOutliningSpanFromBounds(firstSingleLineCommentStart, lastSingleLineCommentEnd));
- }
- }
- }
- function createOutliningSpanFromBounds(pos, end) {
- return createOutliningSpan(ts.createTextSpanFromBounds(pos, end));
- }
- function getOutliningSpanForNode(n, sourceFile) {
- switch (n.kind) {
- case 211 /* Block */:
- if (ts.isFunctionBlock(n)) {
- return spanForNode(n.parent, /*autoCollapse*/ n.parent.kind !== 191 /* ArrowFunction */);
- }
- // Check if the block is standalone, or 'attached' to some parent statement.
- // If the latter, we want to collapse the block, but consider its hint span
- // to be the entire span of the parent.
- switch (n.parent.kind) {
- case 216 /* DoStatement */:
- case 219 /* ForInStatement */:
- case 220 /* ForOfStatement */:
- case 218 /* ForStatement */:
- case 215 /* IfStatement */:
- case 217 /* WhileStatement */:
- case 224 /* WithStatement */:
- case 267 /* CatchClause */:
- return spanForNode(n.parent);
- case 228 /* TryStatement */:
- // Could be the try-block, or the finally-block.
- var tryStatement = n.parent;
- if (tryStatement.tryBlock === n) {
- return spanForNode(n.parent);
- }
- else if (tryStatement.finallyBlock === n) {
- return spanForNode(ts.findChildOfKind(tryStatement, 87 /* FinallyKeyword */, sourceFile));
- }
- // falls through
- default:
- // Block was a standalone block. In this case we want to only collapse
- // the span of the block, independent of any parent span.
- return createOutliningSpan(ts.createTextSpanFromNode(n, sourceFile));
- }
- case 238 /* ModuleBlock */:
- return spanForNode(n.parent);
- case 233 /* ClassDeclaration */:
- case 234 /* InterfaceDeclaration */:
- case 236 /* EnumDeclaration */:
- case 239 /* CaseBlock */:
- return spanForNode(n);
- case 182 /* ObjectLiteralExpression */:
- return spanForObjectOrArrayLiteral(n);
- case 181 /* ArrayLiteralExpression */:
- return spanForObjectOrArrayLiteral(n, 21 /* OpenBracketToken */);
- }
- function spanForObjectOrArrayLiteral(node, open) {
- if (open === void 0) { open = 17 /* OpenBraceToken */; }
- // If the block has no leading keywords and is inside an array literal,
- // we only want to collapse the span of the block.
- // Otherwise, the collapsed section will include the end of the previous line.
- return spanForNode(node, /*autoCollapse*/ false, /*useFullStart*/ !ts.isArrayLiteralExpression(node.parent), open);
- }
- function spanForNode(hintSpanNode, autoCollapse, useFullStart, open) {
- if (autoCollapse === void 0) { autoCollapse = false; }
- if (useFullStart === void 0) { useFullStart = true; }
- if (open === void 0) { open = 17 /* OpenBraceToken */; }
- var openToken = ts.findChildOfKind(n, open, sourceFile);
- var close = open === 17 /* OpenBraceToken */ ? 18 /* CloseBraceToken */ : 22 /* CloseBracketToken */;
- var closeToken = ts.findChildOfKind(n, close, sourceFile);
- if (!openToken || !closeToken) {
- return undefined;
- }
- var textSpan = ts.createTextSpanFromBounds(useFullStart ? openToken.getFullStart() : openToken.getStart(sourceFile), closeToken.getEnd());
- return createOutliningSpan(textSpan, ts.createTextSpanFromNode(hintSpanNode, sourceFile), autoCollapse);
- }
- }
- function createOutliningSpan(textSpan, hintSpan, autoCollapse, bannerText) {
- if (hintSpan === void 0) { hintSpan = textSpan; }
- if (autoCollapse === void 0) { autoCollapse = false; }
- if (bannerText === void 0) { bannerText = "..."; }
- return { textSpan: textSpan, hintSpan: hintSpan, bannerText: bannerText, autoCollapse: autoCollapse };
- }
- })(OutliningElementsCollector = ts.OutliningElementsCollector || (ts.OutliningElementsCollector = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- // Note(cyrusn): this enum is ordered from strongest match type to weakest match type.
- var PatternMatchKind;
- (function (PatternMatchKind) {
- PatternMatchKind[PatternMatchKind["exact"] = 0] = "exact";
- PatternMatchKind[PatternMatchKind["prefix"] = 1] = "prefix";
- PatternMatchKind[PatternMatchKind["substring"] = 2] = "substring";
- PatternMatchKind[PatternMatchKind["camelCase"] = 3] = "camelCase";
- })(PatternMatchKind = ts.PatternMatchKind || (ts.PatternMatchKind = {}));
- function createPatternMatch(kind, punctuationStripped, isCaseSensitive, camelCaseWeight) {
- return {
- kind: kind,
- punctuationStripped: punctuationStripped,
- isCaseSensitive: isCaseSensitive,
- camelCaseWeight: camelCaseWeight
- };
- }
- function createPatternMatcher(pattern) {
- // We'll often see the same candidate string many times when searching (For example, when
- // we see the name of a module that is used everywhere, or the name of an overload). As
- // such, we cache the information we compute about the candidate for the life of this
- // pattern matcher so we don't have to compute it multiple times.
- var stringToWordSpans = ts.createMap();
- pattern = pattern.trim();
- var dotSeparatedSegments = pattern.split(".").map(function (p) { return createSegment(p.trim()); });
- var invalidPattern = dotSeparatedSegments.length === 0 || ts.forEach(dotSeparatedSegments, segmentIsInvalid);
- return {
- getMatches: getMatches,
- getMatchesForLastSegmentOfPattern: getMatchesForLastSegmentOfPattern,
- patternContainsDots: dotSeparatedSegments.length > 1
- };
- // Quick checks so we can bail out when asked to match a candidate.
- function skipMatch(candidate) {
- return invalidPattern || !candidate;
- }
- function getMatchesForLastSegmentOfPattern(candidate) {
- if (skipMatch(candidate)) {
- return undefined;
- }
- return matchSegment(candidate, ts.lastOrUndefined(dotSeparatedSegments));
- }
- function getMatches(candidateContainers, candidate) {
- if (skipMatch(candidate)) {
- return undefined;
- }
- // First, check that the last part of the dot separated pattern matches the name of the
- // candidate. If not, then there's no point in proceeding and doing the more
- // expensive work.
- var candidateMatch = matchSegment(candidate, ts.lastOrUndefined(dotSeparatedSegments));
- if (!candidateMatch) {
- return undefined;
- }
- candidateContainers = candidateContainers || [];
- // -1 because the last part was checked against the name, and only the rest
- // of the parts are checked against the container.
- if (dotSeparatedSegments.length - 1 > candidateContainers.length) {
- // There weren't enough container parts to match against the pattern parts.
- // So this definitely doesn't match.
- return undefined;
- }
- // So far so good. Now break up the container for the candidate and check if all
- // the dotted parts match up correctly.
- var totalMatch = candidateMatch;
- for (var i = dotSeparatedSegments.length - 2, j = candidateContainers.length - 1; i >= 0; i -= 1, j -= 1) {
- var segment = dotSeparatedSegments[i];
- var containerName = candidateContainers[j];
- var containerMatch = matchSegment(containerName, segment);
- if (!containerMatch) {
- // This container didn't match the pattern piece. So there's no match at all.
- return undefined;
- }
- ts.addRange(totalMatch, containerMatch);
- }
- // Success, this symbol's full name matched against the dotted name the user was asking
- // about.
- return totalMatch;
- }
- function getWordSpans(word) {
- var spans = stringToWordSpans.get(word);
- if (!spans) {
- stringToWordSpans.set(word, spans = breakIntoWordSpans(word));
- }
- return spans;
- }
- function matchTextChunk(candidate, chunk, punctuationStripped) {
- var index = indexOfIgnoringCase(candidate, chunk.textLowerCase);
- if (index === 0) {
- if (chunk.text.length === candidate.length) {
- // a) Check if the part matches the candidate entirely, in an case insensitive or
- // sensitive manner. If it does, return that there was an exact match.
- return createPatternMatch(PatternMatchKind.exact, punctuationStripped, /*isCaseSensitive:*/ candidate === chunk.text);
- }
- else {
- // b) Check if the part is a prefix of the candidate, in a case insensitive or sensitive
- // manner. If it does, return that there was a prefix match.
- return createPatternMatch(PatternMatchKind.prefix, punctuationStripped, /*isCaseSensitive:*/ ts.startsWith(candidate, chunk.text));
- }
- }
- var isLowercase = chunk.isLowerCase;
- if (isLowercase) {
- if (index > 0) {
- // c) If the part is entirely lowercase, then check if it is contained anywhere in the
- // candidate in a case insensitive manner. If so, return that there was a substring
- // match.
- //
- // Note: We only have a substring match if the lowercase part is prefix match of some
- // word part. That way we don't match something like 'Class' when the user types 'a'.
- // But we would match 'FooAttribute' (since 'Attribute' starts with 'a').
- var wordSpans = getWordSpans(candidate);
- for (var _i = 0, wordSpans_1 = wordSpans; _i < wordSpans_1.length; _i++) {
- var span_13 = wordSpans_1[_i];
- if (partStartsWith(candidate, span_13, chunk.text, /*ignoreCase:*/ true)) {
- return createPatternMatch(PatternMatchKind.substring, punctuationStripped,
- /*isCaseSensitive:*/ partStartsWith(candidate, span_13, chunk.text, /*ignoreCase:*/ false));
- }
- }
- }
- }
- else {
- // d) If the part was not entirely lowercase, then check if it is contained in the
- // candidate in a case *sensitive* manner. If so, return that there was a substring
- // match.
- if (candidate.indexOf(chunk.text) > 0) {
- return createPatternMatch(PatternMatchKind.substring, punctuationStripped, /*isCaseSensitive:*/ true);
- }
- }
- if (!isLowercase) {
- // e) If the part was not entirely lowercase, then attempt a camel cased match as well.
- if (chunk.characterSpans.length > 0) {
- var candidateParts = getWordSpans(candidate);
- var camelCaseWeight = tryCamelCaseMatch(candidate, candidateParts, chunk, /*ignoreCase:*/ false);
- if (camelCaseWeight !== undefined) {
- return createPatternMatch(PatternMatchKind.camelCase, punctuationStripped, /*isCaseSensitive:*/ true, /*camelCaseWeight:*/ camelCaseWeight);
- }
- camelCaseWeight = tryCamelCaseMatch(candidate, candidateParts, chunk, /*ignoreCase:*/ true);
- if (camelCaseWeight !== undefined) {
- return createPatternMatch(PatternMatchKind.camelCase, punctuationStripped, /*isCaseSensitive:*/ false, /*camelCaseWeight:*/ camelCaseWeight);
- }
- }
- }
- if (isLowercase) {
- // f) Is the pattern a substring of the candidate starting on one of the candidate's word boundaries?
- // We could check every character boundary start of the candidate for the pattern. However, that's
- // an m * n operation in the wost case. Instead, find the first instance of the pattern
- // substring, and see if it starts on a capital letter. It seems unlikely that the user will try to
- // filter the list based on a substring that starts on a capital letter and also with a lowercase one.
- // (Pattern: fogbar, Candidate: quuxfogbarFogBar).
- if (chunk.text.length < candidate.length) {
- if (index > 0 && isUpperCaseLetter(candidate.charCodeAt(index))) {
- return createPatternMatch(PatternMatchKind.substring, punctuationStripped, /*isCaseSensitive:*/ false);
- }
- }
- }
- return undefined;
- }
- function containsSpaceOrAsterisk(text) {
- for (var i = 0; i < text.length; i++) {
- var ch = text.charCodeAt(i);
- if (ch === 32 /* space */ || ch === 42 /* asterisk */) {
- return true;
- }
- }
- return false;
- }
- function matchSegment(candidate, segment) {
- // First check if the segment matches as is. This is also useful if the segment contains
- // characters we would normally strip when splitting into parts that we also may want to
- // match in the candidate. For example if the segment is "@int" and the candidate is
- // "@int", then that will show up as an exact match here.
- //
- // Note: if the segment contains a space or an asterisk then we must assume that it's a
- // multi-word segment.
- if (!containsSpaceOrAsterisk(segment.totalTextChunk.text)) {
- var match = matchTextChunk(candidate, segment.totalTextChunk, /*punctuationStripped:*/ false);
- if (match) {
- return [match];
- }
- }
- // The logic for pattern matching is now as follows:
- //
- // 1) Break the segment passed in into words. Breaking is rather simple and a
- // good way to think about it that if gives you all the individual alphanumeric words
- // of the pattern.
- //
- // 2) For each word try to match the word against the candidate value.
- //
- // 3) Matching is as follows:
- //
- // a) Check if the word matches the candidate entirely, in an case insensitive or
- // sensitive manner. If it does, return that there was an exact match.
- //
- // b) Check if the word is a prefix of the candidate, in a case insensitive or
- // sensitive manner. If it does, return that there was a prefix match.
- //
- // c) If the word is entirely lowercase, then check if it is contained anywhere in the
- // candidate in a case insensitive manner. If so, return that there was a substring
- // match.
- //
- // Note: We only have a substring match if the lowercase part is prefix match of
- // some word part. That way we don't match something like 'Class' when the user
- // types 'a'. But we would match 'FooAttribute' (since 'Attribute' starts with
- // 'a').
- //
- // d) If the word was not entirely lowercase, then check if it is contained in the
- // candidate in a case *sensitive* manner. If so, return that there was a substring
- // match.
- //
- // e) If the word was not entirely lowercase, then attempt a camel cased match as
- // well.
- //
- // f) The word is all lower case. Is it a case insensitive substring of the candidate starting
- // on a part boundary of the candidate?
- //
- // Only if all words have some sort of match is the pattern considered matched.
- var subWordTextChunks = segment.subWordTextChunks;
- var matches;
- for (var _i = 0, subWordTextChunks_1 = subWordTextChunks; _i < subWordTextChunks_1.length; _i++) {
- var subWordTextChunk = subWordTextChunks_1[_i];
- // Try to match the candidate with this word
- var result = matchTextChunk(candidate, subWordTextChunk, /*punctuationStripped:*/ true);
- if (!result) {
- return undefined;
- }
- matches = matches || [];
- matches.push(result);
- }
- return matches;
- }
- function partStartsWith(candidate, candidateSpan, pattern, ignoreCase, patternSpan) {
- var patternPartStart = patternSpan ? patternSpan.start : 0;
- var patternPartLength = patternSpan ? patternSpan.length : pattern.length;
- if (patternPartLength > candidateSpan.length) {
- // Pattern part is longer than the candidate part. There can never be a match.
- return false;
- }
- if (ignoreCase) {
- for (var i = 0; i < patternPartLength; i++) {
- var ch1 = pattern.charCodeAt(patternPartStart + i);
- var ch2 = candidate.charCodeAt(candidateSpan.start + i);
- if (toLowerCase(ch1) !== toLowerCase(ch2)) {
- return false;
- }
- }
- }
- else {
- for (var i = 0; i < patternPartLength; i++) {
- var ch1 = pattern.charCodeAt(patternPartStart + i);
- var ch2 = candidate.charCodeAt(candidateSpan.start + i);
- if (ch1 !== ch2) {
- return false;
- }
- }
- }
- return true;
- }
- function tryCamelCaseMatch(candidate, candidateParts, chunk, ignoreCase) {
- var chunkCharacterSpans = chunk.characterSpans;
- // Note: we may have more pattern parts than candidate parts. This is because multiple
- // pattern parts may match a candidate part. For example "SiUI" against "SimpleUI".
- // We'll have 3 pattern parts Si/U/I against two candidate parts Simple/UI. However, U
- // and I will both match in UI.
- var currentCandidate = 0;
- var currentChunkSpan = 0;
- var firstMatch;
- var contiguous;
- while (true) {
- // Let's consider our termination cases
- if (currentChunkSpan === chunkCharacterSpans.length) {
- // We did match! We shall assign a weight to this
- var weight = 0;
- // Was this contiguous?
- if (contiguous) {
- weight += 1;
- }
- // Did we start at the beginning of the candidate?
- if (firstMatch === 0) {
- weight += 2;
- }
- return weight;
- }
- else if (currentCandidate === candidateParts.length) {
- // No match, since we still have more of the pattern to hit
- return undefined;
- }
- var candidatePart = candidateParts[currentCandidate];
- var gotOneMatchThisCandidate = false;
- // Consider the case of matching SiUI against SimpleUIElement. The candidate parts
- // will be Simple/UI/Element, and the pattern parts will be Si/U/I. We'll match 'Si'
- // against 'Simple' first. Then we'll match 'U' against 'UI'. However, we want to
- // still keep matching pattern parts against that candidate part.
- for (; currentChunkSpan < chunkCharacterSpans.length; currentChunkSpan++) {
- var chunkCharacterSpan = chunkCharacterSpans[currentChunkSpan];
- if (gotOneMatchThisCandidate) {
- // We've already gotten one pattern part match in this candidate. We will
- // only continue trying to consumer pattern parts if the last part and this
- // part are both upper case.
- if (!isUpperCaseLetter(chunk.text.charCodeAt(chunkCharacterSpans[currentChunkSpan - 1].start)) ||
- !isUpperCaseLetter(chunk.text.charCodeAt(chunkCharacterSpans[currentChunkSpan].start))) {
- break;
- }
- }
- if (!partStartsWith(candidate, candidatePart, chunk.text, ignoreCase, chunkCharacterSpan)) {
- break;
- }
- gotOneMatchThisCandidate = true;
- firstMatch = firstMatch === undefined ? currentCandidate : firstMatch;
- // If we were contiguous, then keep that value. If we weren't, then keep that
- // value. If we don't know, then set the value to 'true' as an initial match is
- // obviously contiguous.
- contiguous = contiguous === undefined ? true : contiguous;
- candidatePart = ts.createTextSpan(candidatePart.start + chunkCharacterSpan.length, candidatePart.length - chunkCharacterSpan.length);
- }
- // Check if we matched anything at all. If we didn't, then we need to unset the
- // contiguous bit if we currently had it set.
- // If we haven't set the bit yet, then that means we haven't matched anything so
- // far, and we don't want to change that.
- if (!gotOneMatchThisCandidate && contiguous !== undefined) {
- contiguous = false;
- }
- // Move onto the next candidate.
- currentCandidate++;
- }
- }
- }
- ts.createPatternMatcher = createPatternMatcher;
- function createSegment(text) {
- return {
- totalTextChunk: createTextChunk(text),
- subWordTextChunks: breakPatternIntoTextChunks(text)
- };
- }
- // A segment is considered invalid if we couldn't find any words in it.
- function segmentIsInvalid(segment) {
- return segment.subWordTextChunks.length === 0;
- }
- function isUpperCaseLetter(ch) {
- // Fast check for the ascii range.
- if (ch >= 65 /* A */ && ch <= 90 /* Z */) {
- return true;
- }
- if (ch < 127 /* maxAsciiCharacter */ || !ts.isUnicodeIdentifierStart(ch, 6 /* Latest */)) {
- return false;
- }
- // TODO: find a way to determine this for any unicode characters in a
- // non-allocating manner.
- var str = String.fromCharCode(ch);
- return str === str.toUpperCase();
- }
- function isLowerCaseLetter(ch) {
- // Fast check for the ascii range.
- if (ch >= 97 /* a */ && ch <= 122 /* z */) {
- return true;
- }
- if (ch < 127 /* maxAsciiCharacter */ || !ts.isUnicodeIdentifierStart(ch, 6 /* Latest */)) {
- return false;
- }
- // TODO: find a way to determine this for any unicode characters in a
- // non-allocating manner.
- var str = String.fromCharCode(ch);
- return str === str.toLowerCase();
- }
- // Assumes 'value' is already lowercase.
- function indexOfIgnoringCase(str, value) {
- var n = str.length - value.length;
- for (var i = 0; i <= n; i++) {
- if (startsWithIgnoringCase(str, value, i)) {
- return i;
- }
- }
- return -1;
- }
- // Assumes 'value' is already lowercase.
- function startsWithIgnoringCase(str, value, start) {
- for (var i = 0; i < value.length; i++) {
- var ch1 = toLowerCase(str.charCodeAt(i + start));
- var ch2 = value.charCodeAt(i);
- if (ch1 !== ch2) {
- return false;
- }
- }
- return true;
- }
- function toLowerCase(ch) {
- // Fast convert for the ascii range.
- if (ch >= 65 /* A */ && ch <= 90 /* Z */) {
- return 97 /* a */ + (ch - 65 /* A */);
- }
- if (ch < 127 /* maxAsciiCharacter */) {
- return ch;
- }
- // TODO: find a way to compute this for any unicode characters in a
- // non-allocating manner.
- return String.fromCharCode(ch).toLowerCase().charCodeAt(0);
- }
- function isDigit(ch) {
- // TODO(cyrusn): Find a way to support this for unicode digits.
- return ch >= 48 /* _0 */ && ch <= 57 /* _9 */;
- }
- function isWordChar(ch) {
- return isUpperCaseLetter(ch) || isLowerCaseLetter(ch) || isDigit(ch) || ch === 95 /* _ */ || ch === 36 /* $ */;
- }
- function breakPatternIntoTextChunks(pattern) {
- var result = [];
- var wordStart = 0;
- var wordLength = 0;
- for (var i = 0; i < pattern.length; i++) {
- var ch = pattern.charCodeAt(i);
- if (isWordChar(ch)) {
- if (wordLength === 0) {
- wordStart = i;
- }
- wordLength++;
- }
- else {
- if (wordLength > 0) {
- result.push(createTextChunk(pattern.substr(wordStart, wordLength)));
- wordLength = 0;
- }
- }
- }
- if (wordLength > 0) {
- result.push(createTextChunk(pattern.substr(wordStart, wordLength)));
- }
- return result;
- }
- function createTextChunk(text) {
- var textLowerCase = text.toLowerCase();
- return {
- text: text,
- textLowerCase: textLowerCase,
- isLowerCase: text === textLowerCase,
- characterSpans: breakIntoCharacterSpans(text)
- };
- }
- /* @internal */ function breakIntoCharacterSpans(identifier) {
- return breakIntoSpans(identifier, /*word:*/ false);
- }
- ts.breakIntoCharacterSpans = breakIntoCharacterSpans;
- /* @internal */ function breakIntoWordSpans(identifier) {
- return breakIntoSpans(identifier, /*word:*/ true);
- }
- ts.breakIntoWordSpans = breakIntoWordSpans;
- function breakIntoSpans(identifier, word) {
- var result = [];
- var wordStart = 0;
- for (var i = 1; i < identifier.length; i++) {
- var lastIsDigit = isDigit(identifier.charCodeAt(i - 1));
- var currentIsDigit = isDigit(identifier.charCodeAt(i));
- var hasTransitionFromLowerToUpper = transitionFromLowerToUpper(identifier, word, i);
- var hasTransitionFromUpperToLower = transitionFromUpperToLower(identifier, word, i, wordStart);
- if (charIsPunctuation(identifier.charCodeAt(i - 1)) ||
- charIsPunctuation(identifier.charCodeAt(i)) ||
- lastIsDigit !== currentIsDigit ||
- hasTransitionFromLowerToUpper ||
- hasTransitionFromUpperToLower) {
- if (!isAllPunctuation(identifier, wordStart, i)) {
- result.push(ts.createTextSpan(wordStart, i - wordStart));
- }
- wordStart = i;
- }
- }
- if (!isAllPunctuation(identifier, wordStart, identifier.length)) {
- result.push(ts.createTextSpan(wordStart, identifier.length - wordStart));
- }
- return result;
- }
- function charIsPunctuation(ch) {
- switch (ch) {
- case 33 /* exclamation */:
- case 34 /* doubleQuote */:
- case 35 /* hash */:
- case 37 /* percent */:
- case 38 /* ampersand */:
- case 39 /* singleQuote */:
- case 40 /* openParen */:
- case 41 /* closeParen */:
- case 42 /* asterisk */:
- case 44 /* comma */:
- case 45 /* minus */:
- case 46 /* dot */:
- case 47 /* slash */:
- case 58 /* colon */:
- case 59 /* semicolon */:
- case 63 /* question */:
- case 64 /* at */:
- case 91 /* openBracket */:
- case 92 /* backslash */:
- case 93 /* closeBracket */:
- case 95 /* _ */:
- case 123 /* openBrace */:
- case 125 /* closeBrace */:
- return true;
- }
- return false;
- }
- function isAllPunctuation(identifier, start, end) {
- for (var i = start; i < end; i++) {
- var ch = identifier.charCodeAt(i);
- // We don't consider _ or $ as punctuation as there may be things with that name.
- if (!charIsPunctuation(ch) || ch === 95 /* _ */ || ch === 36 /* $ */) {
- return false;
- }
- }
- return true;
- }
- function transitionFromUpperToLower(identifier, word, index, wordStart) {
- if (word) {
- // Cases this supports:
- // 1) IDisposable -> I, Disposable
- // 2) UIElement -> UI, Element
- // 3) HTMLDocument -> HTML, Document
- //
- // etc.
- if (index !== wordStart &&
- index + 1 < identifier.length) {
- var currentIsUpper = isUpperCaseLetter(identifier.charCodeAt(index));
- var nextIsLower = isLowerCaseLetter(identifier.charCodeAt(index + 1));
- if (currentIsUpper && nextIsLower) {
- // We have a transition from an upper to a lower letter here. But we only
- // want to break if all the letters that preceded are uppercase. i.e. if we
- // have "Foo" we don't want to break that into "F, oo". But if we have
- // "IFoo" or "UIFoo", then we want to break that into "I, Foo" and "UI,
- // Foo". i.e. the last uppercase letter belongs to the lowercase letters
- // that follows. Note: this will make the following not split properly:
- // "HELLOthere". However, these sorts of names do not show up in .Net
- // programs.
- for (var i = wordStart; i < index; i++) {
- if (!isUpperCaseLetter(identifier.charCodeAt(i))) {
- return false;
- }
- }
- return true;
- }
- }
- }
- return false;
- }
- function transitionFromLowerToUpper(identifier, word, index) {
- var lastIsUpper = isUpperCaseLetter(identifier.charCodeAt(index - 1));
- var currentIsUpper = isUpperCaseLetter(identifier.charCodeAt(index));
- // See if the casing indicates we're starting a new word. Note: if we're breaking on
- // words, then just seeing an upper case character isn't enough. Instead, it has to
- // be uppercase and the previous character can't be uppercase.
- //
- // For example, breaking "AddMetadata" on words would make: Add Metadata
- //
- // on characters would be: A dd M etadata
- //
- // Break "AM" on words would be: AM
- //
- // on characters would be: A M
- //
- // We break the search string on characters. But we break the symbol name on words.
- var transition = word
- ? (currentIsUpper && !lastIsUpper)
- : currentIsUpper;
- return transition;
- }
-})(ts || (ts = {}));
-var ts;
-(function (ts) {
- function preProcessFile(sourceText, readImportFiles, detectJavaScriptImports) {
- if (readImportFiles === void 0) { readImportFiles = true; }
- if (detectJavaScriptImports === void 0) { detectJavaScriptImports = false; }
- var pragmaContext = {
- languageVersion: 1 /* ES5 */,
- pragmas: undefined,
- checkJsDirective: undefined,
- referencedFiles: [],
- typeReferenceDirectives: [],
- amdDependencies: [],
- hasNoDefaultLib: undefined,
- moduleName: undefined
- };
- var importedFiles = [];
- var ambientExternalModules;
- var braceNesting = 0;
- // assume that text represent an external module if it contains at least one top level import/export
- // ambient modules that are found inside external modules are interpreted as module augmentations
- var externalModule = false;
- function nextToken() {
- var token = ts.scanner.scan();
- if (token === 17 /* OpenBraceToken */) {
- braceNesting++;
- }
- else if (token === 18 /* CloseBraceToken */) {
- braceNesting--;
- }
- return token;
- }
- function getFileReference() {
- var fileName = ts.scanner.getTokenValue();
- var pos = ts.scanner.getTokenPos();
- return { fileName: fileName, pos: pos, end: pos + fileName.length };
- }
- function recordAmbientExternalModule() {
- if (!ambientExternalModules) {
- ambientExternalModules = [];
- }
- ambientExternalModules.push({ ref: getFileReference(), depth: braceNesting });
- }
- function recordModuleName() {
- importedFiles.push(getFileReference());
- markAsExternalModuleIfTopLevel();
- }
- function markAsExternalModuleIfTopLevel() {
- if (braceNesting === 0) {
- externalModule = true;
- }
- }
- /**
- * Returns true if at least one token was consumed from the stream
- */
- function tryConsumeDeclare() {
- var token = ts.scanner.getToken();
- if (token === 124 /* DeclareKeyword */) {
- // declare module "mod"
- token = nextToken();
- if (token === 129 /* ModuleKeyword */) {
- token = nextToken();
- if (token === 9 /* StringLiteral */) {
- recordAmbientExternalModule();
- }
- }
- return true;
- }
- return false;
- }
- /**
- * Returns true if at least one token was consumed from the stream
- */
- function tryConsumeImport() {
- var token = ts.scanner.getToken();
- if (token === 91 /* ImportKeyword */) {
- token = nextToken();
- if (token === 19 /* OpenParenToken */) {
- token = nextToken();
- if (token === 9 /* StringLiteral */) {
- // import("mod");
- recordModuleName();
- return true;
- }
- }
- else if (token === 9 /* StringLiteral */) {
- // import "mod";
- recordModuleName();
- return true;
- }
- else {
- if (token === 71 /* Identifier */ || ts.isKeyword(token)) {
- token = nextToken();
- if (token === 142 /* FromKeyword */) {
- token = nextToken();
- if (token === 9 /* StringLiteral */) {
- // import d from "mod";
- recordModuleName();
- return true;
- }
- }
- else if (token === 58 /* EqualsToken */) {
- if (tryConsumeRequireCall(/*skipCurrentToken*/ true)) {
- return true;
- }
- }
- else if (token === 26 /* CommaToken */) {
- // consume comma and keep going
- token = nextToken();
- }
- else {
- // unknown syntax
- return true;
- }
- }
- if (token === 17 /* OpenBraceToken */) {
- token = nextToken();
- // consume "{ a as B, c, d as D}" clauses
- // make sure that it stops on EOF
- while (token !== 18 /* CloseBraceToken */ && token !== 1 /* EndOfFileToken */) {
- token = nextToken();
- }
- if (token === 18 /* CloseBraceToken */) {
- token = nextToken();
- if (token === 142 /* FromKeyword */) {
- token = nextToken();
- if (token === 9 /* StringLiteral */) {
- // import {a as A} from "mod";
- // import d, {a, b as B} from "mod"
- recordModuleName();
- }
- }
- }
- }
- else if (token === 39 /* AsteriskToken */) {
- token = nextToken();
- if (token === 118 /* AsKeyword */) {
- token = nextToken();
- if (token === 71 /* Identifier */ || ts.isKeyword(token)) {
- token = nextToken();
- if (token === 142 /* FromKeyword */) {
- token = nextToken();
- if (token === 9 /* StringLiteral */) {
- // import * as NS from "mod"
- // import d, * as NS from "mod"
- recordModuleName();
- }
- }
- }
- }
- }
- }
- return true;
- }
- return false;
- }
- function tryConsumeExport() {
- var token = ts.scanner.getToken();
- if (token === 84 /* ExportKeyword */) {
- markAsExternalModuleIfTopLevel();
- token = nextToken();
- if (token === 17 /* OpenBraceToken */) {
- token = nextToken();
- // consume "{ a as B, c, d as D}" clauses
- // make sure it stops on EOF
- while (token !== 18 /* CloseBraceToken */ && token !== 1 /* EndOfFileToken */) {
- token = nextToken();
- }
- if (token === 18 /* CloseBraceToken */) {
- token = nextToken();
- if (token === 142 /* FromKeyword */) {
- token = nextToken();
- if (token === 9 /* StringLiteral */) {
- // export {a as A} from "mod";
- // export {a, b as B} from "mod"
- recordModuleName();
- }
- }
- }
- }
- else if (token === 39 /* AsteriskToken */) {
- token = nextToken();
- if (token === 142 /* FromKeyword */) {
- token = nextToken();
- if (token === 9 /* StringLiteral */) {
- // export * from "mod"
- recordModuleName();
- }
- }
- }
- else if (token === 91 /* ImportKeyword */) {
- token = nextToken();
- if (token === 71 /* Identifier */ || ts.isKeyword(token)) {
- token = nextToken();
- if (token === 58 /* EqualsToken */) {
- if (tryConsumeRequireCall(/*skipCurrentToken*/ true)) {
- return true;
- }
- }
- }
- }
- return true;
- }
- return false;
- }
- function tryConsumeRequireCall(skipCurrentToken) {
- var token = skipCurrentToken ? nextToken() : ts.scanner.getToken();
- if (token === 133 /* RequireKeyword */) {
- token = nextToken();
- if (token === 19 /* OpenParenToken */) {
- token = nextToken();
- if (token === 9 /* StringLiteral */) {
- // require("mod");
- recordModuleName();
- }
- }
- return true;
- }
- return false;
- }
- function tryConsumeDefine() {
- var token = ts.scanner.getToken();
- if (token === 71 /* Identifier */ && ts.scanner.getTokenValue() === "define") {
- token = nextToken();
- if (token !== 19 /* OpenParenToken */) {
- return true;
- }
- token = nextToken();
- if (token === 9 /* StringLiteral */) {
- // looks like define ("modname", ... - skip string literal and comma
- token = nextToken();
- if (token === 26 /* CommaToken */) {
- token = nextToken();
- }
- else {
- // unexpected token
- return true;
- }
- }
- // should be start of dependency list
- if (token !== 21 /* OpenBracketToken */) {
- return true;
- }
- // skip open bracket
- token = nextToken();
- // scan until ']' or EOF
- while (token !== 22 /* CloseBracketToken */ && token !== 1 /* EndOfFileToken */) {
- // record string literals as module names
- if (token === 9 /* StringLiteral */) {
- recordModuleName();
- }
- token = nextToken();
- }
- return true;
- }
- return false;
- }
- function processImports() {
- ts.scanner.setText(sourceText);
- nextToken();
- // Look for:
- // import "mod";
- // import d from "mod"
- // import {a as A } from "mod";
- // import * as NS from "mod"
- // import d, {a, b as B} from "mod"
- // import i = require("mod");
- // import("mod");
- // export * from "mod"
- // export {a as b} from "mod"
- // export import i = require("mod")
- // (for JavaScript files) require("mod")
- while (true) {
- if (ts.scanner.getToken() === 1 /* EndOfFileToken */) {
- break;
- }
- // check if at least one of alternative have moved scanner forward
- if (tryConsumeDeclare() ||
- tryConsumeImport() ||
- tryConsumeExport() ||
- (detectJavaScriptImports && (tryConsumeRequireCall(/*skipCurrentToken*/ false) || tryConsumeDefine()))) {
- continue;
- }
- else {
- nextToken();
- }
- }
- ts.scanner.setText(undefined);
- }
- if (readImportFiles) {
- processImports();
- }
- ts.processCommentPragmas(pragmaContext, sourceText);
- ts.processPragmasIntoFields(pragmaContext, ts.noop);
- if (externalModule) {
- // for external modules module all nested ambient modules are augmentations
- if (ambientExternalModules) {
- // move all detected ambient modules to imported files since they need to be resolved
- for (var _i = 0, ambientExternalModules_1 = ambientExternalModules; _i < ambientExternalModules_1.length; _i++) {
- var decl = ambientExternalModules_1[_i];
- importedFiles.push(decl.ref);
- }
- }
- return { referencedFiles: pragmaContext.referencedFiles, typeReferenceDirectives: pragmaContext.typeReferenceDirectives, importedFiles: importedFiles, isLibFile: pragmaContext.hasNoDefaultLib, ambientExternalModules: undefined };
- }
- else {
- // for global scripts ambient modules still can have augmentations - look for ambient modules with depth > 0
- var ambientModuleNames = void 0;
- if (ambientExternalModules) {
- for (var _a = 0, ambientExternalModules_2 = ambientExternalModules; _a < ambientExternalModules_2.length; _a++) {
- var decl = ambientExternalModules_2[_a];
- if (decl.depth === 0) {
- if (!ambientModuleNames) {
- ambientModuleNames = [];
- }
- ambientModuleNames.push(decl.ref.fileName);
- }
- else {
- importedFiles.push(decl.ref);
- }
- }
- }
- return { referencedFiles: pragmaContext.referencedFiles, typeReferenceDirectives: pragmaContext.typeReferenceDirectives, importedFiles: importedFiles, isLibFile: pragmaContext.hasNoDefaultLib, ambientExternalModules: ambientModuleNames };
- }
- }
- ts.preProcessFile = preProcessFile;
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var Rename;
- (function (Rename) {
- function getRenameInfo(typeChecker, defaultLibFileName, getCanonicalFileName, sourceFile, position) {
- var getCanonicalDefaultLibName = ts.memoize(function () { return getCanonicalFileName(ts.normalizePath(defaultLibFileName)); });
- var node = ts.getTouchingWord(sourceFile, position, /*includeJsDocComment*/ true);
- var renameInfo = node && nodeIsEligibleForRename(node)
- ? getRenameInfoForNode(node, typeChecker, sourceFile, isDefinedInLibraryFile)
- : undefined;
- return renameInfo || getRenameInfoError(ts.Diagnostics.You_cannot_rename_this_element);
- function isDefinedInLibraryFile(declaration) {
- if (!defaultLibFileName) {
- return false;
- }
- var sourceFile = declaration.getSourceFile();
- var canonicalName = getCanonicalFileName(ts.normalizePath(sourceFile.fileName));
- return canonicalName === getCanonicalDefaultLibName();
- }
- }
- Rename.getRenameInfo = getRenameInfo;
- function getRenameInfoForNode(node, typeChecker, sourceFile, isDefinedInLibraryFile) {
- var symbol = typeChecker.getSymbolAtLocation(node);
- // Only allow a symbol to be renamed if it actually has at least one declaration.
- if (symbol) {
- var declarations = symbol.declarations;
- if (declarations && declarations.length > 0) {
- // Disallow rename for elements that are defined in the standard TypeScript library.
- if (declarations.some(isDefinedInLibraryFile)) {
- return getRenameInfoError(ts.Diagnostics.You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library);
- }
- // Cannot rename `default` as in `import { default as foo } from "./someModule";
- if (ts.isIdentifier(node) && node.originalKeywordKind === 79 /* DefaultKeyword */ && symbol.parent.flags & 1536 /* Module */) {
- return undefined;
- }
- var kind = ts.SymbolDisplay.getSymbolKind(typeChecker, symbol, node);
- var specifierName = (ts.isImportOrExportSpecifierName(node) || ts.isStringOrNumericLiteral(node) && node.parent.kind === 146 /* ComputedPropertyName */)
- ? ts.stripQuotes(ts.getTextOfIdentifierOrLiteral(node))
- : undefined;
- var displayName = specifierName || typeChecker.symbolToString(symbol);
- var fullDisplayName = specifierName || typeChecker.getFullyQualifiedName(symbol);
- return getRenameInfoSuccess(displayName, fullDisplayName, kind, ts.SymbolDisplay.getSymbolModifiers(symbol), node, sourceFile);
- }
- }
- else if (ts.isStringLiteral(node)) {
- if (isDefinedInLibraryFile(node)) {
- return getRenameInfoError(ts.Diagnostics.You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library);
- }
- return getRenameInfoSuccess(node.text, node.text, "var" /* variableElement */, "" /* none */, node, sourceFile);
- }
- }
- function getRenameInfoSuccess(displayName, fullDisplayName, kind, kindModifiers, node, sourceFile) {
- return {
- canRename: true,
- kind: kind,
- displayName: displayName,
- localizedErrorMessage: undefined,
- fullDisplayName: fullDisplayName,
- kindModifiers: kindModifiers,
- triggerSpan: createTriggerSpanForNode(node, sourceFile)
- };
- }
- function getRenameInfoError(diagnostic) {
- return {
- canRename: false,
- localizedErrorMessage: ts.getLocaleSpecificMessage(diagnostic),
- displayName: undefined,
- fullDisplayName: undefined,
- kind: undefined,
- kindModifiers: undefined,
- triggerSpan: undefined
- };
- }
- function createTriggerSpanForNode(node, sourceFile) {
- var start = node.getStart(sourceFile);
- var width = node.getWidth(sourceFile);
- if (node.kind === 9 /* StringLiteral */) {
- // Exclude the quotes
- start += 1;
- width -= 2;
- }
- return ts.createTextSpan(start, width);
- }
- function nodeIsEligibleForRename(node) {
- switch (node.kind) {
- case 71 /* Identifier */:
- case 9 /* StringLiteral */:
- case 99 /* ThisKeyword */:
- return true;
- case 8 /* NumericLiteral */:
- return ts.isLiteralNameOfPropertyDeclarationOrIndexAccess(node);
- default:
- return false;
- }
- }
- })(Rename = ts.Rename || (ts.Rename = {}));
-})(ts || (ts = {}));
-///
-/* @internal */
-var ts;
-(function (ts) {
- var SignatureHelp;
- (function (SignatureHelp) {
- var ArgumentListKind;
- (function (ArgumentListKind) {
- ArgumentListKind[ArgumentListKind["TypeArguments"] = 0] = "TypeArguments";
- ArgumentListKind[ArgumentListKind["CallArguments"] = 1] = "CallArguments";
- ArgumentListKind[ArgumentListKind["TaggedTemplateArguments"] = 2] = "TaggedTemplateArguments";
- ArgumentListKind[ArgumentListKind["JSXAttributesArguments"] = 3] = "JSXAttributesArguments";
- })(ArgumentListKind = SignatureHelp.ArgumentListKind || (SignatureHelp.ArgumentListKind = {}));
- function getSignatureHelpItems(program, sourceFile, position, cancellationToken) {
- var typeChecker = program.getTypeChecker();
- // Decide whether to show signature help
- var startingToken = ts.findTokenOnLeftOfPosition(sourceFile, position);
- if (!startingToken) {
- // We are at the beginning of the file
- return undefined;
- }
- var argumentInfo = getContainingArgumentInfo(startingToken, position, sourceFile);
- if (!argumentInfo)
- return undefined;
- cancellationToken.throwIfCancellationRequested();
- // Semantic filtering of signature help
- var call = argumentInfo.invocation;
- var candidates = [];
- var resolvedSignature = typeChecker.getResolvedSignature(call, candidates, argumentInfo.argumentCount);
- cancellationToken.throwIfCancellationRequested();
- if (!candidates.length) {
- // We didn't have any sig help items produced by the TS compiler. If this is a JS
- // file, then see if we can figure out anything better.
- if (ts.isSourceFileJavaScript(sourceFile)) {
- return createJavaScriptSignatureHelpItems(argumentInfo, program);
- }
- return undefined;
- }
- return createSignatureHelpItems(candidates, resolvedSignature, argumentInfo, typeChecker);
- }
- SignatureHelp.getSignatureHelpItems = getSignatureHelpItems;
- function createJavaScriptSignatureHelpItems(argumentInfo, program) {
- if (argumentInfo.invocation.kind !== 185 /* CallExpression */) {
- return undefined;
- }
- // See if we can find some symbol with the call expression name that has call signatures.
- var callExpression = argumentInfo.invocation;
- var expression = callExpression.expression;
- var name = ts.isIdentifier(expression) ? expression : ts.isPropertyAccessExpression(expression) ? expression.name : undefined;
- if (!name || !name.escapedText) {
- return undefined;
- }
- var typeChecker = program.getTypeChecker();
- for (var _i = 0, _a = program.getSourceFiles(); _i < _a.length; _i++) {
- var sourceFile = _a[_i];
- var nameToDeclarations = sourceFile.getNamedDeclarations();
- var declarations = nameToDeclarations.get(name.text);
- if (declarations) {
- for (var _b = 0, declarations_12 = declarations; _b < declarations_12.length; _b++) {
- var declaration = declarations_12[_b];
- var symbol = declaration.symbol;
- if (symbol) {
- var type = typeChecker.getTypeOfSymbolAtLocation(symbol, declaration);
- if (type) {
- var callSignatures = type.getCallSignatures();
- if (callSignatures && callSignatures.length) {
- return createSignatureHelpItems(callSignatures, callSignatures[0], argumentInfo, typeChecker);
- }
- }
- }
- }
- }
- }
- }
- /**
- * Returns relevant information for the argument list and the current argument if we are
- * in the argument of an invocation; returns undefined otherwise.
- */
- function getImmediatelyContainingArgumentInfo(node, position, sourceFile) {
- if (ts.isCallOrNewExpression(node.parent)) {
- var invocation = node.parent;
- var list = void 0;
- var argumentIndex = void 0;
- // There are 3 cases to handle:
- // 1. The token introduces a list, and should begin a signature help session
- // 2. The token is either not associated with a list, or ends a list, so the session should end
- // 3. The token is buried inside a list, and should give signature help
- //
- // The following are examples of each:
- //
- // Case 1:
- // foo<#T, U>(#a, b) -> The token introduces a list, and should begin a signature help session
- // Case 2:
- // fo#o#(a, b)# -> The token is either not associated with a list, or ends a list, so the session should end
- // Case 3:
- // foo(a#, #b#) -> The token is buried inside a list, and should give signature help
- // Find out if 'node' is an argument, a type argument, or neither
- if (node.kind === 27 /* LessThanToken */ || node.kind === 19 /* OpenParenToken */) {
- // Find the list that starts right *after* the < or ( token.
- // If the user has just opened a list, consider this item 0.
- list = getChildListThatStartsWithOpenerToken(invocation, node, sourceFile);
- ts.Debug.assert(list !== undefined);
- argumentIndex = 0;
- }
- else {
- // findListItemInfo can return undefined if we are not in parent's argument list
- // or type argument list. This includes cases where the cursor is:
- // - To the right of the closing parenthesis, non-substitution template, or template tail.
- // - Between the type arguments and the arguments (greater than token)
- // - On the target of the call (parent.func)
- // - On the 'new' keyword in a 'new' expression
- list = ts.findContainingList(node);
- if (!list)
- return undefined;
- argumentIndex = getArgumentIndex(list, node);
- }
- var kind = invocation.typeArguments && invocation.typeArguments.pos === list.pos ? 0 /* TypeArguments */ : 1 /* CallArguments */;
- var argumentCount = getArgumentCount(list);
- if (argumentIndex !== 0) {
- ts.Debug.assertLessThan(argumentIndex, argumentCount);
- }
- var argumentsSpan = getApplicableSpanForArguments(list, sourceFile);
- return { kind: kind, invocation: invocation, argumentsSpan: argumentsSpan, argumentIndex: argumentIndex, argumentCount: argumentCount };
- }
- else if (node.kind === 13 /* NoSubstitutionTemplateLiteral */ && node.parent.kind === 187 /* TaggedTemplateExpression */) {
- // Check if we're actually inside the template;
- // otherwise we'll fall out and return undefined.
- if (ts.isInsideTemplateLiteral(node, position)) {
- return getArgumentListInfoForTemplate(node.parent, /*argumentIndex*/ 0, sourceFile);
- }
- }
- else if (node.kind === 14 /* TemplateHead */ && node.parent.parent.kind === 187 /* TaggedTemplateExpression */) {
- var templateExpression = node.parent;
- var tagExpression = templateExpression.parent;
- ts.Debug.assert(templateExpression.kind === 200 /* TemplateExpression */);
- var argumentIndex = ts.isInsideTemplateLiteral(node, position) ? 0 : 1;
- return getArgumentListInfoForTemplate(tagExpression, argumentIndex, sourceFile);
- }
- else if (node.parent.kind === 209 /* TemplateSpan */ && node.parent.parent.parent.kind === 187 /* TaggedTemplateExpression */) {
- var templateSpan = node.parent;
- var templateExpression = templateSpan.parent;
- var tagExpression = templateExpression.parent;
- ts.Debug.assert(templateExpression.kind === 200 /* TemplateExpression */);
- // If we're just after a template tail, don't show signature help.
- if (node.kind === 16 /* TemplateTail */ && !ts.isInsideTemplateLiteral(node, position)) {
- return undefined;
- }
- var spanIndex = templateExpression.templateSpans.indexOf(templateSpan);
- var argumentIndex = getArgumentIndexForTemplatePiece(spanIndex, node, position);
- return getArgumentListInfoForTemplate(tagExpression, argumentIndex, sourceFile);
- }
- else if (node.parent && ts.isJsxOpeningLikeElement(node.parent)) {
- // Provide a signature help for JSX opening element or JSX self-closing element.
- // This is not guarantee that JSX tag-name is resolved into stateless function component. (that is done in "getSignatureHelpItems")
- // i.e
- // export function MainButton(props: ButtonProps, context: any): JSX.Element { ... }
- // ' 'b'. So, in this case the arg count will be 2. However, there
- // is a small subtlety. If you have "Foo(a,)", then the child list will just have
- // 'a' ''. So, in the case where the last child is a comma, we increase the
- // arg count by one to compensate.
- //
- // Note: this subtlety only applies to the last comma. If you had "Foo(a,," then
- // we'll have: 'a' '' ''
- // That will give us 2 non-commas. We then add one for the last comma, giving us an
- // arg count of 3.
- var listChildren = argumentsList.getChildren();
- var argumentCount = ts.countWhere(listChildren, function (arg) { return arg.kind !== 26 /* CommaToken */; });
- if (listChildren.length > 0 && ts.lastOrUndefined(listChildren).kind === 26 /* CommaToken */) {
- argumentCount++;
- }
- return argumentCount;
- }
- // spanIndex is either the index for a given template span.
- // This does not give appropriate results for a NoSubstitutionTemplateLiteral
- function getArgumentIndexForTemplatePiece(spanIndex, node, position) {
- // Because the TemplateStringsArray is the first argument, we have to offset each substitution expression by 1.
- // There are three cases we can encounter:
- // 1. We are precisely in the template literal (argIndex = 0).
- // 2. We are in or to the right of the substitution expression (argIndex = spanIndex + 1).
- // 3. We are directly to the right of the template literal, but because we look for the token on the left,
- // not enough to put us in the substitution expression; we should consider ourselves part of
- // the *next* span's expression by offsetting the index (argIndex = (spanIndex + 1) + 1).
- //
- // tslint:disable no-double-space
- // Example: f `# abcd $#{# 1 + 1# }# efghi ${ #"#hello"# } # `
- // ^ ^ ^ ^ ^ ^ ^ ^ ^
- // Case: 1 1 3 2 1 3 2 2 1
- // tslint:enable no-double-space
- ts.Debug.assert(position >= node.getStart(), "Assumed 'position' could not occur before node.");
- if (ts.isTemplateLiteralKind(node.kind)) {
- if (ts.isInsideTemplateLiteral(node, position)) {
- return 0;
- }
- return spanIndex + 2;
- }
- return spanIndex + 1;
- }
- function getArgumentListInfoForTemplate(tagExpression, argumentIndex, sourceFile) {
- // argumentCount is either 1 or (numSpans + 1) to account for the template strings array argument.
- var argumentCount = ts.isNoSubstitutionTemplateLiteral(tagExpression.template) ? 1 : tagExpression.template.templateSpans.length + 1;
- if (argumentIndex !== 0) {
- ts.Debug.assertLessThan(argumentIndex, argumentCount);
- }
- return {
- kind: 2 /* TaggedTemplateArguments */,
- invocation: tagExpression,
- argumentsSpan: getApplicableSpanForTaggedTemplate(tagExpression, sourceFile),
- argumentIndex: argumentIndex,
- argumentCount: argumentCount
- };
- }
- function getApplicableSpanForArguments(argumentsList, sourceFile) {
- // We use full start and skip trivia on the end because we want to include trivia on
- // both sides. For example,
- //
- // foo( /*comment */ a, b, c /*comment*/ )
- // | |
- //
- // The applicable span is from the first bar to the second bar (inclusive,
- // but not including parentheses)
- var applicableSpanStart = argumentsList.getFullStart();
- var applicableSpanEnd = ts.skipTrivia(sourceFile.text, argumentsList.getEnd(), /*stopAfterLineBreak*/ false);
- return ts.createTextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart);
- }
- function getApplicableSpanForTaggedTemplate(taggedTemplate, sourceFile) {
- var template = taggedTemplate.template;
- var applicableSpanStart = template.getStart();
- var applicableSpanEnd = template.getEnd();
- // We need to adjust the end position for the case where the template does not have a tail.
- // Otherwise, we will not show signature help past the expression.
- // For example,
- //
- // ` ${ 1 + 1 foo(10)
- // | |
- // This is because a Missing node has no width. However, what we actually want is to include trivia
- // leading up to the next token in case the user is about to type in a TemplateMiddle or TemplateTail.
- if (template.kind === 200 /* TemplateExpression */) {
- var lastSpan = ts.lastOrUndefined(template.templateSpans);
- if (lastSpan.literal.getFullWidth() === 0) {
- applicableSpanEnd = ts.skipTrivia(sourceFile.text, applicableSpanEnd, /*stopAfterLineBreak*/ false);
- }
- }
- return ts.createTextSpan(applicableSpanStart, applicableSpanEnd - applicableSpanStart);
- }
- function getContainingArgumentInfo(node, position, sourceFile) {
- for (var n = node; n.kind !== 272 /* SourceFile */; n = n.parent) {
- if (ts.isFunctionBlock(n)) {
- return undefined;
- }
- // If the node is not a subspan of its parent, this is a big problem.
- // There have been crashes that might be caused by this violation.
- if (n.pos < n.parent.pos || n.end > n.parent.end) {
- ts.Debug.fail("Node of kind " + n.kind + " is not a subspan of its parent of kind " + n.parent.kind);
- }
- var argumentInfo = getImmediatelyContainingArgumentInfo(n, position, sourceFile);
- if (argumentInfo) {
- return argumentInfo;
- }
- // TODO: Handle generic call with incomplete syntax
- }
- return undefined;
- }
- SignatureHelp.getContainingArgumentInfo = getContainingArgumentInfo;
- function getChildListThatStartsWithOpenerToken(parent, openerToken, sourceFile) {
- var children = parent.getChildren(sourceFile);
- var indexOfOpenerToken = children.indexOf(openerToken);
- ts.Debug.assert(indexOfOpenerToken >= 0 && children.length > indexOfOpenerToken + 1);
- return children[indexOfOpenerToken + 1];
- }
- var signatureHelpNodeBuilderFlags = 8192 /* OmitParameterModifiers */ | 3112960 /* IgnoreErrors */;
- function createSignatureHelpItems(candidates, resolvedSignature, argumentListInfo, typeChecker) {
- var argumentCount = argumentListInfo.argumentCount, applicableSpan = argumentListInfo.argumentsSpan, invocation = argumentListInfo.invocation, argumentIndex = argumentListInfo.argumentIndex;
- var isTypeParameterList = argumentListInfo.kind === 0 /* TypeArguments */;
- var callTarget = ts.getInvokedExpression(invocation);
- var callTargetSymbol = typeChecker.getSymbolAtLocation(callTarget);
- var callTargetDisplayParts = callTargetSymbol && ts.symbolToDisplayParts(typeChecker, callTargetSymbol, /*enclosingDeclaration*/ undefined, /*meaning*/ undefined);
- var printer = ts.createPrinter({ removeComments: true });
- var items = ts.map(candidates, function (candidateSignature) {
- var signatureHelpParameters;
- var prefixDisplayParts = [];
- var suffixDisplayParts = [];
- if (callTargetDisplayParts) {
- ts.addRange(prefixDisplayParts, callTargetDisplayParts);
- }
- var isVariadic;
- if (isTypeParameterList) {
- isVariadic = false; // type parameter lists are not variadic
- prefixDisplayParts.push(ts.punctuationPart(27 /* LessThanToken */));
- var typeParameters = (candidateSignature.target || candidateSignature).typeParameters;
- signatureHelpParameters = typeParameters && typeParameters.length > 0 ? ts.map(typeParameters, createSignatureHelpParameterForTypeParameter) : ts.emptyArray;
- suffixDisplayParts.push(ts.punctuationPart(29 /* GreaterThanToken */));
- var parameterParts = ts.mapToDisplayParts(function (writer) {
- var thisParameter = candidateSignature.thisParameter ? [typeChecker.symbolToParameterDeclaration(candidateSignature.thisParameter, invocation, signatureHelpNodeBuilderFlags)] : [];
- var params = ts.createNodeArray(thisParameter.concat(ts.map(candidateSignature.parameters, function (param) { return typeChecker.symbolToParameterDeclaration(param, invocation, signatureHelpNodeBuilderFlags); })));
- printer.writeList(1296 /* CallExpressionArguments */, params, ts.getSourceFileOfNode(ts.getParseTreeNode(invocation)), writer);
- });
- ts.addRange(suffixDisplayParts, parameterParts);
- }
- else {
- isVariadic = candidateSignature.hasRestParameter;
- var typeParameterParts = ts.mapToDisplayParts(function (writer) {
- if (candidateSignature.typeParameters && candidateSignature.typeParameters.length) {
- var args = ts.createNodeArray(ts.map(candidateSignature.typeParameters, function (p) { return typeChecker.typeParameterToDeclaration(p, invocation); }));
- printer.writeList(26896 /* TypeParameters */, args, ts.getSourceFileOfNode(ts.getParseTreeNode(invocation)), writer);
- }
- });
- ts.addRange(prefixDisplayParts, typeParameterParts);
- prefixDisplayParts.push(ts.punctuationPart(19 /* OpenParenToken */));
- signatureHelpParameters = ts.map(candidateSignature.parameters, createSignatureHelpParameterForParameter);
- suffixDisplayParts.push(ts.punctuationPart(20 /* CloseParenToken */));
- }
- var returnTypeParts = ts.mapToDisplayParts(function (writer) {
- writer.writePunctuation(":");
- writer.writeSpace(" ");
- var predicate = typeChecker.getTypePredicateOfSignature(candidateSignature);
- if (predicate) {
- typeChecker.writeTypePredicate(predicate, invocation, /*flags*/ undefined, writer);
- }
- else {
- typeChecker.writeType(typeChecker.getReturnTypeOfSignature(candidateSignature), invocation, /*flags*/ undefined, writer);
- }
- });
- ts.addRange(suffixDisplayParts, returnTypeParts);
- return {
- isVariadic: isVariadic,
- prefixDisplayParts: prefixDisplayParts,
- suffixDisplayParts: suffixDisplayParts,
- separatorDisplayParts: [ts.punctuationPart(26 /* CommaToken */), ts.spacePart()],
- parameters: signatureHelpParameters,
- documentation: candidateSignature.getDocumentationComment(typeChecker),
- tags: candidateSignature.getJsDocTags()
- };
- });
- if (argumentIndex !== 0) {
- ts.Debug.assertLessThan(argumentIndex, argumentCount);
- }
- var selectedItemIndex = candidates.indexOf(resolvedSignature);
- ts.Debug.assert(selectedItemIndex !== -1); // If candidates is non-empty it should always include bestSignature. We check for an empty candidates before calling this function.
- return { items: items, applicableSpan: applicableSpan, selectedItemIndex: selectedItemIndex, argumentIndex: argumentIndex, argumentCount: argumentCount };
- function createSignatureHelpParameterForParameter(parameter) {
- var displayParts = ts.mapToDisplayParts(function (writer) {
- var param = typeChecker.symbolToParameterDeclaration(parameter, invocation, signatureHelpNodeBuilderFlags);
- printer.writeNode(4 /* Unspecified */, param, ts.getSourceFileOfNode(ts.getParseTreeNode(invocation)), writer);
- });
- return {
- name: parameter.name,
- documentation: parameter.getDocumentationComment(typeChecker),
- displayParts: displayParts,
- isOptional: typeChecker.isOptionalParameter(parameter.valueDeclaration)
- };
- }
- function createSignatureHelpParameterForTypeParameter(typeParameter) {
- var displayParts = ts.mapToDisplayParts(function (writer) {
- var param = typeChecker.typeParameterToDeclaration(typeParameter, invocation);
- printer.writeNode(4 /* Unspecified */, param, ts.getSourceFileOfNode(ts.getParseTreeNode(invocation)), writer);
- });
- return {
- name: typeParameter.symbol.name,
- documentation: ts.emptyArray,
- displayParts: displayParts,
- isOptional: false
- };
- }
- }
- })(SignatureHelp = ts.SignatureHelp || (ts.SignatureHelp = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- function computeSuggestionDiagnostics(sourceFile, program) {
- program.getSemanticDiagnostics(sourceFile);
- var checker = program.getDiagnosticsProducingTypeChecker();
- var diags = [];
- if (sourceFile.commonJsModuleIndicator) {
- diags.push(ts.createDiagnosticForNode(sourceFile.commonJsModuleIndicator, ts.Diagnostics.File_is_a_CommonJS_module_it_may_be_converted_to_an_ES6_module));
- }
- var isJsFile = ts.isSourceFileJavaScript(sourceFile);
- function check(node) {
- switch (node.kind) {
- case 232 /* FunctionDeclaration */:
- case 190 /* FunctionExpression */:
- if (isJsFile) {
- var symbol = node.symbol;
- if (symbol.members && (symbol.members.size > 0)) {
- diags.push(ts.createDiagnosticForNode(ts.isVariableDeclaration(node.parent) ? node.parent.name : node, ts.Diagnostics.This_constructor_function_may_be_converted_to_a_class_declaration));
- }
- }
- break;
- }
- if (!isJsFile && ts.codefix.parameterShouldGetTypeFromJSDoc(node)) {
- diags.push(ts.createDiagnosticForNode(node.name || node, ts.Diagnostics.JSDoc_types_may_be_moved_to_TypeScript_types));
- }
- node.forEachChild(check);
- }
- check(sourceFile);
- if (ts.getAllowSyntheticDefaultImports(program.getCompilerOptions())) {
- for (var _i = 0, _a = sourceFile.imports; _i < _a.length; _i++) {
- var importNode = _a[_i];
- var name = importNameForConvertToDefaultImport(importNode.parent);
- if (!name)
- continue;
- var module = ts.getResolvedModule(sourceFile, importNode.text);
- var resolvedFile = module && program.getSourceFile(module.resolvedFileName);
- if (resolvedFile && resolvedFile.externalModuleIndicator && ts.isExportAssignment(resolvedFile.externalModuleIndicator) && resolvedFile.externalModuleIndicator.isExportEquals) {
- diags.push(ts.createDiagnosticForNode(name, ts.Diagnostics.Import_may_be_converted_to_a_default_import));
- }
- }
- }
- return diags.concat(checker.getSuggestionDiagnostics(sourceFile));
- }
- ts.computeSuggestionDiagnostics = computeSuggestionDiagnostics;
- function importNameForConvertToDefaultImport(node) {
- if (ts.isExternalModuleReference(node)) {
- return node.parent.name;
- }
- if (ts.isImportDeclaration(node)) {
- var importClause = node.importClause, moduleSpecifier = node.moduleSpecifier;
- return importClause && !importClause.name && importClause.namedBindings.kind === 244 /* NamespaceImport */ && ts.isStringLiteral(moduleSpecifier)
- ? importClause.namedBindings.name
- : undefined;
- }
- }
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var SymbolDisplay;
- (function (SymbolDisplay) {
- // TODO(drosen): use contextual SemanticMeaning.
- function getSymbolKind(typeChecker, symbol, location) {
- var result = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(typeChecker, symbol, location);
- if (result !== "" /* unknown */) {
- return result;
- }
- var flags = ts.getCombinedLocalAndExportSymbolFlags(symbol);
- if (flags & 32 /* Class */) {
- return ts.getDeclarationOfKind(symbol, 203 /* ClassExpression */) ?
- "local class" /* localClassElement */ : "class" /* classElement */;
- }
- if (flags & 384 /* Enum */)
- return "enum" /* enumElement */;
- if (flags & 524288 /* TypeAlias */)
- return "type" /* typeElement */;
- if (flags & 64 /* Interface */)
- return "interface" /* interfaceElement */;
- if (flags & 262144 /* TypeParameter */)
- return "type parameter" /* typeParameterElement */;
- if (flags & 262144 /* TypeParameter */)
- return "type parameter" /* typeParameterElement */;
- if (flags & 8 /* EnumMember */)
- return "enum member" /* enumMemberElement */;
- if (flags & 2097152 /* Alias */)
- return "alias" /* alias */;
- if (flags & 1536 /* Module */)
- return "module" /* moduleElement */;
- return result;
- }
- SymbolDisplay.getSymbolKind = getSymbolKind;
- function getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(typeChecker, symbol, location) {
- if (typeChecker.isUndefinedSymbol(symbol)) {
- return "var" /* variableElement */;
- }
- if (typeChecker.isArgumentsSymbol(symbol)) {
- return "local var" /* localVariableElement */;
- }
- if (location.kind === 99 /* ThisKeyword */ && ts.isExpression(location)) {
- return "parameter" /* parameterElement */;
- }
- var flags = ts.getCombinedLocalAndExportSymbolFlags(symbol);
- if (flags & 3 /* Variable */) {
- if (ts.isFirstDeclarationOfSymbolParameter(symbol)) {
- return "parameter" /* parameterElement */;
- }
- else if (symbol.valueDeclaration && ts.isConst(symbol.valueDeclaration)) {
- return "const" /* constElement */;
- }
- else if (ts.forEach(symbol.declarations, ts.isLet)) {
- return "let" /* letElement */;
- }
- return isLocalVariableOrFunction(symbol) ? "local var" /* localVariableElement */ : "var" /* variableElement */;
- }
- if (flags & 16 /* Function */)
- return isLocalVariableOrFunction(symbol) ? "local function" /* localFunctionElement */ : "function" /* functionElement */;
- if (flags & 32768 /* GetAccessor */)
- return "getter" /* memberGetAccessorElement */;
- if (flags & 65536 /* SetAccessor */)
- return "setter" /* memberSetAccessorElement */;
- if (flags & 8192 /* Method */)
- return "method" /* memberFunctionElement */;
- if (flags & 16384 /* Constructor */)
- return "constructor" /* constructorImplementationElement */;
- if (flags & 4 /* Property */) {
- if (flags & 33554432 /* Transient */ && symbol.checkFlags & 6 /* Synthetic */) {
- // If union property is result of union of non method (property/accessors/variables), it is labeled as property
- var unionPropertyKind = ts.forEach(typeChecker.getRootSymbols(symbol), function (rootSymbol) {
- var rootSymbolFlags = rootSymbol.getFlags();
- if (rootSymbolFlags & (98308 /* PropertyOrAccessor */ | 3 /* Variable */)) {
- return "property" /* memberVariableElement */;
- }
- // May be a Function if this was from `typeof N` with `namespace N { function f();. }`.
- ts.Debug.assert(!!(rootSymbolFlags & (8192 /* Method */ | 16 /* Function */)));
- });
- if (!unionPropertyKind) {
- // If this was union of all methods,
- // make sure it has call signatures before we can label it as method
- var typeOfUnionProperty = typeChecker.getTypeOfSymbolAtLocation(symbol, location);
- if (typeOfUnionProperty.getCallSignatures().length) {
- return "method" /* memberFunctionElement */;
- }
- return "property" /* memberVariableElement */;
- }
- return unionPropertyKind;
- }
- // If we requested completions after `x.` at the top-level, we may be at a source file location.
- switch (location.parent && location.parent.kind) {
- // If we've typed a character of the attribute name, will be 'JsxAttribute', else will be 'JsxOpeningElement'.
- case 255 /* JsxOpeningElement */:
- case 253 /* JsxElement */:
- case 254 /* JsxSelfClosingElement */:
- return location.kind === 71 /* Identifier */ ? "property" /* memberVariableElement */ : "JSX attribute" /* jsxAttribute */;
- case 260 /* JsxAttribute */:
- return "JSX attribute" /* jsxAttribute */;
- default:
- return "property" /* memberVariableElement */;
- }
- }
- return "" /* unknown */;
- }
- function getSymbolModifiers(symbol) {
- var nodeModifiers = symbol && symbol.declarations && symbol.declarations.length > 0
- ? ts.getNodeModifiers(symbol.declarations[0])
- : "" /* none */;
- var symbolModifiers = symbol && symbol.flags & 16777216 /* Optional */ ?
- "optional" /* optionalModifier */
- : "" /* none */;
- return nodeModifiers && symbolModifiers ? nodeModifiers + "," + symbolModifiers : nodeModifiers || symbolModifiers;
- }
- SymbolDisplay.getSymbolModifiers = getSymbolModifiers;
- // TODO(drosen): Currently completion entry details passes the SemanticMeaning.All instead of using semanticMeaning of location
- function getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker, symbol, sourceFile, enclosingDeclaration, location, semanticMeaning, alias) {
- if (semanticMeaning === void 0) { semanticMeaning = ts.getMeaningFromLocation(location); }
- var displayParts = [];
- var documentation;
- var tags;
- var symbolFlags = ts.getCombinedLocalAndExportSymbolFlags(symbol);
- var symbolKind = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(typeChecker, symbol, location);
- var hasAddedSymbolInfo;
- var isThisExpression = location.kind === 99 /* ThisKeyword */ && ts.isExpression(location);
- var type;
- var printer;
- var documentationFromAlias;
- // Class at constructor site need to be shown as constructor apart from property,method, vars
- if (symbolKind !== "" /* unknown */ || symbolFlags & 32 /* Class */ || symbolFlags & 2097152 /* Alias */) {
- // If it is accessor they are allowed only if location is at name of the accessor
- if (symbolKind === "getter" /* memberGetAccessorElement */ || symbolKind === "setter" /* memberSetAccessorElement */) {
- symbolKind = "property" /* memberVariableElement */;
- }
- var signature = void 0;
- type = isThisExpression ? typeChecker.getTypeAtLocation(location) : typeChecker.getTypeOfSymbolAtLocation(symbol.exportSymbol || symbol, location);
- if (location.parent && location.parent.kind === 183 /* PropertyAccessExpression */) {
- var right = location.parent.name;
- // Either the location is on the right of a property access, or on the left and the right is missing
- if (right === location || (right && right.getFullWidth() === 0)) {
- location = location.parent;
- }
- }
- // try get the call/construct signature from the type if it matches
- var callExpressionLike = void 0;
- if (ts.isCallOrNewExpression(location)) {
- callExpressionLike = location;
- }
- else if (ts.isCallExpressionTarget(location) || ts.isNewExpressionTarget(location)) {
- callExpressionLike = location.parent;
- }
- else if (location.parent && ts.isJsxOpeningLikeElement(location.parent) && ts.isFunctionLike(symbol.valueDeclaration)) {
- callExpressionLike = location.parent;
- }
- if (callExpressionLike) {
- var candidateSignatures = [];
- signature = typeChecker.getResolvedSignature(callExpressionLike, candidateSignatures);
- var useConstructSignatures = callExpressionLike.kind === 186 /* NewExpression */ || (ts.isCallExpression(callExpressionLike) && callExpressionLike.expression.kind === 97 /* SuperKeyword */);
- var allSignatures = useConstructSignatures ? type.getConstructSignatures() : type.getCallSignatures();
- if (!ts.contains(allSignatures, signature.target) && !ts.contains(allSignatures, signature)) {
- // Get the first signature if there is one -- allSignatures may contain
- // either the original signature or its target, so check for either
- signature = allSignatures.length ? allSignatures[0] : undefined;
- }
- if (signature) {
- if (useConstructSignatures && (symbolFlags & 32 /* Class */)) {
- // Constructor
- symbolKind = "constructor" /* constructorImplementationElement */;
- addPrefixForAnyFunctionOrVar(type.symbol, symbolKind);
- }
- else if (symbolFlags & 2097152 /* Alias */) {
- symbolKind = "alias" /* alias */;
- pushTypePart(symbolKind);
- displayParts.push(ts.spacePart());
- if (useConstructSignatures) {
- displayParts.push(ts.keywordPart(94 /* NewKeyword */));
- displayParts.push(ts.spacePart());
- }
- addFullSymbolName(symbol);
- }
- else {
- addPrefixForAnyFunctionOrVar(symbol, symbolKind);
- }
- switch (symbolKind) {
- case "JSX attribute" /* jsxAttribute */:
- case "property" /* memberVariableElement */:
- case "var" /* variableElement */:
- case "const" /* constElement */:
- case "let" /* letElement */:
- case "parameter" /* parameterElement */:
- case "local var" /* localVariableElement */:
- // If it is call or construct signature of lambda's write type name
- displayParts.push(ts.punctuationPart(56 /* ColonToken */));
- displayParts.push(ts.spacePart());
- if (!(type.flags & 65536 /* Object */ && type.objectFlags & 16 /* Anonymous */) && type.symbol) {
- ts.addRange(displayParts, ts.symbolToDisplayParts(typeChecker, type.symbol, enclosingDeclaration, /*meaning*/ undefined, 4 /* AllowAnyNodeKind */ | 1 /* WriteTypeParametersOrArguments */));
- displayParts.push(ts.lineBreakPart());
- }
- if (useConstructSignatures) {
- displayParts.push(ts.keywordPart(94 /* NewKeyword */));
- displayParts.push(ts.spacePart());
- }
- addSignatureDisplayParts(signature, allSignatures, 262144 /* WriteArrowStyleSignature */);
- break;
- default:
- // Just signature
- addSignatureDisplayParts(signature, allSignatures);
- }
- hasAddedSymbolInfo = true;
- }
- }
- else if ((ts.isNameOfFunctionDeclaration(location) && !(symbolFlags & 98304 /* Accessor */)) || // name of function declaration
- (location.kind === 123 /* ConstructorKeyword */ && location.parent.kind === 154 /* Constructor */)) { // At constructor keyword of constructor declaration
- // get the signature from the declaration and write it
- var functionDeclaration_1 = location.parent;
- // Use function declaration to write the signatures only if the symbol corresponding to this declaration
- var locationIsSymbolDeclaration = ts.find(symbol.declarations, function (declaration) {
- return declaration === (location.kind === 123 /* ConstructorKeyword */ ? functionDeclaration_1.parent : functionDeclaration_1);
- });
- if (locationIsSymbolDeclaration) {
- var allSignatures = functionDeclaration_1.kind === 154 /* Constructor */ ? type.getNonNullableType().getConstructSignatures() : type.getNonNullableType().getCallSignatures();
- if (!typeChecker.isImplementationOfOverload(functionDeclaration_1)) {
- signature = typeChecker.getSignatureFromDeclaration(functionDeclaration_1);
- }
- else {
- signature = allSignatures[0];
- }
- if (functionDeclaration_1.kind === 154 /* Constructor */) {
- // show (constructor) Type(...) signature
- symbolKind = "constructor" /* constructorImplementationElement */;
- addPrefixForAnyFunctionOrVar(type.symbol, symbolKind);
- }
- else {
- // (function/method) symbol(..signature)
- addPrefixForAnyFunctionOrVar(functionDeclaration_1.kind === 157 /* CallSignature */ &&
- !(type.symbol.flags & 2048 /* TypeLiteral */ || type.symbol.flags & 4096 /* ObjectLiteral */) ? type.symbol : symbol, symbolKind);
- }
- addSignatureDisplayParts(signature, allSignatures);
- hasAddedSymbolInfo = true;
- }
- }
- }
- if (symbolFlags & 32 /* Class */ && !hasAddedSymbolInfo && !isThisExpression) {
- addAliasPrefixIfNecessary();
- if (ts.getDeclarationOfKind(symbol, 203 /* ClassExpression */)) {
- // Special case for class expressions because we would like to indicate that
- // the class name is local to the class body (similar to function expression)
- // (local class) class
- pushTypePart("local class" /* localClassElement */);
- }
- else {
- // Class declaration has name which is not local.
- displayParts.push(ts.keywordPart(75 /* ClassKeyword */));
- }
- displayParts.push(ts.spacePart());
- addFullSymbolName(symbol);
- writeTypeParametersOfSymbol(symbol, sourceFile);
- }
- if ((symbolFlags & 64 /* Interface */) && (semanticMeaning & 2 /* Type */)) {
- prefixNextMeaning();
- displayParts.push(ts.keywordPart(109 /* InterfaceKeyword */));
- displayParts.push(ts.spacePart());
- addFullSymbolName(symbol);
- writeTypeParametersOfSymbol(symbol, sourceFile);
- }
- if (symbolFlags & 524288 /* TypeAlias */) {
- prefixNextMeaning();
- displayParts.push(ts.keywordPart(139 /* TypeKeyword */));
- displayParts.push(ts.spacePart());
- addFullSymbolName(symbol);
- writeTypeParametersOfSymbol(symbol, sourceFile);
- displayParts.push(ts.spacePart());
- displayParts.push(ts.operatorPart(58 /* EqualsToken */));
- displayParts.push(ts.spacePart());
- ts.addRange(displayParts, ts.typeToDisplayParts(typeChecker, typeChecker.getDeclaredTypeOfSymbol(symbol), enclosingDeclaration, 8388608 /* InTypeAlias */));
- }
- if (symbolFlags & 384 /* Enum */) {
- prefixNextMeaning();
- if (ts.forEach(symbol.declarations, ts.isConstEnumDeclaration)) {
- displayParts.push(ts.keywordPart(76 /* ConstKeyword */));
- displayParts.push(ts.spacePart());
- }
- displayParts.push(ts.keywordPart(83 /* EnumKeyword */));
- displayParts.push(ts.spacePart());
- addFullSymbolName(symbol);
- }
- if (symbolFlags & 1536 /* Module */) {
- prefixNextMeaning();
- var declaration = ts.getDeclarationOfKind(symbol, 237 /* ModuleDeclaration */);
- var isNamespace = declaration && declaration.name && declaration.name.kind === 71 /* Identifier */;
- displayParts.push(ts.keywordPart(isNamespace ? 130 /* NamespaceKeyword */ : 129 /* ModuleKeyword */));
- displayParts.push(ts.spacePart());
- addFullSymbolName(symbol);
- }
- if ((symbolFlags & 262144 /* TypeParameter */) && (semanticMeaning & 2 /* Type */)) {
- prefixNextMeaning();
- displayParts.push(ts.punctuationPart(19 /* OpenParenToken */));
- displayParts.push(ts.textPart("type parameter"));
- displayParts.push(ts.punctuationPart(20 /* CloseParenToken */));
- displayParts.push(ts.spacePart());
- addFullSymbolName(symbol);
- if (symbol.parent) {
- // Class/Interface type parameter
- addInPrefix();
- addFullSymbolName(symbol.parent, enclosingDeclaration);
- writeTypeParametersOfSymbol(symbol.parent, enclosingDeclaration);
- }
- else {
- // Method/function type parameter
- var decl = ts.getDeclarationOfKind(symbol, 147 /* TypeParameter */);
- ts.Debug.assert(decl !== undefined);
- var declaration = decl.parent;
- if (declaration) {
- if (ts.isFunctionLikeKind(declaration.kind)) {
- addInPrefix();
- var signature = typeChecker.getSignatureFromDeclaration(declaration);
- if (declaration.kind === 158 /* ConstructSignature */) {
- displayParts.push(ts.keywordPart(94 /* NewKeyword */));
- displayParts.push(ts.spacePart());
- }
- else if (declaration.kind !== 157 /* CallSignature */ && declaration.name) {
- addFullSymbolName(declaration.symbol);
- }
- ts.addRange(displayParts, ts.signatureToDisplayParts(typeChecker, signature, sourceFile, 32 /* WriteTypeArgumentsOfSignature */));
- }
- else if (declaration.kind === 235 /* TypeAliasDeclaration */) {
- // Type alias type parameter
- // For example
- // type list = T[]; // Both T will go through same code path
- addInPrefix();
- displayParts.push(ts.keywordPart(139 /* TypeKeyword */));
- displayParts.push(ts.spacePart());
- addFullSymbolName(declaration.symbol);
- writeTypeParametersOfSymbol(declaration.symbol, sourceFile);
- }
- }
- }
- }
- if (symbolFlags & 8 /* EnumMember */) {
- symbolKind = "enum member" /* enumMemberElement */;
- addPrefixForAnyFunctionOrVar(symbol, "enum member");
- var declaration = symbol.declarations[0];
- if (declaration.kind === 271 /* EnumMember */) {
- var constantValue = typeChecker.getConstantValue(declaration);
- if (constantValue !== undefined) {
- displayParts.push(ts.spacePart());
- displayParts.push(ts.operatorPart(58 /* EqualsToken */));
- displayParts.push(ts.spacePart());
- displayParts.push(ts.displayPart(ts.getTextOfConstantValue(constantValue), typeof constantValue === "number" ? ts.SymbolDisplayPartKind.numericLiteral : ts.SymbolDisplayPartKind.stringLiteral));
- }
- }
- }
- if (symbolFlags & 2097152 /* Alias */) {
- prefixNextMeaning();
- if (!hasAddedSymbolInfo) {
- var resolvedSymbol = typeChecker.getAliasedSymbol(symbol);
- if (resolvedSymbol !== symbol && resolvedSymbol.declarations && resolvedSymbol.declarations.length > 0) {
- var resolvedNode = resolvedSymbol.declarations[0];
- var declarationName = ts.getNameOfDeclaration(resolvedNode);
- if (declarationName) {
- var isExternalModuleDeclaration = ts.isModuleWithStringLiteralName(resolvedNode) &&
- ts.hasModifier(resolvedNode, 2 /* Ambient */);
- var shouldUseAliasName = symbol.name !== "default" && !isExternalModuleDeclaration;
- var resolvedInfo = getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker, resolvedSymbol, ts.getSourceFileOfNode(resolvedNode), resolvedNode, declarationName, semanticMeaning, shouldUseAliasName ? symbol : resolvedSymbol);
- displayParts.push.apply(displayParts, resolvedInfo.displayParts);
- displayParts.push(ts.lineBreakPart());
- documentationFromAlias = resolvedInfo.documentation;
- }
- }
- }
- switch (symbol.declarations[0].kind) {
- case 240 /* NamespaceExportDeclaration */:
- displayParts.push(ts.keywordPart(84 /* ExportKeyword */));
- displayParts.push(ts.spacePart());
- displayParts.push(ts.keywordPart(130 /* NamespaceKeyword */));
- break;
- case 247 /* ExportAssignment */:
- displayParts.push(ts.keywordPart(84 /* ExportKeyword */));
- displayParts.push(ts.spacePart());
- displayParts.push(ts.keywordPart(symbol.declarations[0].isExportEquals ? 58 /* EqualsToken */ : 79 /* DefaultKeyword */));
- break;
- default:
- displayParts.push(ts.keywordPart(91 /* ImportKeyword */));
- }
- displayParts.push(ts.spacePart());
- addFullSymbolName(symbol);
- ts.forEach(symbol.declarations, function (declaration) {
- if (declaration.kind === 241 /* ImportEqualsDeclaration */) {
- var importEqualsDeclaration = declaration;
- if (ts.isExternalModuleImportEqualsDeclaration(importEqualsDeclaration)) {
- displayParts.push(ts.spacePart());
- displayParts.push(ts.operatorPart(58 /* EqualsToken */));
- displayParts.push(ts.spacePart());
- displayParts.push(ts.keywordPart(133 /* RequireKeyword */));
- displayParts.push(ts.punctuationPart(19 /* OpenParenToken */));
- displayParts.push(ts.displayPart(ts.getTextOfNode(ts.getExternalModuleImportEqualsDeclarationExpression(importEqualsDeclaration)), ts.SymbolDisplayPartKind.stringLiteral));
- displayParts.push(ts.punctuationPart(20 /* CloseParenToken */));
- }
- else {
- var internalAliasSymbol = typeChecker.getSymbolAtLocation(importEqualsDeclaration.moduleReference);
- if (internalAliasSymbol) {
- displayParts.push(ts.spacePart());
- displayParts.push(ts.operatorPart(58 /* EqualsToken */));
- displayParts.push(ts.spacePart());
- addFullSymbolName(internalAliasSymbol, enclosingDeclaration);
- }
- }
- return true;
- }
- });
- }
- if (!hasAddedSymbolInfo) {
- if (symbolKind !== "" /* unknown */) {
- if (type) {
- if (isThisExpression) {
- prefixNextMeaning();
- displayParts.push(ts.keywordPart(99 /* ThisKeyword */));
- }
- else {
- addPrefixForAnyFunctionOrVar(symbol, symbolKind);
- }
- // For properties, variables and local vars: show the type
- if (symbolKind === "property" /* memberVariableElement */ ||
- symbolKind === "JSX attribute" /* jsxAttribute */ ||
- symbolFlags & 3 /* Variable */ ||
- symbolKind === "local var" /* localVariableElement */ ||
- isThisExpression) {
- displayParts.push(ts.punctuationPart(56 /* ColonToken */));
- displayParts.push(ts.spacePart());
- // If the type is type parameter, format it specially
- if (type.symbol && type.symbol.flags & 262144 /* TypeParameter */) {
- var typeParameterParts = ts.mapToDisplayParts(function (writer) {
- var param = typeChecker.typeParameterToDeclaration(type, enclosingDeclaration);
- getPrinter().writeNode(4 /* Unspecified */, param, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosingDeclaration)), writer);
- });
- ts.addRange(displayParts, typeParameterParts);
- }
- else {
- ts.addRange(displayParts, ts.typeToDisplayParts(typeChecker, type, enclosingDeclaration));
- }
- }
- else if (symbolFlags & 16 /* Function */ ||
- symbolFlags & 8192 /* Method */ ||
- symbolFlags & 16384 /* Constructor */ ||
- symbolFlags & 131072 /* Signature */ ||
- symbolFlags & 98304 /* Accessor */ ||
- symbolKind === "method" /* memberFunctionElement */) {
- var allSignatures = type.getNonNullableType().getCallSignatures();
- if (allSignatures.length) {
- addSignatureDisplayParts(allSignatures[0], allSignatures);
- }
- }
- }
- }
- else {
- symbolKind = getSymbolKind(typeChecker, symbol, location);
- }
- }
- if (!documentation) {
- documentation = symbol.getDocumentationComment(typeChecker);
- tags = symbol.getJsDocTags();
- if (documentation.length === 0 && symbolFlags & 4 /* Property */) {
- // For some special property access expressions like `exports.foo = foo` or `module.exports.foo = foo`
- // there documentation comments might be attached to the right hand side symbol of their declarations.
- // The pattern of such special property access is that the parent symbol is the symbol of the file.
- if (symbol.parent && ts.forEach(symbol.parent.declarations, function (declaration) { return declaration.kind === 272 /* SourceFile */; })) {
- for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) {
- var declaration = _a[_i];
- if (!declaration.parent || declaration.parent.kind !== 198 /* BinaryExpression */) {
- continue;
- }
- var rhsSymbol = typeChecker.getSymbolAtLocation(declaration.parent.right);
- if (!rhsSymbol) {
- continue;
- }
- documentation = rhsSymbol.getDocumentationComment(typeChecker);
- tags = rhsSymbol.getJsDocTags();
- if (documentation.length > 0) {
- break;
- }
- }
- }
- }
- }
- if (documentation.length === 0 && documentationFromAlias) {
- documentation = documentationFromAlias;
- }
- return { displayParts: displayParts, documentation: documentation, symbolKind: symbolKind, tags: tags };
- function getPrinter() {
- if (!printer) {
- printer = ts.createPrinter({ removeComments: true });
- }
- return printer;
- }
- function prefixNextMeaning() {
- if (displayParts.length) {
- displayParts.push(ts.lineBreakPart());
- }
- addAliasPrefixIfNecessary();
- }
- function addAliasPrefixIfNecessary() {
- if (alias) {
- pushTypePart("alias" /* alias */);
- displayParts.push(ts.spacePart());
- }
- }
- function addInPrefix() {
- displayParts.push(ts.spacePart());
- displayParts.push(ts.keywordPart(92 /* InKeyword */));
- displayParts.push(ts.spacePart());
- }
- function addFullSymbolName(symbolToDisplay, enclosingDeclaration) {
- if (alias && symbolToDisplay === symbol) {
- symbolToDisplay = alias;
- }
- var fullSymbolDisplayParts = ts.symbolToDisplayParts(typeChecker, symbolToDisplay, enclosingDeclaration || sourceFile, /*meaning*/ undefined, 1 /* WriteTypeParametersOrArguments */ | 2 /* UseOnlyExternalAliasing */ | 4 /* AllowAnyNodeKind */);
- ts.addRange(displayParts, fullSymbolDisplayParts);
- }
- function addPrefixForAnyFunctionOrVar(symbol, symbolKind) {
- prefixNextMeaning();
- if (symbolKind) {
- pushTypePart(symbolKind);
- if (symbol && !ts.some(symbol.declarations, function (d) { return ts.isArrowFunction(d) || (ts.isFunctionExpression(d) || ts.isClassExpression(d)) && !d.name; })) {
- displayParts.push(ts.spacePart());
- addFullSymbolName(symbol);
- }
- }
- }
- function pushTypePart(symbolKind) {
- switch (symbolKind) {
- case "var" /* variableElement */:
- case "function" /* functionElement */:
- case "let" /* letElement */:
- case "const" /* constElement */:
- case "constructor" /* constructorImplementationElement */:
- displayParts.push(ts.textOrKeywordPart(symbolKind));
- return;
- default:
- displayParts.push(ts.punctuationPart(19 /* OpenParenToken */));
- displayParts.push(ts.textOrKeywordPart(symbolKind));
- displayParts.push(ts.punctuationPart(20 /* CloseParenToken */));
- return;
- }
- }
- function addSignatureDisplayParts(signature, allSignatures, flags) {
- ts.addRange(displayParts, ts.signatureToDisplayParts(typeChecker, signature, enclosingDeclaration, flags | 32 /* WriteTypeArgumentsOfSignature */));
- if (allSignatures.length > 1) {
- displayParts.push(ts.spacePart());
- displayParts.push(ts.punctuationPart(19 /* OpenParenToken */));
- displayParts.push(ts.operatorPart(37 /* PlusToken */));
- displayParts.push(ts.displayPart((allSignatures.length - 1).toString(), ts.SymbolDisplayPartKind.numericLiteral));
- displayParts.push(ts.spacePart());
- displayParts.push(ts.textPart(allSignatures.length === 2 ? "overload" : "overloads"));
- displayParts.push(ts.punctuationPart(20 /* CloseParenToken */));
- }
- documentation = signature.getDocumentationComment(typeChecker);
- tags = signature.getJsDocTags();
- }
- function writeTypeParametersOfSymbol(symbol, enclosingDeclaration) {
- var typeParameterParts = ts.mapToDisplayParts(function (writer) {
- var params = typeChecker.symbolToTypeParameterDeclarations(symbol, enclosingDeclaration);
- getPrinter().writeList(26896 /* TypeParameters */, params, ts.getSourceFileOfNode(ts.getParseTreeNode(enclosingDeclaration)), writer);
- });
- ts.addRange(displayParts, typeParameterParts);
- }
- }
- SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind = getSymbolDisplayPartsDocumentationAndSymbolKind;
- function isLocalVariableOrFunction(symbol) {
- if (symbol.parent) {
- return false; // This is exported symbol
- }
- return ts.forEach(symbol.declarations, function (declaration) {
- // Function expressions are local
- if (declaration.kind === 190 /* FunctionExpression */) {
- return true;
- }
- if (declaration.kind !== 230 /* VariableDeclaration */ && declaration.kind !== 232 /* FunctionDeclaration */) {
- return false;
- }
- // If the parent is not sourceFile or module block it is local variable
- for (var parent = declaration.parent; !ts.isFunctionBlock(parent); parent = parent.parent) {
- // Reached source file or module block
- if (parent.kind === 272 /* SourceFile */ || parent.kind === 238 /* ModuleBlock */) {
- return false;
- }
- }
- // parent is in function block
- return true;
- });
- }
- })(SymbolDisplay = ts.SymbolDisplay || (ts.SymbolDisplay = {}));
-})(ts || (ts = {}));
-var ts;
-(function (ts) {
- /*
- * This function will compile source text from 'input' argument using specified compiler options.
- * If not options are provided - it will use a set of default compiler options.
- * Extra compiler options that will unconditionally be used by this function are:
- * - isolatedModules = true
- * - allowNonTsExtensions = true
- * - noLib = true
- * - noResolve = true
- */
- function transpileModule(input, transpileOptions) {
- var diagnostics = [];
- var options = transpileOptions.compilerOptions ? fixupCompilerOptions(transpileOptions.compilerOptions, diagnostics) : ts.getDefaultCompilerOptions();
- options.isolatedModules = true;
- // transpileModule does not write anything to disk so there is no need to verify that there are no conflicts between input and output paths.
- options.suppressOutputPathCheck = true;
- // Filename can be non-ts file.
- options.allowNonTsExtensions = true;
- // We are not returning a sourceFile for lib file when asked by the program,
- // so pass --noLib to avoid reporting a file not found error.
- options.noLib = true;
- // Clear out other settings that would not be used in transpiling this module
- options.lib = undefined;
- options.types = undefined;
- options.noEmit = undefined;
- options.noEmitOnError = undefined;
- options.paths = undefined;
- options.rootDirs = undefined;
- options.declaration = undefined;
- options.declarationDir = undefined;
- options.out = undefined;
- options.outFile = undefined;
- // We are not doing a full typecheck, we are not resolving the whole context,
- // so pass --noResolve to avoid reporting missing file errors.
- options.noResolve = true;
- // if jsx is specified then treat file as .tsx
- var inputFileName = transpileOptions.fileName || (options.jsx ? "module.tsx" : "module.ts");
- var sourceFile = ts.createSourceFile(inputFileName, input, options.target);
- if (transpileOptions.moduleName) {
- sourceFile.moduleName = transpileOptions.moduleName;
- }
- if (transpileOptions.renamedDependencies) {
- sourceFile.renamedDependencies = ts.createMapFromTemplate(transpileOptions.renamedDependencies);
- }
- var newLine = ts.getNewLineCharacter(options);
- // Output
- var outputText;
- var sourceMapText;
- // Create a compilerHost object to allow the compiler to read and write files
- var compilerHost = {
- getSourceFile: function (fileName) { return fileName === ts.normalizePath(inputFileName) ? sourceFile : undefined; },
- writeFile: function (name, text) {
- if (ts.fileExtensionIs(name, ".map")) {
- ts.Debug.assertEqual(sourceMapText, undefined, "Unexpected multiple source map outputs, file:", name);
- sourceMapText = text;
- }
- else {
- ts.Debug.assertEqual(outputText, undefined, "Unexpected multiple outputs, file:", name);
- outputText = text;
- }
- },
- getDefaultLibFileName: function () { return "lib.d.ts"; },
- useCaseSensitiveFileNames: function () { return false; },
- getCanonicalFileName: function (fileName) { return fileName; },
- getCurrentDirectory: function () { return ""; },
- getNewLine: function () { return newLine; },
- fileExists: function (fileName) { return fileName === inputFileName; },
- readFile: function () { return ""; },
- directoryExists: function () { return true; },
- getDirectories: function () { return []; }
- };
- var program = ts.createProgram([inputFileName], options, compilerHost);
- if (transpileOptions.reportDiagnostics) {
- ts.addRange(/*to*/ diagnostics, /*from*/ program.getSyntacticDiagnostics(sourceFile));
- ts.addRange(/*to*/ diagnostics, /*from*/ program.getOptionsDiagnostics());
- }
- // Emit
- program.emit(/*targetSourceFile*/ undefined, /*writeFile*/ undefined, /*cancellationToken*/ undefined, /*emitOnlyDtsFiles*/ undefined, transpileOptions.transformers);
- ts.Debug.assert(outputText !== undefined, "Output generation failed");
- return { outputText: outputText, diagnostics: diagnostics, sourceMapText: sourceMapText };
- }
- ts.transpileModule = transpileModule;
- /*
- * This is a shortcut function for transpileModule - it accepts transpileOptions as parameters and returns only outputText part of the result.
- */
- function transpile(input, compilerOptions, fileName, diagnostics, moduleName) {
- var output = transpileModule(input, { compilerOptions: compilerOptions, fileName: fileName, reportDiagnostics: !!diagnostics, moduleName: moduleName });
- // addRange correctly handles cases when wither 'from' or 'to' argument is missing
- ts.addRange(diagnostics, output.diagnostics);
- return output.outputText;
- }
- ts.transpile = transpile;
- var commandLineOptionsStringToEnum;
- /** JS users may pass in string values for enum compiler options (such as ModuleKind), so convert. */
- /*@internal*/
- function fixupCompilerOptions(options, diagnostics) {
- // Lazily create this value to fix module loading errors.
- commandLineOptionsStringToEnum = commandLineOptionsStringToEnum || ts.filter(ts.optionDeclarations, function (o) {
- return typeof o.type === "object" && !ts.forEachEntry(o.type, function (v) { return typeof v !== "number"; });
- });
- options = ts.cloneCompilerOptions(options);
- var _loop_9 = function (opt) {
- if (!ts.hasProperty(options, opt.name)) {
- return "continue";
- }
- var value = options[opt.name];
- // Value should be a key of opt.type
- if (ts.isString(value)) {
- // If value is not a string, this will fail
- options[opt.name] = ts.parseCustomTypeOption(opt, value, diagnostics);
- }
- else {
- if (!ts.forEachEntry(opt.type, function (v) { return v === value; })) {
- // Supplied value isn't a valid enum value.
- diagnostics.push(ts.createCompilerDiagnosticForInvalidCustomType(opt));
- }
- }
- };
- for (var _i = 0, commandLineOptionsStringToEnum_1 = commandLineOptionsStringToEnum; _i < commandLineOptionsStringToEnum_1.length; _i++) {
- var opt = commandLineOptionsStringToEnum_1[_i];
- _loop_9(opt);
- }
- return options;
- }
- ts.fixupCompilerOptions = fixupCompilerOptions;
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var formatting;
- (function (formatting) {
- var FormattingRequestKind;
- (function (FormattingRequestKind) {
- FormattingRequestKind[FormattingRequestKind["FormatDocument"] = 0] = "FormatDocument";
- FormattingRequestKind[FormattingRequestKind["FormatSelection"] = 1] = "FormatSelection";
- FormattingRequestKind[FormattingRequestKind["FormatOnEnter"] = 2] = "FormatOnEnter";
- FormattingRequestKind[FormattingRequestKind["FormatOnSemicolon"] = 3] = "FormatOnSemicolon";
- FormattingRequestKind[FormattingRequestKind["FormatOnOpeningCurlyBrace"] = 4] = "FormatOnOpeningCurlyBrace";
- FormattingRequestKind[FormattingRequestKind["FormatOnClosingCurlyBrace"] = 5] = "FormatOnClosingCurlyBrace";
- })(FormattingRequestKind = formatting.FormattingRequestKind || (formatting.FormattingRequestKind = {}));
- var FormattingContext = /** @class */ (function () {
- function FormattingContext(sourceFile, formattingRequestKind, options) {
- this.sourceFile = sourceFile;
- this.formattingRequestKind = formattingRequestKind;
- this.options = options;
- }
- FormattingContext.prototype.updateContext = function (currentRange, currentTokenParent, nextRange, nextTokenParent, commonParent) {
- ts.Debug.assert(currentRange !== undefined, "currentTokenSpan is null");
- ts.Debug.assert(currentTokenParent !== undefined, "currentTokenParent is null");
- ts.Debug.assert(nextRange !== undefined, "nextTokenSpan is null");
- ts.Debug.assert(nextTokenParent !== undefined, "nextTokenParent is null");
- ts.Debug.assert(commonParent !== undefined, "commonParent is null");
- this.currentTokenSpan = currentRange;
- this.currentTokenParent = currentTokenParent;
- this.nextTokenSpan = nextRange;
- this.nextTokenParent = nextTokenParent;
- this.contextNode = commonParent;
- // drop cached results
- this.contextNodeAllOnSameLine = undefined;
- this.nextNodeAllOnSameLine = undefined;
- this.tokensAreOnSameLine = undefined;
- this.contextNodeBlockIsOnOneLine = undefined;
- this.nextNodeBlockIsOnOneLine = undefined;
- };
- FormattingContext.prototype.ContextNodeAllOnSameLine = function () {
- if (this.contextNodeAllOnSameLine === undefined) {
- this.contextNodeAllOnSameLine = this.NodeIsOnOneLine(this.contextNode);
- }
- return this.contextNodeAllOnSameLine;
- };
- FormattingContext.prototype.NextNodeAllOnSameLine = function () {
- if (this.nextNodeAllOnSameLine === undefined) {
- this.nextNodeAllOnSameLine = this.NodeIsOnOneLine(this.nextTokenParent);
- }
- return this.nextNodeAllOnSameLine;
- };
- FormattingContext.prototype.TokensAreOnSameLine = function () {
- if (this.tokensAreOnSameLine === undefined) {
- var startLine = this.sourceFile.getLineAndCharacterOfPosition(this.currentTokenSpan.pos).line;
- var endLine = this.sourceFile.getLineAndCharacterOfPosition(this.nextTokenSpan.pos).line;
- this.tokensAreOnSameLine = (startLine === endLine);
- }
- return this.tokensAreOnSameLine;
- };
- FormattingContext.prototype.ContextNodeBlockIsOnOneLine = function () {
- if (this.contextNodeBlockIsOnOneLine === undefined) {
- this.contextNodeBlockIsOnOneLine = this.BlockIsOnOneLine(this.contextNode);
- }
- return this.contextNodeBlockIsOnOneLine;
- };
- FormattingContext.prototype.NextNodeBlockIsOnOneLine = function () {
- if (this.nextNodeBlockIsOnOneLine === undefined) {
- this.nextNodeBlockIsOnOneLine = this.BlockIsOnOneLine(this.nextTokenParent);
- }
- return this.nextNodeBlockIsOnOneLine;
- };
- FormattingContext.prototype.NodeIsOnOneLine = function (node) {
- var startLine = this.sourceFile.getLineAndCharacterOfPosition(node.getStart(this.sourceFile)).line;
- var endLine = this.sourceFile.getLineAndCharacterOfPosition(node.getEnd()).line;
- return startLine === endLine;
- };
- FormattingContext.prototype.BlockIsOnOneLine = function (node) {
- var openBrace = ts.findChildOfKind(node, 17 /* OpenBraceToken */, this.sourceFile);
- var closeBrace = ts.findChildOfKind(node, 18 /* CloseBraceToken */, this.sourceFile);
- if (openBrace && closeBrace) {
- var startLine = this.sourceFile.getLineAndCharacterOfPosition(openBrace.getEnd()).line;
- var endLine = this.sourceFile.getLineAndCharacterOfPosition(closeBrace.getStart(this.sourceFile)).line;
- return startLine === endLine;
- }
- return false;
- };
- return FormattingContext;
- }());
- formatting.FormattingContext = FormattingContext;
- })(formatting = ts.formatting || (ts.formatting = {}));
-})(ts || (ts = {}));
-///
-///
-/* @internal */
-var ts;
-(function (ts) {
- var formatting;
- (function (formatting) {
- var standardScanner = ts.createScanner(6 /* Latest */, /*skipTrivia*/ false, 0 /* Standard */);
- var jsxScanner = ts.createScanner(6 /* Latest */, /*skipTrivia*/ false, 1 /* JSX */);
- var ScanAction;
- (function (ScanAction) {
- ScanAction[ScanAction["Scan"] = 0] = "Scan";
- ScanAction[ScanAction["RescanGreaterThanToken"] = 1] = "RescanGreaterThanToken";
- ScanAction[ScanAction["RescanSlashToken"] = 2] = "RescanSlashToken";
- ScanAction[ScanAction["RescanTemplateToken"] = 3] = "RescanTemplateToken";
- ScanAction[ScanAction["RescanJsxIdentifier"] = 4] = "RescanJsxIdentifier";
- ScanAction[ScanAction["RescanJsxText"] = 5] = "RescanJsxText";
- })(ScanAction || (ScanAction = {}));
- function getFormattingScanner(text, languageVariant, startPos, endPos, cb) {
- var scanner = languageVariant === 1 /* JSX */ ? jsxScanner : standardScanner;
- scanner.setText(text);
- scanner.setTextPos(startPos);
- var wasNewLine = true;
- var leadingTrivia;
- var trailingTrivia;
- var savedPos;
- var lastScanAction;
- var lastTokenInfo;
- var res = cb({
- advance: advance,
- readTokenInfo: readTokenInfo,
- isOnToken: isOnToken,
- getCurrentLeadingTrivia: function () { return leadingTrivia; },
- lastTrailingTriviaWasNewLine: function () { return wasNewLine; },
- skipToEndOf: skipToEndOf,
- });
- lastTokenInfo = undefined;
- scanner.setText(undefined);
- return res;
- function advance() {
- lastTokenInfo = undefined;
- var isStarted = scanner.getStartPos() !== startPos;
- if (isStarted) {
- wasNewLine = trailingTrivia && ts.lastOrUndefined(trailingTrivia).kind === 4 /* NewLineTrivia */;
- }
- else {
- scanner.scan();
- }
- leadingTrivia = undefined;
- trailingTrivia = undefined;
- var pos = scanner.getStartPos();
- // Read leading trivia and token
- while (pos < endPos) {
- var t = scanner.getToken();
- if (!ts.isTrivia(t)) {
- break;
- }
- // consume leading trivia
- scanner.scan();
- var item = {
- pos: pos,
- end: scanner.getStartPos(),
- kind: t
- };
- pos = scanner.getStartPos();
- leadingTrivia = ts.append(leadingTrivia, item);
- }
- savedPos = scanner.getStartPos();
- }
- function shouldRescanGreaterThanToken(node) {
- switch (node.kind) {
- case 31 /* GreaterThanEqualsToken */:
- case 66 /* GreaterThanGreaterThanEqualsToken */:
- case 67 /* GreaterThanGreaterThanGreaterThanEqualsToken */:
- case 47 /* GreaterThanGreaterThanGreaterThanToken */:
- case 46 /* GreaterThanGreaterThanToken */:
- return true;
- }
- return false;
- }
- function shouldRescanJsxIdentifier(node) {
- if (node.parent) {
- switch (node.parent.kind) {
- case 260 /* JsxAttribute */:
- case 255 /* JsxOpeningElement */:
- case 256 /* JsxClosingElement */:
- case 254 /* JsxSelfClosingElement */:
- // May parse an identifier like `module-layout`; that will be scanned as a keyword at first, but we should parse the whole thing to get an identifier.
- return ts.isKeyword(node.kind) || node.kind === 71 /* Identifier */;
- }
- }
- return false;
- }
- function shouldRescanJsxText(node) {
- return node.kind === 10 /* JsxText */;
- }
- function shouldRescanSlashToken(container) {
- return container.kind === 12 /* RegularExpressionLiteral */;
- }
- function shouldRescanTemplateToken(container) {
- return container.kind === 15 /* TemplateMiddle */ ||
- container.kind === 16 /* TemplateTail */;
- }
- function startsWithSlashToken(t) {
- return t === 41 /* SlashToken */ || t === 63 /* SlashEqualsToken */;
- }
- function readTokenInfo(n) {
- ts.Debug.assert(isOnToken());
- // normally scanner returns the smallest available token
- // check the kind of context node to determine if scanner should have more greedy behavior and consume more text.
- var expectedScanAction = shouldRescanGreaterThanToken(n)
- ? 1 /* RescanGreaterThanToken */
- : shouldRescanSlashToken(n)
- ? 2 /* RescanSlashToken */
- : shouldRescanTemplateToken(n)
- ? 3 /* RescanTemplateToken */
- : shouldRescanJsxIdentifier(n)
- ? 4 /* RescanJsxIdentifier */
- : shouldRescanJsxText(n)
- ? 5 /* RescanJsxText */
- : 0 /* Scan */;
- if (lastTokenInfo && expectedScanAction === lastScanAction) {
- // readTokenInfo was called before with the same expected scan action.
- // No need to re-scan text, return existing 'lastTokenInfo'
- // it is ok to call fixTokenKind here since it does not affect
- // what portion of text is consumed. In contrast rescanning can change it,
- // i.e. for '>=' when originally scanner eats just one character
- // and rescanning forces it to consume more.
- return fixTokenKind(lastTokenInfo, n);
- }
- if (scanner.getStartPos() !== savedPos) {
- ts.Debug.assert(lastTokenInfo !== undefined);
- // readTokenInfo was called before but scan action differs - rescan text
- scanner.setTextPos(savedPos);
- scanner.scan();
- }
- var currentToken = getNextToken(n, expectedScanAction);
- var token = {
- pos: scanner.getStartPos(),
- end: scanner.getTextPos(),
- kind: currentToken
- };
- // consume trailing trivia
- if (trailingTrivia) {
- trailingTrivia = undefined;
- }
- while (scanner.getStartPos() < endPos) {
- currentToken = scanner.scan();
- if (!ts.isTrivia(currentToken)) {
- break;
- }
- var trivia = {
- pos: scanner.getStartPos(),
- end: scanner.getTextPos(),
- kind: currentToken
- };
- if (!trailingTrivia) {
- trailingTrivia = [];
- }
- trailingTrivia.push(trivia);
- if (currentToken === 4 /* NewLineTrivia */) {
- // move past new line
- scanner.scan();
- break;
- }
- }
- lastTokenInfo = { leadingTrivia: leadingTrivia, trailingTrivia: trailingTrivia, token: token };
- return fixTokenKind(lastTokenInfo, n);
- }
- function getNextToken(n, expectedScanAction) {
- var token = scanner.getToken();
- lastScanAction = 0 /* Scan */;
- switch (expectedScanAction) {
- case 1 /* RescanGreaterThanToken */:
- if (token === 29 /* GreaterThanToken */) {
- lastScanAction = 1 /* RescanGreaterThanToken */;
- var newToken = scanner.reScanGreaterToken();
- ts.Debug.assert(n.kind === newToken);
- return newToken;
- }
- break;
- case 2 /* RescanSlashToken */:
- if (startsWithSlashToken(token)) {
- lastScanAction = 2 /* RescanSlashToken */;
- var newToken = scanner.reScanSlashToken();
- ts.Debug.assert(n.kind === newToken);
- return newToken;
- }
- break;
- case 3 /* RescanTemplateToken */:
- if (token === 18 /* CloseBraceToken */) {
- lastScanAction = 3 /* RescanTemplateToken */;
- return scanner.reScanTemplateToken();
- }
- break;
- case 4 /* RescanJsxIdentifier */:
- lastScanAction = 4 /* RescanJsxIdentifier */;
- return scanner.scanJsxIdentifier();
- case 5 /* RescanJsxText */:
- lastScanAction = 5 /* RescanJsxText */;
- return scanner.reScanJsxToken();
- case 0 /* Scan */:
- break;
- default:
- ts.Debug.assertNever(expectedScanAction);
- }
- return token;
- }
- function isOnToken() {
- var current = lastTokenInfo ? lastTokenInfo.token.kind : scanner.getToken();
- var startPos = lastTokenInfo ? lastTokenInfo.token.pos : scanner.getStartPos();
- return startPos < endPos && current !== 1 /* EndOfFileToken */ && !ts.isTrivia(current);
- }
- // when containing node in the tree is token
- // but its kind differs from the kind that was returned by the scanner,
- // then kind needs to be fixed. This might happen in cases
- // when parser interprets token differently, i.e keyword treated as identifier
- function fixTokenKind(tokenInfo, container) {
- if (ts.isToken(container) && tokenInfo.token.kind !== container.kind) {
- tokenInfo.token.kind = container.kind;
- }
- return tokenInfo;
- }
- function skipToEndOf(node) {
- scanner.setTextPos(node.end);
- savedPos = scanner.getStartPos();
- lastScanAction = undefined;
- lastTokenInfo = undefined;
- wasNewLine = false;
- leadingTrivia = undefined;
- trailingTrivia = undefined;
- }
- }
- formatting.getFormattingScanner = getFormattingScanner;
- })(formatting = ts.formatting || (ts.formatting = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var formatting;
- (function (formatting) {
- formatting.anyContext = ts.emptyArray;
- var RuleAction;
- (function (RuleAction) {
- RuleAction[RuleAction["Ignore"] = 1] = "Ignore";
- RuleAction[RuleAction["Space"] = 2] = "Space";
- RuleAction[RuleAction["NewLine"] = 4] = "NewLine";
- RuleAction[RuleAction["Delete"] = 8] = "Delete";
- })(RuleAction = formatting.RuleAction || (formatting.RuleAction = {}));
- var RuleFlags;
- (function (RuleFlags) {
- RuleFlags[RuleFlags["None"] = 0] = "None";
- RuleFlags[RuleFlags["CanDeleteNewLines"] = 1] = "CanDeleteNewLines";
- })(RuleFlags = formatting.RuleFlags || (formatting.RuleFlags = {}));
- })(formatting = ts.formatting || (ts.formatting = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var formatting;
- (function (formatting) {
- function getAllRules() {
- var allTokens = [];
- for (var token = 0 /* FirstToken */; token <= 144 /* LastToken */; token++) {
- allTokens.push(token);
- }
- function anyTokenExcept() {
- var tokens = [];
- for (var _i = 0; _i < arguments.length; _i++) {
- tokens[_i] = arguments[_i];
- }
- return { tokens: allTokens.filter(function (t) { return !tokens.some(function (t2) { return t2 === t; }); }), isSpecific: false };
- }
- var anyToken = { tokens: allTokens, isSpecific: false };
- var anyTokenIncludingMultilineComments = tokenRangeFrom(allTokens.concat([3 /* MultiLineCommentTrivia */]));
- var keywords = tokenRangeFromRange(72 /* FirstKeyword */, 144 /* LastKeyword */);
- var binaryOperators = tokenRangeFromRange(27 /* FirstBinaryOperator */, 70 /* LastBinaryOperator */);
- var binaryKeywordOperators = [92 /* InKeyword */, 93 /* InstanceOfKeyword */, 144 /* OfKeyword */, 118 /* AsKeyword */, 127 /* IsKeyword */];
- var unaryPrefixOperators = [43 /* PlusPlusToken */, 44 /* MinusMinusToken */, 52 /* TildeToken */, 51 /* ExclamationToken */];
- var unaryPrefixExpressions = [
- 8 /* NumericLiteral */, 71 /* Identifier */, 19 /* OpenParenToken */, 21 /* OpenBracketToken */,
- 17 /* OpenBraceToken */, 99 /* ThisKeyword */, 94 /* NewKeyword */
- ];
- var unaryPreincrementExpressions = [71 /* Identifier */, 19 /* OpenParenToken */, 99 /* ThisKeyword */, 94 /* NewKeyword */];
- var unaryPostincrementExpressions = [71 /* Identifier */, 20 /* CloseParenToken */, 22 /* CloseBracketToken */, 94 /* NewKeyword */];
- var unaryPredecrementExpressions = [71 /* Identifier */, 19 /* OpenParenToken */, 99 /* ThisKeyword */, 94 /* NewKeyword */];
- var unaryPostdecrementExpressions = [71 /* Identifier */, 20 /* CloseParenToken */, 22 /* CloseBracketToken */, 94 /* NewKeyword */];
- var comments = [2 /* SingleLineCommentTrivia */, 3 /* MultiLineCommentTrivia */];
- var typeNames = [71 /* Identifier */].concat(ts.typeKeywords);
- // Place a space before open brace in a function declaration
- // TypeScript: Function can have return types, which can be made of tons of different token kinds
- var functionOpenBraceLeftTokenRange = anyTokenIncludingMultilineComments;
- // Place a space before open brace in a TypeScript declaration that has braces as children (class, module, enum, etc)
- var typeScriptOpenBraceLeftTokenRange = tokenRangeFrom([71 /* Identifier */, 3 /* MultiLineCommentTrivia */, 75 /* ClassKeyword */, 84 /* ExportKeyword */, 91 /* ImportKeyword */]);
- // Place a space before open brace in a control flow construct
- var controlOpenBraceLeftTokenRange = tokenRangeFrom([20 /* CloseParenToken */, 3 /* MultiLineCommentTrivia */, 81 /* DoKeyword */, 102 /* TryKeyword */, 87 /* FinallyKeyword */, 82 /* ElseKeyword */]);
- // These rules are higher in priority than user-configurable
- var highPriorityCommonRules = [
- // Leave comments alone
- rule("IgnoreBeforeComment", anyToken, comments, formatting.anyContext, 1 /* Ignore */),
- rule("IgnoreAfterLineComment", 2 /* SingleLineCommentTrivia */, anyToken, formatting.anyContext, 1 /* Ignore */),
- rule("NotSpaceBeforeColon", anyToken, 56 /* ColonToken */, [isNonJsxSameLineTokenContext, isNotBinaryOpContext, isNotTypeAnnotationContext], 8 /* Delete */),
- rule("SpaceAfterColon", 56 /* ColonToken */, anyToken, [isNonJsxSameLineTokenContext, isNotBinaryOpContext], 2 /* Space */),
- rule("NoSpaceBeforeQuestionMark", anyToken, 55 /* QuestionToken */, [isNonJsxSameLineTokenContext, isNotBinaryOpContext], 8 /* Delete */),
- // insert space after '?' only when it is used in conditional operator
- rule("SpaceAfterQuestionMarkInConditionalOperator", 55 /* QuestionToken */, anyToken, [isNonJsxSameLineTokenContext, isConditionalOperatorContext], 2 /* Space */),
- // in other cases there should be no space between '?' and next token
- rule("NoSpaceAfterQuestionMark", 55 /* QuestionToken */, anyToken, [isNonJsxSameLineTokenContext], 8 /* Delete */),
- rule("NoSpaceBeforeDot", anyToken, 23 /* DotToken */, [isNonJsxSameLineTokenContext], 8 /* Delete */),
- rule("NoSpaceAfterDot", 23 /* DotToken */, anyToken, [isNonJsxSameLineTokenContext], 8 /* Delete */),
- // Special handling of unary operators.
- // Prefix operators generally shouldn't have a space between
- // them and their target unary expression.
- rule("NoSpaceAfterUnaryPrefixOperator", unaryPrefixOperators, unaryPrefixExpressions, [isNonJsxSameLineTokenContext, isNotBinaryOpContext], 8 /* Delete */),
- rule("NoSpaceAfterUnaryPreincrementOperator", 43 /* PlusPlusToken */, unaryPreincrementExpressions, [isNonJsxSameLineTokenContext], 8 /* Delete */),
- rule("NoSpaceAfterUnaryPredecrementOperator", 44 /* MinusMinusToken */, unaryPredecrementExpressions, [isNonJsxSameLineTokenContext], 8 /* Delete */),
- rule("NoSpaceBeforeUnaryPostincrementOperator", unaryPostincrementExpressions, 43 /* PlusPlusToken */, [isNonJsxSameLineTokenContext], 8 /* Delete */),
- rule("NoSpaceBeforeUnaryPostdecrementOperator", unaryPostdecrementExpressions, 44 /* MinusMinusToken */, [isNonJsxSameLineTokenContext], 8 /* Delete */),
- // More unary operator special-casing.
- // DevDiv 181814: Be careful when removing leading whitespace
- // around unary operators. Examples:
- // 1 - -2 --X--> 1--2
- // a + ++b --X--> a+++b
- rule("SpaceAfterPostincrementWhenFollowedByAdd", 43 /* PlusPlusToken */, 37 /* PlusToken */, [isNonJsxSameLineTokenContext, isBinaryOpContext], 2 /* Space */),
- rule("SpaceAfterAddWhenFollowedByUnaryPlus", 37 /* PlusToken */, 37 /* PlusToken */, [isNonJsxSameLineTokenContext, isBinaryOpContext], 2 /* Space */),
- rule("SpaceAfterAddWhenFollowedByPreincrement", 37 /* PlusToken */, 43 /* PlusPlusToken */, [isNonJsxSameLineTokenContext, isBinaryOpContext], 2 /* Space */),
- rule("SpaceAfterPostdecrementWhenFollowedBySubtract", 44 /* MinusMinusToken */, 38 /* MinusToken */, [isNonJsxSameLineTokenContext, isBinaryOpContext], 2 /* Space */),
- rule("SpaceAfterSubtractWhenFollowedByUnaryMinus", 38 /* MinusToken */, 38 /* MinusToken */, [isNonJsxSameLineTokenContext, isBinaryOpContext], 2 /* Space */),
- rule("SpaceAfterSubtractWhenFollowedByPredecrement", 38 /* MinusToken */, 44 /* MinusMinusToken */, [isNonJsxSameLineTokenContext, isBinaryOpContext], 2 /* Space */),
- rule("NoSpaceAfterCloseBrace", 18 /* CloseBraceToken */, [26 /* CommaToken */, 25 /* SemicolonToken */], [isNonJsxSameLineTokenContext], 8 /* Delete */),
- // For functions and control block place } on a new line [multi-line rule]
- rule("NewLineBeforeCloseBraceInBlockContext", anyTokenIncludingMultilineComments, 18 /* CloseBraceToken */, [isMultilineBlockContext], 4 /* NewLine */),
- // Space/new line after }.
- rule("SpaceAfterCloseBrace", 18 /* CloseBraceToken */, anyTokenExcept(20 /* CloseParenToken */), [isNonJsxSameLineTokenContext, isAfterCodeBlockContext], 2 /* Space */),
- // Special case for (}, else) and (}, while) since else & while tokens are not part of the tree which makes SpaceAfterCloseBrace rule not applied
- // Also should not apply to })
- rule("SpaceBetweenCloseBraceAndElse", 18 /* CloseBraceToken */, 82 /* ElseKeyword */, [isNonJsxSameLineTokenContext], 2 /* Space */),
- rule("SpaceBetweenCloseBraceAndWhile", 18 /* CloseBraceToken */, 106 /* WhileKeyword */, [isNonJsxSameLineTokenContext], 2 /* Space */),
- rule("NoSpaceBetweenEmptyBraceBrackets", 17 /* OpenBraceToken */, 18 /* CloseBraceToken */, [isNonJsxSameLineTokenContext, isObjectContext], 8 /* Delete */),
- // Add a space after control dec context if the next character is an open bracket ex: 'if (false)[a, b] = [1, 2];' -> 'if (false) [a, b] = [1, 2];'
- rule("SpaceAfterConditionalClosingParen", 20 /* CloseParenToken */, 21 /* OpenBracketToken */, [isControlDeclContext], 2 /* Space */),
- rule("NoSpaceBetweenFunctionKeywordAndStar", 89 /* FunctionKeyword */, 39 /* AsteriskToken */, [isFunctionDeclarationOrFunctionExpressionContext], 8 /* Delete */),
- rule("SpaceAfterStarInGeneratorDeclaration", 39 /* AsteriskToken */, [71 /* Identifier */, 19 /* OpenParenToken */], [isFunctionDeclarationOrFunctionExpressionContext], 2 /* Space */),
- rule("SpaceAfterFunctionInFuncDecl", 89 /* FunctionKeyword */, anyToken, [isFunctionDeclContext], 2 /* Space */),
- // Insert new line after { and before } in multi-line contexts.
- rule("NewLineAfterOpenBraceInBlockContext", 17 /* OpenBraceToken */, anyToken, [isMultilineBlockContext], 4 /* NewLine */),
- // For get/set members, we check for (identifier,identifier) since get/set don't have tokens and they are represented as just an identifier token.
- // Though, we do extra check on the context to make sure we are dealing with get/set node. Example:
- // get x() {}
- // set x(val) {}
- rule("SpaceAfterGetSetInMember", [125 /* GetKeyword */, 136 /* SetKeyword */], 71 /* Identifier */, [isFunctionDeclContext], 2 /* Space */),
- rule("NoSpaceBetweenYieldKeywordAndStar", 116 /* YieldKeyword */, 39 /* AsteriskToken */, [isNonJsxSameLineTokenContext, isYieldOrYieldStarWithOperand], 8 /* Delete */),
- rule("SpaceBetweenYieldOrYieldStarAndOperand", [116 /* YieldKeyword */, 39 /* AsteriskToken */], anyToken, [isNonJsxSameLineTokenContext, isYieldOrYieldStarWithOperand], 2 /* Space */),
- rule("NoSpaceBetweenReturnAndSemicolon", 96 /* ReturnKeyword */, 25 /* SemicolonToken */, [isNonJsxSameLineTokenContext], 8 /* Delete */),
- rule("SpaceAfterCertainKeywords", [104 /* VarKeyword */, 100 /* ThrowKeyword */, 94 /* NewKeyword */, 80 /* DeleteKeyword */, 96 /* ReturnKeyword */, 103 /* TypeOfKeyword */, 121 /* AwaitKeyword */], anyToken, [isNonJsxSameLineTokenContext], 2 /* Space */),
- rule("SpaceAfterLetConstInVariableDeclaration", [110 /* LetKeyword */, 76 /* ConstKeyword */], anyToken, [isNonJsxSameLineTokenContext, isStartOfVariableDeclarationList], 2 /* Space */),
- rule("NoSpaceBeforeOpenParenInFuncCall", anyToken, 19 /* OpenParenToken */, [isNonJsxSameLineTokenContext, isFunctionCallOrNewContext, isPreviousTokenNotComma], 8 /* Delete */),
- // Special case for binary operators (that are keywords). For these we have to add a space and shouldn't follow any user options.
- rule("SpaceBeforeBinaryKeywordOperator", anyToken, binaryKeywordOperators, [isNonJsxSameLineTokenContext, isBinaryOpContext], 2 /* Space */),
- rule("SpaceAfterBinaryKeywordOperator", binaryKeywordOperators, anyToken, [isNonJsxSameLineTokenContext, isBinaryOpContext], 2 /* Space */),
- rule("SpaceAfterVoidOperator", 105 /* VoidKeyword */, anyToken, [isNonJsxSameLineTokenContext, isVoidOpContext], 2 /* Space */),
- // Async-await
- rule("SpaceBetweenAsyncAndOpenParen", 120 /* AsyncKeyword */, 19 /* OpenParenToken */, [isArrowFunctionContext, isNonJsxSameLineTokenContext], 2 /* Space */),
- rule("SpaceBetweenAsyncAndFunctionKeyword", 120 /* AsyncKeyword */, 89 /* FunctionKeyword */, [isNonJsxSameLineTokenContext], 2 /* Space */),
- // template string
- rule("NoSpaceBetweenTagAndTemplateString", 71 /* Identifier */, [13 /* NoSubstitutionTemplateLiteral */, 14 /* TemplateHead */], [isNonJsxSameLineTokenContext], 8 /* Delete */),
- // JSX opening elements
- rule("SpaceBeforeJsxAttribute", anyToken, 71 /* Identifier */, [isNextTokenParentJsxAttribute, isNonJsxSameLineTokenContext], 2 /* Space */),
- rule("SpaceBeforeSlashInJsxOpeningElement", anyToken, 41 /* SlashToken */, [isJsxSelfClosingElementContext, isNonJsxSameLineTokenContext], 2 /* Space */),
- rule("NoSpaceBeforeGreaterThanTokenInJsxOpeningElement", 41 /* SlashToken */, 29 /* GreaterThanToken */, [isJsxSelfClosingElementContext, isNonJsxSameLineTokenContext], 8 /* Delete */),
- rule("NoSpaceBeforeEqualInJsxAttribute", anyToken, 58 /* EqualsToken */, [isJsxAttributeContext, isNonJsxSameLineTokenContext], 8 /* Delete */),
- rule("NoSpaceAfterEqualInJsxAttribute", 58 /* EqualsToken */, anyToken, [isJsxAttributeContext, isNonJsxSameLineTokenContext], 8 /* Delete */),
- // TypeScript-specific rules
- // Use of module as a function call. e.g.: import m2 = module("m2");
- rule("NoSpaceAfterModuleImport", [129 /* ModuleKeyword */, 133 /* RequireKeyword */], 19 /* OpenParenToken */, [isNonJsxSameLineTokenContext], 8 /* Delete */),
- // Add a space around certain TypeScript keywords
- rule("SpaceAfterCertainTypeScriptKeywords", [
- 117 /* AbstractKeyword */,
- 75 /* ClassKeyword */,
- 124 /* DeclareKeyword */,
- 79 /* DefaultKeyword */,
- 83 /* EnumKeyword */,
- 84 /* ExportKeyword */,
- 85 /* ExtendsKeyword */,
- 125 /* GetKeyword */,
- 108 /* ImplementsKeyword */,
- 91 /* ImportKeyword */,
- 109 /* InterfaceKeyword */,
- 129 /* ModuleKeyword */,
- 130 /* NamespaceKeyword */,
- 112 /* PrivateKeyword */,
- 114 /* PublicKeyword */,
- 113 /* ProtectedKeyword */,
- 132 /* ReadonlyKeyword */,
- 136 /* SetKeyword */,
- 115 /* StaticKeyword */,
- 139 /* TypeKeyword */,
- 142 /* FromKeyword */,
- 128 /* KeyOfKeyword */,
- 126 /* InferKeyword */,
- ], anyToken, [isNonJsxSameLineTokenContext], 2 /* Space */),
- rule("SpaceBeforeCertainTypeScriptKeywords", anyToken, [85 /* ExtendsKeyword */, 108 /* ImplementsKeyword */, 142 /* FromKeyword */], [isNonJsxSameLineTokenContext], 2 /* Space */),
- // Treat string literals in module names as identifiers, and add a space between the literal and the opening Brace braces, e.g.: module "m2" {
- rule("SpaceAfterModuleName", 9 /* StringLiteral */, 17 /* OpenBraceToken */, [isModuleDeclContext], 2 /* Space */),
- // Lambda expressions
- rule("SpaceBeforeArrow", anyToken, 36 /* EqualsGreaterThanToken */, [isNonJsxSameLineTokenContext], 2 /* Space */),
- rule("SpaceAfterArrow", 36 /* EqualsGreaterThanToken */, anyToken, [isNonJsxSameLineTokenContext], 2 /* Space */),
- // Optional parameters and let args
- rule("NoSpaceAfterEllipsis", 24 /* DotDotDotToken */, 71 /* Identifier */, [isNonJsxSameLineTokenContext], 8 /* Delete */),
- rule("NoSpaceAfterOptionalParameters", 55 /* QuestionToken */, [20 /* CloseParenToken */, 26 /* CommaToken */], [isNonJsxSameLineTokenContext, isNotBinaryOpContext], 8 /* Delete */),
- // Remove spaces in empty interface literals. e.g.: x: {}
- rule("NoSpaceBetweenEmptyInterfaceBraceBrackets", 17 /* OpenBraceToken */, 18 /* CloseBraceToken */, [isNonJsxSameLineTokenContext, isObjectTypeContext], 8 /* Delete */),
- // generics and type assertions
- rule("NoSpaceBeforeOpenAngularBracket", typeNames, 27 /* LessThanToken */, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], 8 /* Delete */),
- rule("NoSpaceBetweenCloseParenAndAngularBracket", 20 /* CloseParenToken */, 27 /* LessThanToken */, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], 8 /* Delete */),
- rule("NoSpaceAfterOpenAngularBracket", 27 /* LessThanToken */, anyToken, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], 8 /* Delete */),
- rule("NoSpaceBeforeCloseAngularBracket", anyToken, 29 /* GreaterThanToken */, [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], 8 /* Delete */),
- rule("NoSpaceAfterCloseAngularBracket", 29 /* GreaterThanToken */, [19 /* OpenParenToken */, 21 /* OpenBracketToken */, 29 /* GreaterThanToken */, 26 /* CommaToken */], [isNonJsxSameLineTokenContext, isTypeArgumentOrParameterOrAssertionContext], 8 /* Delete */),
- // decorators
- rule("SpaceBeforeAt", [20 /* CloseParenToken */, 71 /* Identifier */], 57 /* AtToken */, [isNonJsxSameLineTokenContext], 2 /* Space */),
- rule("NoSpaceAfterAt", 57 /* AtToken */, anyToken, [isNonJsxSameLineTokenContext], 8 /* Delete */),
- // Insert space after @ in decorator
- rule("SpaceAfterDecorator", anyToken, [
- 117 /* AbstractKeyword */,
- 71 /* Identifier */,
- 84 /* ExportKeyword */,
- 79 /* DefaultKeyword */,
- 75 /* ClassKeyword */,
- 115 /* StaticKeyword */,
- 114 /* PublicKeyword */,
- 112 /* PrivateKeyword */,
- 113 /* ProtectedKeyword */,
- 125 /* GetKeyword */,
- 136 /* SetKeyword */,
- 21 /* OpenBracketToken */,
- 39 /* AsteriskToken */,
- ], [isEndOfDecoratorContextOnSameLine], 2 /* Space */),
- rule("NoSpaceBeforeNonNullAssertionOperator", anyToken, 51 /* ExclamationToken */, [isNonJsxSameLineTokenContext, isNonNullAssertionContext], 8 /* Delete */),
- rule("NoSpaceAfterNewKeywordOnConstructorSignature", 94 /* NewKeyword */, 19 /* OpenParenToken */, [isNonJsxSameLineTokenContext, isConstructorSignatureContext], 8 /* Delete */),
- ];
- // These rules are applied after high priority
- var userConfigurableRules = [
- // Treat constructor as an identifier in a function declaration, and remove spaces between constructor and following left parentheses
- rule("SpaceAfterConstructor", 123 /* ConstructorKeyword */, 19 /* OpenParenToken */, [isOptionEnabled("insertSpaceAfterConstructor"), isNonJsxSameLineTokenContext], 2 /* Space */),
- rule("NoSpaceAfterConstructor", 123 /* ConstructorKeyword */, 19 /* OpenParenToken */, [isOptionDisabledOrUndefined("insertSpaceAfterConstructor"), isNonJsxSameLineTokenContext], 8 /* Delete */),
- rule("SpaceAfterComma", 26 /* CommaToken */, anyToken, [isOptionEnabled("insertSpaceAfterCommaDelimiter"), isNonJsxSameLineTokenContext, isNonJsxElementOrFragmentContext, isNextTokenNotCloseBracket], 2 /* Space */),
- rule("NoSpaceAfterComma", 26 /* CommaToken */, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterCommaDelimiter"), isNonJsxSameLineTokenContext, isNonJsxElementOrFragmentContext], 8 /* Delete */),
- // Insert space after function keyword for anonymous functions
- rule("SpaceAfterAnonymousFunctionKeyword", 89 /* FunctionKeyword */, 19 /* OpenParenToken */, [isOptionEnabled("insertSpaceAfterFunctionKeywordForAnonymousFunctions"), isFunctionDeclContext], 2 /* Space */),
- rule("NoSpaceAfterAnonymousFunctionKeyword", 89 /* FunctionKeyword */, 19 /* OpenParenToken */, [isOptionDisabledOrUndefined("insertSpaceAfterFunctionKeywordForAnonymousFunctions"), isFunctionDeclContext], 8 /* Delete */),
- // Insert space after keywords in control flow statements
- rule("SpaceAfterKeywordInControl", keywords, 19 /* OpenParenToken */, [isOptionEnabled("insertSpaceAfterKeywordsInControlFlowStatements"), isControlDeclContext], 2 /* Space */),
- rule("NoSpaceAfterKeywordInControl", keywords, 19 /* OpenParenToken */, [isOptionDisabledOrUndefined("insertSpaceAfterKeywordsInControlFlowStatements"), isControlDeclContext], 8 /* Delete */),
- // Insert space after opening and before closing nonempty parenthesis
- rule("SpaceAfterOpenParen", 19 /* OpenParenToken */, anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], 2 /* Space */),
- rule("SpaceBeforeCloseParen", anyToken, 20 /* CloseParenToken */, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], 2 /* Space */),
- rule("SpaceBetweenOpenParens", 19 /* OpenParenToken */, 19 /* OpenParenToken */, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], 2 /* Space */),
- rule("NoSpaceBetweenParens", 19 /* OpenParenToken */, 20 /* CloseParenToken */, [isNonJsxSameLineTokenContext], 8 /* Delete */),
- rule("NoSpaceAfterOpenParen", 19 /* OpenParenToken */, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], 8 /* Delete */),
- rule("NoSpaceBeforeCloseParen", anyToken, 20 /* CloseParenToken */, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis"), isNonJsxSameLineTokenContext], 8 /* Delete */),
- // Insert space after opening and before closing nonempty brackets
- rule("SpaceAfterOpenBracket", 21 /* OpenBracketToken */, anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], 2 /* Space */),
- rule("SpaceBeforeCloseBracket", anyToken, 22 /* CloseBracketToken */, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], 2 /* Space */),
- rule("NoSpaceBetweenBrackets", 21 /* OpenBracketToken */, 22 /* CloseBracketToken */, [isNonJsxSameLineTokenContext], 8 /* Delete */),
- rule("NoSpaceAfterOpenBracket", 21 /* OpenBracketToken */, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], 8 /* Delete */),
- rule("NoSpaceBeforeCloseBracket", anyToken, 22 /* CloseBracketToken */, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets"), isNonJsxSameLineTokenContext], 8 /* Delete */),
- // Insert a space after { and before } in single-line contexts, but remove space from empty object literals {}.
- rule("SpaceAfterOpenBrace", 17 /* OpenBraceToken */, anyToken, [isOptionEnabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isBraceWrappedContext], 2 /* Space */),
- rule("SpaceBeforeCloseBrace", anyToken, 18 /* CloseBraceToken */, [isOptionEnabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isBraceWrappedContext], 2 /* Space */),
- rule("NoSpaceBetweenEmptyBraceBrackets", 17 /* OpenBraceToken */, 18 /* CloseBraceToken */, [isNonJsxSameLineTokenContext, isObjectContext], 8 /* Delete */),
- rule("NoSpaceAfterOpenBrace", 17 /* OpenBraceToken */, anyToken, [isOptionDisabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isNonJsxSameLineTokenContext], 8 /* Delete */),
- rule("NoSpaceBeforeCloseBrace", anyToken, 18 /* CloseBraceToken */, [isOptionDisabled("insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces"), isNonJsxSameLineTokenContext], 8 /* Delete */),
- // Insert space after opening and before closing template string braces
- rule("SpaceAfterTemplateHeadAndMiddle", [14 /* TemplateHead */, 15 /* TemplateMiddle */], anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], 2 /* Space */),
- rule("SpaceBeforeTemplateMiddleAndTail", anyToken, [15 /* TemplateMiddle */, 16 /* TemplateTail */], [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], 2 /* Space */),
- rule("NoSpaceAfterTemplateHeadAndMiddle", [14 /* TemplateHead */, 15 /* TemplateMiddle */], anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], 8 /* Delete */),
- rule("NoSpaceBeforeTemplateMiddleAndTail", anyToken, [15 /* TemplateMiddle */, 16 /* TemplateTail */], [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces"), isNonJsxSameLineTokenContext], 8 /* Delete */),
- // No space after { and before } in JSX expression
- rule("SpaceAfterOpenBraceInJsxExpression", 17 /* OpenBraceToken */, anyToken, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], 2 /* Space */),
- rule("SpaceBeforeCloseBraceInJsxExpression", anyToken, 18 /* CloseBraceToken */, [isOptionEnabled("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], 2 /* Space */),
- rule("NoSpaceAfterOpenBraceInJsxExpression", 17 /* OpenBraceToken */, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], 8 /* Delete */),
- rule("NoSpaceBeforeCloseBraceInJsxExpression", anyToken, 18 /* CloseBraceToken */, [isOptionDisabledOrUndefined("insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces"), isNonJsxSameLineTokenContext, isJsxExpressionContext], 8 /* Delete */),
- // Insert space after semicolon in for statement
- rule("SpaceAfterSemicolonInFor", 25 /* SemicolonToken */, anyToken, [isOptionEnabled("insertSpaceAfterSemicolonInForStatements"), isNonJsxSameLineTokenContext, isForContext], 2 /* Space */),
- rule("NoSpaceAfterSemicolonInFor", 25 /* SemicolonToken */, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterSemicolonInForStatements"), isNonJsxSameLineTokenContext, isForContext], 8 /* Delete */),
- // Insert space before and after binary operators
- rule("SpaceBeforeBinaryOperator", anyToken, binaryOperators, [isOptionEnabled("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], 2 /* Space */),
- rule("SpaceAfterBinaryOperator", binaryOperators, anyToken, [isOptionEnabled("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], 2 /* Space */),
- rule("NoSpaceBeforeBinaryOperator", anyToken, binaryOperators, [isOptionDisabledOrUndefined("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], 8 /* Delete */),
- rule("NoSpaceAfterBinaryOperator", binaryOperators, anyToken, [isOptionDisabledOrUndefined("insertSpaceBeforeAndAfterBinaryOperators"), isNonJsxSameLineTokenContext, isBinaryOpContext], 8 /* Delete */),
- rule("SpaceBeforeOpenParenInFuncDecl", anyToken, 19 /* OpenParenToken */, [isOptionEnabled("insertSpaceBeforeFunctionParenthesis"), isNonJsxSameLineTokenContext, isFunctionDeclContext], 2 /* Space */),
- rule("NoSpaceBeforeOpenParenInFuncDecl", anyToken, 19 /* OpenParenToken */, [isOptionDisabledOrUndefined("insertSpaceBeforeFunctionParenthesis"), isNonJsxSameLineTokenContext, isFunctionDeclContext], 8 /* Delete */),
- // Open Brace braces after control block
- rule("NewLineBeforeOpenBraceInControl", controlOpenBraceLeftTokenRange, 17 /* OpenBraceToken */, [isOptionEnabled("placeOpenBraceOnNewLineForControlBlocks"), isControlDeclContext, isBeforeMultilineBlockContext], 4 /* NewLine */, 1 /* CanDeleteNewLines */),
- // Open Brace braces after function
- // TypeScript: Function can have return types, which can be made of tons of different token kinds
- rule("NewLineBeforeOpenBraceInFunction", functionOpenBraceLeftTokenRange, 17 /* OpenBraceToken */, [isOptionEnabled("placeOpenBraceOnNewLineForFunctions"), isFunctionDeclContext, isBeforeMultilineBlockContext], 4 /* NewLine */, 1 /* CanDeleteNewLines */),
- // Open Brace braces after TypeScript module/class/interface
- rule("NewLineBeforeOpenBraceInTypeScriptDeclWithBlock", typeScriptOpenBraceLeftTokenRange, 17 /* OpenBraceToken */, [isOptionEnabled("placeOpenBraceOnNewLineForFunctions"), isTypeScriptDeclWithBlockContext, isBeforeMultilineBlockContext], 4 /* NewLine */, 1 /* CanDeleteNewLines */),
- rule("SpaceAfterTypeAssertion", 29 /* GreaterThanToken */, anyToken, [isOptionEnabled("insertSpaceAfterTypeAssertion"), isNonJsxSameLineTokenContext, isTypeAssertionContext], 2 /* Space */),
- rule("NoSpaceAfterTypeAssertion", 29 /* GreaterThanToken */, anyToken, [isOptionDisabledOrUndefined("insertSpaceAfterTypeAssertion"), isNonJsxSameLineTokenContext, isTypeAssertionContext], 8 /* Delete */),
- rule("SpaceBeforeTypeAnnotation", anyToken, 56 /* ColonToken */, [isOptionEnabled("insertSpaceBeforeTypeAnnotation"), isNonJsxSameLineTokenContext, isTypeAnnotationContext], 2 /* Space */),
- rule("NoSpaceBeforeTypeAnnotation", anyToken, 56 /* ColonToken */, [isOptionDisabledOrUndefined("insertSpaceBeforeTypeAnnotation"), isNonJsxSameLineTokenContext, isTypeAnnotationContext], 8 /* Delete */),
- ];
- // These rules are lower in priority than user-configurable. Rules earlier in this list have priority over rules later in the list.
- var lowPriorityCommonRules = [
- // Space after keyword but not before ; or : or ?
- rule("NoSpaceBeforeSemicolon", anyToken, 25 /* SemicolonToken */, [isNonJsxSameLineTokenContext], 8 /* Delete */),
- rule("SpaceBeforeOpenBraceInControl", controlOpenBraceLeftTokenRange, 17 /* OpenBraceToken */, [isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForControlBlocks"), isControlDeclContext, isNotFormatOnEnter, isSameLineTokenOrBeforeBlockContext], 2 /* Space */, 1 /* CanDeleteNewLines */),
- rule("SpaceBeforeOpenBraceInFunction", functionOpenBraceLeftTokenRange, 17 /* OpenBraceToken */, [isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForFunctions"), isFunctionDeclContext, isBeforeBlockContext, isNotFormatOnEnter, isSameLineTokenOrBeforeBlockContext], 2 /* Space */, 1 /* CanDeleteNewLines */),
- rule("SpaceBeforeOpenBraceInTypeScriptDeclWithBlock", typeScriptOpenBraceLeftTokenRange, 17 /* OpenBraceToken */, [isOptionDisabledOrUndefinedOrTokensOnSameLine("placeOpenBraceOnNewLineForFunctions"), isTypeScriptDeclWithBlockContext, isNotFormatOnEnter, isSameLineTokenOrBeforeBlockContext], 2 /* Space */, 1 /* CanDeleteNewLines */),
- rule("NoSpaceBeforeComma", anyToken, 26 /* CommaToken */, [isNonJsxSameLineTokenContext], 8 /* Delete */),
- // No space before and after indexer `x[]`
- rule("NoSpaceBeforeOpenBracket", anyTokenExcept(120 /* AsyncKeyword */, 73 /* CaseKeyword */), 21 /* OpenBracketToken */, [isNonJsxSameLineTokenContext], 8 /* Delete */),
- rule("NoSpaceAfterCloseBracket", 22 /* CloseBracketToken */, anyToken, [isNonJsxSameLineTokenContext, isNotBeforeBlockInFunctionDeclarationContext], 8 /* Delete */),
- rule("SpaceAfterSemicolon", 25 /* SemicolonToken */, anyToken, [isNonJsxSameLineTokenContext], 2 /* Space */),
- // Remove extra space between for and await
- rule("SpaceBetweenForAndAwaitKeyword", 88 /* ForKeyword */, 121 /* AwaitKeyword */, [isNonJsxSameLineTokenContext], 2 /* Space */),
- // Add a space between statements. All keywords except (do,else,case) has open/close parens after them.
- // So, we have a rule to add a space for [),Any], [do,Any], [else,Any], and [case,Any]
- rule("SpaceBetweenStatements", [20 /* CloseParenToken */, 81 /* DoKeyword */, 82 /* ElseKeyword */, 73 /* CaseKeyword */], anyToken, [isNonJsxSameLineTokenContext, isNonJsxElementOrFragmentContext, isNotForContext], 2 /* Space */),
- // This low-pri rule takes care of "try {" and "finally {" in case the rule SpaceBeforeOpenBraceInControl didn't execute on FormatOnEnter.
- rule("SpaceAfterTryFinally", [102 /* TryKeyword */, 87 /* FinallyKeyword */], 17 /* OpenBraceToken */, [isNonJsxSameLineTokenContext], 2 /* Space */),
- ];
- return highPriorityCommonRules.concat(userConfigurableRules, lowPriorityCommonRules);
- }
- formatting.getAllRules = getAllRules;
- function rule(debugName, left, right, context, action, flags) {
- if (flags === void 0) { flags = 0 /* None */; }
- return { leftTokenRange: toTokenRange(left), rightTokenRange: toTokenRange(right), rule: { debugName: debugName, context: context, action: action, flags: flags } };
- }
- function tokenRangeFrom(tokens) {
- return { tokens: tokens, isSpecific: true };
- }
- function toTokenRange(arg) {
- return typeof arg === "number" ? tokenRangeFrom([arg]) : ts.isArray(arg) ? tokenRangeFrom(arg) : arg;
- }
- function tokenRangeFromRange(from, to, except) {
- if (except === void 0) { except = []; }
- var tokens = [];
- for (var token = from; token <= to; token++) {
- if (!ts.contains(except, token)) {
- tokens.push(token);
- }
- }
- return tokenRangeFrom(tokens);
- }
- ///
- /// Contexts
- ///
- function isOptionEnabled(optionName) {
- return function (context) { return context.options && context.options.hasOwnProperty(optionName) && !!context.options[optionName]; };
- }
- function isOptionDisabled(optionName) {
- return function (context) { return context.options && context.options.hasOwnProperty(optionName) && !context.options[optionName]; };
- }
- function isOptionDisabledOrUndefined(optionName) {
- return function (context) { return !context.options || !context.options.hasOwnProperty(optionName) || !context.options[optionName]; };
- }
- function isOptionDisabledOrUndefinedOrTokensOnSameLine(optionName) {
- return function (context) { return !context.options || !context.options.hasOwnProperty(optionName) || !context.options[optionName] || context.TokensAreOnSameLine(); };
- }
- function isOptionEnabledOrUndefined(optionName) {
- return function (context) { return !context.options || !context.options.hasOwnProperty(optionName) || !!context.options[optionName]; };
- }
- function isForContext(context) {
- return context.contextNode.kind === 218 /* ForStatement */;
- }
- function isNotForContext(context) {
- return !isForContext(context);
- }
- function isBinaryOpContext(context) {
- switch (context.contextNode.kind) {
- case 198 /* BinaryExpression */:
- case 199 /* ConditionalExpression */:
- case 170 /* ConditionalType */:
- case 206 /* AsExpression */:
- case 250 /* ExportSpecifier */:
- case 246 /* ImportSpecifier */:
- case 160 /* TypePredicate */:
- case 168 /* UnionType */:
- case 169 /* IntersectionType */:
- return true;
- // equals in binding elements: function foo([[x, y] = [1, 2]])
- case 180 /* BindingElement */:
- // equals in type X = ...
- case 235 /* TypeAliasDeclaration */:
- // equal in import a = module('a');
- case 241 /* ImportEqualsDeclaration */:
- // equal in let a = 0;
- case 230 /* VariableDeclaration */:
- // equal in p = 0;
- case 148 /* Parameter */:
- case 271 /* EnumMember */:
- case 151 /* PropertyDeclaration */:
- case 150 /* PropertySignature */:
- return context.currentTokenSpan.kind === 58 /* EqualsToken */ || context.nextTokenSpan.kind === 58 /* EqualsToken */;
- // "in" keyword in for (let x in []) { }
- case 219 /* ForInStatement */:
- // "in" keyword in [P in keyof T]: T[P]
- case 147 /* TypeParameter */:
- return context.currentTokenSpan.kind === 92 /* InKeyword */ || context.nextTokenSpan.kind === 92 /* InKeyword */;
- // Technically, "of" is not a binary operator, but format it the same way as "in"
- case 220 /* ForOfStatement */:
- return context.currentTokenSpan.kind === 144 /* OfKeyword */ || context.nextTokenSpan.kind === 144 /* OfKeyword */;
- }
- return false;
- }
- function isNotBinaryOpContext(context) {
- return !isBinaryOpContext(context);
- }
- function isNotTypeAnnotationContext(context) {
- return !isTypeAnnotationContext(context);
- }
- function isTypeAnnotationContext(context) {
- var contextKind = context.contextNode.kind;
- return contextKind === 151 /* PropertyDeclaration */ ||
- contextKind === 150 /* PropertySignature */ ||
- contextKind === 148 /* Parameter */ ||
- contextKind === 230 /* VariableDeclaration */ ||
- ts.isFunctionLikeKind(contextKind);
- }
- function isConditionalOperatorContext(context) {
- return context.contextNode.kind === 199 /* ConditionalExpression */ ||
- context.contextNode.kind === 170 /* ConditionalType */;
- }
- function isSameLineTokenOrBeforeBlockContext(context) {
- return context.TokensAreOnSameLine() || isBeforeBlockContext(context);
- }
- function isBraceWrappedContext(context) {
- return context.contextNode.kind === 178 /* ObjectBindingPattern */ ||
- context.contextNode.kind === 176 /* MappedType */ ||
- isSingleLineBlockContext(context);
- }
- // This check is done before an open brace in a control construct, a function, or a typescript block declaration
- function isBeforeMultilineBlockContext(context) {
- return isBeforeBlockContext(context) && !(context.NextNodeAllOnSameLine() || context.NextNodeBlockIsOnOneLine());
- }
- function isMultilineBlockContext(context) {
- return isBlockContext(context) && !(context.ContextNodeAllOnSameLine() || context.ContextNodeBlockIsOnOneLine());
- }
- function isSingleLineBlockContext(context) {
- return isBlockContext(context) && (context.ContextNodeAllOnSameLine() || context.ContextNodeBlockIsOnOneLine());
- }
- function isBlockContext(context) {
- return nodeIsBlockContext(context.contextNode);
- }
- function isBeforeBlockContext(context) {
- return nodeIsBlockContext(context.nextTokenParent);
- }
- // IMPORTANT!!! This method must return true ONLY for nodes with open and close braces as immediate children
- function nodeIsBlockContext(node) {
- if (nodeIsTypeScriptDeclWithBlockContext(node)) {
- // This means we are in a context that looks like a block to the user, but in the grammar is actually not a node (it's a class, module, enum, object type literal, etc).
- return true;
- }
- switch (node.kind) {
- case 211 /* Block */:
- case 239 /* CaseBlock */:
- case 182 /* ObjectLiteralExpression */:
- case 238 /* ModuleBlock */:
- return true;
- }
- return false;
- }
- function isFunctionDeclContext(context) {
- switch (context.contextNode.kind) {
- case 232 /* FunctionDeclaration */:
- case 153 /* MethodDeclaration */:
- case 152 /* MethodSignature */:
- // case SyntaxKind.MemberFunctionDeclaration:
- case 155 /* GetAccessor */:
- case 156 /* SetAccessor */:
- // case SyntaxKind.MethodSignature:
- case 157 /* CallSignature */:
- case 190 /* FunctionExpression */:
- case 154 /* Constructor */:
- case 191 /* ArrowFunction */:
- // case SyntaxKind.ConstructorDeclaration:
- // case SyntaxKind.SimpleArrowFunctionExpression:
- // case SyntaxKind.ParenthesizedArrowFunctionExpression:
- case 234 /* InterfaceDeclaration */: // This one is not truly a function, but for formatting purposes, it acts just like one
- return true;
- }
- return false;
- }
- function isFunctionDeclarationOrFunctionExpressionContext(context) {
- return context.contextNode.kind === 232 /* FunctionDeclaration */ || context.contextNode.kind === 190 /* FunctionExpression */;
- }
- function isTypeScriptDeclWithBlockContext(context) {
- return nodeIsTypeScriptDeclWithBlockContext(context.contextNode);
- }
- function nodeIsTypeScriptDeclWithBlockContext(node) {
- switch (node.kind) {
- case 233 /* ClassDeclaration */:
- case 203 /* ClassExpression */:
- case 234 /* InterfaceDeclaration */:
- case 236 /* EnumDeclaration */:
- case 165 /* TypeLiteral */:
- case 237 /* ModuleDeclaration */:
- case 248 /* ExportDeclaration */:
- case 249 /* NamedExports */:
- case 242 /* ImportDeclaration */:
- case 245 /* NamedImports */:
- return true;
- }
- return false;
- }
- function isAfterCodeBlockContext(context) {
- switch (context.currentTokenParent.kind) {
- case 233 /* ClassDeclaration */:
- case 237 /* ModuleDeclaration */:
- case 236 /* EnumDeclaration */:
- case 267 /* CatchClause */:
- case 238 /* ModuleBlock */:
- case 225 /* SwitchStatement */:
- return true;
- case 211 /* Block */: {
- var blockParent = context.currentTokenParent.parent;
- // In a codefix scenario, we can't rely on parents being set. So just always return true.
- if (!blockParent || blockParent.kind !== 191 /* ArrowFunction */ && blockParent.kind !== 190 /* FunctionExpression */) {
- return true;
- }
- }
- }
- return false;
- }
- function isControlDeclContext(context) {
- switch (context.contextNode.kind) {
- case 215 /* IfStatement */:
- case 225 /* SwitchStatement */:
- case 218 /* ForStatement */:
- case 219 /* ForInStatement */:
- case 220 /* ForOfStatement */:
- case 217 /* WhileStatement */:
- case 228 /* TryStatement */:
- case 216 /* DoStatement */:
- case 224 /* WithStatement */:
- // TODO
- // case SyntaxKind.ElseClause:
- case 267 /* CatchClause */:
- return true;
- default:
- return false;
- }
- }
- function isObjectContext(context) {
- return context.contextNode.kind === 182 /* ObjectLiteralExpression */;
- }
- function isFunctionCallContext(context) {
- return context.contextNode.kind === 185 /* CallExpression */;
- }
- function isNewContext(context) {
- return context.contextNode.kind === 186 /* NewExpression */;
- }
- function isFunctionCallOrNewContext(context) {
- return isFunctionCallContext(context) || isNewContext(context);
- }
- function isPreviousTokenNotComma(context) {
- return context.currentTokenSpan.kind !== 26 /* CommaToken */;
- }
- function isNextTokenNotCloseBracket(context) {
- return context.nextTokenSpan.kind !== 22 /* CloseBracketToken */;
- }
- function isArrowFunctionContext(context) {
- return context.contextNode.kind === 191 /* ArrowFunction */;
- }
- function isNonJsxSameLineTokenContext(context) {
- return context.TokensAreOnSameLine() && context.contextNode.kind !== 10 /* JsxText */;
- }
- function isNonJsxElementOrFragmentContext(context) {
- return context.contextNode.kind !== 253 /* JsxElement */ && context.contextNode.kind !== 257 /* JsxFragment */;
- }
- function isJsxExpressionContext(context) {
- return context.contextNode.kind === 263 /* JsxExpression */ || context.contextNode.kind === 262 /* JsxSpreadAttribute */;
- }
- function isNextTokenParentJsxAttribute(context) {
- return context.nextTokenParent.kind === 260 /* JsxAttribute */;
- }
- function isJsxAttributeContext(context) {
- return context.contextNode.kind === 260 /* JsxAttribute */;
- }
- function isJsxSelfClosingElementContext(context) {
- return context.contextNode.kind === 254 /* JsxSelfClosingElement */;
- }
- function isNotBeforeBlockInFunctionDeclarationContext(context) {
- return !isFunctionDeclContext(context) && !isBeforeBlockContext(context);
- }
- function isEndOfDecoratorContextOnSameLine(context) {
- return context.TokensAreOnSameLine() &&
- context.contextNode.decorators &&
- nodeIsInDecoratorContext(context.currentTokenParent) &&
- !nodeIsInDecoratorContext(context.nextTokenParent);
- }
- function nodeIsInDecoratorContext(node) {
- while (ts.isExpressionNode(node)) {
- node = node.parent;
- }
- return node.kind === 149 /* Decorator */;
- }
- function isStartOfVariableDeclarationList(context) {
- return context.currentTokenParent.kind === 231 /* VariableDeclarationList */ &&
- context.currentTokenParent.getStart(context.sourceFile) === context.currentTokenSpan.pos;
- }
- function isNotFormatOnEnter(context) {
- return context.formattingRequestKind !== 2 /* FormatOnEnter */;
- }
- function isModuleDeclContext(context) {
- return context.contextNode.kind === 237 /* ModuleDeclaration */;
- }
- function isObjectTypeContext(context) {
- return context.contextNode.kind === 165 /* TypeLiteral */; // && context.contextNode.parent.kind !== SyntaxKind.InterfaceDeclaration;
- }
- function isConstructorSignatureContext(context) {
- return context.contextNode.kind === 158 /* ConstructSignature */;
- }
- function isTypeArgumentOrParameterOrAssertion(token, parent) {
- if (token.kind !== 27 /* LessThanToken */ && token.kind !== 29 /* GreaterThanToken */) {
- return false;
- }
- switch (parent.kind) {
- case 161 /* TypeReference */:
- case 188 /* TypeAssertionExpression */:
- case 235 /* TypeAliasDeclaration */:
- case 233 /* ClassDeclaration */:
- case 203 /* ClassExpression */:
- case 234 /* InterfaceDeclaration */:
- case 232 /* FunctionDeclaration */:
- case 190 /* FunctionExpression */:
- case 191 /* ArrowFunction */:
- case 153 /* MethodDeclaration */:
- case 152 /* MethodSignature */:
- case 157 /* CallSignature */:
- case 158 /* ConstructSignature */:
- case 185 /* CallExpression */:
- case 186 /* NewExpression */:
- case 205 /* ExpressionWithTypeArguments */:
- return true;
- default:
- return false;
- }
- }
- function isTypeArgumentOrParameterOrAssertionContext(context) {
- return isTypeArgumentOrParameterOrAssertion(context.currentTokenSpan, context.currentTokenParent) ||
- isTypeArgumentOrParameterOrAssertion(context.nextTokenSpan, context.nextTokenParent);
- }
- function isTypeAssertionContext(context) {
- return context.contextNode.kind === 188 /* TypeAssertionExpression */;
- }
- function isVoidOpContext(context) {
- return context.currentTokenSpan.kind === 105 /* VoidKeyword */ && context.currentTokenParent.kind === 194 /* VoidExpression */;
- }
- function isYieldOrYieldStarWithOperand(context) {
- return context.contextNode.kind === 201 /* YieldExpression */ && context.contextNode.expression !== undefined;
- }
- function isNonNullAssertionContext(context) {
- return context.contextNode.kind === 207 /* NonNullExpression */;
- }
- })(formatting = ts.formatting || (ts.formatting = {}));
-})(ts || (ts = {}));
-///
-/* @internal */
-var ts;
-(function (ts) {
- var formatting;
- (function (formatting) {
- function getFormatContext(options) {
- return { options: options, getRule: getRulesMap() };
- }
- formatting.getFormatContext = getFormatContext;
- var rulesMapCache;
- function getRulesMap() {
- if (rulesMapCache === undefined) {
- rulesMapCache = createRulesMap(formatting.getAllRules());
- }
- return rulesMapCache;
- }
- function createRulesMap(rules) {
- var map = buildMap(rules);
- return function (context) {
- var bucket = map[getRuleBucketIndex(context.currentTokenSpan.kind, context.nextTokenSpan.kind)];
- return bucket && ts.find(bucket, function (rule) { return ts.every(rule.context, function (c) { return c(context); }); });
- };
- }
- function buildMap(rules) {
- // Map from bucket index to array of rules
- var map = new Array(mapRowLength * mapRowLength);
- // This array is used only during construction of the rulesbucket in the map
- var rulesBucketConstructionStateList = new Array(map.length);
- for (var _i = 0, rules_1 = rules; _i < rules_1.length; _i++) {
- var rule = rules_1[_i];
- var specificRule = rule.leftTokenRange.isSpecific && rule.rightTokenRange.isSpecific;
- for (var _a = 0, _b = rule.leftTokenRange.tokens; _a < _b.length; _a++) {
- var left = _b[_a];
- for (var _c = 0, _d = rule.rightTokenRange.tokens; _c < _d.length; _c++) {
- var right = _d[_c];
- var index = getRuleBucketIndex(left, right);
- var rulesBucket = map[index];
- if (rulesBucket === undefined) {
- rulesBucket = map[index] = [];
- }
- addRule(rulesBucket, rule.rule, specificRule, rulesBucketConstructionStateList, index);
- }
- }
- }
- return map;
- }
- function getRuleBucketIndex(row, column) {
- ts.Debug.assert(row <= 144 /* LastKeyword */ && column <= 144 /* LastKeyword */, "Must compute formatting context from tokens");
- return (row * mapRowLength) + column;
- }
- var maskBitSize = 5;
- var mask = 31; // MaskBitSize bits
- var mapRowLength = 144 /* LastToken */ + 1;
- var RulesPosition;
- (function (RulesPosition) {
- RulesPosition[RulesPosition["IgnoreRulesSpecific"] = 0] = "IgnoreRulesSpecific";
- RulesPosition[RulesPosition["IgnoreRulesAny"] = maskBitSize * 1] = "IgnoreRulesAny";
- RulesPosition[RulesPosition["ContextRulesSpecific"] = maskBitSize * 2] = "ContextRulesSpecific";
- RulesPosition[RulesPosition["ContextRulesAny"] = maskBitSize * 3] = "ContextRulesAny";
- RulesPosition[RulesPosition["NoContextRulesSpecific"] = maskBitSize * 4] = "NoContextRulesSpecific";
- RulesPosition[RulesPosition["NoContextRulesAny"] = maskBitSize * 5] = "NoContextRulesAny";
- })(RulesPosition || (RulesPosition = {}));
- // The Rules list contains all the inserted rules into a rulebucket in the following order:
- // 1- Ignore rules with specific token combination
- // 2- Ignore rules with any token combination
- // 3- Context rules with specific token combination
- // 4- Context rules with any token combination
- // 5- Non-context rules with specific token combination
- // 6- Non-context rules with any token combination
- //
- // The member rulesInsertionIndexBitmap is used to describe the number of rules
- // in each sub-bucket (above) hence can be used to know the index of where to insert
- // the next rule. It's a bitmap which contains 6 different sections each is given 5 bits.
- //
- // Example:
- // In order to insert a rule to the end of sub-bucket (3), we get the index by adding
- // the values in the bitmap segments 3rd, 2nd, and 1st.
- function addRule(rules, rule, specificTokens, constructionState, rulesBucketIndex) {
- var position = rule.action === 1 /* Ignore */
- ? specificTokens ? RulesPosition.IgnoreRulesSpecific : RulesPosition.IgnoreRulesAny
- : rule.context !== formatting.anyContext
- ? specificTokens ? RulesPosition.ContextRulesSpecific : RulesPosition.ContextRulesAny
- : specificTokens ? RulesPosition.NoContextRulesSpecific : RulesPosition.NoContextRulesAny;
- var state = constructionState[rulesBucketIndex] || 0;
- rules.splice(getInsertionIndex(state, position), 0, rule);
- constructionState[rulesBucketIndex] = increaseInsertionIndex(state, position);
- }
- function getInsertionIndex(indexBitmap, maskPosition) {
- var index = 0;
- for (var pos = 0; pos <= maskPosition; pos += maskBitSize) {
- index += indexBitmap & mask;
- indexBitmap >>= maskBitSize;
- }
- return index;
- }
- function increaseInsertionIndex(indexBitmap, maskPosition) {
- var value = ((indexBitmap >> maskPosition) & mask) + 1;
- ts.Debug.assert((value & mask) === value, "Adding more rules into the sub-bucket than allowed. Maximum allowed is 32 rules.");
- return (indexBitmap & ~(mask << maskPosition)) | (value << maskPosition);
- }
- })(formatting = ts.formatting || (ts.formatting = {}));
-})(ts || (ts = {}));
-///
-///
-///
-///
-/* @internal */
-var ts;
-(function (ts) {
- var formatting;
- (function (formatting) {
- var Constants;
- (function (Constants) {
- Constants[Constants["Unknown"] = -1] = "Unknown";
- })(Constants || (Constants = {}));
- function formatOnEnter(position, sourceFile, formatContext) {
- var line = sourceFile.getLineAndCharacterOfPosition(position).line;
- if (line === 0) {
- return [];
- }
- // After the enter key, the cursor is now at a new line. The new line may or may not contain non-whitespace characters.
- // If the new line has only whitespaces, we won't want to format this line, because that would remove the indentation as
- // trailing whitespaces. So the end of the formatting span should be the later one between:
- // 1. the end of the previous line
- // 2. the last non-whitespace character in the current line
- var endOfFormatSpan = ts.getEndLinePosition(line, sourceFile);
- while (ts.isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(endOfFormatSpan))) {
- endOfFormatSpan--;
- }
- // if the character at the end of the span is a line break, we shouldn't include it, because it indicates we don't want to
- // touch the current line at all. Also, on some OSes the line break consists of two characters (\r\n), we should test if the
- // previous character before the end of format span is line break character as well.
- if (ts.isLineBreak(sourceFile.text.charCodeAt(endOfFormatSpan))) {
- endOfFormatSpan--;
- }
- var span = {
- // get start position for the previous line
- pos: ts.getStartPositionOfLine(line - 1, sourceFile),
- // end value is exclusive so add 1 to the result
- end: endOfFormatSpan + 1
- };
- return formatSpan(span, sourceFile, formatContext, 2 /* FormatOnEnter */);
- }
- formatting.formatOnEnter = formatOnEnter;
- function formatOnSemicolon(position, sourceFile, formatContext) {
- var semicolon = findImmediatelyPrecedingTokenOfKind(position, 25 /* SemicolonToken */, sourceFile);
- return formatNodeLines(findOutermostNodeWithinListLevel(semicolon), sourceFile, formatContext, 3 /* FormatOnSemicolon */);
- }
- formatting.formatOnSemicolon = formatOnSemicolon;
- function formatOnOpeningCurly(position, sourceFile, formatContext) {
- var openingCurly = findImmediatelyPrecedingTokenOfKind(position, 17 /* OpenBraceToken */, sourceFile);
- if (!openingCurly) {
- return [];
- }
- var curlyBraceRange = openingCurly.parent;
- var outermostNode = findOutermostNodeWithinListLevel(curlyBraceRange);
- /**
- * We limit the span to end at the opening curly to handle the case where
- * the brace matched to that just typed will be incorrect after further edits.
- * For example, we could type the opening curly for the following method
- * body without brace-matching activated:
- * ```
- * class C {
- * foo()
- * }
- * ```
- * and we wouldn't want to move the closing brace.
- */
- var textRange = {
- pos: ts.getLineStartPositionForPosition(outermostNode.getStart(sourceFile), sourceFile),
- end: position
- };
- return formatSpan(textRange, sourceFile, formatContext, 4 /* FormatOnOpeningCurlyBrace */);
- }
- formatting.formatOnOpeningCurly = formatOnOpeningCurly;
- function formatOnClosingCurly(position, sourceFile, formatContext) {
- var precedingToken = findImmediatelyPrecedingTokenOfKind(position, 18 /* CloseBraceToken */, sourceFile);
- return formatNodeLines(findOutermostNodeWithinListLevel(precedingToken), sourceFile, formatContext, 5 /* FormatOnClosingCurlyBrace */);
- }
- formatting.formatOnClosingCurly = formatOnClosingCurly;
- function formatDocument(sourceFile, formatContext) {
- var span = {
- pos: 0,
- end: sourceFile.text.length
- };
- return formatSpan(span, sourceFile, formatContext, 0 /* FormatDocument */);
- }
- formatting.formatDocument = formatDocument;
- function formatSelection(start, end, sourceFile, formatContext) {
- // format from the beginning of the line
- var span = {
- pos: ts.getLineStartPositionForPosition(start, sourceFile),
- end: end,
- };
- return formatSpan(span, sourceFile, formatContext, 1 /* FormatSelection */);
- }
- formatting.formatSelection = formatSelection;
- /**
- * Validating `expectedTokenKind` ensures the token was typed in the context we expect (eg: not a comment).
- * @param expectedTokenKind The kind of the last token constituting the desired parent node.
- */
- function findImmediatelyPrecedingTokenOfKind(end, expectedTokenKind, sourceFile) {
- var precedingToken = ts.findPrecedingToken(end, sourceFile);
- return precedingToken && precedingToken.kind === expectedTokenKind && end === precedingToken.getEnd() ?
- precedingToken :
- undefined;
- }
- /**
- * Finds the highest node enclosing `node` at the same list level as `node`
- * and whose end does not exceed `node.end`.
- *
- * Consider typing the following
- * ```
- * let x = 1;
- * while (true) {
- * }
- * ```
- * Upon typing the closing curly, we want to format the entire `while`-statement, but not the preceding
- * variable declaration.
- */
- function findOutermostNodeWithinListLevel(node) {
- var current = node;
- while (current &&
- current.parent &&
- current.parent.end === node.end &&
- !isListElement(current.parent, current)) {
- current = current.parent;
- }
- return current;
- }
- // Returns true if node is a element in some list in parent
- // i.e. parent is class declaration with the list of members and node is one of members.
- function isListElement(parent, node) {
- switch (parent.kind) {
- case 233 /* ClassDeclaration */:
- case 234 /* InterfaceDeclaration */:
- return ts.rangeContainsRange(parent.members, node);
- case 237 /* ModuleDeclaration */:
- var body = parent.body;
- return body && body.kind === 238 /* ModuleBlock */ && ts.rangeContainsRange(body.statements, node);
- case 272 /* SourceFile */:
- case 211 /* Block */:
- case 238 /* ModuleBlock */:
- return ts.rangeContainsRange(parent.statements, node);
- case 267 /* CatchClause */:
- return ts.rangeContainsRange(parent.block.statements, node);
- }
- return false;
- }
- /** find node that fully contains given text range */
- function findEnclosingNode(range, sourceFile) {
- return find(sourceFile);
- function find(n) {
- var candidate = ts.forEachChild(n, function (c) { return ts.startEndContainsRange(c.getStart(sourceFile), c.end, range) && c; });
- if (candidate) {
- var result = find(candidate);
- if (result) {
- return result;
- }
- }
- return n;
- }
- }
- /** formatting is not applied to ranges that contain parse errors.
- * This function will return a predicate that for a given text range will tell
- * if there are any parse errors that overlap with the range.
- */
- function prepareRangeContainsErrorFunction(errors, originalRange) {
- if (!errors.length) {
- return rangeHasNoErrors;
- }
- // pick only errors that fall in range
- var sorted = errors
- .filter(function (d) { return ts.rangeOverlapsWithStartEnd(originalRange, d.start, d.start + d.length); })
- .sort(function (e1, e2) { return e1.start - e2.start; });
- if (!sorted.length) {
- return rangeHasNoErrors;
- }
- var index = 0;
- return function (r) {
- // in current implementation sequence of arguments [r1, r2...] is monotonically increasing.
- // 'index' tracks the index of the most recent error that was checked.
- while (true) {
- if (index >= sorted.length) {
- // all errors in the range were already checked -> no error in specified range
- return false;
- }
- var error = sorted[index];
- if (r.end <= error.start) {
- // specified range ends before the error refered by 'index' - no error in range
- return false;
- }
- if (ts.startEndOverlapsWithStartEnd(r.pos, r.end, error.start, error.start + error.length)) {
- // specified range overlaps with error range
- return true;
- }
- index++;
- }
- };
- function rangeHasNoErrors() {
- return false;
- }
- }
- /**
- * Start of the original range might fall inside the comment - scanner will not yield appropriate results
- * This function will look for token that is located before the start of target range
- * and return its end as start position for the scanner.
- */
- function getScanStartPosition(enclosingNode, originalRange, sourceFile) {
- var start = enclosingNode.getStart(sourceFile);
- if (start === originalRange.pos && enclosingNode.end === originalRange.end) {
- return start;
- }
- var precedingToken = ts.findPrecedingToken(originalRange.pos, sourceFile);
- if (!precedingToken) {
- // no preceding token found - start from the beginning of enclosing node
- return enclosingNode.pos;
- }
- // preceding token ends after the start of original range (i.e when originalRange.pos falls in the middle of literal)
- // start from the beginning of enclosingNode to handle the entire 'originalRange'
- if (precedingToken.end >= originalRange.pos) {
- return enclosingNode.pos;
- }
- return precedingToken.end;
- }
- /*
- * For cases like
- * if (a ||
- * b ||$
- * c) {...}
- * If we hit Enter at $ we want line ' b ||' to be indented.
- * Formatting will be applied to the last two lines.
- * Node that fully encloses these lines is binary expression 'a ||...'.
- * Initial indentation for this node will be 0.
- * Binary expressions don't introduce new indentation scopes, however it is possible
- * that some parent node on the same line does - like if statement in this case.
- * Note that we are considering parents only from the same line with initial node -
- * if parent is on the different line - its delta was already contributed
- * to the initial indentation.
- */
- function getOwnOrInheritedDelta(n, options, sourceFile) {
- var previousLine = -1 /* Unknown */;
- var child;
- while (n) {
- var line = sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile)).line;
- if (previousLine !== -1 /* Unknown */ && line !== previousLine) {
- break;
- }
- if (formatting.SmartIndenter.shouldIndentChildNode(n, child)) {
- return options.indentSize;
- }
- previousLine = line;
- child = n;
- n = n.parent;
- }
- return 0;
- }
- /* @internal */
- function formatNodeGivenIndentation(node, sourceFileLike, languageVariant, initialIndentation, delta, formatContext) {
- var range = { pos: 0, end: sourceFileLike.text.length };
- return formatting.getFormattingScanner(sourceFileLike.text, languageVariant, range.pos, range.end, function (scanner) { return formatSpanWorker(range, node, initialIndentation, delta, scanner, formatContext, 1 /* FormatSelection */, function (_) { return false; }, // assume that node does not have any errors
- sourceFileLike); });
- }
- formatting.formatNodeGivenIndentation = formatNodeGivenIndentation;
- function formatNodeLines(node, sourceFile, formatContext, requestKind) {
- if (!node) {
- return [];
- }
- var span = {
- pos: ts.getLineStartPositionForPosition(node.getStart(sourceFile), sourceFile),
- end: node.end
- };
- return formatSpan(span, sourceFile, formatContext, requestKind);
- }
- function formatSpan(originalRange, sourceFile, formatContext, requestKind) {
- // find the smallest node that fully wraps the range and compute the initial indentation for the node
- var enclosingNode = findEnclosingNode(originalRange, sourceFile);
- return formatting.getFormattingScanner(sourceFile.text, sourceFile.languageVariant, getScanStartPosition(enclosingNode, originalRange, sourceFile), originalRange.end, function (scanner) { return formatSpanWorker(originalRange, enclosingNode, formatting.SmartIndenter.getIndentationForNode(enclosingNode, originalRange, sourceFile, formatContext.options), getOwnOrInheritedDelta(enclosingNode, formatContext.options, sourceFile), scanner, formatContext, requestKind, prepareRangeContainsErrorFunction(sourceFile.parseDiagnostics, originalRange), sourceFile); });
- }
- function formatSpanWorker(originalRange, enclosingNode, initialIndentation, delta, formattingScanner, _a, requestKind, rangeContainsError, sourceFile) {
- var options = _a.options, getRule = _a.getRule;
- // formatting context is used by rules provider
- var formattingContext = new formatting.FormattingContext(sourceFile, requestKind, options);
- var previousRange;
- var previousParent;
- var previousRangeStartLine;
- var lastIndentedLine;
- var indentationOnLastIndentedLine;
- var edits = [];
- formattingScanner.advance();
- if (formattingScanner.isOnToken()) {
- var startLine = sourceFile.getLineAndCharacterOfPosition(enclosingNode.getStart(sourceFile)).line;
- var undecoratedStartLine = startLine;
- if (enclosingNode.decorators) {
- undecoratedStartLine = sourceFile.getLineAndCharacterOfPosition(ts.getNonDecoratorTokenPosOfNode(enclosingNode, sourceFile)).line;
- }
- processNode(enclosingNode, enclosingNode, startLine, undecoratedStartLine, initialIndentation, delta);
- }
- if (!formattingScanner.isOnToken()) {
- var leadingTrivia = formattingScanner.getCurrentLeadingTrivia();
- if (leadingTrivia) {
- processTrivia(leadingTrivia, enclosingNode, enclosingNode, /*dynamicIndentation*/ undefined);
- trimTrailingWhitespacesForRemainingRange();
- }
- }
- return edits;
- // local functions
- /** Tries to compute the indentation for a list element.
- * If list element is not in range then
- * function will pick its actual indentation
- * so it can be pushed downstream as inherited indentation.
- * If list element is in the range - its indentation will be equal
- * to inherited indentation from its predecessors.
- */
- function tryComputeIndentationForListItem(startPos, endPos, parentStartLine, range, inheritedIndentation) {
- if (ts.rangeOverlapsWithStartEnd(range, startPos, endPos) ||
- ts.rangeContainsStartEnd(range, startPos, endPos) /* Not to miss zero-range nodes e.g. JsxText */) {
- if (inheritedIndentation !== -1 /* Unknown */) {
- return inheritedIndentation;
- }
- }
- else {
- var startLine = sourceFile.getLineAndCharacterOfPosition(startPos).line;
- var startLinePosition = ts.getLineStartPositionForPosition(startPos, sourceFile);
- var column = formatting.SmartIndenter.findFirstNonWhitespaceColumn(startLinePosition, startPos, sourceFile, options);
- if (startLine !== parentStartLine || startPos === column) {
- // Use the base indent size if it is greater than
- // the indentation of the inherited predecessor.
- var baseIndentSize = formatting.SmartIndenter.getBaseIndentation(options);
- return baseIndentSize > column ? baseIndentSize : column;
- }
- }
- return -1 /* Unknown */;
- }
- function computeIndentation(node, startLine, inheritedIndentation, parent, parentDynamicIndentation, effectiveParentStartLine) {
- var delta = formatting.SmartIndenter.shouldIndentChildNode(node) ? options.indentSize : 0;
- if (effectiveParentStartLine === startLine) {
- // if node is located on the same line with the parent
- // - inherit indentation from the parent
- // - push children if either parent of node itself has non-zero delta
- return {
- indentation: startLine === lastIndentedLine ? indentationOnLastIndentedLine : parentDynamicIndentation.getIndentation(),
- delta: Math.min(options.indentSize, parentDynamicIndentation.getDelta(node) + delta)
- };
- }
- else if (inheritedIndentation === -1 /* Unknown */) {
- if (node.kind === 19 /* OpenParenToken */ && startLine === lastIndentedLine) {
- // the is used for chaining methods formatting
- // - we need to get the indentation on last line and the delta of parent
- return { indentation: indentationOnLastIndentedLine, delta: parentDynamicIndentation.getDelta(node) };
- }
- else if (formatting.SmartIndenter.childStartsOnTheSameLineWithElseInIfStatement(parent, node, startLine, sourceFile)) {
- return { indentation: parentDynamicIndentation.getIndentation(), delta: delta };
- }
- else {
- return { indentation: parentDynamicIndentation.getIndentation() + parentDynamicIndentation.getDelta(node), delta: delta };
- }
- }
- else {
- return { indentation: inheritedIndentation, delta: delta };
- }
- }
- function getFirstNonDecoratorTokenOfNode(node) {
- if (node.modifiers && node.modifiers.length) {
- return node.modifiers[0].kind;
- }
- switch (node.kind) {
- case 233 /* ClassDeclaration */: return 75 /* ClassKeyword */;
- case 234 /* InterfaceDeclaration */: return 109 /* InterfaceKeyword */;
- case 232 /* FunctionDeclaration */: return 89 /* FunctionKeyword */;
- case 236 /* EnumDeclaration */: return 236 /* EnumDeclaration */;
- case 155 /* GetAccessor */: return 125 /* GetKeyword */;
- case 156 /* SetAccessor */: return 136 /* SetKeyword */;
- case 153 /* MethodDeclaration */:
- if (node.asteriskToken) {
- return 39 /* AsteriskToken */;
- }
- // falls through
- case 151 /* PropertyDeclaration */:
- case 148 /* Parameter */:
- return ts.getNameOfDeclaration(node).kind;
- }
- }
- function getDynamicIndentation(node, nodeStartLine, indentation, delta) {
- return {
- getIndentationForComment: function (kind, tokenIndentation, container) {
- switch (kind) {
- // preceding comment to the token that closes the indentation scope inherits the indentation from the scope
- // .. {
- // // comment
- // }
- case 18 /* CloseBraceToken */:
- case 22 /* CloseBracketToken */:
- case 20 /* CloseParenToken */:
- return indentation + getDelta(container);
- }
- return tokenIndentation !== -1 /* Unknown */ ? tokenIndentation : indentation;
- },
- getIndentationForToken: function (line, kind, container) {
- return shouldAddDelta(line, kind, container) ? indentation + getDelta(container) : indentation;
- },
- getIndentation: function () { return indentation; },
- getDelta: getDelta,
- recomputeIndentation: function (lineAdded) {
- if (node.parent && formatting.SmartIndenter.shouldIndentChildNode(node.parent, node)) {
- indentation += lineAdded ? options.indentSize : -options.indentSize;
- delta = formatting.SmartIndenter.shouldIndentChildNode(node) ? options.indentSize : 0;
- }
- }
- };
- function shouldAddDelta(line, kind, container) {
- switch (kind) {
- // open and close brace, 'else' and 'while' (in do statement) tokens has indentation of the parent
- case 17 /* OpenBraceToken */:
- case 18 /* CloseBraceToken */:
- case 19 /* OpenParenToken */:
- case 20 /* CloseParenToken */:
- case 82 /* ElseKeyword */:
- case 106 /* WhileKeyword */:
- case 57 /* AtToken */:
- return false;
- case 41 /* SlashToken */:
- case 29 /* GreaterThanToken */:
- switch (container.kind) {
- case 255 /* JsxOpeningElement */:
- case 256 /* JsxClosingElement */:
- case 254 /* JsxSelfClosingElement */:
- return false;
- }
- break;
- case 21 /* OpenBracketToken */:
- case 22 /* CloseBracketToken */:
- if (container.kind !== 176 /* MappedType */) {
- return false;
- }
- break;
- }
- // if token line equals to the line of containing node (this is a first token in the node) - use node indentation
- return nodeStartLine !== line
- // if this token is the first token following the list of decorators, we do not need to indent
- && !(node.decorators && kind === getFirstNonDecoratorTokenOfNode(node));
- }
- function getDelta(child) {
- // Delta value should be zero when the node explicitly prevents indentation of the child node
- return formatting.SmartIndenter.nodeWillIndentChild(node, child, /*indentByDefault*/ true) ? delta : 0;
- }
- }
- function processNode(node, contextNode, nodeStartLine, undecoratedNodeStartLine, indentation, delta) {
- if (!ts.rangeOverlapsWithStartEnd(originalRange, node.getStart(sourceFile), node.getEnd())) {
- return;
- }
- var nodeDynamicIndentation = getDynamicIndentation(node, nodeStartLine, indentation, delta);
- // a useful observations when tracking context node
- // /
- // [a]
- // / | \
- // [b] [c] [d]
- // node 'a' is a context node for nodes 'b', 'c', 'd'
- // except for the leftmost leaf token in [b] - in this case context node ('e') is located somewhere above 'a'
- // this rule can be applied recursively to child nodes of 'a'.
- //
- // context node is set to parent node value after processing every child node
- // context node is set to parent of the token after processing every token
- var childContextNode = contextNode;
- // if there are any tokens that logically belong to node and interleave child nodes
- // such tokens will be consumed in processChildNode for the child that follows them
- ts.forEachChild(node, function (child) {
- processChildNode(child, /*inheritedIndentation*/ -1 /* Unknown */, node, nodeDynamicIndentation, nodeStartLine, undecoratedNodeStartLine, /*isListItem*/ false);
- }, function (nodes) {
- processChildNodes(nodes, node, nodeStartLine, nodeDynamicIndentation);
- });
- // proceed any tokens in the node that are located after child nodes
- while (formattingScanner.isOnToken()) {
- var tokenInfo = formattingScanner.readTokenInfo(node);
- if (tokenInfo.token.end > node.end) {
- break;
- }
- consumeTokenAndAdvanceScanner(tokenInfo, node, nodeDynamicIndentation, node);
- }
- function processChildNode(child, inheritedIndentation, parent, parentDynamicIndentation, parentStartLine, undecoratedParentStartLine, isListItem, isFirstListItem) {
- var childStartPos = child.getStart(sourceFile);
- var childStartLine = sourceFile.getLineAndCharacterOfPosition(childStartPos).line;
- var undecoratedChildStartLine = childStartLine;
- if (child.decorators) {
- undecoratedChildStartLine = sourceFile.getLineAndCharacterOfPosition(ts.getNonDecoratorTokenPosOfNode(child, sourceFile)).line;
- }
- // if child is a list item - try to get its indentation, only if parent is within the original range.
- var childIndentationAmount = -1 /* Unknown */;
- if (isListItem && ts.rangeContainsRange(originalRange, parent)) {
- childIndentationAmount = tryComputeIndentationForListItem(childStartPos, child.end, parentStartLine, originalRange, inheritedIndentation);
- if (childIndentationAmount !== -1 /* Unknown */) {
- inheritedIndentation = childIndentationAmount;
- }
- }
- // child node is outside the target range - do not dive inside
- if (!ts.rangeOverlapsWithStartEnd(originalRange, child.pos, child.end)) {
- if (child.end < originalRange.pos) {
- formattingScanner.skipToEndOf(child);
- }
- return inheritedIndentation;
- }
- if (child.getFullWidth() === 0) {
- return inheritedIndentation;
- }
- while (formattingScanner.isOnToken()) {
- // proceed any parent tokens that are located prior to child.getStart()
- var tokenInfo = formattingScanner.readTokenInfo(node);
- if (tokenInfo.token.end > childStartPos) {
- // stop when formatting scanner advances past the beginning of the child
- break;
- }
- consumeTokenAndAdvanceScanner(tokenInfo, node, parentDynamicIndentation, node);
- }
- if (!formattingScanner.isOnToken()) {
- return inheritedIndentation;
- }
- // JSX text shouldn't affect indenting
- if (ts.isToken(child) && child.kind !== 10 /* JsxText */) {
- // if child node is a token, it does not impact indentation, proceed it using parent indentation scope rules
- var tokenInfo = formattingScanner.readTokenInfo(child);
- ts.Debug.assert(tokenInfo.token.end === child.end, "Token end is child end");
- consumeTokenAndAdvanceScanner(tokenInfo, node, parentDynamicIndentation, child);
- return inheritedIndentation;
- }
- var effectiveParentStartLine = child.kind === 149 /* Decorator */ ? childStartLine : undecoratedParentStartLine;
- var childIndentation = computeIndentation(child, childStartLine, childIndentationAmount, node, parentDynamicIndentation, effectiveParentStartLine);
- processNode(child, childContextNode, childStartLine, undecoratedChildStartLine, childIndentation.indentation, childIndentation.delta);
- if (child.kind === 10 /* JsxText */) {
- var range = { pos: child.getStart(), end: child.getEnd() };
- indentMultilineCommentOrJsxText(range, childIndentation.indentation, /*firstLineIsIndented*/ true, /*indentFinalLine*/ false);
- }
- childContextNode = node;
- if (isFirstListItem && parent.kind === 181 /* ArrayLiteralExpression */ && inheritedIndentation === -1 /* Unknown */) {
- inheritedIndentation = childIndentation.indentation;
- }
- return inheritedIndentation;
- }
- function processChildNodes(nodes, parent, parentStartLine, parentDynamicIndentation) {
- ts.Debug.assert(ts.isNodeArray(nodes));
- var listStartToken = getOpenTokenForList(parent, nodes);
- var listEndToken = getCloseTokenForOpenToken(listStartToken);
- var listDynamicIndentation = parentDynamicIndentation;
- var startLine = parentStartLine;
- if (listStartToken !== 0 /* Unknown */) {
- // introduce a new indentation scope for lists (including list start and end tokens)
- while (formattingScanner.isOnToken()) {
- var tokenInfo = formattingScanner.readTokenInfo(parent);
- if (tokenInfo.token.end > nodes.pos) {
- // stop when formatting scanner moves past the beginning of node list
- break;
- }
- else if (tokenInfo.token.kind === listStartToken) {
- // consume list start token
- startLine = sourceFile.getLineAndCharacterOfPosition(tokenInfo.token.pos).line;
- var indentation_1 = computeIndentation(tokenInfo.token, startLine, -1 /* Unknown */, parent, parentDynamicIndentation, parentStartLine);
- listDynamicIndentation = getDynamicIndentation(parent, parentStartLine, indentation_1.indentation, indentation_1.delta);
- consumeTokenAndAdvanceScanner(tokenInfo, parent, listDynamicIndentation, parent);
- }
- else {
- // consume any tokens that precede the list as child elements of 'node' using its indentation scope
- consumeTokenAndAdvanceScanner(tokenInfo, parent, parentDynamicIndentation, parent);
- }
- }
- }
- var inheritedIndentation = -1 /* Unknown */;
- for (var i = 0; i < nodes.length; i++) {
- var child = nodes[i];
- inheritedIndentation = processChildNode(child, inheritedIndentation, node, listDynamicIndentation, startLine, startLine, /*isListItem*/ true, /*isFirstListItem*/ i === 0);
- }
- if (listEndToken !== 0 /* Unknown */) {
- if (formattingScanner.isOnToken()) {
- var tokenInfo = formattingScanner.readTokenInfo(parent);
- // consume the list end token only if it is still belong to the parent
- // there might be the case when current token matches end token but does not considered as one
- // function (x: function) <--
- // without this check close paren will be interpreted as list end token for function expression which is wrong
- if (tokenInfo.token.kind === listEndToken && ts.rangeContainsRange(parent, tokenInfo.token)) {
- // consume list end token
- consumeTokenAndAdvanceScanner(tokenInfo, parent, listDynamicIndentation, parent);
- }
- }
- }
- }
- function consumeTokenAndAdvanceScanner(currentTokenInfo, parent, dynamicIndentation, container) {
- ts.Debug.assert(ts.rangeContainsRange(parent, currentTokenInfo.token));
- var lastTriviaWasNewLine = formattingScanner.lastTrailingTriviaWasNewLine();
- var indentToken = false;
- if (currentTokenInfo.leadingTrivia) {
- processTrivia(currentTokenInfo.leadingTrivia, parent, childContextNode, dynamicIndentation);
- }
- var lineAction = 0 /* None */;
- var isTokenInRange = ts.rangeContainsRange(originalRange, currentTokenInfo.token);
- var tokenStart = sourceFile.getLineAndCharacterOfPosition(currentTokenInfo.token.pos);
- if (isTokenInRange) {
- var rangeHasError = rangeContainsError(currentTokenInfo.token);
- // save previousRange since processRange will overwrite this value with current one
- var savePreviousRange = previousRange;
- lineAction = processRange(currentTokenInfo.token, tokenStart, parent, childContextNode, dynamicIndentation);
- // do not indent comments\token if token range overlaps with some error
- if (!rangeHasError) {
- if (lineAction === 0 /* None */) {
- // indent token only if end line of previous range does not match start line of the token
- var prevEndLine = savePreviousRange && sourceFile.getLineAndCharacterOfPosition(savePreviousRange.end).line;
- indentToken = lastTriviaWasNewLine && tokenStart.line !== prevEndLine;
- }
- else {
- indentToken = lineAction === 1 /* LineAdded */;
- }
- }
- }
- if (currentTokenInfo.trailingTrivia) {
- processTrivia(currentTokenInfo.trailingTrivia, parent, childContextNode, dynamicIndentation);
- }
- if (indentToken) {
- var tokenIndentation = (isTokenInRange && !rangeContainsError(currentTokenInfo.token)) ?
- dynamicIndentation.getIndentationForToken(tokenStart.line, currentTokenInfo.token.kind, container) :
- -1 /* Unknown */;
- var indentNextTokenOrTrivia = true;
- if (currentTokenInfo.leadingTrivia) {
- var commentIndentation = dynamicIndentation.getIndentationForComment(currentTokenInfo.token.kind, tokenIndentation, container);
- for (var _i = 0, _a = currentTokenInfo.leadingTrivia; _i < _a.length; _i++) {
- var triviaItem = _a[_i];
- var triviaInRange = ts.rangeContainsRange(originalRange, triviaItem);
- switch (triviaItem.kind) {
- case 3 /* MultiLineCommentTrivia */:
- if (triviaInRange) {
- indentMultilineCommentOrJsxText(triviaItem, commentIndentation, /*firstLineIsIndented*/ !indentNextTokenOrTrivia);
- }
- indentNextTokenOrTrivia = false;
- break;
- case 2 /* SingleLineCommentTrivia */:
- if (indentNextTokenOrTrivia && triviaInRange) {
- insertIndentation(triviaItem.pos, commentIndentation, /*lineAdded*/ false);
- }
- indentNextTokenOrTrivia = false;
- break;
- case 4 /* NewLineTrivia */:
- indentNextTokenOrTrivia = true;
- break;
- }
- }
- }
- // indent token only if is it is in target range and does not overlap with any error ranges
- if (tokenIndentation !== -1 /* Unknown */ && indentNextTokenOrTrivia) {
- insertIndentation(currentTokenInfo.token.pos, tokenIndentation, lineAction === 1 /* LineAdded */);
- lastIndentedLine = tokenStart.line;
- indentationOnLastIndentedLine = tokenIndentation;
- }
- }
- formattingScanner.advance();
- childContextNode = parent;
- }
- }
- function processTrivia(trivia, parent, contextNode, dynamicIndentation) {
- for (var _i = 0, trivia_1 = trivia; _i < trivia_1.length; _i++) {
- var triviaItem = trivia_1[_i];
- if (ts.isComment(triviaItem.kind) && ts.rangeContainsRange(originalRange, triviaItem)) {
- var triviaItemStart = sourceFile.getLineAndCharacterOfPosition(triviaItem.pos);
- processRange(triviaItem, triviaItemStart, parent, contextNode, dynamicIndentation);
- }
- }
- }
- function processRange(range, rangeStart, parent, contextNode, dynamicIndentation) {
- var rangeHasError = rangeContainsError(range);
- var lineAction = 0 /* None */;
- if (!rangeHasError) {
- if (!previousRange) {
- // trim whitespaces starting from the beginning of the span up to the current line
- var originalStart = sourceFile.getLineAndCharacterOfPosition(originalRange.pos);
- trimTrailingWhitespacesForLines(originalStart.line, rangeStart.line);
- }
- else {
- lineAction =
- processPair(range, rangeStart.line, parent, previousRange, previousRangeStartLine, previousParent, contextNode, dynamicIndentation);
- }
- }
- previousRange = range;
- previousParent = parent;
- previousRangeStartLine = rangeStart.line;
- return lineAction;
- }
- function processPair(currentItem, currentStartLine, currentParent, previousItem, previousStartLine, previousParent, contextNode, dynamicIndentation) {
- formattingContext.updateContext(previousItem, previousParent, currentItem, currentParent, contextNode);
- var rule = getRule(formattingContext);
- var trimTrailingWhitespaces;
- var lineAction = 0 /* None */;
- if (rule) {
- lineAction = applyRuleEdits(rule, previousItem, previousStartLine, currentItem, currentStartLine);
- switch (lineAction) {
- case 2 /* LineRemoved */:
- // Handle the case where the next line is moved to be the end of this line.
- // In this case we don't indent the next line in the next pass.
- if (currentParent.getStart(sourceFile) === currentItem.pos) {
- dynamicIndentation.recomputeIndentation(/*lineAddedByFormatting*/ false);
- }
- break;
- case 1 /* LineAdded */:
- // Handle the case where token2 is moved to the new line.
- // In this case we indent token2 in the next pass but we set
- // sameLineIndent flag to notify the indenter that the indentation is within the line.
- if (currentParent.getStart(sourceFile) === currentItem.pos) {
- dynamicIndentation.recomputeIndentation(/*lineAddedByFormatting*/ true);
- }
- break;
- default:
- ts.Debug.assert(lineAction === 0 /* None */);
- }
- // We need to trim trailing whitespace between the tokens if they were on different lines, and no rule was applied to put them on the same line
- trimTrailingWhitespaces = !(rule.action & 8 /* Delete */) && rule.flags !== 1 /* CanDeleteNewLines */;
- }
- else {
- trimTrailingWhitespaces = true;
- }
- if (currentStartLine !== previousStartLine && trimTrailingWhitespaces) {
- // We need to trim trailing whitespace between the tokens if they were on different lines, and no rule was applied to put them on the same line
- trimTrailingWhitespacesForLines(previousStartLine, currentStartLine, previousItem);
- }
- return lineAction;
- }
- function insertIndentation(pos, indentation, lineAdded) {
- var indentationString = getIndentationString(indentation, options);
- if (lineAdded) {
- // new line is added before the token by the formatting rules
- // insert indentation string at the very beginning of the token
- recordReplace(pos, 0, indentationString);
- }
- else {
- var tokenStart = sourceFile.getLineAndCharacterOfPosition(pos);
- var startLinePosition = ts.getStartPositionOfLine(tokenStart.line, sourceFile);
- if (indentation !== characterToColumn(startLinePosition, tokenStart.character) || indentationIsDifferent(indentationString, startLinePosition)) {
- recordReplace(startLinePosition, tokenStart.character, indentationString);
- }
- }
- }
- function characterToColumn(startLinePosition, characterInLine) {
- var column = 0;
- for (var i = 0; i < characterInLine; i++) {
- if (sourceFile.text.charCodeAt(startLinePosition + i) === 9 /* tab */) {
- column += options.tabSize - column % options.tabSize;
- }
- else {
- column++;
- }
- }
- return column;
- }
- function indentationIsDifferent(indentationString, startLinePosition) {
- return indentationString !== sourceFile.text.substr(startLinePosition, indentationString.length);
- }
- function indentMultilineCommentOrJsxText(commentRange, indentation, firstLineIsIndented, indentFinalLine) {
- if (indentFinalLine === void 0) { indentFinalLine = true; }
- // split comment in lines
- var startLine = sourceFile.getLineAndCharacterOfPosition(commentRange.pos).line;
- var endLine = sourceFile.getLineAndCharacterOfPosition(commentRange.end).line;
- var parts;
- if (startLine === endLine) {
- if (!firstLineIsIndented) {
- // treat as single line comment
- insertIndentation(commentRange.pos, indentation, /*lineAdded*/ false);
- }
- return;
- }
- else {
- parts = [];
- var startPos = commentRange.pos;
- for (var line = startLine; line < endLine; line++) {
- var endOfLine = ts.getEndLinePosition(line, sourceFile);
- parts.push({ pos: startPos, end: endOfLine });
- startPos = ts.getStartPositionOfLine(line + 1, sourceFile);
- }
- if (indentFinalLine) {
- parts.push({ pos: startPos, end: commentRange.end });
- }
- }
- var startLinePos = ts.getStartPositionOfLine(startLine, sourceFile);
- var nonWhitespaceColumnInFirstPart = formatting.SmartIndenter.findFirstNonWhitespaceCharacterAndColumn(startLinePos, parts[0].pos, sourceFile, options);
- if (indentation === nonWhitespaceColumnInFirstPart.column) {
- return;
- }
- var startIndex = 0;
- if (firstLineIsIndented) {
- startIndex = 1;
- startLine++;
- }
- // shift all parts on the delta size
- var delta = indentation - nonWhitespaceColumnInFirstPart.column;
- for (var i = startIndex; i < parts.length; i++, startLine++) {
- var startLinePos_1 = ts.getStartPositionOfLine(startLine, sourceFile);
- var nonWhitespaceCharacterAndColumn = i === 0
- ? nonWhitespaceColumnInFirstPart
- : formatting.SmartIndenter.findFirstNonWhitespaceCharacterAndColumn(parts[i].pos, parts[i].end, sourceFile, options);
- var newIndentation = nonWhitespaceCharacterAndColumn.column + delta;
- if (newIndentation > 0) {
- var indentationString = getIndentationString(newIndentation, options);
- recordReplace(startLinePos_1, nonWhitespaceCharacterAndColumn.character, indentationString);
- }
- else {
- recordDelete(startLinePos_1, nonWhitespaceCharacterAndColumn.character);
- }
- }
- }
- function trimTrailingWhitespacesForLines(line1, line2, range) {
- for (var line = line1; line < line2; line++) {
- var lineStartPosition = ts.getStartPositionOfLine(line, sourceFile);
- var lineEndPosition = ts.getEndLinePosition(line, sourceFile);
- // do not trim whitespaces in comments or template expression
- if (range && (ts.isComment(range.kind) || ts.isStringOrRegularExpressionOrTemplateLiteral(range.kind)) && range.pos <= lineEndPosition && range.end > lineEndPosition) {
- continue;
- }
- var whitespaceStart = getTrailingWhitespaceStartPosition(lineStartPosition, lineEndPosition);
- if (whitespaceStart !== -1) {
- ts.Debug.assert(whitespaceStart === lineStartPosition || !ts.isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(whitespaceStart - 1)));
- recordDelete(whitespaceStart, lineEndPosition + 1 - whitespaceStart);
- }
- }
- }
- /**
- * @param start The position of the first character in range
- * @param end The position of the last character in range
- */
- function getTrailingWhitespaceStartPosition(start, end) {
- var pos = end;
- while (pos >= start && ts.isWhiteSpaceSingleLine(sourceFile.text.charCodeAt(pos))) {
- pos--;
- }
- if (pos !== end) {
- return pos + 1;
- }
- return -1;
- }
- /**
- * Trimming will be done for lines after the previous range
- */
- function trimTrailingWhitespacesForRemainingRange() {
- var startPosition = previousRange ? previousRange.end : originalRange.pos;
- var startLine = sourceFile.getLineAndCharacterOfPosition(startPosition).line;
- var endLine = sourceFile.getLineAndCharacterOfPosition(originalRange.end).line;
- trimTrailingWhitespacesForLines(startLine, endLine + 1, previousRange);
- }
- function recordDelete(start, len) {
- if (len) {
- edits.push(ts.createTextChangeFromStartLength(start, len, ""));
- }
- }
- function recordReplace(start, len, newText) {
- if (len || newText) {
- edits.push(ts.createTextChangeFromStartLength(start, len, newText));
- }
- }
- function applyRuleEdits(rule, previousRange, previousStartLine, currentRange, currentStartLine) {
- var onLaterLine = currentStartLine !== previousStartLine;
- switch (rule.action) {
- case 1 /* Ignore */:
- // no action required
- return 0 /* None */;
- case 8 /* Delete */:
- if (previousRange.end !== currentRange.pos) {
- // delete characters starting from t1.end up to t2.pos exclusive
- recordDelete(previousRange.end, currentRange.pos - previousRange.end);
- return onLaterLine ? 2 /* LineRemoved */ : 0 /* None */;
- }
- break;
- case 4 /* NewLine */:
- // exit early if we on different lines and rule cannot change number of newlines
- // if line1 and line2 are on subsequent lines then no edits are required - ok to exit
- // if line1 and line2 are separated with more than one newline - ok to exit since we cannot delete extra new lines
- if (rule.flags !== 1 /* CanDeleteNewLines */ && previousStartLine !== currentStartLine) {
- return 0 /* None */;
- }
- // edit should not be applied if we have one line feed between elements
- var lineDelta = currentStartLine - previousStartLine;
- if (lineDelta !== 1) {
- recordReplace(previousRange.end, currentRange.pos - previousRange.end, options.newLineCharacter);
- return onLaterLine ? 0 /* None */ : 1 /* LineAdded */;
- }
- break;
- case 2 /* Space */:
- // exit early if we on different lines and rule cannot change number of newlines
- if (rule.flags !== 1 /* CanDeleteNewLines */ && previousStartLine !== currentStartLine) {
- return 0 /* None */;
- }
- var posDelta = currentRange.pos - previousRange.end;
- if (posDelta !== 1 || sourceFile.text.charCodeAt(previousRange.end) !== 32 /* space */) {
- recordReplace(previousRange.end, currentRange.pos - previousRange.end, " ");
- return onLaterLine ? 2 /* LineRemoved */ : 0 /* None */;
- }
- }
- return 0 /* None */;
- }
- }
- var LineAction;
- (function (LineAction) {
- LineAction[LineAction["None"] = 0] = "None";
- LineAction[LineAction["LineAdded"] = 1] = "LineAdded";
- LineAction[LineAction["LineRemoved"] = 2] = "LineRemoved";
- })(LineAction || (LineAction = {}));
- /**
- * @param precedingToken pass `null` if preceding token was already computed and result was `undefined`.
- */
- function getRangeOfEnclosingComment(sourceFile, position, onlyMultiLine, precedingToken, // tslint:disable-line:no-null-keyword
- tokenAtPosition, predicate) {
- if (tokenAtPosition === void 0) { tokenAtPosition = ts.getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false); }
- var tokenStart = tokenAtPosition.getStart(sourceFile);
- if (tokenStart <= position && position < tokenAtPosition.getEnd()) {
- return undefined;
- }
- if (precedingToken === undefined) {
- precedingToken = ts.findPrecedingToken(position, sourceFile);
- }
- // Between two consecutive tokens, all comments are either trailing on the former
- // or leading on the latter (and none are in both lists).
- var trailingRangesOfPreviousToken = precedingToken && ts.getTrailingCommentRanges(sourceFile.text, precedingToken.end);
- var leadingCommentRangesOfNextToken = ts.getLeadingCommentRangesOfNode(tokenAtPosition, sourceFile);
- var commentRanges = trailingRangesOfPreviousToken && leadingCommentRangesOfNextToken ?
- trailingRangesOfPreviousToken.concat(leadingCommentRangesOfNextToken) :
- trailingRangesOfPreviousToken || leadingCommentRangesOfNextToken;
- if (commentRanges) {
- for (var _i = 0, commentRanges_1 = commentRanges; _i < commentRanges_1.length; _i++) {
- var range = commentRanges_1[_i];
- // The end marker of a single-line comment does not include the newline character.
- // With caret at `^`, in the following case, we are inside a comment (^ denotes the cursor position):
- //
- // // asdf ^\n
- //
- // But for closed multi-line comments, we don't want to be inside the comment in the following case:
- //
- // /* asdf */^
- //
- // However, unterminated multi-line comments *do* contain their end.
- //
- // Internally, we represent the end of the comment at the newline and closing '/', respectively.
- //
- if ((range.pos < position && position < range.end ||
- position === range.end && (range.kind === 2 /* SingleLineCommentTrivia */ || position === sourceFile.getFullWidth()))) {
- return (range.kind === 3 /* MultiLineCommentTrivia */ || !onlyMultiLine) && (!predicate || predicate(range)) ? range : undefined;
- }
- }
- }
- return undefined;
- }
- formatting.getRangeOfEnclosingComment = getRangeOfEnclosingComment;
- function getOpenTokenForList(node, list) {
- switch (node.kind) {
- case 154 /* Constructor */:
- case 232 /* FunctionDeclaration */:
- case 190 /* FunctionExpression */:
- case 153 /* MethodDeclaration */:
- case 152 /* MethodSignature */:
- case 191 /* ArrowFunction */:
- if (node.typeParameters === list) {
- return 27 /* LessThanToken */;
- }
- else if (node.parameters === list) {
- return 19 /* OpenParenToken */;
- }
- break;
- case 185 /* CallExpression */:
- case 186 /* NewExpression */:
- if (node.typeArguments === list) {
- return 27 /* LessThanToken */;
- }
- else if (node.arguments === list) {
- return 19 /* OpenParenToken */;
- }
- break;
- case 161 /* TypeReference */:
- if (node.typeArguments === list) {
- return 27 /* LessThanToken */;
- }
- }
- return 0 /* Unknown */;
- }
- function getCloseTokenForOpenToken(kind) {
- switch (kind) {
- case 19 /* OpenParenToken */:
- return 20 /* CloseParenToken */;
- case 27 /* LessThanToken */:
- return 29 /* GreaterThanToken */;
- }
- return 0 /* Unknown */;
- }
- var internedSizes;
- var internedTabsIndentation;
- var internedSpacesIndentation;
- function getIndentationString(indentation, options) {
- // reset interned strings if FormatCodeOptions were changed
- var resetInternedStrings = !internedSizes || (internedSizes.tabSize !== options.tabSize || internedSizes.indentSize !== options.indentSize);
- if (resetInternedStrings) {
- internedSizes = { tabSize: options.tabSize, indentSize: options.indentSize };
- internedTabsIndentation = internedSpacesIndentation = undefined;
- }
- if (!options.convertTabsToSpaces) {
- var tabs = Math.floor(indentation / options.tabSize);
- var spaces = indentation - tabs * options.tabSize;
- var tabString = void 0;
- if (!internedTabsIndentation) {
- internedTabsIndentation = [];
- }
- if (internedTabsIndentation[tabs] === undefined) {
- internedTabsIndentation[tabs] = tabString = ts.repeatString("\t", tabs);
- }
- else {
- tabString = internedTabsIndentation[tabs];
- }
- return spaces ? tabString + ts.repeatString(" ", spaces) : tabString;
- }
- else {
- var spacesString = void 0;
- var quotient = Math.floor(indentation / options.indentSize);
- var remainder = indentation % options.indentSize;
- if (!internedSpacesIndentation) {
- internedSpacesIndentation = [];
- }
- if (internedSpacesIndentation[quotient] === undefined) {
- spacesString = ts.repeatString(" ", options.indentSize * quotient);
- internedSpacesIndentation[quotient] = spacesString;
- }
- else {
- spacesString = internedSpacesIndentation[quotient];
- }
- return remainder ? spacesString + ts.repeatString(" ", remainder) : spacesString;
- }
- }
- formatting.getIndentationString = getIndentationString;
- })(formatting = ts.formatting || (ts.formatting = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var formatting;
- (function (formatting) {
- var SmartIndenter;
- (function (SmartIndenter) {
- var Value;
- (function (Value) {
- Value[Value["Unknown"] = -1] = "Unknown";
- })(Value || (Value = {}));
- /**
- * @param assumeNewLineBeforeCloseBrace
- * `false` when called on text from a real source file.
- * `true` when we need to assume `position` is on a newline.
- *
- * This is useful for codefixes. Consider
- * ```
- * function f() {
- * |}
- * ```
- * with `position` at `|`.
- *
- * When inserting some text after an open brace, we would like to get indentation as if a newline was already there.
- * By default indentation at `position` will be 0 so 'assumeNewLineBeforeCloseBrace' overrides this behavior.
- */
- function getIndentation(position, sourceFile, options, assumeNewLineBeforeCloseBrace) {
- if (assumeNewLineBeforeCloseBrace === void 0) { assumeNewLineBeforeCloseBrace = false; }
- if (position > sourceFile.text.length) {
- return getBaseIndentation(options); // past EOF
- }
- // no indentation when the indent style is set to none,
- // so we can return fast
- if (options.indentStyle === ts.IndentStyle.None) {
- return 0;
- }
- var precedingToken = ts.findPrecedingToken(position, sourceFile);
- var enclosingCommentRange = formatting.getRangeOfEnclosingComment(sourceFile, position, /*onlyMultiLine*/ true, precedingToken || null); // tslint:disable-line:no-null-keyword
- if (enclosingCommentRange) {
- return getCommentIndent(sourceFile, position, options, enclosingCommentRange);
- }
- if (!precedingToken) {
- return getBaseIndentation(options);
- }
- // no indentation in string \regex\template literals
- var precedingTokenIsLiteral = ts.isStringOrRegularExpressionOrTemplateLiteral(precedingToken.kind);
- if (precedingTokenIsLiteral && precedingToken.getStart(sourceFile) <= position && position < precedingToken.end) {
- return 0;
- }
- var lineAtPosition = sourceFile.getLineAndCharacterOfPosition(position).line;
- // indentation is first non-whitespace character in a previous line
- // for block indentation, we should look for a line which contains something that's not
- // whitespace.
- if (options.indentStyle === ts.IndentStyle.Block) {
- return getBlockIndent(sourceFile, position, options);
- }
- if (precedingToken.kind === 26 /* CommaToken */ && precedingToken.parent.kind !== 198 /* BinaryExpression */) {
- // previous token is comma that separates items in list - find the previous item and try to derive indentation from it
- var actualIndentation = getActualIndentationForListItemBeforeComma(precedingToken, sourceFile, options);
- if (actualIndentation !== -1 /* Unknown */) {
- return actualIndentation;
- }
- }
- return getSmartIndent(sourceFile, position, precedingToken, lineAtPosition, assumeNewLineBeforeCloseBrace, options);
- }
- SmartIndenter.getIndentation = getIndentation;
- function getCommentIndent(sourceFile, position, options, enclosingCommentRange) {
- var previousLine = ts.getLineAndCharacterOfPosition(sourceFile, position).line - 1;
- var commentStartLine = ts.getLineAndCharacterOfPosition(sourceFile, enclosingCommentRange.pos).line;
- ts.Debug.assert(commentStartLine >= 0);
- if (previousLine <= commentStartLine) {
- return findFirstNonWhitespaceColumn(ts.getStartPositionOfLine(commentStartLine, sourceFile), position, sourceFile, options);
- }
- var startPostionOfLine = ts.getStartPositionOfLine(previousLine, sourceFile);
- var _a = findFirstNonWhitespaceCharacterAndColumn(startPostionOfLine, position, sourceFile, options), column = _a.column, character = _a.character;
- if (column === 0) {
- return column;
- }
- var firstNonWhitespaceCharacterCode = sourceFile.text.charCodeAt(startPostionOfLine + character);
- return firstNonWhitespaceCharacterCode === 42 /* asterisk */ ? column - 1 : column;
- }
- function getBlockIndent(sourceFile, position, options) {
- // move backwards until we find a line with a non-whitespace character,
- // then find the first non-whitespace character for that line.
- var current = position;
- while (current > 0) {
- var char = sourceFile.text.charCodeAt(current);
- if (!ts.isWhiteSpaceLike(char)) {
- break;
- }
- current--;
- }
- var lineStart = ts.getLineStartPositionForPosition(current, sourceFile);
- return findFirstNonWhitespaceColumn(lineStart, current, sourceFile, options);
- }
- function getSmartIndent(sourceFile, position, precedingToken, lineAtPosition, assumeNewLineBeforeCloseBrace, options) {
- // try to find node that can contribute to indentation and includes 'position' starting from 'precedingToken'
- // if such node is found - compute initial indentation for 'position' inside this node
- var previous;
- var current = precedingToken;
- while (current) {
- if (ts.positionBelongsToNode(current, position, sourceFile) && shouldIndentChildNode(current, previous, /*isNextChild*/ true)) {
- var currentStart = getStartLineAndCharacterForNode(current, sourceFile);
- var nextTokenKind = nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken, current, lineAtPosition, sourceFile);
- var indentationDelta = nextTokenKind !== 0 /* Unknown */
- // handle cases when codefix is about to be inserted before the close brace
- ? assumeNewLineBeforeCloseBrace && nextTokenKind === 2 /* CloseBrace */ ? options.indentSize : 0
- : lineAtPosition !== currentStart.line ? options.indentSize : 0;
- return getIndentationForNodeWorker(current, currentStart, /*ignoreActualIndentationRange*/ undefined, indentationDelta, sourceFile, /*isNextChild*/ true, options);
- }
- // check if current node is a list item - if yes, take indentation from it
- var actualIndentation = getActualIndentationForListItem(current, sourceFile, options);
- if (actualIndentation !== -1 /* Unknown */) {
- return actualIndentation;
- }
- actualIndentation = getLineIndentationWhenExpressionIsInMultiLine(current, sourceFile, options);
- if (actualIndentation !== -1 /* Unknown */) {
- return actualIndentation + options.indentSize;
- }
- previous = current;
- current = current.parent;
- }
- // no parent was found - return the base indentation of the SourceFile
- return getBaseIndentation(options);
- }
- function getIndentationForNode(n, ignoreActualIndentationRange, sourceFile, options) {
- var start = sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile));
- return getIndentationForNodeWorker(n, start, ignoreActualIndentationRange, /*indentationDelta*/ 0, sourceFile, /*isNextChild*/ false, options);
- }
- SmartIndenter.getIndentationForNode = getIndentationForNode;
- function getBaseIndentation(options) {
- return options.baseIndentSize || 0;
- }
- SmartIndenter.getBaseIndentation = getBaseIndentation;
- function getIndentationForNodeWorker(current, currentStart, ignoreActualIndentationRange, indentationDelta, sourceFile, isNextChild, options) {
- var parent = current.parent;
- // Walk up the tree and collect indentation for parent-child node pairs. Indentation is not added if
- // * parent and child nodes start on the same line, or
- // * parent is an IfStatement and child starts on the same line as an 'else clause'.
- while (parent) {
- var useActualIndentation = true;
- if (ignoreActualIndentationRange) {
- var start = current.getStart(sourceFile);
- useActualIndentation = start < ignoreActualIndentationRange.pos || start > ignoreActualIndentationRange.end;
- }
- if (useActualIndentation) {
- // check if current node is a list item - if yes, take indentation from it
- var actualIndentation = getActualIndentationForListItem(current, sourceFile, options);
- if (actualIndentation !== -1 /* Unknown */) {
- return actualIndentation + indentationDelta;
- }
- }
- var containingListOrParentStart = getContainingListOrParentStart(parent, current, sourceFile);
- var parentAndChildShareLine = containingListOrParentStart.line === currentStart.line ||
- childStartsOnTheSameLineWithElseInIfStatement(parent, current, currentStart.line, sourceFile);
- if (useActualIndentation) {
- // try to fetch actual indentation for current node from source text
- var actualIndentation = getActualIndentationForNode(current, parent, currentStart, parentAndChildShareLine, sourceFile, options);
- if (actualIndentation !== -1 /* Unknown */) {
- return actualIndentation + indentationDelta;
- }
- actualIndentation = getLineIndentationWhenExpressionIsInMultiLine(current, sourceFile, options);
- if (actualIndentation !== -1 /* Unknown */) {
- return actualIndentation + indentationDelta;
- }
- }
- // increase indentation if parent node wants its content to be indented and parent and child nodes don't start on the same line
- if (shouldIndentChildNode(parent, current, isNextChild) && !parentAndChildShareLine) {
- indentationDelta += options.indentSize;
- }
- // In our AST, a call argument's `parent` is the call-expression, not the argument list.
- // We would like to increase indentation based on the relationship between an argument and its argument-list,
- // so we spoof the starting position of the (parent) call-expression to match the (non-parent) argument-list.
- // But, the spoofed start-value could then cause a problem when comparing the start position of the call-expression
- // to *its* parent (in the case of an iife, an expression statement), adding an extra level of indentation.
- //
- // Instead, when at an argument, we unspoof the starting position of the enclosing call expression
- // *after* applying indentation for the argument.
- var useTrueStart = isArgumentAndStartLineOverlapsExpressionBeingCalled(parent, current, currentStart.line, sourceFile);
- current = parent;
- parent = current.parent;
- currentStart = useTrueStart ? sourceFile.getLineAndCharacterOfPosition(current.getStart(sourceFile)) : containingListOrParentStart;
- }
- return indentationDelta + getBaseIndentation(options);
- }
- function getContainingListOrParentStart(parent, child, sourceFile) {
- var containingList = getContainingList(child, sourceFile);
- var startPos = containingList ? containingList.pos : parent.getStart(sourceFile);
- return sourceFile.getLineAndCharacterOfPosition(startPos);
- }
- /*
- * Function returns Value.Unknown if indentation cannot be determined
- */
- function getActualIndentationForListItemBeforeComma(commaToken, sourceFile, options) {
- // previous token is comma that separates items in list - find the previous item and try to derive indentation from it
- var commaItemInfo = ts.findListItemInfo(commaToken);
- if (commaItemInfo && commaItemInfo.listItemIndex > 0) {
- return deriveActualIndentationFromList(commaItemInfo.list.getChildren(), commaItemInfo.listItemIndex - 1, sourceFile, options);
- }
- else {
- // handle broken code gracefully
- return -1 /* Unknown */;
- }
- }
- /*
- * Function returns Value.Unknown if actual indentation for node should not be used (i.e because node is nested expression)
- */
- function getActualIndentationForNode(current, parent, currentLineAndChar, parentAndChildShareLine, sourceFile, options) {
- // actual indentation is used for statements\declarations if one of cases below is true:
- // - parent is SourceFile - by default immediate children of SourceFile are not indented except when user indents them manually
- // - parent and child are not on the same line
- var useActualIndentation = (ts.isDeclaration(current) || ts.isStatementButNotDeclaration(current)) &&
- (parent.kind === 272 /* SourceFile */ || !parentAndChildShareLine);
- if (!useActualIndentation) {
- return -1 /* Unknown */;
- }
- return findColumnForFirstNonWhitespaceCharacterInLine(currentLineAndChar, sourceFile, options);
- }
- var NextTokenKind;
- (function (NextTokenKind) {
- NextTokenKind[NextTokenKind["Unknown"] = 0] = "Unknown";
- NextTokenKind[NextTokenKind["OpenBrace"] = 1] = "OpenBrace";
- NextTokenKind[NextTokenKind["CloseBrace"] = 2] = "CloseBrace";
- })(NextTokenKind || (NextTokenKind = {}));
- function nextTokenIsCurlyBraceOnSameLineAsCursor(precedingToken, current, lineAtPosition, sourceFile) {
- var nextToken = ts.findNextToken(precedingToken, current);
- if (!nextToken) {
- return 0 /* Unknown */;
- }
- if (nextToken.kind === 17 /* OpenBraceToken */) {
- // open braces are always indented at the parent level
- return 1 /* OpenBrace */;
- }
- else if (nextToken.kind === 18 /* CloseBraceToken */) {
- // close braces are indented at the parent level if they are located on the same line with cursor
- // this means that if new line will be added at $ position, this case will be indented
- // class A {
- // $
- // }
- /// and this one - not
- // class A {
- // $}
- var nextTokenStartLine = getStartLineAndCharacterForNode(nextToken, sourceFile).line;
- return lineAtPosition === nextTokenStartLine ? 2 /* CloseBrace */ : 0 /* Unknown */;
- }
- return 0 /* Unknown */;
- }
- function getStartLineAndCharacterForNode(n, sourceFile) {
- return sourceFile.getLineAndCharacterOfPosition(n.getStart(sourceFile));
- }
- function isArgumentAndStartLineOverlapsExpressionBeingCalled(parent, child, childStartLine, sourceFile) {
- if (!(ts.isCallExpression(parent) && ts.contains(parent.arguments, child))) {
- return false;
- }
- var expressionOfCallExpressionEnd = parent.expression.getEnd();
- var expressionOfCallExpressionEndLine = ts.getLineAndCharacterOfPosition(sourceFile, expressionOfCallExpressionEnd).line;
- return expressionOfCallExpressionEndLine === childStartLine;
- }
- SmartIndenter.isArgumentAndStartLineOverlapsExpressionBeingCalled = isArgumentAndStartLineOverlapsExpressionBeingCalled;
- function childStartsOnTheSameLineWithElseInIfStatement(parent, child, childStartLine, sourceFile) {
- if (parent.kind === 215 /* IfStatement */ && parent.elseStatement === child) {
- var elseKeyword = ts.findChildOfKind(parent, 82 /* ElseKeyword */, sourceFile);
- ts.Debug.assert(elseKeyword !== undefined);
- var elseKeywordStartLine = getStartLineAndCharacterForNode(elseKeyword, sourceFile).line;
- return elseKeywordStartLine === childStartLine;
- }
- return false;
- }
- SmartIndenter.childStartsOnTheSameLineWithElseInIfStatement = childStartsOnTheSameLineWithElseInIfStatement;
- function getListIfStartEndIsInListRange(list, start, end) {
- return list && ts.rangeContainsStartEnd(list, start, end) ? list : undefined;
- }
- function getContainingList(node, sourceFile) {
- if (node.parent) {
- switch (node.parent.kind) {
- case 161 /* TypeReference */:
- return getListIfStartEndIsInListRange(node.parent.typeArguments, node.getStart(sourceFile), node.getEnd());
- case 182 /* ObjectLiteralExpression */:
- return node.parent.properties;
- case 181 /* ArrayLiteralExpression */:
- return node.parent.elements;
- case 232 /* FunctionDeclaration */:
- case 190 /* FunctionExpression */:
- case 191 /* ArrowFunction */:
- case 153 /* MethodDeclaration */:
- case 152 /* MethodSignature */:
- case 157 /* CallSignature */:
- case 154 /* Constructor */:
- case 163 /* ConstructorType */:
- case 158 /* ConstructSignature */: {
- var start = node.getStart(sourceFile);
- return getListIfStartEndIsInListRange(node.parent.typeParameters, start, node.getEnd()) ||
- getListIfStartEndIsInListRange(node.parent.parameters, start, node.getEnd());
- }
- case 233 /* ClassDeclaration */:
- return getListIfStartEndIsInListRange(node.parent.typeParameters, node.getStart(sourceFile), node.getEnd());
- case 186 /* NewExpression */:
- case 185 /* CallExpression */: {
- var start = node.getStart(sourceFile);
- return getListIfStartEndIsInListRange(node.parent.typeArguments, start, node.getEnd()) ||
- getListIfStartEndIsInListRange(node.parent.arguments, start, node.getEnd());
- }
- case 231 /* VariableDeclarationList */:
- return getListIfStartEndIsInListRange(node.parent.declarations, node.getStart(sourceFile), node.getEnd());
- case 245 /* NamedImports */:
- case 249 /* NamedExports */:
- return getListIfStartEndIsInListRange(node.parent.elements, node.getStart(sourceFile), node.getEnd());
- }
- }
- return undefined;
- }
- SmartIndenter.getContainingList = getContainingList;
- function getActualIndentationForListItem(node, sourceFile, options) {
- var containingList = getContainingList(node, sourceFile);
- if (containingList) {
- var index = containingList.indexOf(node);
- if (index !== -1) {
- return deriveActualIndentationFromList(containingList, index, sourceFile, options);
- }
- }
- return -1 /* Unknown */;
- }
- function getLineIndentationWhenExpressionIsInMultiLine(node, sourceFile, options) {
- // actual indentation should not be used when:
- // - node is close parenthesis - this is the end of the expression
- if (node.kind === 20 /* CloseParenToken */) {
- return -1 /* Unknown */;
- }
- if (node.parent && ts.isCallOrNewExpression(node.parent) && node.parent.expression !== node) {
- var fullCallOrNewExpression = node.parent.expression;
- var startingExpression = getStartingExpression(fullCallOrNewExpression);
- if (fullCallOrNewExpression === startingExpression) {
- return -1 /* Unknown */;
- }
- var fullCallOrNewExpressionEnd = sourceFile.getLineAndCharacterOfPosition(fullCallOrNewExpression.end);
- var startingExpressionEnd = sourceFile.getLineAndCharacterOfPosition(startingExpression.end);
- if (fullCallOrNewExpressionEnd.line === startingExpressionEnd.line) {
- return -1 /* Unknown */;
- }
- return findColumnForFirstNonWhitespaceCharacterInLine(fullCallOrNewExpressionEnd, sourceFile, options);
- }
- return -1 /* Unknown */;
- function getStartingExpression(node) {
- while (true) {
- switch (node.kind) {
- case 185 /* CallExpression */:
- case 186 /* NewExpression */:
- case 183 /* PropertyAccessExpression */:
- case 184 /* ElementAccessExpression */:
- node = node.expression;
- break;
- default:
- return node;
- }
- }
- }
- }
- function deriveActualIndentationFromList(list, index, sourceFile, options) {
- ts.Debug.assert(index >= 0 && index < list.length);
- var node = list[index];
- // walk toward the start of the list starting from current node and check if the line is the same for all items.
- // if end line for item [i - 1] differs from the start line for item [i] - find column of the first non-whitespace character on the line of item [i]
- var lineAndCharacter = getStartLineAndCharacterForNode(node, sourceFile);
- for (var i = index - 1; i >= 0; i--) {
- if (list[i].kind === 26 /* CommaToken */) {
- continue;
- }
- // skip list items that ends on the same line with the current list element
- var prevEndLine = sourceFile.getLineAndCharacterOfPosition(list[i].end).line;
- if (prevEndLine !== lineAndCharacter.line) {
- return findColumnForFirstNonWhitespaceCharacterInLine(lineAndCharacter, sourceFile, options);
- }
- lineAndCharacter = getStartLineAndCharacterForNode(list[i], sourceFile);
- }
- return -1 /* Unknown */;
- }
- function findColumnForFirstNonWhitespaceCharacterInLine(lineAndCharacter, sourceFile, options) {
- var lineStart = sourceFile.getPositionOfLineAndCharacter(lineAndCharacter.line, 0);
- return findFirstNonWhitespaceColumn(lineStart, lineStart + lineAndCharacter.character, sourceFile, options);
- }
- /**
- * Character is the actual index of the character since the beginning of the line.
- * Column - position of the character after expanding tabs to spaces.
- * "0\t2$"
- * value of 'character' for '$' is 3
- * value of 'column' for '$' is 6 (assuming that tab size is 4)
- */
- function findFirstNonWhitespaceCharacterAndColumn(startPos, endPos, sourceFile, options) {
- var character = 0;
- var column = 0;
- for (var pos = startPos; pos < endPos; pos++) {
- var ch = sourceFile.text.charCodeAt(pos);
- if (!ts.isWhiteSpaceSingleLine(ch)) {
- break;
- }
- if (ch === 9 /* tab */) {
- column += options.tabSize + (column % options.tabSize);
- }
- else {
- column++;
- }
- character++;
- }
- return { column: column, character: character };
- }
- SmartIndenter.findFirstNonWhitespaceCharacterAndColumn = findFirstNonWhitespaceCharacterAndColumn;
- function findFirstNonWhitespaceColumn(startPos, endPos, sourceFile, options) {
- return findFirstNonWhitespaceCharacterAndColumn(startPos, endPos, sourceFile, options).column;
- }
- SmartIndenter.findFirstNonWhitespaceColumn = findFirstNonWhitespaceColumn;
- function nodeContentIsAlwaysIndented(kind) {
- switch (kind) {
- case 214 /* ExpressionStatement */:
- case 233 /* ClassDeclaration */:
- case 203 /* ClassExpression */:
- case 234 /* InterfaceDeclaration */:
- case 236 /* EnumDeclaration */:
- case 235 /* TypeAliasDeclaration */:
- case 181 /* ArrayLiteralExpression */:
- case 211 /* Block */:
- case 238 /* ModuleBlock */:
- case 182 /* ObjectLiteralExpression */:
- case 165 /* TypeLiteral */:
- case 176 /* MappedType */:
- case 167 /* TupleType */:
- case 239 /* CaseBlock */:
- case 265 /* DefaultClause */:
- case 264 /* CaseClause */:
- case 189 /* ParenthesizedExpression */:
- case 183 /* PropertyAccessExpression */:
- case 185 /* CallExpression */:
- case 186 /* NewExpression */:
- case 212 /* VariableStatement */:
- case 230 /* VariableDeclaration */:
- case 247 /* ExportAssignment */:
- case 223 /* ReturnStatement */:
- case 199 /* ConditionalExpression */:
- case 179 /* ArrayBindingPattern */:
- case 178 /* ObjectBindingPattern */:
- case 255 /* JsxOpeningElement */:
- case 258 /* JsxOpeningFragment */:
- case 254 /* JsxSelfClosingElement */:
- case 263 /* JsxExpression */:
- case 152 /* MethodSignature */:
- case 157 /* CallSignature */:
- case 158 /* ConstructSignature */:
- case 148 /* Parameter */:
- case 162 /* FunctionType */:
- case 163 /* ConstructorType */:
- case 172 /* ParenthesizedType */:
- case 187 /* TaggedTemplateExpression */:
- case 195 /* AwaitExpression */:
- case 249 /* NamedExports */:
- case 245 /* NamedImports */:
- case 250 /* ExportSpecifier */:
- case 246 /* ImportSpecifier */:
- case 268 /* PropertyAssignment */:
- case 151 /* PropertyDeclaration */:
- return true;
- }
- return false;
- }
- function nodeWillIndentChild(parent, child, indentByDefault) {
- var childKind = child ? child.kind : 0 /* Unknown */;
- switch (parent.kind) {
- case 216 /* DoStatement */:
- case 217 /* WhileStatement */:
- case 219 /* ForInStatement */:
- case 220 /* ForOfStatement */:
- case 218 /* ForStatement */:
- case 215 /* IfStatement */:
- case 232 /* FunctionDeclaration */:
- case 190 /* FunctionExpression */:
- case 153 /* MethodDeclaration */:
- case 191 /* ArrowFunction */:
- case 154 /* Constructor */:
- case 155 /* GetAccessor */:
- case 156 /* SetAccessor */:
- return childKind !== 211 /* Block */;
- case 248 /* ExportDeclaration */:
- return childKind !== 249 /* NamedExports */;
- case 242 /* ImportDeclaration */:
- return childKind !== 243 /* ImportClause */ ||
- (!!child.namedBindings && child.namedBindings.kind !== 245 /* NamedImports */);
- case 253 /* JsxElement */:
- return childKind !== 256 /* JsxClosingElement */;
- case 257 /* JsxFragment */:
- return childKind !== 259 /* JsxClosingFragment */;
- }
- // No explicit rule for given nodes so the result will follow the default value argument
- return indentByDefault;
- }
- SmartIndenter.nodeWillIndentChild = nodeWillIndentChild;
- function isControlFlowEndingStatement(kind, parent) {
- switch (kind) {
- case 223 /* ReturnStatement */:
- case 227 /* ThrowStatement */: {
- if (parent.kind !== 211 /* Block */) {
- return true;
- }
- var grandParent = parent.parent;
- // In a function, we may want to write inner functions after this.
- return !(grandParent && grandParent.kind === 190 /* FunctionExpression */ || grandParent.kind === 232 /* FunctionDeclaration */);
- }
- case 221 /* ContinueStatement */:
- case 222 /* BreakStatement */:
- return true;
- default:
- return false;
- }
- }
- /**
- * True when the parent node should indent the given child by an explicit rule.
- * @param isNextChild If true, we are judging indent of a hypothetical child *after* this one, not the current child.
- */
- function shouldIndentChildNode(parent, child, isNextChild) {
- if (isNextChild === void 0) { isNextChild = false; }
- return (nodeContentIsAlwaysIndented(parent.kind) || nodeWillIndentChild(parent, child, /*indentByDefault*/ false))
- && !(isNextChild && child && isControlFlowEndingStatement(child.kind, parent));
- }
- SmartIndenter.shouldIndentChildNode = shouldIndentChildNode;
- })(SmartIndenter = formatting.SmartIndenter || (formatting.SmartIndenter = {}));
- })(formatting = ts.formatting || (ts.formatting = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var textChanges;
- (function (textChanges_1) {
- /**
- * Currently for simplicity we store recovered positions on the node itself.
- * It can be changed to side-table later if we decide that current design is too invasive.
- */
- function getPos(n) {
- var result = n.__pos;
- ts.Debug.assert(typeof result === "number");
- return result;
- }
- function setPos(n, pos) {
- ts.Debug.assert(typeof pos === "number");
- n.__pos = pos;
- }
- function getEnd(n) {
- var result = n.__end;
- ts.Debug.assert(typeof result === "number");
- return result;
- }
- function setEnd(n, end) {
- ts.Debug.assert(typeof end === "number");
- n.__end = end;
- }
- var Position;
- (function (Position) {
- Position[Position["FullStart"] = 0] = "FullStart";
- Position[Position["Start"] = 1] = "Start";
- })(Position = textChanges_1.Position || (textChanges_1.Position = {}));
- function skipWhitespacesAndLineBreaks(text, start) {
- return ts.skipTrivia(text, start, /*stopAfterLineBreak*/ false, /*stopAtComments*/ true);
- }
- function hasCommentsBeforeLineBreak(text, start) {
- var i = start;
- while (i < text.length) {
- var ch = text.charCodeAt(i);
- if (ts.isWhiteSpaceSingleLine(ch)) {
- i++;
- continue;
- }
- return ch === 47 /* slash */;
- }
- return false;
- }
- textChanges_1.useNonAdjustedPositions = {
- useNonAdjustedStartPosition: true,
- useNonAdjustedEndPosition: true,
- };
- var ChangeKind;
- (function (ChangeKind) {
- ChangeKind[ChangeKind["Remove"] = 0] = "Remove";
- ChangeKind[ChangeKind["ReplaceWithSingleNode"] = 1] = "ReplaceWithSingleNode";
- ChangeKind[ChangeKind["ReplaceWithMultipleNodes"] = 2] = "ReplaceWithMultipleNodes";
- })(ChangeKind || (ChangeKind = {}));
- function getSeparatorCharacter(separator) {
- return ts.tokenToString(separator.kind);
- }
- textChanges_1.getSeparatorCharacter = getSeparatorCharacter;
- function getAdjustedStartPosition(sourceFile, node, options, position) {
- if (options.useNonAdjustedStartPosition) {
- return node.getStart(sourceFile);
- }
- var fullStart = node.getFullStart();
- var start = node.getStart(sourceFile);
- if (fullStart === start) {
- return start;
- }
- var fullStartLine = ts.getLineStartPositionForPosition(fullStart, sourceFile);
- var startLine = ts.getLineStartPositionForPosition(start, sourceFile);
- if (startLine === fullStartLine) {
- // full start and start of the node are on the same line
- // a, b;
- // ^ ^
- // | start
- // fullstart
- // when b is replaced - we usually want to keep the leading trvia
- // when b is deleted - we delete it
- return position === Position.Start ? start : fullStart;
- }
- // get start position of the line following the line that contains fullstart position
- // (but only if the fullstart isn't the very beginning of the file)
- var nextLineStart = fullStart > 0 ? 1 : 0;
- var adjustedStartPosition = ts.getStartPositionOfLine(ts.getLineOfLocalPosition(sourceFile, fullStartLine) + nextLineStart, sourceFile);
- // skip whitespaces/newlines
- adjustedStartPosition = skipWhitespacesAndLineBreaks(sourceFile.text, adjustedStartPosition);
- return ts.getStartPositionOfLine(ts.getLineOfLocalPosition(sourceFile, adjustedStartPosition), sourceFile);
- }
- textChanges_1.getAdjustedStartPosition = getAdjustedStartPosition;
- function getAdjustedEndPosition(sourceFile, node, options) {
- if (options.useNonAdjustedEndPosition || ts.isExpression(node)) {
- return node.getEnd();
- }
- var end = node.getEnd();
- var newEnd = ts.skipTrivia(sourceFile.text, end, /*stopAfterLineBreak*/ true);
- return newEnd !== end && ts.isLineBreak(sourceFile.text.charCodeAt(newEnd - 1))
- ? newEnd
- : end;
- }
- textChanges_1.getAdjustedEndPosition = getAdjustedEndPosition;
- /**
- * Checks if 'candidate' argument is a legal separator in the list that contains 'node' as an element
- */
- function isSeparator(node, candidate) {
- return candidate && node.parent && (candidate.kind === 26 /* CommaToken */ || (candidate.kind === 25 /* SemicolonToken */ && node.parent.kind === 182 /* ObjectLiteralExpression */));
- }
- function spaces(count) {
- var s = "";
- for (var i = 0; i < count; i++) {
- s += " ";
- }
- return s;
- }
- var ChangeTracker = /** @class */ (function () {
- /** Public for tests only. Other callers should use `ChangeTracker.with`. */
- function ChangeTracker(newLineCharacter, formatContext) {
- this.newLineCharacter = newLineCharacter;
- this.formatContext = formatContext;
- this.changes = [];
- this.deletedNodesInLists = []; // Stores ids of nodes in lists that we already deleted. Used to avoid deleting `, ` twice in `a, b`.
- // Map from class id to nodes to insert at the start
- this.nodesInsertedAtClassStarts = ts.createMap();
- }
- ChangeTracker.fromContext = function (context) {
- return new ChangeTracker(ts.getNewLineOrDefaultFromHost(context.host, context.formatContext.options), context.formatContext);
- };
- ChangeTracker.with = function (context, cb) {
- var tracker = ChangeTracker.fromContext(context);
- cb(tracker);
- return tracker.getChanges();
- };
- ChangeTracker.prototype.deleteRange = function (sourceFile, range) {
- this.changes.push({ kind: ChangeKind.Remove, sourceFile: sourceFile, range: range });
- return this;
- };
- /** Warning: This deletes comments too. See `copyComments` in `convertFunctionToEs6Class`. */
- ChangeTracker.prototype.deleteNode = function (sourceFile, node, options) {
- if (options === void 0) { options = {}; }
- var startPosition = getAdjustedStartPosition(sourceFile, node, options, Position.FullStart);
- var endPosition = getAdjustedEndPosition(sourceFile, node, options);
- this.deleteRange(sourceFile, { pos: startPosition, end: endPosition });
- return this;
- };
- ChangeTracker.prototype.deleteNodeRange = function (sourceFile, startNode, endNode, options) {
- if (options === void 0) { options = {}; }
- var startPosition = getAdjustedStartPosition(sourceFile, startNode, options, Position.FullStart);
- var endPosition = getAdjustedEndPosition(sourceFile, endNode, options);
- this.deleteRange(sourceFile, { pos: startPosition, end: endPosition });
- return this;
- };
- ChangeTracker.prototype.deleteNodeInList = function (sourceFile, node) {
- var containingList = ts.formatting.SmartIndenter.getContainingList(node, sourceFile);
- if (!containingList) {
- ts.Debug.fail("node is not a list element");
- return this;
- }
- var index = ts.indexOfNode(containingList, node);
- if (index < 0) {
- return this;
- }
- if (containingList.length === 1) {
- this.deleteNode(sourceFile, node);
- return this;
- }
- var id = ts.getNodeId(node);
- ts.Debug.assert(!this.deletedNodesInLists[id], "Deleting a node twice");
- this.deletedNodesInLists[id] = true;
- if (index !== containingList.length - 1) {
- var nextToken = ts.getTokenAtPosition(sourceFile, node.end, /*includeJsDocComment*/ false);
- if (nextToken && isSeparator(node, nextToken)) {
- // find first non-whitespace position in the leading trivia of the node
- var startPosition = ts.skipTrivia(sourceFile.text, getAdjustedStartPosition(sourceFile, node, {}, Position.FullStart), /*stopAfterLineBreak*/ false, /*stopAtComments*/ true);
- var nextElement = containingList[index + 1];
- /// find first non-whitespace position in the leading trivia of the next node
- var endPosition = ts.skipTrivia(sourceFile.text, getAdjustedStartPosition(sourceFile, nextElement, {}, Position.FullStart), /*stopAfterLineBreak*/ false, /*stopAtComments*/ true);
- // shift next node so its first non-whitespace position will be moved to the first non-whitespace position of the deleted node
- this.deleteRange(sourceFile, { pos: startPosition, end: endPosition });
- }
- }
- else {
- var prev = containingList[index - 1];
- if (this.deletedNodesInLists[ts.getNodeId(prev)]) {
- var pos = ts.skipTrivia(sourceFile.text, getAdjustedStartPosition(sourceFile, node, {}, Position.FullStart), /*stopAfterLineBreak*/ false, /*stopAtComments*/ true);
- var end = getAdjustedEndPosition(sourceFile, node, {});
- this.deleteRange(sourceFile, { pos: pos, end: end });
- }
- else {
- var previousToken = ts.getTokenAtPosition(sourceFile, containingList[index - 1].end, /*includeJsDocComment*/ false);
- if (previousToken && isSeparator(node, previousToken)) {
- this.deleteNodeRange(sourceFile, previousToken, node);
- }
- }
- }
- return this;
- };
- // TODO (https://github.com/Microsoft/TypeScript/issues/21246): default should probably be useNonAdjustedPositions
- ChangeTracker.prototype.replaceRange = function (sourceFile, range, newNode, options) {
- if (options === void 0) { options = {}; }
- this.changes.push({ kind: ChangeKind.ReplaceWithSingleNode, sourceFile: sourceFile, range: range, options: options, node: newNode });
- return this;
- };
- // TODO (https://github.com/Microsoft/TypeScript/issues/21246): default should probably be useNonAdjustedPositions
- ChangeTracker.prototype.replaceNode = function (sourceFile, oldNode, newNode, options) {
- if (options === void 0) { options = {}; }
- var pos = getAdjustedStartPosition(sourceFile, oldNode, options, Position.Start);
- var end = getAdjustedEndPosition(sourceFile, oldNode, options);
- return this.replaceRange(sourceFile, { pos: pos, end: end }, newNode, options);
- };
- // TODO (https://github.com/Microsoft/TypeScript/issues/21246): default should probably be useNonAdjustedPositions
- ChangeTracker.prototype.replaceNodeRange = function (sourceFile, startNode, endNode, newNode, options) {
- if (options === void 0) { options = {}; }
- var pos = getAdjustedStartPosition(sourceFile, startNode, options, Position.Start);
- var end = getAdjustedEndPosition(sourceFile, endNode, options);
- return this.replaceRange(sourceFile, { pos: pos, end: end }, newNode, options);
- };
- ChangeTracker.prototype.replaceRangeWithNodes = function (sourceFile, range, newNodes, options) {
- if (options === void 0) { options = textChanges_1.useNonAdjustedPositions; }
- this.changes.push({ kind: ChangeKind.ReplaceWithMultipleNodes, sourceFile: sourceFile, range: range, options: options, nodes: newNodes });
- return this;
- };
- ChangeTracker.prototype.replaceNodeWithNodes = function (sourceFile, oldNode, newNodes, options) {
- if (options === void 0) { options = textChanges_1.useNonAdjustedPositions; }
- var pos = getAdjustedStartPosition(sourceFile, oldNode, options, Position.Start);
- var end = getAdjustedEndPosition(sourceFile, oldNode, options);
- return this.replaceRangeWithNodes(sourceFile, { pos: pos, end: end }, newNodes, options);
- };
- ChangeTracker.prototype.replaceNodeRangeWithNodes = function (sourceFile, startNode, endNode, newNodes, options) {
- if (options === void 0) { options = textChanges_1.useNonAdjustedPositions; }
- var pos = getAdjustedStartPosition(sourceFile, startNode, options, Position.Start);
- var end = getAdjustedEndPosition(sourceFile, endNode, options);
- return this.replaceRangeWithNodes(sourceFile, { pos: pos, end: end }, newNodes, options);
- };
- ChangeTracker.prototype.insertNodeAt = function (sourceFile, pos, newNode, options) {
- if (options === void 0) { options = {}; }
- this.changes.push({ kind: ChangeKind.ReplaceWithSingleNode, sourceFile: sourceFile, options: options, node: newNode, range: { pos: pos, end: pos } });
- return this;
- };
- ChangeTracker.prototype.insertNodesAt = function (sourceFile, pos, newNodes, options) {
- if (options === void 0) { options = {}; }
- this.changes.push({ kind: ChangeKind.ReplaceWithMultipleNodes, sourceFile: sourceFile, options: options, nodes: newNodes, range: { pos: pos, end: pos } });
- };
- ChangeTracker.prototype.insertNodeAtTopOfFile = function (sourceFile, newNode, blankLineBetween) {
- var pos = getInsertionPositionAtSourceFileTop(sourceFile);
- this.insertNodeAt(sourceFile, pos, newNode, {
- prefix: pos === 0 ? undefined : this.newLineCharacter,
- suffix: (ts.isLineBreak(sourceFile.text.charCodeAt(pos)) ? "" : this.newLineCharacter) + (blankLineBetween ? this.newLineCharacter : ""),
- });
- };
- ChangeTracker.prototype.insertNodeBefore = function (sourceFile, before, newNode, blankLineBetween) {
- if (blankLineBetween === void 0) { blankLineBetween = false; }
- var pos = getAdjustedStartPosition(sourceFile, before, {}, Position.Start);
- return this.replaceRange(sourceFile, { pos: pos, end: pos }, newNode, this.getOptionsForInsertNodeBefore(before, blankLineBetween));
- };
- ChangeTracker.prototype.insertModifierBefore = function (sourceFile, modifier, before) {
- var pos = before.getStart(sourceFile);
- this.replaceRange(sourceFile, { pos: pos, end: pos }, ts.createToken(modifier), { suffix: " " });
- };
- /** Prefer this over replacing a node with another that has a type annotation, as it avoids reformatting the other parts of the node. */
- ChangeTracker.prototype.insertTypeAnnotation = function (sourceFile, node, type) {
- var end = (ts.isFunctionLike(node)
- // If no `)`, is an arrow function `x => x`, so use the end of the first parameter
- ? ts.findChildOfKind(node, 20 /* CloseParenToken */, sourceFile) || ts.first(node.parameters)
- : node.kind !== 230 /* VariableDeclaration */ && node.questionToken ? node.questionToken : node.name).end;
- this.insertNodeAt(sourceFile, end, type, { prefix: ": " });
- };
- ChangeTracker.prototype.insertTypeParameters = function (sourceFile, node, typeParameters) {
- // If no `(`, is an arrow function `x => x`, so use the pos of the first parameter
- var start = (ts.findChildOfKind(node, 19 /* OpenParenToken */, sourceFile) || ts.first(node.parameters)).getStart(sourceFile);
- this.insertNodesAt(sourceFile, start, typeParameters, { prefix: "<", suffix: ">" });
- };
- ChangeTracker.prototype.getOptionsForInsertNodeBefore = function (before, doubleNewlines) {
- if (ts.isStatement(before) || ts.isClassElement(before)) {
- return { suffix: doubleNewlines ? this.newLineCharacter + this.newLineCharacter : this.newLineCharacter };
- }
- else if (ts.isVariableDeclaration(before)) { // insert `x = 1, ` into `const x = 1, y = 2;
- return { suffix: ", " };
- }
- else if (ts.isParameter(before)) {
- return {};
- }
- return ts.Debug.failBadSyntaxKind(before); // We haven't handled this kind of node yet -- add it
- };
- ChangeTracker.prototype.insertNodeAtConstructorStart = function (sourceFile, ctr, newStatement) {
- var firstStatement = ts.firstOrUndefined(ctr.body.statements);
- if (!firstStatement || !ctr.body.multiLine) {
- this.replaceConstructorBody(sourceFile, ctr, [newStatement].concat(ctr.body.statements));
- }
- else {
- this.insertNodeBefore(sourceFile, firstStatement, newStatement);
- }
- };
- ChangeTracker.prototype.insertNodeAtConstructorEnd = function (sourceFile, ctr, newStatement) {
- var lastStatement = ts.lastOrUndefined(ctr.body.statements);
- if (!lastStatement || !ctr.body.multiLine) {
- this.replaceConstructorBody(sourceFile, ctr, ctr.body.statements.concat([newStatement]));
- }
- else {
- this.insertNodeAfter(sourceFile, lastStatement, newStatement);
- }
- };
- ChangeTracker.prototype.replaceConstructorBody = function (sourceFile, ctr, statements) {
- this.replaceNode(sourceFile, ctr.body, ts.createBlock(statements, /*multiLine*/ true), { useNonAdjustedEndPosition: true });
- };
- ChangeTracker.prototype.insertNodeAtEndOfScope = function (sourceFile, scope, newNode) {
- var pos = getAdjustedStartPosition(sourceFile, scope.getLastToken(), {}, Position.Start);
- this.replaceRange(sourceFile, { pos: pos, end: pos }, newNode, {
- prefix: ts.isLineBreak(sourceFile.text.charCodeAt(scope.getLastToken().pos)) ? this.newLineCharacter : this.newLineCharacter + this.newLineCharacter,
- suffix: this.newLineCharacter
- });
- };
- ChangeTracker.prototype.insertNodeAtClassStart = function (sourceFile, cls, newElement) {
- var firstMember = ts.firstOrUndefined(cls.members);
- if (!firstMember) {
- var id = ts.getNodeId(cls).toString();
- var newMembers = this.nodesInsertedAtClassStarts.get(id);
- if (newMembers) {
- ts.Debug.assert(newMembers.sourceFile === sourceFile && newMembers.cls === cls);
- newMembers.members.push(newElement);
- }
- else {
- this.nodesInsertedAtClassStarts.set(id, { sourceFile: sourceFile, cls: cls, members: [newElement] });
- }
- }
- else {
- this.insertNodeBefore(sourceFile, firstMember, newElement);
- }
- };
- ChangeTracker.prototype.insertNodeAfter = function (sourceFile, after, newNode) {
- if (needSemicolonBetween(after, newNode)) {
- // check if previous statement ends with semicolon
- // if not - insert semicolon to preserve the code from changing the meaning due to ASI
- if (sourceFile.text.charCodeAt(after.end - 1) !== 59 /* semicolon */) {
- this.changes.push({
- kind: ChangeKind.ReplaceWithSingleNode,
- sourceFile: sourceFile,
- options: {},
- range: { pos: after.end, end: after.end },
- node: ts.createToken(25 /* SemicolonToken */)
- });
- }
- }
- var endPosition = getAdjustedEndPosition(sourceFile, after, {});
- return this.replaceRange(sourceFile, { pos: endPosition, end: endPosition }, newNode, this.getInsertNodeAfterOptions(after));
- };
- ChangeTracker.prototype.getInsertNodeAfterOptions = function (node) {
- if (ts.isClassDeclaration(node) || ts.isModuleDeclaration(node)) {
- return { prefix: this.newLineCharacter, suffix: this.newLineCharacter };
- }
- else if (ts.isStatement(node) || ts.isClassOrTypeElement(node)) {
- return { suffix: this.newLineCharacter };
- }
- else if (ts.isVariableDeclaration(node)) {
- return { prefix: ", " };
- }
- else if (ts.isParameter(node)) {
- return {};
- }
- return ts.Debug.failBadSyntaxKind(node); // We haven't handled this kind of node yet -- add it
- };
- /**
- * This function should be used to insert nodes in lists when nodes don't carry separators as the part of the node range,
- * i.e. arguments in arguments lists, parameters in parameter lists etc.
- * Note that separators are part of the node in statements and class elements.
- */
- ChangeTracker.prototype.insertNodeInListAfter = function (sourceFile, after, newNode) {
- var containingList = ts.formatting.SmartIndenter.getContainingList(after, sourceFile);
- if (!containingList) {
- ts.Debug.fail("node is not a list element");
- return this;
- }
- var index = ts.indexOfNode(containingList, after);
- if (index < 0) {
- return this;
- }
- var end = after.getEnd();
- if (index !== containingList.length - 1) {
- // any element except the last one
- // use next sibling as an anchor
- var nextToken = ts.getTokenAtPosition(sourceFile, after.end, /*includeJsDocComment*/ false);
- if (nextToken && isSeparator(after, nextToken)) {
- // for list
- // a, b, c
- // create change for adding 'e' after 'a' as
- // - find start of next element after a (it is b)
- // - use this start as start and end position in final change
- // - build text of change by formatting the text of node + separator + whitespace trivia of b
- // in multiline case it will work as
- // a,
- // b,
- // c,
- // result - '*' denotes leading trivia that will be inserted after new text (displayed as '#')
- // a,*
- // ***insertedtext#
- // ###b,
- // c,
- // find line and character of the next element
- var lineAndCharOfNextElement = ts.getLineAndCharacterOfPosition(sourceFile, skipWhitespacesAndLineBreaks(sourceFile.text, containingList[index + 1].getFullStart()));
- // find line and character of the token that precedes next element (usually it is separator)
- var lineAndCharOfNextToken = ts.getLineAndCharacterOfPosition(sourceFile, nextToken.end);
- var prefix = void 0;
- var startPos = void 0;
- if (lineAndCharOfNextToken.line === lineAndCharOfNextElement.line) {
- // next element is located on the same line with separator:
- // a,$$$$b
- // ^ ^
- // | |-next element
- // |-separator
- // where $$$ is some leading trivia
- // for a newly inserted node we'll maintain the same relative position comparing to separator and replace leading trivia with spaces
- // a, x,$$$$b
- // ^ ^ ^
- // | | |-next element
- // | |-new inserted node padded with spaces
- // |-separator
- startPos = nextToken.end;
- prefix = spaces(lineAndCharOfNextElement.character - lineAndCharOfNextToken.character);
- }
- else {
- // next element is located on different line that separator
- // let insert position be the beginning of the line that contains next element
- startPos = ts.getStartPositionOfLine(lineAndCharOfNextElement.line, sourceFile);
- }
- this.changes.push({
- kind: ChangeKind.ReplaceWithSingleNode,
- sourceFile: sourceFile,
- range: { pos: startPos, end: containingList[index + 1].getStart(sourceFile) },
- node: newNode,
- options: {
- prefix: prefix,
- // write separator and leading trivia of the next element as suffix
- suffix: "" + ts.tokenToString(nextToken.kind) + sourceFile.text.substring(nextToken.end, containingList[index + 1].getStart(sourceFile))
- }
- });
- }
- }
- else {
- var afterStart = after.getStart(sourceFile);
- var afterStartLinePosition = ts.getLineStartPositionForPosition(afterStart, sourceFile);
- var separator = void 0;
- var multilineList = false;
- // insert element after the last element in the list that has more than one item
- // pick the element preceding the after element to:
- // - pick the separator
- // - determine if list is a multiline
- if (containingList.length === 1) {
- // if list has only one element then we'll format is as multiline if node has comment in trailing trivia, or as singleline otherwise
- // i.e. var x = 1 // this is x
- // | new element will be inserted at this position
- separator = 26 /* CommaToken */;
- }
- else {
- // element has more than one element, pick separator from the list
- var tokenBeforeInsertPosition = ts.findPrecedingToken(after.pos, sourceFile);
- separator = isSeparator(after, tokenBeforeInsertPosition) ? tokenBeforeInsertPosition.kind : 26 /* CommaToken */;
- // determine if list is multiline by checking lines of after element and element that precedes it.
- var afterMinusOneStartLinePosition = ts.getLineStartPositionForPosition(containingList[index - 1].getStart(sourceFile), sourceFile);
- multilineList = afterMinusOneStartLinePosition !== afterStartLinePosition;
- }
- if (hasCommentsBeforeLineBreak(sourceFile.text, after.end)) {
- // in this case we'll always treat containing list as multiline
- multilineList = true;
- }
- if (multilineList) {
- // insert separator immediately following the 'after' node to preserve comments in trailing trivia
- this.changes.push({
- kind: ChangeKind.ReplaceWithSingleNode,
- sourceFile: sourceFile,
- range: { pos: end, end: end },
- node: ts.createToken(separator),
- options: {}
- });
- // use the same indentation as 'after' item
- var indentation = ts.formatting.SmartIndenter.findFirstNonWhitespaceColumn(afterStartLinePosition, afterStart, sourceFile, this.formatContext.options);
- // insert element before the line break on the line that contains 'after' element
- var insertPos = ts.skipTrivia(sourceFile.text, end, /*stopAfterLineBreak*/ true, /*stopAtComments*/ false);
- if (insertPos !== end && ts.isLineBreak(sourceFile.text.charCodeAt(insertPos - 1))) {
- insertPos--;
- }
- this.changes.push({
- kind: ChangeKind.ReplaceWithSingleNode,
- sourceFile: sourceFile,
- range: { pos: insertPos, end: insertPos },
- node: newNode,
- options: { indentation: indentation, prefix: this.newLineCharacter }
- });
- }
- else {
- this.changes.push({
- kind: ChangeKind.ReplaceWithSingleNode,
- sourceFile: sourceFile,
- range: { pos: end, end: end },
- node: newNode,
- options: { prefix: ts.tokenToString(separator) + " " }
- });
- }
- }
- return this;
- };
- ChangeTracker.prototype.finishInsertNodeAtClassStart = function () {
- var _this = this;
- this.nodesInsertedAtClassStarts.forEach(function (_a) {
- var sourceFile = _a.sourceFile, cls = _a.cls, members = _a.members;
- var newCls = cls.kind === 233 /* ClassDeclaration */
- ? ts.updateClassDeclaration(cls, cls.decorators, cls.modifiers, cls.name, cls.typeParameters, cls.heritageClauses, members)
- : ts.updateClassExpression(cls, cls.modifiers, cls.name, cls.typeParameters, cls.heritageClauses, members);
- _this.replaceNode(sourceFile, cls, newCls, { useNonAdjustedEndPosition: true });
- });
- };
- /**
- * Note: after calling this, the TextChanges object must be discarded!
- * @param validate only for tests
- * The reason we must validate as part of this method is that `getNonFormattedText` changes the node's positions,
- * so we can only call this once and can't get the non-formatted text separately.
- */
- ChangeTracker.prototype.getChanges = function (validate) {
- this.finishInsertNodeAtClassStart();
- return changesToText.getTextChangesFromChanges(this.changes, this.newLineCharacter, this.formatContext, validate);
- };
- return ChangeTracker;
- }());
- textChanges_1.ChangeTracker = ChangeTracker;
- var changesToText;
- (function (changesToText) {
- function getTextChangesFromChanges(changes, newLineCharacter, formatContext, validate) {
- return ts.group(changes, function (c) { return c.sourceFile.path; }).map(function (changesInFile) {
- var sourceFile = changesInFile[0].sourceFile;
- // order changes by start position
- var normalized = ts.stableSort(changesInFile, function (a, b) { return a.range.pos - b.range.pos; });
- var _loop_10 = function (i) {
- ts.Debug.assert(normalized[i].range.end <= normalized[i + 1].range.pos, "Changes overlap", function () {
- return JSON.stringify(normalized[i].range) + " and " + JSON.stringify(normalized[i + 1].range);
- });
- };
- // verify that change intervals do not overlap, except possibly at end points.
- for (var i = 0; i < normalized.length - 2; i++) {
- _loop_10(i);
- }
- var textChanges = normalized.map(function (c) {
- return ts.createTextChange(ts.createTextSpanFromRange(c.range), computeNewText(c, sourceFile, newLineCharacter, formatContext, validate));
- });
- return { fileName: sourceFile.fileName, textChanges: textChanges };
- });
- }
- changesToText.getTextChangesFromChanges = getTextChangesFromChanges;
- function computeNewText(change, sourceFile, newLineCharacter, formatContext, validate) {
- if (change.kind === ChangeKind.Remove) {
- return "";
- }
- var _a = change.options, options = _a === void 0 ? {} : _a, pos = change.range.pos;
- var format = function (n) { return getFormattedTextOfNode(n, sourceFile, pos, options, newLineCharacter, formatContext, validate); };
- var text = change.kind === ChangeKind.ReplaceWithMultipleNodes
- ? change.nodes.map(function (n) { return ts.removeSuffix(format(n), newLineCharacter); }).join(newLineCharacter)
- : format(change.node);
- // strip initial indentation (spaces or tabs) if text will be inserted in the middle of the line
- var noIndent = (options.preserveLeadingWhitespace || options.indentation !== undefined || ts.getLineStartPositionForPosition(pos, sourceFile) === pos) ? text : text.replace(/^\s+/, "");
- return (options.prefix || "") + noIndent + (options.suffix || "");
- }
- /** Note: this may mutate `nodeIn`. */
- function getFormattedTextOfNode(nodeIn, sourceFile, pos, options, newLineCharacter, formatContext, validate) {
- var _a = getNonformattedText(nodeIn, sourceFile, newLineCharacter), node = _a.node, text = _a.text;
- if (validate)
- validate(node, text);
- var formatOptions = formatContext.options;
- var initialIndentation = options.indentation !== undefined
- ? options.indentation
- : (options.useIndentationFromFile !== false)
- ? ts.formatting.SmartIndenter.getIndentation(pos, sourceFile, formatOptions, options.prefix === newLineCharacter || ts.getLineStartPositionForPosition(pos, sourceFile) === pos)
- : 0;
- var delta = options.delta !== undefined
- ? options.delta
- : ts.formatting.SmartIndenter.shouldIndentChildNode(nodeIn)
- ? (formatOptions.indentSize || 0)
- : 0;
- var file = { text: text, getLineAndCharacterOfPosition: function (pos) { return ts.getLineAndCharacterOfPosition(this, pos); } };
- var changes = ts.formatting.formatNodeGivenIndentation(node, file, sourceFile.languageVariant, initialIndentation, delta, formatContext);
- return applyChanges(text, changes);
- }
- /** Note: output node may be mutated input node. */
- function getNonformattedText(node, sourceFile, newLineCharacter) {
- var writer = new Writer(newLineCharacter);
- var newLine = newLineCharacter === "\n" ? 1 /* LineFeed */ : 0 /* CarriageReturnLineFeed */;
- ts.createPrinter({ newLine: newLine }, writer).writeNode(4 /* Unspecified */, node, sourceFile, writer);
- return { text: writer.getText(), node: assignPositionsToNode(node) };
- }
- })(changesToText || (changesToText = {}));
- function applyChanges(text, changes) {
- for (var i = changes.length - 1; i >= 0; i--) {
- var change = changes[i];
- text = "" + text.substring(0, change.span.start) + change.newText + text.substring(ts.textSpanEnd(change.span));
- }
- return text;
- }
- textChanges_1.applyChanges = applyChanges;
- function isTrivia(s) {
- return ts.skipTrivia(s, 0) === s.length;
- }
- function assignPositionsToNode(node) {
- var visited = ts.visitEachChild(node, assignPositionsToNode, ts.nullTransformationContext, assignPositionsToNodeArray, assignPositionsToNode);
- // create proxy node for non synthesized nodes
- var newNode = ts.nodeIsSynthesized(visited) ? visited : Object.create(visited);
- newNode.pos = getPos(node);
- newNode.end = getEnd(node);
- return newNode;
- }
- function assignPositionsToNodeArray(nodes, visitor, test, start, count) {
- var visited = ts.visitNodes(nodes, visitor, test, start, count);
- if (!visited) {
- return visited;
- }
- // clone nodearray if necessary
- var nodeArray = visited === nodes ? ts.createNodeArray(visited.slice(0)) : visited;
- nodeArray.pos = getPos(nodes);
- nodeArray.end = getEnd(nodes);
- return nodeArray;
- }
- var Writer = /** @class */ (function () {
- function Writer(newLine) {
- var _this = this;
- this.lastNonTriviaPosition = 0;
- this.writer = ts.createTextWriter(newLine);
- this.onEmitNode = function (hint, node, printCallback) {
- if (node) {
- setPos(node, _this.lastNonTriviaPosition);
- }
- printCallback(hint, node);
- if (node) {
- setEnd(node, _this.lastNonTriviaPosition);
- }
- };
- this.onBeforeEmitNodeArray = function (nodes) {
- if (nodes) {
- setPos(nodes, _this.lastNonTriviaPosition);
- }
- };
- this.onAfterEmitNodeArray = function (nodes) {
- if (nodes) {
- setEnd(nodes, _this.lastNonTriviaPosition);
- }
- };
- this.onBeforeEmitToken = function (node) {
- if (node) {
- setPos(node, _this.lastNonTriviaPosition);
- }
- };
- this.onAfterEmitToken = function (node) {
- if (node) {
- setEnd(node, _this.lastNonTriviaPosition);
- }
- };
- }
- Writer.prototype.setLastNonTriviaPosition = function (s, force) {
- if (force || !isTrivia(s)) {
- this.lastNonTriviaPosition = this.writer.getTextPos();
- var i = 0;
- while (ts.isWhiteSpaceLike(s.charCodeAt(s.length - i - 1))) {
- i++;
- }
- // trim trailing whitespaces
- this.lastNonTriviaPosition -= i;
- }
- };
- Writer.prototype.write = function (s) {
- this.writer.write(s);
- this.setLastNonTriviaPosition(s, /*force*/ false);
- };
- Writer.prototype.writeKeyword = function (s) {
- this.writer.writeKeyword(s);
- this.setLastNonTriviaPosition(s, /*force*/ false);
- };
- Writer.prototype.writeOperator = function (s) {
- this.writer.writeOperator(s);
- this.setLastNonTriviaPosition(s, /*force*/ false);
- };
- Writer.prototype.writePunctuation = function (s) {
- this.writer.writePunctuation(s);
- this.setLastNonTriviaPosition(s, /*force*/ false);
- };
- Writer.prototype.writeParameter = function (s) {
- this.writer.writeParameter(s);
- this.setLastNonTriviaPosition(s, /*force*/ false);
- };
- Writer.prototype.writeProperty = function (s) {
- this.writer.writeProperty(s);
- this.setLastNonTriviaPosition(s, /*force*/ false);
- };
- Writer.prototype.writeSpace = function (s) {
- this.writer.writeSpace(s);
- this.setLastNonTriviaPosition(s, /*force*/ false);
- };
- Writer.prototype.writeStringLiteral = function (s) {
- this.writer.writeStringLiteral(s);
- this.setLastNonTriviaPosition(s, /*force*/ false);
- };
- Writer.prototype.writeSymbol = function (s, sym) {
- this.writer.writeSymbol(s, sym);
- this.setLastNonTriviaPosition(s, /*force*/ false);
- };
- Writer.prototype.writeTextOfNode = function (text, node) {
- this.writer.writeTextOfNode(text, node);
- };
- Writer.prototype.writeLine = function () {
- this.writer.writeLine();
- };
- Writer.prototype.increaseIndent = function () {
- this.writer.increaseIndent();
- };
- Writer.prototype.decreaseIndent = function () {
- this.writer.decreaseIndent();
- };
- Writer.prototype.getText = function () {
- return this.writer.getText();
- };
- Writer.prototype.rawWrite = function (s) {
- this.writer.rawWrite(s);
- this.setLastNonTriviaPosition(s, /*force*/ false);
- };
- Writer.prototype.writeLiteral = function (s) {
- this.writer.writeLiteral(s);
- this.setLastNonTriviaPosition(s, /*force*/ true);
- };
- Writer.prototype.getTextPos = function () {
- return this.writer.getTextPos();
- };
- Writer.prototype.getLine = function () {
- return this.writer.getLine();
- };
- Writer.prototype.getColumn = function () {
- return this.writer.getColumn();
- };
- Writer.prototype.getIndent = function () {
- return this.writer.getIndent();
- };
- Writer.prototype.isAtStartOfLine = function () {
- return this.writer.isAtStartOfLine();
- };
- Writer.prototype.clear = function () {
- this.writer.clear();
- this.lastNonTriviaPosition = 0;
- };
- return Writer;
- }());
- function getInsertionPositionAtSourceFileTop(_a) {
- var text = _a.text;
- var shebang = ts.getShebang(text);
- var position = 0;
- if (shebang !== undefined) {
- position = shebang.length;
- advancePastLineBreak();
- }
- // For a source file, it is possible there are detached comments we should not skip
- var ranges = ts.getLeadingCommentRanges(text, position);
- if (!ranges)
- return position;
- // However we should still skip a pinned comment at the top
- if (ranges.length && ranges[0].kind === 3 /* MultiLineCommentTrivia */ && ts.isPinnedComment(text, ranges[0])) {
- position = ranges[0].end;
- advancePastLineBreak();
- ranges = ranges.slice(1);
- }
- // As well as any triple slash references
- for (var _i = 0, ranges_1 = ranges; _i < ranges_1.length; _i++) {
- var range = ranges_1[_i];
- if (range.kind === 2 /* SingleLineCommentTrivia */ && ts.isRecognizedTripleSlashComment(text, range.pos, range.end)) {
- position = range.end;
- advancePastLineBreak();
- continue;
- }
- break;
- }
- return position;
- function advancePastLineBreak() {
- if (position < text.length) {
- var charCode = text.charCodeAt(position);
- if (ts.isLineBreak(charCode)) {
- position++;
- if (position < text.length && charCode === 13 /* carriageReturn */ && text.charCodeAt(position) === 10 /* lineFeed */) {
- position++;
- }
- }
- }
- }
- }
- function needSemicolonBetween(a, b) {
- return (ts.isPropertySignature(a) || ts.isPropertyDeclaration(a)) && ts.isClassOrTypeElement(b) && b.name.kind === 146 /* ComputedPropertyName */
- || ts.isStatementButNotDeclaration(a) && ts.isStatementButNotDeclaration(b); // TODO: only if b would start with a `(` or `[`
- }
- })(textChanges = ts.textChanges || (ts.textChanges = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var codeFixRegistrations = [];
- var fixIdToRegistration = ts.createMap();
- function registerCodeFix(reg) {
- for (var _i = 0, _a = reg.errorCodes; _i < _a.length; _i++) {
- var error = _a[_i];
- var registrations = codeFixRegistrations[error];
- if (!registrations) {
- registrations = [];
- codeFixRegistrations[error] = registrations;
- }
- registrations.push(reg);
- }
- if (reg.fixIds) {
- for (var _b = 0, _c = reg.fixIds; _b < _c.length; _b++) {
- var fixId = _c[_b];
- ts.Debug.assert(!fixIdToRegistration.has(fixId));
- fixIdToRegistration.set(fixId, reg);
- }
- }
- }
- codefix.registerCodeFix = registerCodeFix;
- function getSupportedErrorCodes() {
- return Object.keys(codeFixRegistrations);
- }
- codefix.getSupportedErrorCodes = getSupportedErrorCodes;
- function getFixes(context) {
- var fixes = codeFixRegistrations[context.errorCode];
- var allActions = [];
- ts.forEach(fixes, function (f) {
- var actions = f.getCodeActions(context);
- if (actions && actions.length > 0) {
- for (var _i = 0, actions_1 = actions; _i < actions_1.length; _i++) {
- var action = actions_1[_i];
- if (action === undefined) {
- context.host.log("Action for error code " + context.errorCode + " added an invalid action entry; please log a bug");
- }
- else {
- allActions.push(action);
- }
- }
- }
- });
- return allActions;
- }
- codefix.getFixes = getFixes;
- function getAllFixes(context) {
- // Currently fixId is always a string.
- return fixIdToRegistration.get(ts.cast(context.fixId, ts.isString)).getAllCodeActions(context);
- }
- codefix.getAllFixes = getAllFixes;
- function createCombinedCodeActions(changes, commands) {
- return { changes: changes, commands: commands };
- }
- function createFileTextChanges(fileName, textChanges) {
- return { fileName: fileName, textChanges: textChanges };
- }
- codefix.createFileTextChanges = createFileTextChanges;
- function codeFixAll(context, errorCodes, use) {
- var commands = [];
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) {
- return eachDiagnostic(context, errorCodes, function (diag) { return use(t, diag, commands); });
- });
- return createCombinedCodeActions(changes, commands.length === 0 ? undefined : commands);
- }
- codefix.codeFixAll = codeFixAll;
- function eachDiagnostic(_a, errorCodes, cb) {
- var program = _a.program, sourceFile = _a.sourceFile;
- for (var _i = 0, _b = program.getSemanticDiagnostics(sourceFile).concat(ts.computeSuggestionDiagnostics(sourceFile, program)); _i < _b.length; _i++) {
- var diag = _b[_i];
- if (ts.contains(errorCodes, diag.code)) {
- cb(diag);
- }
- }
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var refactor;
- (function (refactor_1) {
- // A map with the refactor code as key, the refactor itself as value
- // e.g. nonSuggestableRefactors[refactorCode] -> the refactor you want
- var refactors = ts.createMap();
- /** @param name An unique code associated with each refactor. Does not have to be human-readable. */
- function registerRefactor(name, refactor) {
- refactors.set(name, refactor);
- }
- refactor_1.registerRefactor = registerRefactor;
- function getApplicableRefactors(context) {
- return ts.arrayFrom(ts.flatMapIterator(refactors.values(), function (refactor) {
- return context.cancellationToken && context.cancellationToken.isCancellationRequested() ? undefined : refactor.getAvailableActions(context);
- }));
- }
- refactor_1.getApplicableRefactors = getApplicableRefactors;
- function getEditsForRefactor(context, refactorName, actionName) {
- var refactor = refactors.get(refactorName);
- return refactor && refactor.getEditsForAction(context, actionName);
- }
- refactor_1.getEditsForRefactor = getEditsForRefactor;
- })(refactor = ts.refactor || (ts.refactor = {}));
- function getRefactorContextLength(context) {
- return context.endPosition === undefined ? 0 : context.endPosition - context.startPosition;
- }
- ts.getRefactorContextLength = getRefactorContextLength;
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "addMissingInvocationForDecorator";
- var errorCodes = [ts.Diagnostics._0_accepts_too_few_arguments_to_be_used_as_a_decorator_here_Did_you_mean_to_call_it_first_and_write_0.code];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return makeChange(t, context.sourceFile, context.span.start); });
- return [{ description: ts.getLocaleSpecificMessage(ts.Diagnostics.Call_decorator_expression), changes: changes, fixId: fixId }];
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) { return makeChange(changes, diag.file, diag.start); }); },
- });
- function makeChange(changeTracker, sourceFile, pos) {
- var token = ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false);
- var decorator = ts.findAncestor(token, ts.isDecorator);
- ts.Debug.assert(!!decorator, "Expected position to be owned by a decorator.");
- var replacement = ts.createCall(decorator.expression, /*typeArguments*/ undefined, /*argumentsArray*/ undefined);
- changeTracker.replaceNode(sourceFile, decorator.expression, replacement);
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "annotateWithTypeFromJSDoc";
- var errorCodes = [ts.Diagnostics.JSDoc_types_may_be_moved_to_TypeScript_types.code];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var decl = getDeclaration(context.sourceFile, context.span.start);
- if (!decl)
- return;
- var description = ts.getLocaleSpecificMessage(ts.Diagnostics.Annotate_with_type_from_JSDoc);
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(t, context.sourceFile, decl); });
- return [{ description: description, changes: changes, fixId: fixId }];
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) {
- var decl = getDeclaration(diag.file, diag.start);
- if (decl)
- doChange(changes, diag.file, decl);
- }); },
- });
- function getDeclaration(file, pos) {
- var name = ts.getTokenAtPosition(file, pos, /*includeJsDocComment*/ false);
- // For an arrow function with no name, 'name' lands on the first parameter.
- return ts.tryCast(ts.isParameter(name.parent) ? name.parent.parent : name.parent, parameterShouldGetTypeFromJSDoc);
- }
- function parameterShouldGetTypeFromJSDoc(node) {
- return isDeclarationWithType(node) && hasUsableJSDoc(node);
- }
- codefix.parameterShouldGetTypeFromJSDoc = parameterShouldGetTypeFromJSDoc;
- function hasUsableJSDoc(decl) {
- return ts.isFunctionLikeDeclaration(decl)
- ? decl.parameters.some(hasUsableJSDoc) || (!decl.type && !!ts.getJSDocReturnType(decl))
- : !decl.type && !!ts.getJSDocType(decl);
- }
- function doChange(changes, sourceFile, decl) {
- if (ts.isFunctionLikeDeclaration(decl) && (ts.getJSDocReturnType(decl) || decl.parameters.some(function (p) { return !!ts.getJSDocType(p); }))) {
- if (!decl.typeParameters) {
- var typeParameters = ts.getJSDocTypeParameterDeclarations(decl);
- if (typeParameters)
- changes.insertTypeParameters(sourceFile, decl, typeParameters);
- }
- var needParens = ts.isArrowFunction(decl) && !ts.findChildOfKind(decl, 19 /* OpenParenToken */, sourceFile);
- if (needParens)
- changes.insertNodeBefore(sourceFile, ts.first(decl.parameters), ts.createToken(19 /* OpenParenToken */));
- for (var _i = 0, _a = decl.parameters; _i < _a.length; _i++) {
- var param = _a[_i];
- if (!param.type) {
- var paramType = ts.getJSDocType(param);
- if (paramType)
- changes.insertTypeAnnotation(sourceFile, param, transformJSDocType(paramType));
- }
- }
- if (needParens)
- changes.insertNodeAfter(sourceFile, ts.last(decl.parameters), ts.createToken(20 /* CloseParenToken */));
- if (!decl.type) {
- var returnType = ts.getJSDocReturnType(decl);
- if (returnType)
- changes.insertTypeAnnotation(sourceFile, decl, transformJSDocType(returnType));
- }
- }
- else {
- var jsdocType = ts.Debug.assertDefined(ts.getJSDocType(decl)); // If not defined, shouldn't have been an error to fix
- ts.Debug.assert(!decl.type); // If defined, shouldn't have been an error to fix.
- changes.insertTypeAnnotation(sourceFile, decl, transformJSDocType(jsdocType));
- }
- }
- function isDeclarationWithType(node) {
- return ts.isFunctionLikeDeclaration(node) ||
- node.kind === 230 /* VariableDeclaration */ ||
- node.kind === 150 /* PropertySignature */ ||
- node.kind === 151 /* PropertyDeclaration */;
- }
- function transformJSDocType(node) {
- switch (node.kind) {
- case 275 /* JSDocAllType */:
- case 276 /* JSDocUnknownType */:
- return ts.createTypeReferenceNode("any", ts.emptyArray);
- case 279 /* JSDocOptionalType */:
- return transformJSDocOptionalType(node);
- case 278 /* JSDocNonNullableType */:
- return transformJSDocType(node.type);
- case 277 /* JSDocNullableType */:
- return transformJSDocNullableType(node);
- case 281 /* JSDocVariadicType */:
- return transformJSDocVariadicType(node);
- case 280 /* JSDocFunctionType */:
- return transformJSDocFunctionType(node);
- case 161 /* TypeReference */:
- return transformJSDocTypeReference(node);
- default:
- var visited = ts.visitEachChild(node, transformJSDocType, /*context*/ undefined);
- ts.setEmitFlags(visited, 1 /* SingleLine */);
- return visited;
- }
- }
- function transformJSDocOptionalType(node) {
- return ts.createUnionTypeNode([ts.visitNode(node.type, transformJSDocType), ts.createTypeReferenceNode("undefined", ts.emptyArray)]);
- }
- function transformJSDocNullableType(node) {
- return ts.createUnionTypeNode([ts.visitNode(node.type, transformJSDocType), ts.createTypeReferenceNode("null", ts.emptyArray)]);
- }
- function transformJSDocVariadicType(node) {
- return ts.createArrayTypeNode(ts.visitNode(node.type, transformJSDocType));
- }
- function transformJSDocFunctionType(node) {
- return ts.createFunctionTypeNode(ts.emptyArray, node.parameters.map(transformJSDocParameter), node.type);
- }
- function transformJSDocParameter(node) {
- var index = node.parent.parameters.indexOf(node);
- var isRest = node.type.kind === 281 /* JSDocVariadicType */ && index === node.parent.parameters.length - 1;
- var name = node.name || (isRest ? "rest" : "arg" + index);
- var dotdotdot = isRest ? ts.createToken(24 /* DotDotDotToken */) : node.dotDotDotToken;
- return ts.createParameter(node.decorators, node.modifiers, dotdotdot, name, node.questionToken, ts.visitNode(node.type, transformJSDocType), node.initializer);
- }
- function transformJSDocTypeReference(node) {
- var name = node.typeName;
- var args = node.typeArguments;
- if (ts.isIdentifier(node.typeName)) {
- if (ts.isJSDocIndexSignature(node)) {
- return transformJSDocIndexSignature(node);
- }
- var text = node.typeName.text;
- switch (node.typeName.text) {
- case "String":
- case "Boolean":
- case "Object":
- case "Number":
- text = text.toLowerCase();
- break;
- case "array":
- case "date":
- case "promise":
- text = text[0].toUpperCase() + text.slice(1);
- break;
- }
- name = ts.createIdentifier(text);
- if ((text === "Array" || text === "Promise") && !node.typeArguments) {
- args = ts.createNodeArray([ts.createTypeReferenceNode("any", ts.emptyArray)]);
- }
- else {
- args = ts.visitNodes(node.typeArguments, transformJSDocType);
- }
- }
- return ts.createTypeReferenceNode(name, args);
- }
- function transformJSDocIndexSignature(node) {
- var index = ts.createParameter(
- /*decorators*/ undefined,
- /*modifiers*/ undefined,
- /*dotDotDotToken*/ undefined, node.typeArguments[0].kind === 134 /* NumberKeyword */ ? "n" : "s",
- /*questionToken*/ undefined, ts.createTypeReferenceNode(node.typeArguments[0].kind === 134 /* NumberKeyword */ ? "number" : "string", []),
- /*initializer*/ undefined);
- var indexSignature = ts.createTypeLiteralNode([ts.createIndexSignature(/*decorators*/ undefined, /*modifiers*/ undefined, [index], node.typeArguments[1])]);
- ts.setEmitFlags(indexSignature, 1 /* SingleLine */);
- return indexSignature;
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "convertFunctionToEs6Class";
- var errorCodes = [ts.Diagnostics.This_constructor_function_may_be_converted_to_a_class_declaration.code];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(t, context.sourceFile, context.span.start, context.program.getTypeChecker()); });
- return [{ description: ts.getLocaleSpecificMessage(ts.Diagnostics.Convert_function_to_an_ES2015_class), changes: changes, fixId: fixId }];
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, err) { return doChange(changes, err.file, err.start, context.program.getTypeChecker()); }); },
- });
- function doChange(changes, sourceFile, position, checker) {
- var deletedNodes = [];
- var deletes = [];
- var ctorSymbol = checker.getSymbolAtLocation(ts.getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false));
- if (!ctorSymbol || !(ctorSymbol.flags & (16 /* Function */ | 3 /* Variable */))) {
- // Bad input
- return undefined;
- }
- var ctorDeclaration = ctorSymbol.valueDeclaration;
- var precedingNode;
- var newClassDeclaration;
- switch (ctorDeclaration.kind) {
- case 232 /* FunctionDeclaration */:
- precedingNode = ctorDeclaration;
- deleteNode(ctorDeclaration);
- newClassDeclaration = createClassFromFunctionDeclaration(ctorDeclaration);
- break;
- case 230 /* VariableDeclaration */:
- precedingNode = ctorDeclaration.parent.parent;
- if (ctorDeclaration.parent.declarations.length === 1) {
- deleteNode(precedingNode);
- }
- else {
- deleteNode(ctorDeclaration, /*inList*/ true);
- }
- newClassDeclaration = createClassFromVariableDeclaration(ctorDeclaration);
- break;
- }
- if (!newClassDeclaration) {
- return undefined;
- }
- copyComments(ctorDeclaration, newClassDeclaration, sourceFile);
- // Because the preceding node could be touched, we need to insert nodes before delete nodes.
- changes.insertNodeAfter(sourceFile, precedingNode, newClassDeclaration);
- for (var _i = 0, deletes_1 = deletes; _i < deletes_1.length; _i++) {
- var deleteCallback = deletes_1[_i];
- deleteCallback();
- }
- function deleteNode(node, inList) {
- if (inList === void 0) { inList = false; }
- if (deletedNodes.some(function (n) { return ts.isNodeDescendantOf(node, n); })) {
- // Parent node has already been deleted; do nothing
- return;
- }
- deletedNodes.push(node);
- if (inList) {
- deletes.push(function () { return changes.deleteNodeInList(sourceFile, node); });
- }
- else {
- deletes.push(function () { return changes.deleteNode(sourceFile, node); });
- }
- }
- function createClassElementsFromSymbol(symbol) {
- var memberElements = [];
- // all instance members are stored in the "member" array of symbol
- if (symbol.members) {
- symbol.members.forEach(function (member) {
- var memberElement = createClassElement(member, /*modifiers*/ undefined);
- if (memberElement) {
- memberElements.push(memberElement);
- }
- });
- }
- // all static members are stored in the "exports" array of symbol
- if (symbol.exports) {
- symbol.exports.forEach(function (member) {
- var memberElement = createClassElement(member, [ts.createToken(115 /* StaticKeyword */)]);
- if (memberElement) {
- memberElements.push(memberElement);
- }
- });
- }
- return memberElements;
- function shouldConvertDeclaration(_target, source) {
- // Right now the only thing we can convert are function expressions - other values shouldn't get
- // transformed. We can update this once ES public class properties are available.
- return ts.isFunctionLike(source);
- }
- function createClassElement(symbol, modifiers) {
- // both properties and methods are bound as property symbols
- if (!(symbol.flags & 4 /* Property */)) {
- return;
- }
- var memberDeclaration = symbol.valueDeclaration;
- var assignmentBinaryExpression = memberDeclaration.parent;
- if (!shouldConvertDeclaration(memberDeclaration, assignmentBinaryExpression.right)) {
- return;
- }
- // delete the entire statement if this expression is the sole expression to take care of the semicolon at the end
- var nodeToDelete = assignmentBinaryExpression.parent && assignmentBinaryExpression.parent.kind === 214 /* ExpressionStatement */
- ? assignmentBinaryExpression.parent : assignmentBinaryExpression;
- deleteNode(nodeToDelete);
- if (!assignmentBinaryExpression.right) {
- return ts.createProperty([], modifiers, symbol.name, /*questionToken*/ undefined,
- /*type*/ undefined, /*initializer*/ undefined);
- }
- switch (assignmentBinaryExpression.right.kind) {
- case 190 /* FunctionExpression */: {
- var functionExpression = assignmentBinaryExpression.right;
- var fullModifiers = ts.concatenate(modifiers, getModifierKindFromSource(functionExpression, 120 /* AsyncKeyword */));
- var method = ts.createMethod(/*decorators*/ undefined, fullModifiers, /*asteriskToken*/ undefined, memberDeclaration.name, /*questionToken*/ undefined,
- /*typeParameters*/ undefined, functionExpression.parameters, /*type*/ undefined, functionExpression.body);
- copyComments(assignmentBinaryExpression, method, sourceFile);
- return method;
- }
- case 191 /* ArrowFunction */: {
- var arrowFunction = assignmentBinaryExpression.right;
- var arrowFunctionBody = arrowFunction.body;
- var bodyBlock = void 0;
- // case 1: () => { return [1,2,3] }
- if (arrowFunctionBody.kind === 211 /* Block */) {
- bodyBlock = arrowFunctionBody;
- }
- // case 2: () => [1,2,3]
- else {
- bodyBlock = ts.createBlock([ts.createReturn(arrowFunctionBody)]);
- }
- var fullModifiers = ts.concatenate(modifiers, getModifierKindFromSource(arrowFunction, 120 /* AsyncKeyword */));
- var method = ts.createMethod(/*decorators*/ undefined, fullModifiers, /*asteriskToken*/ undefined, memberDeclaration.name, /*questionToken*/ undefined,
- /*typeParameters*/ undefined, arrowFunction.parameters, /*type*/ undefined, bodyBlock);
- copyComments(assignmentBinaryExpression, method, sourceFile);
- return method;
- }
- default: {
- // Don't try to declare members in JavaScript files
- if (ts.isSourceFileJavaScript(sourceFile)) {
- return;
- }
- var prop = ts.createProperty(/*decorators*/ undefined, modifiers, memberDeclaration.name, /*questionToken*/ undefined,
- /*type*/ undefined, assignmentBinaryExpression.right);
- copyComments(assignmentBinaryExpression.parent, prop, sourceFile);
- return prop;
- }
- }
- }
- }
- function createClassFromVariableDeclaration(node) {
- var initializer = node.initializer;
- if (!initializer || initializer.kind !== 190 /* FunctionExpression */) {
- return undefined;
- }
- if (node.name.kind !== 71 /* Identifier */) {
- return undefined;
- }
- var memberElements = createClassElementsFromSymbol(initializer.symbol);
- if (initializer.body) {
- memberElements.unshift(ts.createConstructor(/*decorators*/ undefined, /*modifiers*/ undefined, initializer.parameters, initializer.body));
- }
- var modifiers = getModifierKindFromSource(precedingNode, 84 /* ExportKeyword */);
- var cls = ts.createClassDeclaration(/*decorators*/ undefined, modifiers, node.name,
- /*typeParameters*/ undefined, /*heritageClauses*/ undefined, memberElements);
- // Don't call copyComments here because we'll already leave them in place
- return cls;
- }
- function createClassFromFunctionDeclaration(node) {
- var memberElements = createClassElementsFromSymbol(ctorSymbol);
- if (node.body) {
- memberElements.unshift(ts.createConstructor(/*decorators*/ undefined, /*modifiers*/ undefined, node.parameters, node.body));
- }
- var modifiers = getModifierKindFromSource(node, 84 /* ExportKeyword */);
- var cls = ts.createClassDeclaration(/*decorators*/ undefined, modifiers, node.name,
- /*typeParameters*/ undefined, /*heritageClauses*/ undefined, memberElements);
- // Don't call copyComments here because we'll already leave them in place
- return cls;
- }
- }
- function copyComments(sourceNode, targetNode, sourceFile) {
- ts.forEachLeadingCommentRange(sourceFile.text, sourceNode.pos, function (pos, end, kind, htnl) {
- if (kind === 3 /* MultiLineCommentTrivia */) {
- // Remove leading /*
- pos += 2;
- // Remove trailing */
- end -= 2;
- }
- else {
- // Remove leading //
- pos += 2;
- }
- ts.addSyntheticLeadingComment(targetNode, kind, sourceFile.text.slice(pos, end), htnl);
- });
- }
- function getModifierKindFromSource(source, kind) {
- return ts.filter(source.modifiers, function (modifier) { return modifier.kind === kind; });
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- codefix.registerCodeFix({
- errorCodes: [ts.Diagnostics.File_is_a_CommonJS_module_it_may_be_converted_to_an_ES6_module.code],
- getCodeActions: function (context) {
- var description = ts.getLocaleSpecificMessage(ts.Diagnostics.Convert_to_ES6_module);
- var sourceFile = context.sourceFile, program = context.program;
- var changes = ts.textChanges.ChangeTracker.with(context, function (changes) {
- var moduleExportsChangedToDefault = convertFileToEs6Module(sourceFile, program.getTypeChecker(), changes, program.getCompilerOptions().target);
- if (moduleExportsChangedToDefault) {
- for (var _i = 0, _a = program.getSourceFiles(); _i < _a.length; _i++) {
- var importingFile = _a[_i];
- fixImportOfModuleExports(importingFile, sourceFile, changes);
- }
- }
- });
- // No support for fix-all since this applies to the whole file at once anyway.
- return [{ description: description, changes: changes, fixId: undefined }];
- },
- });
- function fixImportOfModuleExports(importingFile, exportingFile, changes) {
- for (var _i = 0, _a = importingFile.imports; _i < _a.length; _i++) {
- var moduleSpecifier = _a[_i];
- var imported = ts.getResolvedModule(importingFile, moduleSpecifier.text);
- if (!imported || imported.resolvedFileName !== exportingFile.fileName) {
- continue;
- }
- var parent = moduleSpecifier.parent;
- switch (parent.kind) {
- case 252 /* ExternalModuleReference */: {
- var importEq = parent.parent;
- changes.replaceNode(importingFile, importEq, makeImport(importEq.name, /*namedImports*/ undefined, moduleSpecifier.text));
- break;
- }
- case 185 /* CallExpression */: {
- var call = parent;
- if (ts.isRequireCall(call, /*checkArgumentIsStringLiteral*/ false)) {
- changes.replaceNode(importingFile, parent, ts.createPropertyAccess(ts.getSynthesizedDeepClone(call), "default"));
- }
- break;
- }
- }
- }
- }
- /** @returns Whether we converted a `module.exports =` to a default export. */
- function convertFileToEs6Module(sourceFile, checker, changes, target) {
- var identifiers = { original: collectFreeIdentifiers(sourceFile), additional: ts.createMap() };
- var exports = collectExportRenames(sourceFile, checker, identifiers);
- convertExportsAccesses(sourceFile, exports, changes);
- var moduleExportsChangedToDefault = false;
- for (var _i = 0, _a = sourceFile.statements; _i < _a.length; _i++) {
- var statement = _a[_i];
- var moduleExportsChanged = convertStatement(sourceFile, statement, checker, changes, identifiers, target, exports);
- moduleExportsChangedToDefault = moduleExportsChangedToDefault || moduleExportsChanged;
- }
- return moduleExportsChangedToDefault;
- }
- function collectExportRenames(sourceFile, checker, identifiers) {
- var res = ts.createMap();
- forEachExportReference(sourceFile, function (node) {
- var _a = node.name, text = _a.text, originalKeywordKind = _a.originalKeywordKind;
- if (!res.has(text) && (originalKeywordKind !== undefined && ts.isNonContextualKeyword(originalKeywordKind)
- || checker.resolveName(node.name.text, node, 67216319 /* Value */, /*excludeGlobals*/ true))) {
- // Unconditionally add an underscore in case `text` is a keyword.
- res.set(text, makeUniqueName("_" + text, identifiers));
- }
- });
- return res;
- }
- function convertExportsAccesses(sourceFile, exports, changes) {
- forEachExportReference(sourceFile, function (node, isAssignmentLhs) {
- if (isAssignmentLhs) {
- return;
- }
- var text = node.name.text;
- changes.replaceNode(sourceFile, node, ts.createIdentifier(exports.get(text) || text));
- });
- }
- function forEachExportReference(sourceFile, cb) {
- sourceFile.forEachChild(function recur(node) {
- if (ts.isPropertyAccessExpression(node) && ts.isExportsOrModuleExportsOrAlias(sourceFile, node.expression)) {
- var parent = node.parent;
- cb(node, ts.isBinaryExpression(parent) && parent.left === node && parent.operatorToken.kind === 58 /* EqualsToken */);
- }
- node.forEachChild(recur);
- });
- }
- function convertStatement(sourceFile, statement, checker, changes, identifiers, target, exports) {
- switch (statement.kind) {
- case 212 /* VariableStatement */:
- convertVariableStatement(sourceFile, statement, changes, checker, identifiers, target);
- return false;
- case 214 /* ExpressionStatement */: {
- var expression = statement.expression;
- switch (expression.kind) {
- case 185 /* CallExpression */: {
- if (ts.isRequireCall(expression, /*checkArgumentIsStringLiteral*/ true)) {
- // For side-effecting require() call, just make a side-effecting import.
- changes.replaceNode(sourceFile, statement, makeImport(/*name*/ undefined, /*namedImports*/ undefined, expression.arguments[0].text));
- }
- return false;
- }
- case 198 /* BinaryExpression */: {
- var _a = expression, left = _a.left, operatorToken = _a.operatorToken, right = _a.right;
- return operatorToken.kind === 58 /* EqualsToken */ && convertAssignment(sourceFile, checker, statement, left, right, changes, exports);
- }
- }
- }
- // falls through
- default:
- return false;
- }
- }
- function convertVariableStatement(sourceFile, statement, changes, checker, identifiers, target) {
- var declarationList = statement.declarationList;
- var foundImport = false;
- var newNodes = ts.flatMap(declarationList.declarations, function (decl) {
- var name = decl.name, initializer = decl.initializer;
- if (ts.isExportsOrModuleExportsOrAlias(sourceFile, initializer)) {
- // `const alias = module.exports;` can be removed.
- foundImport = true;
- return [];
- }
- if (ts.isRequireCall(initializer, /*checkArgumentIsStringLiteral*/ true)) {
- foundImport = true;
- return convertSingleImport(sourceFile, name, initializer.arguments[0].text, changes, checker, identifiers, target);
- }
- else if (ts.isPropertyAccessExpression(initializer) && ts.isRequireCall(initializer.expression, /*checkArgumentIsStringLiteral*/ true)) {
- foundImport = true;
- return convertPropertyAccessImport(name, initializer.name.text, initializer.expression.arguments[0].text, identifiers);
- }
- else {
- // Move it out to its own variable statement.
- return ts.createVariableStatement(/*modifiers*/ undefined, ts.createVariableDeclarationList([decl], declarationList.flags));
- }
- });
- if (foundImport) {
- // useNonAdjustedEndPosition to ensure we don't eat the newline after the statement.
- changes.replaceNodeWithNodes(sourceFile, statement, newNodes);
- }
- }
- /** Converts `const name = require("moduleSpecifier").propertyName` */
- function convertPropertyAccessImport(name, propertyName, moduleSpecifier, identifiers) {
- switch (name.kind) {
- case 178 /* ObjectBindingPattern */:
- case 179 /* ArrayBindingPattern */: {
- // `const [a, b] = require("c").d` --> `import { d } from "c"; const [a, b] = d;`
- var tmp = makeUniqueName(propertyName, identifiers);
- return [
- makeSingleImport(tmp, propertyName, moduleSpecifier),
- makeConst(/*modifiers*/ undefined, name, ts.createIdentifier(tmp)),
- ];
- }
- case 71 /* Identifier */:
- // `const a = require("b").c` --> `import { c as a } from "./b";
- return [makeSingleImport(name.text, propertyName, moduleSpecifier)];
- default:
- ts.Debug.assertNever(name);
- }
- }
- function convertAssignment(sourceFile, checker, statement, left, right, changes, exports) {
- if (!ts.isPropertyAccessExpression(left)) {
- return false;
- }
- if (ts.isExportsOrModuleExportsOrAlias(sourceFile, left)) {
- if (ts.isExportsOrModuleExportsOrAlias(sourceFile, right)) {
- // `const alias = module.exports;` or `module.exports = alias;` can be removed.
- changes.deleteNode(sourceFile, statement);
- }
- else {
- var newNodes = ts.isObjectLiteralExpression(right) ? tryChangeModuleExportsObject(right) : undefined;
- var changedToDefaultExport = false;
- if (!newNodes) {
- (_a = convertModuleExportsToExportDefault(right, checker), newNodes = _a[0], changedToDefaultExport = _a[1]);
- }
- changes.replaceNodeWithNodes(sourceFile, statement, newNodes);
- return changedToDefaultExport;
- }
- }
- else if (ts.isExportsOrModuleExportsOrAlias(sourceFile, left.expression)) {
- convertNamedExport(sourceFile, statement, left.name, right, changes, exports);
- }
- return false;
- var _a;
- }
- /**
- * Convert `module.exports = { ... }` to individual exports..
- * We can't always do this if the module has interesting members -- then it will be a default export instead.
- */
- function tryChangeModuleExportsObject(object) {
- return ts.mapAllOrFail(object.properties, function (prop) {
- switch (prop.kind) {
- case 155 /* GetAccessor */:
- case 156 /* SetAccessor */:
- // TODO: Maybe we should handle this? See fourslash test `refactorConvertToEs6Module_export_object_shorthand.ts`.
- case 269 /* ShorthandPropertyAssignment */:
- case 270 /* SpreadAssignment */:
- return undefined;
- case 268 /* PropertyAssignment */:
- return !ts.isIdentifier(prop.name) ? undefined : convertExportsDotXEquals(prop.name.text, prop.initializer);
- case 153 /* MethodDeclaration */:
- return !ts.isIdentifier(prop.name) ? undefined : functionExpressionToDeclaration(prop.name.text, [ts.createToken(84 /* ExportKeyword */)], prop);
- default:
- ts.Debug.assertNever(prop);
- }
- });
- }
- function convertNamedExport(sourceFile, statement, propertyName, right, changes, exports) {
- // If "originalKeywordKind" was set, this is e.g. `exports.
- var text = propertyName.text;
- var rename = exports.get(text);
- if (rename !== undefined) {
- /*
- const _class = 0;
- export { _class as class };
- */
- var newNodes = [
- makeConst(/*modifiers*/ undefined, rename, right),
- makeExportDeclaration([ts.createExportSpecifier(rename, text)]),
- ];
- changes.replaceNodeWithNodes(sourceFile, statement, newNodes);
- }
- else {
- changes.replaceNode(sourceFile, statement, convertExportsDotXEquals(text, right), { useNonAdjustedEndPosition: true });
- }
- }
- function convertModuleExportsToExportDefault(exported, checker) {
- var modifiers = [ts.createToken(84 /* ExportKeyword */), ts.createToken(79 /* DefaultKeyword */)];
- switch (exported.kind) {
- case 190 /* FunctionExpression */:
- case 191 /* ArrowFunction */: {
- // `module.exports = function f() {}` --> `export default function f() {}`
- var fn = exported;
- return [[functionExpressionToDeclaration(fn.name && fn.name.text, modifiers, fn)], true];
- }
- case 203 /* ClassExpression */: {
- // `module.exports = class C {}` --> `export default class C {}`
- var cls = exported;
- return [[classExpressionToDeclaration(cls.name && cls.name.text, modifiers, cls)], true];
- }
- case 185 /* CallExpression */:
- if (ts.isRequireCall(exported, /*checkArgumentIsStringLiteral*/ true)) {
- return convertReExportAll(exported.arguments[0], checker);
- }
- // falls through
- default:
- // `module.exports = 0;` --> `export default 0;`
- return [[ts.createExportAssignment(/*decorators*/ undefined, /*modifiers*/ undefined, /*isExportEquals*/ false, exported)], true];
- }
- }
- function convertReExportAll(reExported, checker) {
- // `module.exports = require("x");` ==> `export * from "x"; export { default } from "x";`
- var moduleSpecifier = reExported.text;
- var moduleSymbol = checker.getSymbolAtLocation(reExported);
- var exports = moduleSymbol ? moduleSymbol.exports : ts.emptyUnderscoreEscapedMap;
- return exports.has("export=")
- ? [[reExportDefault(moduleSpecifier)], true]
- : !exports.has("default")
- ? [[reExportStar(moduleSpecifier)], false]
- // If there's some non-default export, must include both `export *` and `export default`.
- : exports.size > 1 ? [[reExportStar(moduleSpecifier), reExportDefault(moduleSpecifier)], true] : [[reExportDefault(moduleSpecifier)], true];
- }
- function reExportStar(moduleSpecifier) {
- return makeExportDeclaration(/*exportClause*/ undefined, moduleSpecifier);
- }
- function reExportDefault(moduleSpecifier) {
- return makeExportDeclaration([ts.createExportSpecifier(/*propertyName*/ undefined, "default")], moduleSpecifier);
- }
- function convertExportsDotXEquals(name, exported) {
- var modifiers = [ts.createToken(84 /* ExportKeyword */)];
- switch (exported.kind) {
- case 190 /* FunctionExpression */: {
- var expressionName = exported.name;
- if (expressionName && expressionName.text !== name) {
- // `exports.f = function g() {}` -> `export const f = function g() {}`
- return exportConst();
- }
- }
- // falls through
- case 191 /* ArrowFunction */:
- // `exports.f = function() {}` --> `export function f() {}`
- return functionExpressionToDeclaration(name, modifiers, exported);
- case 203 /* ClassExpression */:
- // `exports.C = class {}` --> `export class C {}`
- return classExpressionToDeclaration(name, modifiers, exported);
- default:
- return exportConst();
- }
- function exportConst() {
- // `exports.x = 0;` --> `export const x = 0;`
- return makeConst(modifiers, ts.createIdentifier(name), exported);
- }
- }
- /**
- * Converts `const <> = require("x");`.
- * Returns nodes that will replace the variable declaration for the commonjs import.
- * May also make use `changes` to remove qualifiers at the use sites of imports, to change `mod.x` to `x`.
- */
- function convertSingleImport(file, name, moduleSpecifier, changes, checker, identifiers, target) {
- switch (name.kind) {
- case 178 /* ObjectBindingPattern */: {
- var importSpecifiers = ts.mapAllOrFail(name.elements, function (e) {
- return e.dotDotDotToken || e.initializer || e.propertyName && !ts.isIdentifier(e.propertyName) || !ts.isIdentifier(e.name)
- ? undefined
- : makeImportSpecifier(e.propertyName && e.propertyName.text, e.name.text);
- });
- if (importSpecifiers) {
- return [makeImport(/*name*/ undefined, importSpecifiers, moduleSpecifier)];
- }
- }
- // falls through -- object destructuring has an interesting pattern and must be a variable declaration
- case 179 /* ArrayBindingPattern */: {
- /*
- import x from "x";
- const [a, b, c] = x;
- */
- var tmp = makeUniqueName(codefix.moduleSpecifierToValidIdentifier(moduleSpecifier, target), identifiers);
- return [
- makeImport(ts.createIdentifier(tmp), /*namedImports*/ undefined, moduleSpecifier),
- makeConst(/*modifiers*/ undefined, ts.getSynthesizedDeepClone(name), ts.createIdentifier(tmp)),
- ];
- }
- case 71 /* Identifier */:
- return convertSingleIdentifierImport(file, name, moduleSpecifier, changes, checker, identifiers);
- default:
- ts.Debug.assertNever(name);
- }
- }
- /**
- * Convert `import x = require("x").`
- * Also converts uses like `x.y()` to `y()` and uses a named import.
- */
- function convertSingleIdentifierImport(file, name, moduleSpecifier, changes, checker, identifiers) {
- var nameSymbol = checker.getSymbolAtLocation(name);
- // Maps from module property name to name actually used. (The same if there isn't shadowing.)
- var namedBindingsNames = ts.createMap();
- // True if there is some non-property use like `x()` or `f(x)`.
- var needDefaultImport = false;
- for (var _i = 0, _a = identifiers.original.get(name.text); _i < _a.length; _i++) {
- var use = _a[_i];
- if (checker.getSymbolAtLocation(use) !== nameSymbol || use === name) {
- // This was a use of a different symbol with the same name, due to shadowing. Ignore.
- continue;
- }
- var parent = use.parent;
- if (ts.isPropertyAccessExpression(parent)) {
- var expression = parent.expression, propertyName = parent.name.text;
- ts.Debug.assert(expression === use); // Else shouldn't have been in `collectIdentifiers`
- var idName = namedBindingsNames.get(propertyName);
- if (idName === undefined) {
- idName = makeUniqueName(propertyName, identifiers);
- namedBindingsNames.set(propertyName, idName);
- }
- changes.replaceNode(file, parent, ts.createIdentifier(idName));
- }
- else {
- needDefaultImport = true;
- }
- }
- var namedBindings = namedBindingsNames.size === 0 ? undefined : ts.arrayFrom(ts.mapIterator(namedBindingsNames.entries(), function (_a) {
- var propertyName = _a[0], idName = _a[1];
- return ts.createImportSpecifier(propertyName === idName ? undefined : ts.createIdentifier(propertyName), ts.createIdentifier(idName));
- }));
- if (!namedBindings) {
- // If it was unused, ensure that we at least import *something*.
- needDefaultImport = true;
- }
- return [makeImport(needDefaultImport ? ts.getSynthesizedDeepClone(name) : undefined, namedBindings, moduleSpecifier)];
- }
- // Identifiers helpers
- function makeUniqueName(name, identifiers) {
- while (identifiers.original.has(name) || identifiers.additional.has(name)) {
- name = "_" + name;
- }
- identifiers.additional.set(name, true);
- return name;
- }
- function collectFreeIdentifiers(file) {
- var map = ts.createMultiMap();
- file.forEachChild(function recur(node) {
- if (ts.isIdentifier(node) && isFreeIdentifier(node)) {
- map.add(node.text, node);
- }
- node.forEachChild(recur);
- });
- return map;
- }
- function isFreeIdentifier(node) {
- var parent = node.parent;
- switch (parent.kind) {
- case 183 /* PropertyAccessExpression */:
- return parent.name !== node;
- case 180 /* BindingElement */:
- return parent.propertyName !== node;
- default:
- return true;
- }
- }
- // Node helpers
- function functionExpressionToDeclaration(name, additionalModifiers, fn) {
- return ts.createFunctionDeclaration(ts.getSynthesizedDeepClones(fn.decorators), // TODO: GH#19915 Don't think this is even legal.
- ts.concatenate(additionalModifiers, ts.getSynthesizedDeepClones(fn.modifiers)), ts.getSynthesizedDeepClone(fn.asteriskToken), name, ts.getSynthesizedDeepClones(fn.typeParameters), ts.getSynthesizedDeepClones(fn.parameters), ts.getSynthesizedDeepClone(fn.type), ts.convertToFunctionBody(ts.getSynthesizedDeepClone(fn.body)));
- }
- function classExpressionToDeclaration(name, additionalModifiers, cls) {
- return ts.createClassDeclaration(ts.getSynthesizedDeepClones(cls.decorators), // TODO: GH#19915 Don't think this is even legal.
- ts.concatenate(additionalModifiers, ts.getSynthesizedDeepClones(cls.modifiers)), name, ts.getSynthesizedDeepClones(cls.typeParameters), ts.getSynthesizedDeepClones(cls.heritageClauses), ts.getSynthesizedDeepClones(cls.members));
- }
- function makeSingleImport(localName, propertyName, moduleSpecifier) {
- return propertyName === "default"
- ? makeImport(ts.createIdentifier(localName), /*namedImports*/ undefined, moduleSpecifier)
- : makeImport(/*name*/ undefined, [makeImportSpecifier(propertyName, localName)], moduleSpecifier);
- }
- function makeImport(name, namedImports, moduleSpecifier) {
- return makeImportDeclaration(name, namedImports, ts.createLiteral(moduleSpecifier));
- }
- function makeImportDeclaration(name, namedImports, moduleSpecifier) {
- var importClause = (name || namedImports) && ts.createImportClause(name, namedImports && ts.createNamedImports(namedImports));
- return ts.createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, importClause, moduleSpecifier);
- }
- codefix.makeImportDeclaration = makeImportDeclaration;
- function makeImportSpecifier(propertyName, name) {
- return ts.createImportSpecifier(propertyName !== undefined && propertyName !== name ? ts.createIdentifier(propertyName) : undefined, ts.createIdentifier(name));
- }
- function makeConst(modifiers, name, init) {
- return ts.createVariableStatement(modifiers, ts.createVariableDeclarationList([ts.createVariableDeclaration(name, /*type*/ undefined, init)], 2 /* Const */));
- }
- function makeExportDeclaration(exportSpecifiers, moduleSpecifier) {
- return ts.createExportDeclaration(
- /*decorators*/ undefined,
- /*modifiers*/ undefined, exportSpecifiers && ts.createNamedExports(exportSpecifiers), moduleSpecifier === undefined ? undefined : ts.createLiteral(moduleSpecifier));
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "correctQualifiedNameToIndexedAccessType";
- var errorCodes = [ts.Diagnostics.Cannot_access_0_1_because_0_is_a_type_but_not_a_namespace_Did_you_mean_to_retrieve_the_type_of_the_property_1_in_0_with_0_1.code];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var qualifiedName = getQualifiedName(context.sourceFile, context.span.start);
- if (!qualifiedName)
- return undefined;
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(t, context.sourceFile, qualifiedName); });
- var description = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Rewrite_as_the_indexed_access_type_0), [qualifiedName.left.text + "[\"" + qualifiedName.right.text + "\"]"]);
- return [{ description: description, changes: changes, fixId: fixId }];
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) {
- var q = getQualifiedName(diag.file, diag.start);
- if (q) {
- doChange(changes, diag.file, q);
- }
- }); },
- });
- function getQualifiedName(sourceFile, pos) {
- var qualifiedName = ts.findAncestor(ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ true), ts.isQualifiedName);
- ts.Debug.assert(!!qualifiedName, "Expected position to be owned by a qualified name.");
- return ts.isIdentifier(qualifiedName.left) ? qualifiedName : undefined;
- }
- function doChange(changeTracker, sourceFile, qualifiedName) {
- var rightText = qualifiedName.right.text;
- var replacement = ts.createIndexedAccessTypeNode(ts.createTypeReferenceNode(qualifiedName.left, /*typeArguments*/ undefined), ts.createLiteralTypeNode(ts.createLiteral(rightText)));
- changeTracker.replaceNode(sourceFile, qualifiedName, replacement);
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var errorCodes = [ts.Diagnostics.Class_0_incorrectly_implements_interface_1.code,
- ts.Diagnostics.Class_0_incorrectly_implements_class_1_Did_you_mean_to_extend_1_and_inherit_its_members_as_a_subclass.code];
- var fixId = "fixClassIncorrectlyImplementsInterface"; // TODO: share a group with fixClassDoesntImplementInheritedAbstractMember?
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var program = context.program, sourceFile = context.sourceFile, span = context.span;
- var classDeclaration = getClass(sourceFile, span.start);
- var checker = program.getTypeChecker();
- return ts.mapDefined(ts.getClassImplementsHeritageClauseElements(classDeclaration), function (implementedTypeNode) {
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return addMissingDeclarations(checker, implementedTypeNode, sourceFile, classDeclaration, t); });
- if (changes.length === 0)
- return undefined;
- var description = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Implement_interface_0), [implementedTypeNode.getText()]);
- return { description: description, changes: changes, fixId: fixId };
- });
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) {
- var seenClassDeclarations = ts.createMap();
- return codefix.codeFixAll(context, errorCodes, function (changes, diag) {
- var classDeclaration = getClass(diag.file, diag.start);
- if (ts.addToSeen(seenClassDeclarations, ts.getNodeId(classDeclaration))) {
- for (var _i = 0, _a = ts.getClassImplementsHeritageClauseElements(classDeclaration); _i < _a.length; _i++) {
- var implementedTypeNode = _a[_i];
- addMissingDeclarations(context.program.getTypeChecker(), implementedTypeNode, diag.file, classDeclaration, changes);
- }
- }
- });
- },
- });
- function getClass(sourceFile, pos) {
- return ts.Debug.assertDefined(ts.getContainingClass(ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false)));
- }
- function addMissingDeclarations(checker, implementedTypeNode, sourceFile, classDeclaration, changeTracker) {
- // Note that this is ultimately derived from a map indexed by symbol names,
- // so duplicates cannot occur.
- var implementedType = checker.getTypeAtLocation(implementedTypeNode);
- var implementedTypeSymbols = checker.getPropertiesOfType(implementedType);
- var nonPrivateMembers = implementedTypeSymbols.filter(function (symbol) { return !(ts.getModifierFlags(symbol.valueDeclaration) & 8 /* Private */); });
- var classType = checker.getTypeAtLocation(classDeclaration);
- if (!checker.getIndexTypeOfType(classType, 1 /* Number */)) {
- createMissingIndexSignatureDeclaration(implementedType, 1 /* Number */);
- }
- if (!checker.getIndexTypeOfType(classType, 0 /* String */)) {
- createMissingIndexSignatureDeclaration(implementedType, 0 /* String */);
- }
- codefix.createMissingMemberNodes(classDeclaration, nonPrivateMembers, checker, function (member) { return changeTracker.insertNodeAtClassStart(sourceFile, classDeclaration, member); });
- function createMissingIndexSignatureDeclaration(type, kind) {
- var indexInfoOfKind = checker.getIndexInfoOfType(type, kind);
- if (indexInfoOfKind) {
- changeTracker.insertNodeAtClassStart(sourceFile, classDeclaration, checker.indexInfoToIndexSignatureDeclaration(indexInfoOfKind, kind, classDeclaration));
- }
- }
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var errorCodes = [
- ts.Diagnostics.Property_0_does_not_exist_on_type_1.code,
- ts.Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2.code,
- ];
- var fixId = "addMissingMember";
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var info = getInfo(context.sourceFile, context.span.start, context.program.getTypeChecker());
- if (!info)
- return undefined;
- var classDeclaration = info.classDeclaration, classDeclarationSourceFile = info.classDeclarationSourceFile, inJs = info.inJs, makeStatic = info.makeStatic, token = info.token, call = info.call;
- var methodCodeAction = call && getActionForMethodDeclaration(context, classDeclarationSourceFile, classDeclaration, token, call, makeStatic, inJs);
- var addMember = inJs ?
- ts.singleElementArray(getActionsForAddMissingMemberInJavaScriptFile(context, classDeclarationSourceFile, classDeclaration, token.text, makeStatic)) :
- getActionsForAddMissingMemberInTypeScriptFile(context, classDeclarationSourceFile, classDeclaration, token, makeStatic);
- return ts.concatenate(ts.singleElementArray(methodCodeAction), addMember);
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) {
- var seenNames = ts.createMap();
- return codefix.codeFixAll(context, errorCodes, function (changes, diag) {
- var program = context.program;
- var info = getInfo(diag.file, diag.start, program.getTypeChecker());
- if (!info)
- return;
- var classDeclaration = info.classDeclaration, classDeclarationSourceFile = info.classDeclarationSourceFile, inJs = info.inJs, makeStatic = info.makeStatic, token = info.token, call = info.call;
- if (!ts.addToSeen(seenNames, token.text)) {
- return;
- }
- // Always prefer to add a method declaration if possible.
- if (call) {
- addMethodDeclaration(changes, classDeclarationSourceFile, classDeclaration, token, call, makeStatic, inJs);
- }
- else {
- if (inJs) {
- addMissingMemberInJs(changes, classDeclarationSourceFile, classDeclaration, token.text, makeStatic);
- }
- else {
- var typeNode = getTypeNode(program.getTypeChecker(), classDeclaration, token);
- addPropertyDeclaration(changes, classDeclarationSourceFile, classDeclaration, token.text, typeNode, makeStatic);
- }
- }
- });
- },
- });
- function getInfo(tokenSourceFile, tokenPos, checker) {
- // The identifier of the missing property. eg:
- // this.missing = 1;
- // ^^^^^^^
- var token = ts.getTokenAtPosition(tokenSourceFile, tokenPos, /*includeJsDocComment*/ false);
- if (!ts.isIdentifier(token)) {
- return undefined;
- }
- var classAndMakeStatic = getClassAndMakeStatic(token, checker);
- if (!classAndMakeStatic) {
- return undefined;
- }
- var classDeclaration = classAndMakeStatic.classDeclaration, makeStatic = classAndMakeStatic.makeStatic;
- var classDeclarationSourceFile = classDeclaration.getSourceFile();
- var inJs = ts.isInJavaScriptFile(classDeclarationSourceFile);
- var call = ts.tryCast(token.parent.parent, ts.isCallExpression);
- return { token: token, classDeclaration: classDeclaration, makeStatic: makeStatic, classDeclarationSourceFile: classDeclarationSourceFile, inJs: inJs, call: call };
- }
- function getClassAndMakeStatic(token, checker) {
- var parent = token.parent;
- if (!ts.isPropertyAccessExpression(parent)) {
- return undefined;
- }
- if (parent.expression.kind === 99 /* ThisKeyword */) {
- var containingClassMemberDeclaration = ts.getThisContainer(token, /*includeArrowFunctions*/ false);
- if (!ts.isClassElement(containingClassMemberDeclaration)) {
- return undefined;
- }
- var classDeclaration = containingClassMemberDeclaration.parent;
- // Property accesses on `this` in a static method are accesses of a static member.
- return ts.isClassLike(classDeclaration) ? { classDeclaration: classDeclaration, makeStatic: ts.hasModifier(containingClassMemberDeclaration, 32 /* Static */) } : undefined;
- }
- else {
- var leftExpressionType = checker.getTypeAtLocation(parent.expression);
- var symbol = leftExpressionType.symbol;
- if (!(symbol && leftExpressionType.flags & 65536 /* Object */ && symbol.flags & 32 /* Class */)) {
- return undefined;
- }
- var classDeclaration = ts.cast(ts.first(symbol.declarations), ts.isClassLike);
- // The expression is a class symbol but the type is not the instance-side.
- return { classDeclaration: classDeclaration, makeStatic: leftExpressionType !== checker.getDeclaredTypeOfSymbol(symbol) };
- }
- }
- function getActionsForAddMissingMemberInJavaScriptFile(context, classDeclarationSourceFile, classDeclaration, tokenName, makeStatic) {
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return addMissingMemberInJs(t, classDeclarationSourceFile, classDeclaration, tokenName, makeStatic); });
- if (changes.length === 0)
- return undefined;
- var description = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(makeStatic ? ts.Diagnostics.Initialize_static_property_0 : ts.Diagnostics.Initialize_property_0_in_the_constructor), [tokenName]);
- return { description: description, changes: changes, fixId: fixId };
- }
- function addMissingMemberInJs(changeTracker, classDeclarationSourceFile, classDeclaration, tokenName, makeStatic) {
- if (makeStatic) {
- if (classDeclaration.kind === 203 /* ClassExpression */) {
- return;
- }
- var className = classDeclaration.name.getText();
- var staticInitialization = initializePropertyToUndefined(ts.createIdentifier(className), tokenName);
- changeTracker.insertNodeAfter(classDeclarationSourceFile, classDeclaration, staticInitialization);
- }
- else {
- var classConstructor = ts.getFirstConstructorWithBody(classDeclaration);
- if (!classConstructor) {
- return;
- }
- var propertyInitialization = initializePropertyToUndefined(ts.createThis(), tokenName);
- changeTracker.insertNodeAtConstructorEnd(classDeclarationSourceFile, classConstructor, propertyInitialization);
- }
- }
- function initializePropertyToUndefined(obj, propertyName) {
- return ts.createStatement(ts.createAssignment(ts.createPropertyAccess(obj, propertyName), ts.createIdentifier("undefined")));
- }
- function getActionsForAddMissingMemberInTypeScriptFile(context, classDeclarationSourceFile, classDeclaration, token, makeStatic) {
- var typeNode = getTypeNode(context.program.getTypeChecker(), classDeclaration, token);
- var addProp = createAddPropertyDeclarationAction(context, classDeclarationSourceFile, classDeclaration, makeStatic, token.text, typeNode);
- return makeStatic ? [addProp] : [addProp, createAddIndexSignatureAction(context, classDeclarationSourceFile, classDeclaration, token.text, typeNode)];
- }
- function getTypeNode(checker, classDeclaration, token) {
- var typeNode;
- if (token.parent.parent.kind === 198 /* BinaryExpression */) {
- var binaryExpression = token.parent.parent;
- var otherExpression = token.parent === binaryExpression.left ? binaryExpression.right : binaryExpression.left;
- var widenedType = checker.getWidenedType(checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(otherExpression)));
- typeNode = checker.typeToTypeNode(widenedType, classDeclaration);
- }
- return typeNode || ts.createKeywordTypeNode(119 /* AnyKeyword */);
- }
- function createAddPropertyDeclarationAction(context, classDeclarationSourceFile, classDeclaration, makeStatic, tokenName, typeNode) {
- var description = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(makeStatic ? ts.Diagnostics.Declare_static_property_0 : ts.Diagnostics.Declare_property_0), [tokenName]);
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return addPropertyDeclaration(t, classDeclarationSourceFile, classDeclaration, tokenName, typeNode, makeStatic); });
- return { description: description, changes: changes, fixId: fixId };
- }
- function addPropertyDeclaration(changeTracker, classDeclarationSourceFile, classDeclaration, tokenName, typeNode, makeStatic) {
- var property = ts.createProperty(
- /*decorators*/ undefined,
- /*modifiers*/ makeStatic ? [ts.createToken(115 /* StaticKeyword */)] : undefined, tokenName,
- /*questionToken*/ undefined, typeNode,
- /*initializer*/ undefined);
- changeTracker.insertNodeAtClassStart(classDeclarationSourceFile, classDeclaration, property);
- }
- function createAddIndexSignatureAction(context, classDeclarationSourceFile, classDeclaration, tokenName, typeNode) {
- // Index signatures cannot have the static modifier.
- var stringTypeNode = ts.createKeywordTypeNode(137 /* StringKeyword */);
- var indexingParameter = ts.createParameter(
- /*decorators*/ undefined,
- /*modifiers*/ undefined,
- /*dotDotDotToken*/ undefined, "x",
- /*questionToken*/ undefined, stringTypeNode,
- /*initializer*/ undefined);
- var indexSignature = ts.createIndexSignature(
- /*decorators*/ undefined,
- /*modifiers*/ undefined, [indexingParameter], typeNode);
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return t.insertNodeAtClassStart(classDeclarationSourceFile, classDeclaration, indexSignature); });
- // No fixId here because code-fix-all currently only works on adding individual named properties.
- return { description: ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Add_index_signature_for_property_0), [tokenName]), changes: changes, fixId: undefined };
- }
- function getActionForMethodDeclaration(context, classDeclarationSourceFile, classDeclaration, token, callExpression, makeStatic, inJs) {
- var description = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(makeStatic ? ts.Diagnostics.Declare_static_method_0 : ts.Diagnostics.Declare_method_0), [token.text]);
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return addMethodDeclaration(t, classDeclarationSourceFile, classDeclaration, token, callExpression, makeStatic, inJs); });
- return { description: description, changes: changes, fixId: fixId };
- }
- function addMethodDeclaration(changeTracker, classDeclarationSourceFile, classDeclaration, token, callExpression, makeStatic, inJs) {
- var methodDeclaration = codefix.createMethodFromCallExpression(callExpression, token.text, inJs, makeStatic);
- changeTracker.insertNodeAtClassStart(classDeclarationSourceFile, classDeclaration, methodDeclaration);
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "fixSpelling";
- var errorCodes = [
- ts.Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2.code,
- ts.Diagnostics.Cannot_find_name_0_Did_you_mean_1.code,
- ];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var sourceFile = context.sourceFile;
- var info = getInfo(sourceFile, context.span.start, context.program.getTypeChecker());
- if (!info)
- return undefined;
- var node = info.node, suggestion = info.suggestion;
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(t, sourceFile, node, suggestion); });
- var description = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Change_spelling_to_0), [suggestion]);
- return [{ description: description, changes: changes, fixId: fixId }];
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) {
- var info = getInfo(diag.file, diag.start, context.program.getTypeChecker());
- if (info)
- doChange(changes, context.sourceFile, info.node, info.suggestion);
- }); },
- });
- function getInfo(sourceFile, pos, checker) {
- // This is the identifier of the misspelled word. eg:
- // this.speling = 1;
- // ^^^^^^^
- var node = ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false); // TODO: GH#15852
- var suggestion;
- if (ts.isPropertyAccessExpression(node.parent) && node.parent.name === node) {
- ts.Debug.assert(node.kind === 71 /* Identifier */);
- var containingType = checker.getTypeAtLocation(node.parent.expression);
- suggestion = checker.getSuggestionForNonexistentProperty(node, containingType);
- }
- else {
- var meaning = ts.getMeaningFromLocation(node);
- var name = ts.getTextOfNode(node);
- ts.Debug.assert(name !== undefined, "name should be defined");
- suggestion = checker.getSuggestionForNonexistentSymbol(node, name, convertSemanticMeaningToSymbolFlags(meaning));
- }
- return suggestion === undefined ? undefined : { node: node, suggestion: suggestion };
- }
- function doChange(changes, sourceFile, node, suggestion) {
- changes.replaceNode(sourceFile, node, ts.createIdentifier(suggestion));
- }
- function convertSemanticMeaningToSymbolFlags(meaning) {
- var flags = 0;
- if (meaning & 4 /* Namespace */) {
- flags |= 1920 /* Namespace */;
- }
- if (meaning & 2 /* Type */) {
- flags |= 67901928 /* Type */;
- }
- if (meaning & 1 /* Value */) {
- flags |= 67216319 /* Value */;
- }
- return flags;
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "fixCannotFindModule";
- var errorCodes = [ts.Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type.code];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var codeAction = tryGetCodeActionForInstallPackageTypes(context.host, context.sourceFile.fileName, getModuleName(context.sourceFile, context.span.start));
- return codeAction && [__assign({ fixId: fixId }, codeAction)];
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (_, diag, commands) {
- var pkg = getTypesPackageNameToInstall(context.host, getModuleName(diag.file, diag.start));
- if (pkg) {
- commands.push(getCommand(diag.file.fileName, pkg));
- }
- }); },
- });
- function getModuleName(sourceFile, pos) {
- return ts.cast(ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false), ts.isStringLiteral).text;
- }
- function getCommand(fileName, packageName) {
- return { type: "install package", file: fileName, packageName: packageName };
- }
- function getTypesPackageNameToInstall(host, moduleName) {
- var packageName = ts.getPackageName(moduleName).packageName;
- // If !registry, registry not available yet, can't do anything.
- return host.isKnownTypesPackageName(packageName) ? ts.getTypesPackageName(packageName) : undefined;
- }
- function tryGetCodeActionForInstallPackageTypes(host, fileName, moduleName) {
- var packageName = getTypesPackageNameToInstall(host, moduleName);
- return packageName === undefined ? undefined : {
- description: ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Install_0), [packageName]),
- changes: [],
- commands: [getCommand(fileName, packageName)],
- };
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var errorCodes = [
- ts.Diagnostics.Non_abstract_class_0_does_not_implement_inherited_abstract_member_1_from_class_2.code,
- ts.Diagnostics.Non_abstract_class_expression_does_not_implement_inherited_abstract_member_0_from_class_1.code,
- ];
- var fixId = "fixClassDoesntImplementInheritedAbstractMember";
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var program = context.program, sourceFile = context.sourceFile, span = context.span;
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) {
- return addMissingMembers(getClass(sourceFile, span.start), sourceFile, program.getTypeChecker(), t);
- });
- return changes.length === 0 ? undefined : [{ description: ts.getLocaleSpecificMessage(ts.Diagnostics.Implement_inherited_abstract_class), changes: changes, fixId: fixId }];
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) {
- var seenClassDeclarations = ts.createMap();
- return codefix.codeFixAll(context, errorCodes, function (changes, diag) {
- var classDeclaration = getClass(diag.file, diag.start);
- if (ts.addToSeen(seenClassDeclarations, ts.getNodeId(classDeclaration))) {
- addMissingMembers(classDeclaration, context.sourceFile, context.program.getTypeChecker(), changes);
- }
- });
- },
- });
- function getClass(sourceFile, pos) {
- // Token is the identifier in the case of a class declaration
- // or the class keyword token in the case of a class expression.
- var token = ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false);
- return ts.cast(token.parent, ts.isClassLike);
- }
- function addMissingMembers(classDeclaration, sourceFile, checker, changeTracker) {
- var extendsNode = ts.getClassExtendsHeritageClauseElement(classDeclaration);
- var instantiatedExtendsType = checker.getTypeAtLocation(extendsNode);
- // Note that this is ultimately derived from a map indexed by symbol names,
- // so duplicates cannot occur.
- var abstractAndNonPrivateExtendsSymbols = checker.getPropertiesOfType(instantiatedExtendsType).filter(symbolPointsToNonPrivateAndAbstractMember);
- codefix.createMissingMemberNodes(classDeclaration, abstractAndNonPrivateExtendsSymbols, checker, function (member) { return changeTracker.insertNodeAtClassStart(sourceFile, classDeclaration, member); });
- }
- function symbolPointsToNonPrivateAndAbstractMember(symbol) {
- // See `codeFixClassExtendAbstractProtectedProperty.ts` in https://github.com/Microsoft/TypeScript/pull/11547/files
- // (now named `codeFixClassExtendAbstractPrivateProperty.ts`)
- var flags = ts.getModifierFlags(ts.first(symbol.getDeclarations()));
- return !(flags & 8 /* Private */) && !!(flags & 128 /* Abstract */);
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "classSuperMustPrecedeThisAccess";
- var errorCodes = [ts.Diagnostics.super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class.code];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var sourceFile = context.sourceFile, span = context.span;
- var nodes = getNodes(sourceFile, span.start);
- if (!nodes)
- return undefined;
- var constructor = nodes.constructor, superCall = nodes.superCall;
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(t, sourceFile, constructor, superCall); });
- return [{ description: ts.getLocaleSpecificMessage(ts.Diagnostics.Make_super_call_the_first_statement_in_the_constructor), changes: changes, fixId: fixId }];
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) {
- var sourceFile = context.sourceFile;
- var seenClasses = ts.createMap(); // Ensure we only do this once per class.
- return codefix.codeFixAll(context, errorCodes, function (changes, diag) {
- var nodes = getNodes(diag.file, diag.start);
- if (!nodes)
- return;
- var constructor = nodes.constructor, superCall = nodes.superCall;
- if (ts.addToSeen(seenClasses, ts.getNodeId(constructor.parent))) {
- doChange(changes, sourceFile, constructor, superCall);
- }
- });
- },
- });
- function doChange(changes, sourceFile, constructor, superCall) {
- changes.insertNodeAtConstructorStart(sourceFile, constructor, superCall);
- changes.deleteNode(sourceFile, superCall);
- }
- function getNodes(sourceFile, pos) {
- var token = ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false);
- if (token.kind !== 99 /* ThisKeyword */)
- return undefined;
- var constructor = ts.getContainingFunction(token);
- var superCall = findSuperCall(constructor.body);
- // figure out if the `this` access is actually inside the supercall
- // i.e. super(this.a), since in that case we won't suggest a fix
- return superCall && !superCall.expression.arguments.some(function (arg) { return ts.isPropertyAccessExpression(arg) && arg.expression === token; }) ? { constructor: constructor, superCall: superCall } : undefined;
- }
- function findSuperCall(n) {
- return ts.isExpressionStatement(n) && ts.isSuperCall(n.expression)
- ? n
- : ts.isFunctionLike(n)
- ? undefined
- : ts.forEachChild(n, findSuperCall);
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "constructorForDerivedNeedSuperCall";
- var errorCodes = [ts.Diagnostics.Constructors_for_derived_classes_must_contain_a_super_call.code];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var sourceFile = context.sourceFile, span = context.span;
- var ctr = getNode(sourceFile, span.start);
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(t, sourceFile, ctr); });
- return [{ description: ts.getLocaleSpecificMessage(ts.Diagnostics.Add_missing_super_call), changes: changes, fixId: fixId }];
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) {
- return doChange(changes, context.sourceFile, getNode(diag.file, diag.start));
- }); },
- });
- function getNode(sourceFile, pos) {
- var token = ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false);
- ts.Debug.assert(token.kind === 123 /* ConstructorKeyword */);
- return token.parent;
- }
- function doChange(changes, sourceFile, ctr) {
- var superCall = ts.createStatement(ts.createCall(ts.createSuper(), /*typeArguments*/ undefined, /*argumentsArray*/ ts.emptyArray));
- changes.insertNodeAtConstructorStart(sourceFile, ctr, superCall);
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "extendsInterfaceBecomesImplements";
- var errorCodes = [ts.Diagnostics.Cannot_extend_an_interface_0_Did_you_mean_implements.code];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var sourceFile = context.sourceFile;
- var nodes = getNodes(sourceFile, context.span.start);
- if (!nodes)
- return undefined;
- var extendsToken = nodes.extendsToken, heritageClauses = nodes.heritageClauses;
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return doChanges(t, sourceFile, extendsToken, heritageClauses); });
- return [{ description: ts.getLocaleSpecificMessage(ts.Diagnostics.Change_extends_to_implements), changes: changes, fixId: fixId }];
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) {
- var nodes = getNodes(diag.file, diag.start);
- if (nodes)
- doChanges(changes, diag.file, nodes.extendsToken, nodes.heritageClauses);
- }); },
- });
- function getNodes(sourceFile, pos) {
- var token = ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false);
- var heritageClauses = ts.getContainingClass(token).heritageClauses;
- var extendsToken = heritageClauses[0].getFirstToken();
- return extendsToken.kind === 85 /* ExtendsKeyword */ ? { extendsToken: extendsToken, heritageClauses: heritageClauses } : undefined;
- }
- function doChanges(changes, sourceFile, extendsToken, heritageClauses) {
- changes.replaceNode(sourceFile, extendsToken, ts.createToken(108 /* ImplementsKeyword */), ts.textChanges.useNonAdjustedPositions);
- // If there is already an implements clause, replace the implements keyword with a comma.
- if (heritageClauses.length === 2 &&
- heritageClauses[0].token === 85 /* ExtendsKeyword */ &&
- heritageClauses[1].token === 108 /* ImplementsKeyword */) {
- var implementsToken = heritageClauses[1].getFirstToken();
- var implementsFullStart = implementsToken.getFullStart();
- changes.replaceRange(sourceFile, { pos: implementsFullStart, end: implementsFullStart }, ts.createToken(26 /* CommaToken */));
- // Rough heuristic: delete trailing whitespace after keyword so that it's not excessive.
- // (Trailing because leading might be indentation, which is more sensitive.)
- var text = sourceFile.text;
- var end = implementsToken.end;
- while (end < text.length && ts.isWhiteSpaceSingleLine(text.charCodeAt(end))) {
- end++;
- }
- changes.deleteRange(sourceFile, { pos: implementsToken.getStart(), end: end });
- }
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "forgottenThisPropertyAccess";
- var errorCodes = [ts.Diagnostics.Cannot_find_name_0_Did_you_mean_the_instance_member_this_0.code];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var sourceFile = context.sourceFile;
- var token = getNode(sourceFile, context.span.start);
- if (!token) {
- return undefined;
- }
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(t, sourceFile, token); });
- return [{ description: ts.getLocaleSpecificMessage(ts.Diagnostics.Add_this_to_unresolved_variable), changes: changes, fixId: fixId }];
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) {
- doChange(changes, context.sourceFile, getNode(diag.file, diag.start));
- }); },
- });
- function getNode(sourceFile, pos) {
- var node = ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false);
- return ts.isIdentifier(node) ? node : undefined;
- }
- function doChange(changes, sourceFile, token) {
- if (!token) {
- return;
- }
- // TODO (https://github.com/Microsoft/TypeScript/issues/21246): use shared helper
- ts.suppressLeadingAndTrailingTrivia(token);
- changes.replaceNode(sourceFile, token, ts.createPropertyAccess(ts.createThis(), token), ts.textChanges.useNonAdjustedPositions);
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixIdPrefix = "unusedIdentifier_prefix";
- var fixIdDelete = "unusedIdentifier_delete";
- var errorCodes = [
- ts.Diagnostics._0_is_declared_but_its_value_is_never_read.code,
- ts.Diagnostics.Property_0_is_declared_but_its_value_is_never_read.code,
- ts.Diagnostics.All_imports_in_import_declaration_are_unused.code,
- ];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var errorCode = context.errorCode, sourceFile = context.sourceFile;
- var importDecl = tryGetFullImport(sourceFile, context.span.start);
- if (importDecl) {
- var description = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Remove_import_from_0), [ts.showModuleSpecifier(importDecl)]);
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return t.deleteNode(sourceFile, importDecl); });
- return [{ description: description, changes: changes, fixId: fixIdDelete }];
- }
- var token = getToken(sourceFile, ts.textSpanEnd(context.span));
- var result = [];
- var deletion = ts.textChanges.ChangeTracker.with(context, function (t) { return tryDeleteDeclaration(t, sourceFile, token); });
- if (deletion.length) {
- var description = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Remove_declaration_for_Colon_0), [token.getText()]);
- result.push({ description: description, changes: deletion, fixId: fixIdDelete });
- }
- var prefix = ts.textChanges.ChangeTracker.with(context, function (t) { return tryPrefixDeclaration(t, errorCode, sourceFile, token); });
- if (prefix.length) {
- var description = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Prefix_0_with_an_underscore), [token.getText()]);
- result.push({ description: description, changes: prefix, fixId: fixIdPrefix });
- }
- return result;
- },
- fixIds: [fixIdPrefix, fixIdDelete],
- getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) {
- var sourceFile = context.sourceFile;
- var token = ts.findPrecedingToken(ts.textSpanEnd(diag), diag.file);
- switch (context.fixId) {
- case fixIdPrefix:
- if (ts.isIdentifier(token) && canPrefix(token)) {
- tryPrefixDeclaration(changes, diag.code, sourceFile, token);
- }
- break;
- case fixIdDelete:
- var importDecl = tryGetFullImport(diag.file, diag.start);
- if (importDecl) {
- changes.deleteNode(sourceFile, importDecl);
- }
- else {
- tryDeleteDeclaration(changes, sourceFile, token);
- }
- break;
- default:
- ts.Debug.fail(JSON.stringify(context.fixId));
- }
- }); },
- });
- // Sometimes the diagnostic span is an entire ImportDeclaration, so we should remove the whole thing.
- function tryGetFullImport(sourceFile, pos) {
- var startToken = ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false);
- return startToken.kind === 91 /* ImportKeyword */ ? ts.tryCast(startToken.parent, ts.isImportDeclaration) : undefined;
- }
- function getToken(sourceFile, pos) {
- var token = ts.findPrecedingToken(pos, sourceFile);
- // this handles var ["computed"] = 12;
- return token.kind === 22 /* CloseBracketToken */ ? ts.findPrecedingToken(pos - 1, sourceFile) : token;
- }
- function tryPrefixDeclaration(changes, errorCode, sourceFile, token) {
- // Don't offer to prefix a property.
- if (errorCode !== ts.Diagnostics.Property_0_is_declared_but_its_value_is_never_read.code && ts.isIdentifier(token) && canPrefix(token)) {
- changes.replaceNode(sourceFile, token, ts.createIdentifier("_" + token.text));
- }
- }
- function canPrefix(token) {
- switch (token.parent.kind) {
- case 148 /* Parameter */:
- return true;
- case 230 /* VariableDeclaration */: {
- var varDecl = token.parent;
- switch (varDecl.parent.parent.kind) {
- case 220 /* ForOfStatement */:
- case 219 /* ForInStatement */:
- return true;
- }
- }
- }
- return false;
- }
- function tryDeleteDeclaration(changes, sourceFile, token) {
- switch (token.kind) {
- case 71 /* Identifier */:
- tryDeleteIdentifier(changes, sourceFile, token);
- break;
- case 151 /* PropertyDeclaration */:
- case 244 /* NamespaceImport */:
- changes.deleteNode(sourceFile, token.parent);
- break;
- default:
- tryDeleteDefault(changes, sourceFile, token);
- }
- }
- function tryDeleteDefault(changes, sourceFile, token) {
- if (ts.isDeclarationName(token)) {
- changes.deleteNode(sourceFile, token.parent);
- }
- else if (ts.isLiteralComputedPropertyDeclarationName(token)) {
- changes.deleteNode(sourceFile, token.parent.parent);
- }
- }
- function tryDeleteIdentifier(changes, sourceFile, identifier) {
- var parent = identifier.parent;
- switch (parent.kind) {
- case 230 /* VariableDeclaration */:
- tryDeleteVariableDeclaration(changes, sourceFile, parent);
- break;
- case 147 /* TypeParameter */:
- var typeParameters = parent.parent.typeParameters;
- if (typeParameters.length === 1) {
- var previousToken = ts.getTokenAtPosition(sourceFile, typeParameters.pos - 1, /*includeJsDocComment*/ false);
- var nextToken = ts.getTokenAtPosition(sourceFile, typeParameters.end, /*includeJsDocComment*/ false);
- ts.Debug.assert(previousToken.kind === 27 /* LessThanToken */);
- ts.Debug.assert(nextToken.kind === 29 /* GreaterThanToken */);
- changes.deleteNodeRange(sourceFile, previousToken, nextToken);
- }
- else {
- changes.deleteNodeInList(sourceFile, parent);
- }
- break;
- case 148 /* Parameter */:
- var oldFunction = parent.parent;
- if (ts.isArrowFunction(oldFunction) && oldFunction.parameters.length === 1) {
- // Lambdas with exactly one parameter are special because, after removal, there
- // must be an empty parameter list (i.e. `()`) and this won't necessarily be the
- // case if the parameter is simply removed (e.g. in `x => 1`).
- var newFunction = ts.updateArrowFunction(oldFunction, oldFunction.modifiers, oldFunction.typeParameters,
- /*parameters*/ undefined, oldFunction.type, oldFunction.equalsGreaterThanToken, oldFunction.body);
- // Drop leading and trailing trivia of the new function because we're only going
- // to replace the span (vs the full span) of the old function - the old leading
- // and trailing trivia will remain.
- ts.suppressLeadingAndTrailingTrivia(newFunction);
- changes.replaceNode(sourceFile, oldFunction, newFunction, ts.textChanges.useNonAdjustedPositions);
- }
- else {
- changes.deleteNodeInList(sourceFile, parent);
- }
- break;
- // handle case where 'import a = A;'
- case 241 /* ImportEqualsDeclaration */:
- var importEquals = ts.getAncestor(identifier, 241 /* ImportEqualsDeclaration */);
- changes.deleteNode(sourceFile, importEquals);
- break;
- case 246 /* ImportSpecifier */:
- var namedImports = parent.parent;
- if (namedImports.elements.length === 1) {
- tryDeleteNamedImportBinding(changes, sourceFile, namedImports);
- }
- else {
- // delete import specifier
- changes.deleteNodeInList(sourceFile, parent);
- }
- break;
- case 243 /* ImportClause */: // this covers both 'import |d|' and 'import |d,| *'
- var importClause = parent;
- if (!importClause.namedBindings) { // |import d from './file'|
- changes.deleteNode(sourceFile, ts.getAncestor(importClause, 242 /* ImportDeclaration */));
- }
- else {
- // import |d,| * as ns from './file'
- var start = importClause.name.getStart(sourceFile);
- var nextToken = ts.getTokenAtPosition(sourceFile, importClause.name.end, /*includeJsDocComment*/ false);
- if (nextToken && nextToken.kind === 26 /* CommaToken */) {
- // shift first non-whitespace position after comma to the start position of the node
- var end = ts.skipTrivia(sourceFile.text, nextToken.end, /*stopAfterLineBreaks*/ false, /*stopAtComments*/ true);
- changes.deleteRange(sourceFile, { pos: start, end: end });
- }
- else {
- changes.deleteNode(sourceFile, importClause.name);
- }
- }
- break;
- case 244 /* NamespaceImport */:
- tryDeleteNamedImportBinding(changes, sourceFile, parent);
- break;
- default:
- tryDeleteDefault(changes, sourceFile, identifier);
- break;
- }
- }
- function tryDeleteNamedImportBinding(changes, sourceFile, namedBindings) {
- if (namedBindings.parent.name) {
- // Delete named imports while preserving the default import
- // import d|, * as ns| from './file'
- // import d|, { a }| from './file'
- var previousToken = ts.getTokenAtPosition(sourceFile, namedBindings.pos - 1, /*includeJsDocComment*/ false);
- if (previousToken && previousToken.kind === 26 /* CommaToken */) {
- changes.deleteRange(sourceFile, { pos: previousToken.getStart(), end: namedBindings.end });
- }
- }
- else {
- // Delete the entire import declaration
- // |import * as ns from './file'|
- // |import { a } from './file'|
- var importDecl = ts.getAncestor(namedBindings, 242 /* ImportDeclaration */);
- changes.deleteNode(sourceFile, importDecl);
- }
- }
- // token.parent is a variableDeclaration
- function tryDeleteVariableDeclaration(changes, sourceFile, varDecl) {
- switch (varDecl.parent.parent.kind) {
- case 218 /* ForStatement */: {
- var forStatement = varDecl.parent.parent;
- var forInitializer = forStatement.initializer;
- if (forInitializer.declarations.length === 1) {
- changes.deleteNode(sourceFile, forInitializer);
- }
- else {
- changes.deleteNodeInList(sourceFile, varDecl);
- }
- break;
- }
- case 220 /* ForOfStatement */:
- var forOfStatement = varDecl.parent.parent;
- ts.Debug.assert(forOfStatement.initializer.kind === 231 /* VariableDeclarationList */);
- var forOfInitializer = forOfStatement.initializer;
- changes.replaceNode(sourceFile, forOfInitializer.declarations[0], ts.createObjectLiteral());
- break;
- case 219 /* ForInStatement */:
- case 228 /* TryStatement */:
- break;
- default:
- var variableStatement = varDecl.parent.parent;
- if (variableStatement.declarationList.declarations.length === 1) {
- changes.deleteNode(sourceFile, variableStatement);
- }
- else {
- changes.deleteNodeInList(sourceFile, varDecl);
- }
- }
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixIdPlain = "fixJSDocTypes_plain";
- var fixIdNullable = "fixJSDocTypes_nullable";
- var errorCodes = [ts.Diagnostics.JSDoc_types_can_only_be_used_inside_documentation_comments.code];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var sourceFile = context.sourceFile;
- var checker = context.program.getTypeChecker();
- var info = getInfo(sourceFile, context.span.start, checker);
- if (!info)
- return undefined;
- var typeNode = info.typeNode, type = info.type;
- var original = typeNode.getText(sourceFile);
- var actions = [fix(type, fixIdPlain)];
- if (typeNode.kind === 277 /* JSDocNullableType */) {
- // for nullable types, suggest the flow-compatible `T | null | undefined`
- // in addition to the jsdoc/closure-compatible `T | null`
- actions.push(fix(checker.getNullableType(type, 4096 /* Undefined */), fixIdNullable));
- }
- return actions;
- function fix(type, fixId) {
- var newText = checker.typeToString(type);
- var description = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Change_0_to_1), [original, newText]);
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(t, sourceFile, typeNode, type, checker); });
- return { description: description, changes: changes, fixId: fixId };
- }
- },
- fixIds: [fixIdPlain, fixIdNullable],
- getAllCodeActions: function (context) {
- var fixId = context.fixId, program = context.program, sourceFile = context.sourceFile;
- var checker = program.getTypeChecker();
- return codefix.codeFixAll(context, errorCodes, function (changes, err) {
- var info = getInfo(err.file, err.start, checker);
- if (!info)
- return;
- var typeNode = info.typeNode, type = info.type;
- var fixedType = typeNode.kind === 277 /* JSDocNullableType */ && fixId === fixIdNullable ? checker.getNullableType(type, 4096 /* Undefined */) : type;
- doChange(changes, sourceFile, typeNode, fixedType, checker);
- });
- }
- });
- function doChange(changes, sourceFile, oldTypeNode, newType, checker) {
- changes.replaceNode(sourceFile, oldTypeNode, checker.typeToTypeNode(newType, /*enclosingDeclaration*/ oldTypeNode));
- }
- function getInfo(sourceFile, pos, checker) {
- var decl = ts.findAncestor(ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false), isTypeContainer);
- var typeNode = decl && decl.type;
- return typeNode && { typeNode: typeNode, type: checker.getTypeFromTypeNode(typeNode) };
- }
- function isTypeContainer(node) {
- // NOTE: Some locations are not handled yet:
- // MappedTypeNode.typeParameters and SignatureDeclaration.typeParameters, as well as CallExpression.typeArguments
- switch (node.kind) {
- case 206 /* AsExpression */:
- case 157 /* CallSignature */:
- case 158 /* ConstructSignature */:
- case 232 /* FunctionDeclaration */:
- case 155 /* GetAccessor */:
- case 159 /* IndexSignature */:
- case 176 /* MappedType */:
- case 153 /* MethodDeclaration */:
- case 152 /* MethodSignature */:
- case 148 /* Parameter */:
- case 151 /* PropertyDeclaration */:
- case 150 /* PropertySignature */:
- case 156 /* SetAccessor */:
- case 235 /* TypeAliasDeclaration */:
- case 188 /* TypeAssertionExpression */:
- case 230 /* VariableDeclaration */:
- return true;
- default:
- return false;
- }
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "fixAwaitInSyncFunction";
- var errorCodes = [
- ts.Diagnostics.await_expression_is_only_allowed_within_an_async_function.code,
- ts.Diagnostics.A_for_await_of_statement_is_only_allowed_within_an_async_function_or_async_generator.code,
- ];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var sourceFile = context.sourceFile, span = context.span;
- var nodes = getNodes(sourceFile, span.start);
- if (!nodes)
- return undefined;
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(t, sourceFile, nodes); });
- return [{ description: ts.getLocaleSpecificMessage(ts.Diagnostics.Add_async_modifier_to_containing_function), changes: changes, fixId: fixId }];
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) {
- var nodes = getNodes(diag.file, diag.start);
- if (!nodes)
- return;
- doChange(changes, context.sourceFile, nodes);
- }); },
- });
- function getReturnType(expr) {
- if (expr.type) {
- return expr.type;
- }
- if (ts.isVariableDeclaration(expr.parent) &&
- expr.parent.type &&
- ts.isFunctionTypeNode(expr.parent.type)) {
- return expr.parent.type.type;
- }
- }
- function getNodes(sourceFile, start) {
- var token = ts.getTokenAtPosition(sourceFile, start, /*includeJsDocComment*/ false);
- var containingFunction = ts.getContainingFunction(token);
- if (!containingFunction) {
- return;
- }
- var insertBefore;
- switch (containingFunction.kind) {
- case 153 /* MethodDeclaration */:
- insertBefore = containingFunction.name;
- break;
- case 232 /* FunctionDeclaration */:
- case 190 /* FunctionExpression */:
- insertBefore = ts.findChildOfKind(containingFunction, 89 /* FunctionKeyword */, sourceFile);
- break;
- case 191 /* ArrowFunction */:
- insertBefore = ts.findChildOfKind(containingFunction, 19 /* OpenParenToken */, sourceFile) || ts.first(containingFunction.parameters);
- break;
- default:
- return;
- }
- return {
- insertBefore: insertBefore,
- returnType: getReturnType(containingFunction)
- };
- }
- function doChange(changes, sourceFile, _a) {
- var insertBefore = _a.insertBefore, returnType = _a.returnType;
- if (returnType) {
- var entityName = ts.getEntityNameFromTypeNode(returnType);
- if (!entityName || entityName.kind !== 71 /* Identifier */ || entityName.text !== "Promise") {
- changes.replaceNode(sourceFile, returnType, ts.createTypeReferenceNode("Promise", ts.createNodeArray([returnType])));
- }
- }
- changes.insertModifierBefore(sourceFile, 120 /* AsyncKeyword */, insertBefore);
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var ChangeTracker = ts.textChanges.ChangeTracker;
- codefix.registerCodeFix({
- errorCodes: [
- ts.Diagnostics.Cannot_find_name_0.code,
- ts.Diagnostics.Cannot_find_name_0_Did_you_mean_1.code,
- ts.Diagnostics.Cannot_find_namespace_0.code,
- ts.Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead.code
- ],
- getCodeActions: getImportCodeActions,
- // TODO: GH#20315
- fixIds: [],
- getAllCodeActions: ts.notImplemented,
- });
- function createCodeAction(descriptionDiagnostic, diagnosticArgs, changes) {
- var description = ts.formatMessage.apply(undefined, [undefined, descriptionDiagnostic].concat(diagnosticArgs));
- // TODO: GH#20315
- return { description: description, changes: changes, fixId: undefined };
- }
- function convertToImportCodeFixContext(context, symbolToken, symbolName) {
- var useCaseSensitiveFileNames = context.host.useCaseSensitiveFileNames ? context.host.useCaseSensitiveFileNames() : false;
- var program = context.program;
- var checker = program.getTypeChecker();
- return {
- host: context.host,
- formatContext: context.formatContext,
- sourceFile: context.sourceFile,
- program: program,
- checker: checker,
- compilerOptions: program.getCompilerOptions(),
- cachedImportDeclarations: [],
- getCanonicalFileName: ts.createGetCanonicalFileName(useCaseSensitiveFileNames),
- symbolName: symbolName,
- symbolToken: symbolToken
- };
- }
- var ImportKind;
- (function (ImportKind) {
- ImportKind[ImportKind["Named"] = 0] = "Named";
- ImportKind[ImportKind["Default"] = 1] = "Default";
- ImportKind[ImportKind["Namespace"] = 2] = "Namespace";
- ImportKind[ImportKind["Equals"] = 3] = "Equals";
- })(ImportKind || (ImportKind = {}));
- function getImportCompletionAction(exportedSymbol, moduleSymbol, sourceFile, symbolName, host, program, checker, compilerOptions, allSourceFiles, formatContext, getCanonicalFileName, symbolToken) {
- var exportInfos = getAllReExportingModules(exportedSymbol, checker, allSourceFiles);
- ts.Debug.assert(exportInfos.some(function (info) { return info.moduleSymbol === moduleSymbol; }));
- // We sort the best codefixes first, so taking `first` is best for completions.
- var moduleSpecifier = ts.first(getNewImportInfos(program, sourceFile, exportInfos, compilerOptions, getCanonicalFileName, host)).moduleSpecifier;
- var ctx = { host: host, program: program, checker: checker, compilerOptions: compilerOptions, sourceFile: sourceFile, formatContext: formatContext, symbolName: symbolName, getCanonicalFileName: getCanonicalFileName, symbolToken: symbolToken };
- return { moduleSpecifier: moduleSpecifier, codeAction: ts.first(getCodeActionsForImport(exportInfos, ctx)) };
- }
- codefix.getImportCompletionAction = getImportCompletionAction;
- function getAllReExportingModules(exportedSymbol, checker, allSourceFiles) {
- var result = [];
- forEachExternalModule(checker, allSourceFiles, function (moduleSymbol) {
- for (var _i = 0, _a = checker.getExportsOfModule(moduleSymbol); _i < _a.length; _i++) {
- var exported = _a[_i];
- if (ts.skipAlias(exported, checker) === exportedSymbol) {
- var isDefaultExport = checker.tryGetMemberInModuleExports("default" /* Default */, moduleSymbol) === exported;
- result.push({ moduleSymbol: moduleSymbol, importKind: isDefaultExport ? 1 /* Default */ : 0 /* Named */ });
- }
- }
- });
- return result;
- }
- function getCodeActionsForImport(exportInfos, context) {
- var existingImports = ts.flatMap(exportInfos, function (info) {
- return getImportDeclarations(info, context.checker, context.sourceFile, context.cachedImportDeclarations);
- });
- // It is possible that multiple import statements with the same specifier exist in the file.
- // e.g.
- //
- // import * as ns from "foo";
- // import { member1, member2 } from "foo";
- //
- // member3/**/ <-- cusor here
- //
- // in this case we should provie 2 actions:
- // 1. change "member3" to "ns.member3"
- // 2. add "member3" to the second import statement's import list
- // and it is up to the user to decide which one fits best.
- var useExistingImportActions = !context.symbolToken || !ts.isIdentifier(context.symbolToken) ? ts.emptyArray : ts.mapDefined(existingImports, function (_a) {
- var declaration = _a.declaration;
- var namespace = getNamespaceImportName(declaration);
- if (namespace) {
- var moduleSymbol = context.checker.getAliasedSymbol(context.checker.getSymbolAtLocation(namespace));
- if (moduleSymbol && moduleSymbol.exports.has(ts.escapeLeadingUnderscores(context.symbolName))) {
- return getCodeActionForUseExistingNamespaceImport(namespace.text, context, context.symbolToken);
- }
- }
- });
- return useExistingImportActions.concat(getCodeActionsForAddImport(exportInfos, context, existingImports));
- }
- function getNamespaceImportName(declaration) {
- if (declaration.kind === 242 /* ImportDeclaration */) {
- var namedBindings = declaration.importClause && ts.isImportClause(declaration.importClause) && declaration.importClause.namedBindings;
- return namedBindings && namedBindings.kind === 244 /* NamespaceImport */ ? namedBindings.name : undefined;
- }
- else {
- return declaration.name;
- }
- }
- // TODO(anhans): This doesn't seem important to cache... just use an iterator instead of creating a new array?
- function getImportDeclarations(_a, checker, _b, cachedImportDeclarations) {
- var moduleSymbol = _a.moduleSymbol, importKind = _a.importKind;
- var imports = _b.imports;
- if (cachedImportDeclarations === void 0) { cachedImportDeclarations = []; }
- var moduleSymbolId = ts.getUniqueSymbolId(moduleSymbol, checker);
- var cached = cachedImportDeclarations[moduleSymbolId];
- if (!cached) {
- cached = cachedImportDeclarations[moduleSymbolId] = ts.mapDefined(imports, function (importModuleSpecifier) {
- var declaration = checker.getSymbolAtLocation(importModuleSpecifier) === moduleSymbol ? getImportDeclaration(importModuleSpecifier) : undefined;
- return declaration && { declaration: declaration, importKind: importKind };
- });
- }
- return cached;
- }
- function getImportDeclaration(_a) {
- var parent = _a.parent;
- switch (parent.kind) {
- case 242 /* ImportDeclaration */:
- return parent;
- case 252 /* ExternalModuleReference */:
- return parent.parent;
- case 248 /* ExportDeclaration */:
- case 185 /* CallExpression */: // For "require()" calls
- // Ignore these, can't add imports to them.
- return undefined;
- default:
- ts.Debug.fail();
- }
- }
- function getCodeActionForNewImport(context, _a) {
- var moduleSpecifier = _a.moduleSpecifier, importKind = _a.importKind;
- var sourceFile = context.sourceFile, symbolName = context.symbolName;
- var lastImportDeclaration = ts.findLast(sourceFile.statements, ts.isAnyImportSyntax);
- var moduleSpecifierWithoutQuotes = ts.stripQuotes(moduleSpecifier);
- var quotedModuleSpecifier = createStringLiteralWithQuoteStyle(sourceFile, moduleSpecifierWithoutQuotes);
- var importDecl = importKind !== 3 /* Equals */
- ? ts.createImportDeclaration(
- /*decorators*/ undefined,
- /*modifiers*/ undefined, createImportClauseOfKind(importKind, symbolName), quotedModuleSpecifier)
- : ts.createImportEqualsDeclaration(
- /*decorators*/ undefined,
- /*modifiers*/ undefined, ts.createIdentifier(symbolName), ts.createExternalModuleReference(quotedModuleSpecifier));
- var changes = ChangeTracker.with(context, function (changeTracker) {
- if (lastImportDeclaration) {
- changeTracker.insertNodeAfter(sourceFile, lastImportDeclaration, importDecl);
- }
- else {
- changeTracker.insertNodeAtTopOfFile(sourceFile, importDecl, /*blankLineBetween*/ true);
- }
- });
- // if this file doesn't have any import statements, insert an import statement and then insert a new line
- // between the only import statement and user code. Otherwise just insert the statement because chances
- // are there are already a new line seperating code and import statements.
- return createCodeAction(ts.Diagnostics.Import_0_from_module_1, [symbolName, moduleSpecifierWithoutQuotes], changes);
- }
- function createStringLiteralWithQuoteStyle(sourceFile, text) {
- var literal = ts.createLiteral(text);
- var firstModuleSpecifier = ts.firstOrUndefined(sourceFile.imports);
- literal.singleQuote = !!firstModuleSpecifier && !ts.isStringDoubleQuoted(firstModuleSpecifier, sourceFile);
- return literal;
- }
- function usesJsExtensionOnImports(sourceFile) {
- return ts.firstDefined(sourceFile.imports, function (_a) {
- var text = _a.text;
- return ts.pathIsRelative(text) ? ts.fileExtensionIs(text, ".js" /* Js */) : undefined;
- }) || false;
- }
- function createImportClauseOfKind(kind, symbolName) {
- var id = ts.createIdentifier(symbolName);
- switch (kind) {
- case 1 /* Default */:
- return ts.createImportClause(id, /*namedBindings*/ undefined);
- case 2 /* Namespace */:
- return ts.createImportClause(/*name*/ undefined, ts.createNamespaceImport(id));
- case 0 /* Named */:
- return ts.createImportClause(/*name*/ undefined, ts.createNamedImports([ts.createImportSpecifier(/*propertyName*/ undefined, id)]));
- default:
- ts.Debug.assertNever(kind);
- }
- }
- function getNewImportInfos(program, sourceFile, moduleSymbols, options, getCanonicalFileName, host) {
- var baseUrl = options.baseUrl, paths = options.paths, rootDirs = options.rootDirs;
- var addJsExtension = usesJsExtensionOnImports(sourceFile);
- var choicesForEachExportingModule = ts.flatMap(moduleSymbols, function (_a) {
- var moduleSymbol = _a.moduleSymbol, importKind = _a.importKind;
- var modulePathsGroups = getAllModulePaths(program, moduleSymbol.valueDeclaration.getSourceFile()).map(function (moduleFileName) {
- var sourceDirectory = ts.getDirectoryPath(sourceFile.fileName);
- var global = tryGetModuleNameFromAmbientModule(moduleSymbol)
- || tryGetModuleNameFromTypeRoots(options, host, getCanonicalFileName, moduleFileName, addJsExtension)
- || tryGetModuleNameAsNodeModule(options, moduleFileName, host, getCanonicalFileName, sourceDirectory)
- || rootDirs && tryGetModuleNameFromRootDirs(rootDirs, moduleFileName, sourceDirectory, getCanonicalFileName);
- if (global) {
- return [global];
- }
- var relativePath = removeExtensionAndIndexPostFix(getRelativePath(moduleFileName, sourceDirectory, getCanonicalFileName), options, addJsExtension);
- if (!baseUrl) {
- return [relativePath];
- }
- var relativeToBaseUrl = getRelativePathIfInDirectory(moduleFileName, baseUrl, getCanonicalFileName);
- if (!relativeToBaseUrl) {
- return [relativePath];
- }
- var importRelativeToBaseUrl = removeExtensionAndIndexPostFix(relativeToBaseUrl, options, addJsExtension);
- if (paths) {
- var fromPaths = tryGetModuleNameFromPaths(ts.removeFileExtension(relativeToBaseUrl), importRelativeToBaseUrl, paths);
- if (fromPaths) {
- return [fromPaths];
- }
- }
- if (isPathRelativeToParent(relativeToBaseUrl)) {
- return [relativePath];
- }
- /*
- Prefer a relative import over a baseUrl import if it doesn't traverse up to baseUrl.
-
- Suppose we have:
- baseUrl = /base
- sourceDirectory = /base/a/b
- moduleFileName = /base/foo/bar
- Then:
- relativePath = ../../foo/bar
- getRelativePathNParents(relativePath) = 2
- pathFromSourceToBaseUrl = ../../
- getRelativePathNParents(pathFromSourceToBaseUrl) = 2
- 2 < 2 = false
- In this case we should prefer using the baseUrl path "/a/b" instead of the relative path "../../foo/bar".
-
- Suppose we have:
- baseUrl = /base
- sourceDirectory = /base/foo/a
- moduleFileName = /base/foo/bar
- Then:
- relativePath = ../a
- getRelativePathNParents(relativePath) = 1
- pathFromSourceToBaseUrl = ../../
- getRelativePathNParents(pathFromSourceToBaseUrl) = 2
- 1 < 2 = true
- In this case we should prefer using the relative path "../a" instead of the baseUrl path "foo/a".
- */
- var pathFromSourceToBaseUrl = getRelativePath(baseUrl, sourceDirectory, getCanonicalFileName);
- var relativeFirst = getRelativePathNParents(relativePath) < getRelativePathNParents(pathFromSourceToBaseUrl);
- return relativeFirst ? [relativePath, importRelativeToBaseUrl] : [importRelativeToBaseUrl, relativePath];
- });
- return modulePathsGroups.map(function (group) { return group.map(function (moduleSpecifier) { return ({ moduleSpecifier: moduleSpecifier, importKind: importKind }); }); });
- });
- // Sort to keep the shortest paths first, but keep [relativePath, importRelativeToBaseUrl] groups together
- return ts.flatten(choicesForEachExportingModule.sort(function (a, b) { return ts.first(a).moduleSpecifier.length - ts.first(b).moduleSpecifier.length; }));
- }
- /**
- * Looks for a existing imports that use symlinks to this module.
- * Only if no symlink is available, the real path will be used.
- */
- function getAllModulePaths(program, _a) {
- var fileName = _a.fileName;
- var symlinks = ts.mapDefined(program.getSourceFiles(), function (sf) {
- return sf.resolvedModules && ts.firstDefinedIterator(sf.resolvedModules.values(), function (res) {
- return res && res.resolvedFileName === fileName ? res.originalPath : undefined;
- });
- });
- return symlinks.length === 0 ? [fileName] : symlinks;
- }
- function getRelativePathNParents(relativePath) {
- var count = 0;
- for (var i = 0; i + 3 <= relativePath.length && relativePath.slice(i, i + 3) === "../"; i += 3) {
- count++;
- }
- return count;
- }
- function tryGetModuleNameFromAmbientModule(moduleSymbol) {
- var decl = moduleSymbol.valueDeclaration;
- if (ts.isModuleDeclaration(decl) && ts.isStringLiteral(decl.name)) {
- return decl.name.text;
- }
- }
- function tryGetModuleNameFromPaths(relativeToBaseUrlWithIndex, relativeToBaseUrl, paths) {
- for (var key in paths) {
- for (var _i = 0, _a = paths[key]; _i < _a.length; _i++) {
- var patternText_1 = _a[_i];
- var pattern = ts.removeFileExtension(ts.normalizePath(patternText_1));
- var indexOfStar = pattern.indexOf("*");
- if (indexOfStar === 0 && pattern.length === 1) {
- continue;
- }
- else if (indexOfStar !== -1) {
- var prefix = pattern.substr(0, indexOfStar);
- var suffix = pattern.substr(indexOfStar + 1);
- if (relativeToBaseUrl.length >= prefix.length + suffix.length &&
- ts.startsWith(relativeToBaseUrl, prefix) &&
- ts.endsWith(relativeToBaseUrl, suffix)) {
- var matchedStar = relativeToBaseUrl.substr(prefix.length, relativeToBaseUrl.length - suffix.length);
- return key.replace("*", matchedStar); // CodeQL [SM02383] According to the documentation at L24706, there is at most one matching asterisk.
- }
- }
- else if (pattern === relativeToBaseUrl || pattern === relativeToBaseUrlWithIndex) {
- return key;
- }
- }
- }
- }
- function tryGetModuleNameFromRootDirs(rootDirs, moduleFileName, sourceDirectory, getCanonicalFileName) {
- var normalizedTargetPath = getPathRelativeToRootDirs(moduleFileName, rootDirs, getCanonicalFileName);
- if (normalizedTargetPath === undefined) {
- return undefined;
- }
- var normalizedSourcePath = getPathRelativeToRootDirs(sourceDirectory, rootDirs, getCanonicalFileName);
- var relativePath = normalizedSourcePath !== undefined ? getRelativePath(normalizedTargetPath, normalizedSourcePath, getCanonicalFileName) : normalizedTargetPath;
- return ts.removeFileExtension(relativePath);
- }
- function tryGetModuleNameFromTypeRoots(options, host, getCanonicalFileName, moduleFileName, addJsExtension) {
- var roots = ts.getEffectiveTypeRoots(options, host);
- return ts.firstDefined(roots, function (unNormalizedTypeRoot) {
- var typeRoot = ts.toPath(unNormalizedTypeRoot, /*basePath*/ undefined, getCanonicalFileName);
- if (ts.startsWith(moduleFileName, typeRoot)) {
- return removeExtensionAndIndexPostFix(moduleFileName.substring(typeRoot.length + 1), options, addJsExtension);
- }
- });
- }
- function tryGetModuleNameAsNodeModule(options, moduleFileName, host, getCanonicalFileName, sourceDirectory) {
- if (ts.getEmitModuleResolutionKind(options) !== ts.ModuleResolutionKind.NodeJs) {
- // nothing to do here
- return undefined;
- }
- var parts = getNodeModulePathParts(moduleFileName);
- if (!parts) {
- return undefined;
- }
- // Simplify the full file path to something that can be resolved by Node.
- // If the module could be imported by a directory name, use that directory's name
- var moduleSpecifier = getDirectoryOrExtensionlessFileName(moduleFileName);
- // Get a path that's relative to node_modules or the importing file's path
- moduleSpecifier = getNodeResolvablePath(moduleSpecifier);
- // If the module was found in @types, get the actual Node package name
- return ts.getPackageNameFromAtTypesDirectory(moduleSpecifier);
- function getDirectoryOrExtensionlessFileName(path) {
- // If the file is the main module, it can be imported by the package name
- var packageRootPath = path.substring(0, parts.packageRootIndex);
- var packageJsonPath = ts.combinePaths(packageRootPath, "package.json");
- if (host.fileExists(packageJsonPath)) {
- var packageJsonContent = JSON.parse(host.readFile(packageJsonPath));
- if (packageJsonContent) {
- var mainFileRelative = packageJsonContent.typings || packageJsonContent.types || packageJsonContent.main;
- if (mainFileRelative) {
- var mainExportFile = ts.toPath(mainFileRelative, packageRootPath, getCanonicalFileName);
- if (mainExportFile === getCanonicalFileName(path)) {
- return packageRootPath;
- }
- }
- }
- }
- // We still have a file name - remove the extension
- var fullModulePathWithoutExtension = ts.removeFileExtension(path);
- // If the file is /index, it can be imported by its directory name
- if (getCanonicalFileName(fullModulePathWithoutExtension.substring(parts.fileNameIndex)) === "/index") {
- return fullModulePathWithoutExtension.substring(0, parts.fileNameIndex);
- }
- return fullModulePathWithoutExtension;
- }
- function getNodeResolvablePath(path) {
- var basePath = path.substring(0, parts.topLevelNodeModulesIndex);
- if (sourceDirectory.indexOf(basePath) === 0) {
- // if node_modules folder is in this folder or any of its parent folders, no need to keep it.
- return path.substring(parts.topLevelPackageNameIndex + 1);
- }
- else {
- return getRelativePath(path, sourceDirectory, getCanonicalFileName);
- }
- }
- }
- function getNodeModulePathParts(fullPath) {
- // If fullPath can't be valid module file within node_modules, returns undefined.
- // Example of expected pattern: /base/path/node_modules/[@scope/otherpackage/@otherscope/node_modules/]package/[subdirectory/]file.js
- // Returns indices: ^ ^ ^ ^
- var topLevelNodeModulesIndex = 0;
- var topLevelPackageNameIndex = 0;
- var packageRootIndex = 0;
- var fileNameIndex = 0;
- var States;
- (function (States) {
- States[States["BeforeNodeModules"] = 0] = "BeforeNodeModules";
- States[States["NodeModules"] = 1] = "NodeModules";
- States[States["Scope"] = 2] = "Scope";
- States[States["PackageContent"] = 3] = "PackageContent";
- })(States || (States = {}));
- var partStart = 0;
- var partEnd = 0;
- var state = 0 /* BeforeNodeModules */;
- while (partEnd >= 0) {
- partStart = partEnd;
- partEnd = fullPath.indexOf("/", partStart + 1);
- switch (state) {
- case 0 /* BeforeNodeModules */:
- if (fullPath.indexOf("/node_modules/", partStart) === partStart) {
- topLevelNodeModulesIndex = partStart;
- topLevelPackageNameIndex = partEnd;
- state = 1 /* NodeModules */;
- }
- break;
- case 1 /* NodeModules */:
- case 2 /* Scope */:
- if (state === 1 /* NodeModules */ && fullPath.charAt(partStart + 1) === "@") {
- state = 2 /* Scope */;
- }
- else {
- packageRootIndex = partEnd;
- state = 3 /* PackageContent */;
- }
- break;
- case 3 /* PackageContent */:
- if (fullPath.indexOf("/node_modules/", partStart) === partStart) {
- state = 1 /* NodeModules */;
- }
- else {
- state = 3 /* PackageContent */;
- }
- break;
- }
- }
- fileNameIndex = partStart;
- return state > 1 /* NodeModules */ ? { topLevelNodeModulesIndex: topLevelNodeModulesIndex, topLevelPackageNameIndex: topLevelPackageNameIndex, packageRootIndex: packageRootIndex, fileNameIndex: fileNameIndex } : undefined;
- }
- function getPathRelativeToRootDirs(path, rootDirs, getCanonicalFileName) {
- return ts.firstDefined(rootDirs, function (rootDir) {
- var relativePath = getRelativePathIfInDirectory(path, rootDir, getCanonicalFileName);
- return isPathRelativeToParent(relativePath) ? undefined : relativePath;
- });
- }
- function removeExtensionAndIndexPostFix(fileName, options, addJsExtension) {
- var noExtension = ts.removeFileExtension(fileName);
- return addJsExtension
- ? noExtension + ".js"
- : ts.getEmitModuleResolutionKind(options) === ts.ModuleResolutionKind.NodeJs
- ? ts.removeSuffix(noExtension, "/index")
- : noExtension;
- }
- function getRelativePathIfInDirectory(path, directoryPath, getCanonicalFileName) {
- var relativePath = ts.getRelativePathToDirectoryOrUrl(directoryPath, path, directoryPath, getCanonicalFileName, /*isAbsolutePathAnUrl*/ false);
- return ts.isRootedDiskPath(relativePath) ? undefined : relativePath;
- }
- function isPathRelativeToParent(path) {
- return ts.startsWith(path, "..");
- }
- function getRelativePath(path, directoryPath, getCanonicalFileName) {
- var relativePath = ts.getRelativePathToDirectoryOrUrl(directoryPath, path, directoryPath, getCanonicalFileName, /*isAbsolutePathAnUrl*/ false);
- return !ts.pathIsRelative(relativePath) ? "./" + relativePath : relativePath;
- }
- function getCodeActionsForAddImport(exportInfos, ctx, existingImports) {
- var fromExistingImport = ts.firstDefined(existingImports, function (_a) {
- var declaration = _a.declaration, importKind = _a.importKind;
- if (declaration.kind === 242 /* ImportDeclaration */ && declaration.importClause) {
- var changes = tryUpdateExistingImport(ctx, ts.isImportClause(declaration.importClause) && declaration.importClause || undefined, importKind);
- if (changes) {
- var moduleSpecifierWithoutQuotes = ts.stripQuotes(declaration.moduleSpecifier.getText());
- return createCodeAction(ts.Diagnostics.Add_0_to_existing_import_declaration_from_1, [ctx.symbolName, moduleSpecifierWithoutQuotes], changes);
- }
- }
- });
- if (fromExistingImport) {
- return [fromExistingImport];
- }
- var existingDeclaration = ts.firstDefined(existingImports, newImportInfoFromExistingSpecifier);
- var newImportInfos = existingDeclaration
- ? [existingDeclaration]
- : getNewImportInfos(ctx.program, ctx.sourceFile, exportInfos, ctx.compilerOptions, ctx.getCanonicalFileName, ctx.host);
- return newImportInfos.map(function (info) { return getCodeActionForNewImport(ctx, info); });
- }
- function newImportInfoFromExistingSpecifier(_a) {
- var declaration = _a.declaration, importKind = _a.importKind;
- var expression = declaration.kind === 242 /* ImportDeclaration */
- ? declaration.moduleSpecifier
- : declaration.moduleReference.kind === 252 /* ExternalModuleReference */
- ? declaration.moduleReference.expression
- : undefined;
- return expression && ts.isStringLiteral(expression) ? { moduleSpecifier: expression.text, importKind: importKind } : undefined;
- }
- function tryUpdateExistingImport(context, importClause, importKind) {
- var symbolName = context.symbolName, sourceFile = context.sourceFile;
- var name = importClause.name;
- var namedBindings = (importClause.kind !== 241 /* ImportEqualsDeclaration */ && importClause).namedBindings;
- switch (importKind) {
- case 1 /* Default */:
- return name ? undefined : ChangeTracker.with(context, function (t) {
- return t.replaceNode(sourceFile, importClause, ts.createImportClause(ts.createIdentifier(symbolName), namedBindings));
- });
- case 0 /* Named */: {
- var newImportSpecifier_1 = ts.createImportSpecifier(/*propertyName*/ undefined, ts.createIdentifier(symbolName));
- if (namedBindings && namedBindings.kind === 245 /* NamedImports */ && namedBindings.elements.length !== 0) {
- // There are already named imports; add another.
- return ChangeTracker.with(context, function (t) { return t.insertNodeInListAfter(sourceFile, namedBindings.elements[namedBindings.elements.length - 1], newImportSpecifier_1); });
- }
- if (!namedBindings || namedBindings.kind === 245 /* NamedImports */ && namedBindings.elements.length === 0) {
- return ChangeTracker.with(context, function (t) {
- return t.replaceNode(sourceFile, importClause, ts.createImportClause(name, ts.createNamedImports([newImportSpecifier_1])));
- });
- }
- return undefined;
- }
- case 2 /* Namespace */:
- return namedBindings ? undefined : ChangeTracker.with(context, function (t) {
- return t.replaceNode(sourceFile, importClause, ts.createImportClause(name, ts.createNamespaceImport(ts.createIdentifier(symbolName))));
- });
- case 3 /* Equals */:
- return undefined;
- default:
- ts.Debug.assertNever(importKind);
- }
- }
- function getCodeActionForUseExistingNamespaceImport(namespacePrefix, context, symbolToken) {
- var symbolName = context.symbolName, sourceFile = context.sourceFile;
- /**
- * Cases:
- * import * as ns from "mod"
- * import default, * as ns from "mod"
- * import ns = require("mod")
- *
- * Because there is no import list, we alter the reference to include the
- * namespace instead of altering the import declaration. For example, "foo" would
- * become "ns.foo"
- */
- var changes = ChangeTracker.with(context, function (tracker) {
- return tracker.replaceNode(sourceFile, symbolToken, ts.createPropertyAccess(ts.createIdentifier(namespacePrefix), symbolToken));
- });
- return createCodeAction(ts.Diagnostics.Change_0_to_1, [symbolName, namespacePrefix + "." + symbolName], changes);
- }
- function getImportCodeActions(context) {
- return context.errorCode === ts.Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead.code
- ? getActionsForUMDImport(context)
- : getActionsForNonUMDImport(context);
- }
- function getActionsForUMDImport(context) {
- var token = ts.getTokenAtPosition(context.sourceFile, context.span.start, /*includeJsDocComment*/ false);
- var checker = context.program.getTypeChecker();
- var umdSymbol;
- if (ts.isIdentifier(token)) {
- // try the identifier to see if it is the umd symbol
- umdSymbol = checker.getSymbolAtLocation(token);
- }
- if (!ts.isUMDExportSymbol(umdSymbol)) {
- // The error wasn't for the symbolAtLocation, it was for the JSX tag itself, which needs access to e.g. `React`.
- var parent = token.parent;
- var isNodeOpeningLikeElement = ts.isJsxOpeningLikeElement(parent);
- if ((ts.isJsxOpeningLikeElement && parent.tagName === token) || parent.kind === 258 /* JsxOpeningFragment */) {
- umdSymbol = checker.resolveName(checker.getJsxNamespace(parent), isNodeOpeningLikeElement ? parent.tagName : parent, 67216319 /* Value */, /*excludeGlobals*/ false);
- }
- }
- if (ts.isUMDExportSymbol(umdSymbol)) {
- var symbol = checker.getAliasedSymbol(umdSymbol);
- if (symbol) {
- return getCodeActionsForImport([{ moduleSymbol: symbol, importKind: getUmdImportKind(context.program.getCompilerOptions()) }], convertToImportCodeFixContext(context, token, umdSymbol.name));
- }
- }
- return undefined;
- }
- function getUmdImportKind(compilerOptions) {
- // Import a synthetic `default` if enabled.
- if (ts.getAllowSyntheticDefaultImports(compilerOptions)) {
- return 1 /* Default */;
- }
- // When a synthetic `default` is unavailable, use `import..require` if the module kind supports it.
- var moduleKind = ts.getEmitModuleKind(compilerOptions);
- switch (moduleKind) {
- case ts.ModuleKind.AMD:
- case ts.ModuleKind.CommonJS:
- case ts.ModuleKind.UMD:
- return 3 /* Equals */;
- case ts.ModuleKind.System:
- case ts.ModuleKind.ES2015:
- case ts.ModuleKind.ESNext:
- case ts.ModuleKind.None:
- // Fall back to the `import * as ns` style import.
- return 2 /* Namespace */;
- default:
- return ts.Debug.assertNever(moduleKind);
- }
- }
- function getActionsForNonUMDImport(context) {
- // This will always be an Identifier, since the diagnostics we fix only fail on identifiers.
- var sourceFile = context.sourceFile, span = context.span, program = context.program, cancellationToken = context.cancellationToken;
- var checker = program.getTypeChecker();
- var symbolToken = ts.getTokenAtPosition(sourceFile, span.start, /*includeJsDocComment*/ false);
- // If we're at ``, we must check if `Foo` is already in scope, and if so, get an import for `React` instead.
- var symbolName = ts.isJsxOpeningLikeElement(symbolToken.parent)
- && symbolToken.parent.tagName === symbolToken
- && (!ts.isIdentifier(symbolToken) || ts.isIntrinsicJsxName(symbolToken.text) || checker.resolveName(symbolToken.text, symbolToken, 67108863 /* All */, /*excludeGlobals*/ false))
- ? checker.getJsxNamespace()
- : ts.isIdentifier(symbolToken) ? symbolToken.text : undefined;
- if (!symbolName)
- return undefined;
- // "default" is a keyword and not a legal identifier for the import, so we don't expect it here
- ts.Debug.assert(symbolName !== "default");
- var currentTokenMeaning = ts.getMeaningFromLocation(symbolToken);
- // For each original symbol, keep all re-exports of that symbol together so we can call `getCodeActionsForImport` on the whole group at once.
- // Maps symbol id to info for modules providing that symbol (original export + re-exports).
- var originalSymbolToExportInfos = ts.createMultiMap();
- function addSymbol(moduleSymbol, exportedSymbol, importKind) {
- originalSymbolToExportInfos.add(ts.getUniqueSymbolId(exportedSymbol, checker).toString(), { moduleSymbol: moduleSymbol, importKind: importKind });
- }
- forEachExternalModuleToImportFrom(checker, sourceFile, program.getSourceFiles(), function (moduleSymbol) {
- cancellationToken.throwIfCancellationRequested();
- // check the default export
- var defaultExport = checker.tryGetMemberInModuleExports("default" /* Default */, moduleSymbol);
- if (defaultExport) {
- var localSymbol = ts.getLocalSymbolForExportDefault(defaultExport);
- if ((localSymbol && localSymbol.escapedName === symbolName ||
- getEscapedNameForExportDefault(defaultExport) === symbolName ||
- moduleSymbolToValidIdentifier(moduleSymbol, program.getCompilerOptions().target) === symbolName) && checkSymbolHasMeaning(localSymbol || defaultExport, currentTokenMeaning)) {
- addSymbol(moduleSymbol, localSymbol || defaultExport, 1 /* Default */);
- }
- }
- // check exports with the same name
- var exportSymbolWithIdenticalName = checker.tryGetMemberInModuleExportsAndProperties(symbolName, moduleSymbol);
- if (exportSymbolWithIdenticalName && checkSymbolHasMeaning(exportSymbolWithIdenticalName, currentTokenMeaning)) {
- addSymbol(moduleSymbol, exportSymbolWithIdenticalName, 0 /* Named */);
- }
- function getEscapedNameForExportDefault(symbol) {
- return ts.firstDefined(symbol.declarations, function (declaration) {
- if (ts.isExportAssignment(declaration)) {
- if (ts.isIdentifier(declaration.expression)) {
- return declaration.expression.escapedText;
- }
- }
- else if (ts.isExportSpecifier(declaration)) {
- ts.Debug.assert(declaration.name.escapedText === "default" /* Default */);
- if (declaration.propertyName) {
- return declaration.propertyName.escapedText;
- }
- }
- });
- }
- });
- return ts.arrayFrom(ts.flatMapIterator(originalSymbolToExportInfos.values(), function (exportInfos) { return getCodeActionsForImport(exportInfos, convertToImportCodeFixContext(context, symbolToken, symbolName)); }));
- }
- function checkSymbolHasMeaning(_a, meaning) {
- var declarations = _a.declarations;
- return ts.some(declarations, function (decl) { return !!(ts.getMeaningFromDeclaration(decl) & meaning); });
- }
- function forEachExternalModuleToImportFrom(checker, from, allSourceFiles, cb) {
- forEachExternalModule(checker, allSourceFiles, function (module, sourceFile) {
- if (sourceFile === undefined || sourceFile !== from && isImportablePath(from.fileName, sourceFile.fileName)) {
- cb(module);
- }
- });
- }
- codefix.forEachExternalModuleToImportFrom = forEachExternalModuleToImportFrom;
- function forEachExternalModule(checker, allSourceFiles, cb) {
- for (var _i = 0, _a = checker.getAmbientModules(); _i < _a.length; _i++) {
- var ambient = _a[_i];
- cb(ambient, /*sourceFile*/ undefined);
- }
- for (var _b = 0, allSourceFiles_1 = allSourceFiles; _b < allSourceFiles_1.length; _b++) {
- var sourceFile = allSourceFiles_1[_b];
- if (ts.isExternalOrCommonJsModule(sourceFile)) {
- cb(sourceFile.symbol, sourceFile);
- }
- }
- }
- /**
- * Don't include something from a `node_modules` that isn't actually reachable by a global import.
- * A relative import to node_modules is usually a bad idea.
- */
- function isImportablePath(fromPath, toPath) {
- // If it's in a `node_modules` but is not reachable from here via a global import, don't bother.
- var toNodeModules = ts.forEachAncestorDirectory(toPath, function (ancestor) { return ts.getBaseFileName(ancestor) === "node_modules" ? ancestor : undefined; });
- return toNodeModules === undefined || ts.startsWith(fromPath, ts.getDirectoryPath(toNodeModules));
- }
- function moduleSymbolToValidIdentifier(moduleSymbol, target) {
- return moduleSpecifierToValidIdentifier(ts.removeFileExtension(ts.getBaseFileName(moduleSymbol.name)), target);
- }
- codefix.moduleSymbolToValidIdentifier = moduleSymbolToValidIdentifier;
- function moduleSpecifierToValidIdentifier(moduleSpecifier, target) {
- var res = "";
- var lastCharWasValid = true;
- var firstCharCode = moduleSpecifier.charCodeAt(0);
- if (ts.isIdentifierStart(firstCharCode, target)) {
- res += String.fromCharCode(firstCharCode);
- }
- else {
- lastCharWasValid = false;
- }
- for (var i = 1; i < moduleSpecifier.length; i++) {
- var ch = moduleSpecifier.charCodeAt(i);
- var isValid = ts.isIdentifierPart(ch, target);
- if (isValid) {
- var char = String.fromCharCode(ch);
- if (!lastCharWasValid) {
- char = char.toUpperCase();
- }
- res += char;
- }
- lastCharWasValid = isValid;
- }
- // Need `|| "_"` to ensure result isn't empty.
- return !ts.isStringANonContextualKeyword(res) ? res || "_" : "_" + res;
- }
- codefix.moduleSpecifierToValidIdentifier = moduleSpecifierToValidIdentifier;
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "disableJsDiagnostics";
- var errorCodes = ts.mapDefined(Object.keys(ts.Diagnostics), function (key) {
- var diag = ts.Diagnostics[key];
- return diag.category === ts.DiagnosticCategory.Error ? diag.code : undefined;
- });
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var sourceFile = context.sourceFile, program = context.program, span = context.span, host = context.host, formatContext = context.formatContext;
- if (!ts.isInJavaScriptFile(sourceFile) || !ts.isCheckJsEnabledForFile(sourceFile, program.getCompilerOptions())) {
- return undefined;
- }
- var fixes = [
- {
- description: ts.getLocaleSpecificMessage(ts.Diagnostics.Disable_checking_for_this_file),
- changes: [codefix.createFileTextChanges(sourceFile.fileName, [
- ts.createTextChange(sourceFile.checkJsDirective
- ? ts.createTextSpanFromBounds(sourceFile.checkJsDirective.pos, sourceFile.checkJsDirective.end)
- : ts.createTextSpan(0, 0), "// @ts-nocheck" + ts.getNewLineOrDefaultFromHost(host, formatContext.options)),
- ])],
- // fixId unnecessary because adding `// @ts-nocheck` even once will ignore every error in the file.
- fixId: undefined,
- }
- ];
- if (isValidSuppressLocation(sourceFile, span.start)) {
- fixes.unshift({
- description: ts.getLocaleSpecificMessage(ts.Diagnostics.Ignore_this_error_message),
- changes: ts.textChanges.ChangeTracker.with(context, function (t) { return makeChange(t, sourceFile, span.start); }),
- fixId: fixId,
- });
- }
- return fixes;
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) {
- var seenLines = ts.createMap();
- return codefix.codeFixAll(context, errorCodes, function (changes, diag) {
- if (isValidSuppressLocation(diag.file, diag.start)) {
- makeChange(changes, diag.file, diag.start, seenLines);
- }
- });
- },
- });
- function isValidSuppressLocation(sourceFile, position) {
- return !ts.isInComment(sourceFile, position) && !ts.isInString(sourceFile, position) && !ts.isInTemplateString(sourceFile, position);
- }
- function makeChange(changes, sourceFile, position, seenLines) {
- var lineNumber = ts.getLineAndCharacterOfPosition(sourceFile, position).line;
- // Only need to add `// @ts-ignore` for a line once.
- if (seenLines && !ts.addToSeen(seenLines, lineNumber)) {
- return;
- }
- var lineStartPosition = ts.getStartPositionOfLine(lineNumber, sourceFile);
- var startPosition = ts.getFirstNonSpaceCharacterPosition(sourceFile.text, lineStartPosition);
- // First try to see if we can put the '// @ts-ignore' on the previous line.
- // We need to make sure that we are not in the middle of a string literal or a comment.
- // If so, we do not want to separate the node from its comment if we can.
- // Otherwise, add an extra new line immediately before the error span.
- var insertAtLineStart = isValidSuppressLocation(sourceFile, startPosition);
- var token = ts.getTouchingToken(sourceFile, insertAtLineStart ? startPosition : position, /*includeJsDocComment*/ false);
- var clone = ts.setStartsOnNewLine(ts.getSynthesizedDeepClone(token), true);
- ts.addSyntheticLeadingComment(clone, 2 /* SingleLineCommentTrivia */, " @ts-ignore");
- changes.replaceNode(sourceFile, token, clone, { preserveLeadingWhitespace: true, prefix: insertAtLineStart ? undefined : changes.newLineCharacter });
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- /**
- * Finds members of the resolved type that are missing in the class pointed to by class decl
- * and generates source code for the missing members.
- * @param possiblyMissingSymbols The collection of symbols to filter and then get insertions for.
- * @returns Empty string iff there are no member insertions.
- */
- function createMissingMemberNodes(classDeclaration, possiblyMissingSymbols, checker, out) {
- var classMembers = classDeclaration.symbol.members;
- for (var _i = 0, possiblyMissingSymbols_1 = possiblyMissingSymbols; _i < possiblyMissingSymbols_1.length; _i++) {
- var symbol = possiblyMissingSymbols_1[_i];
- if (!classMembers.has(symbol.escapedName)) {
- addNewNodeForMemberSymbol(symbol, classDeclaration, checker, out);
- }
- }
- }
- codefix.createMissingMemberNodes = createMissingMemberNodes;
- /**
- * @returns Empty string iff there we can't figure out a representation for `symbol` in `enclosingDeclaration`.
- */
- function addNewNodeForMemberSymbol(symbol, enclosingDeclaration, checker, out) {
- var declarations = symbol.getDeclarations();
- if (!(declarations && declarations.length)) {
- return undefined;
- }
- var declaration = declarations[0];
- // Clone name to remove leading trivia.
- var name = ts.getSynthesizedDeepClone(ts.getNameOfDeclaration(declaration));
- var visibilityModifier = createVisibilityModifier(ts.getModifierFlags(declaration));
- var modifiers = visibilityModifier ? ts.createNodeArray([visibilityModifier]) : undefined;
- var type = checker.getWidenedType(checker.getTypeOfSymbolAtLocation(symbol, enclosingDeclaration));
- var optional = !!(symbol.flags & 16777216 /* Optional */);
- switch (declaration.kind) {
- case 155 /* GetAccessor */:
- case 156 /* SetAccessor */:
- case 150 /* PropertySignature */:
- case 151 /* PropertyDeclaration */:
- var typeNode = checker.typeToTypeNode(type, enclosingDeclaration);
- out(ts.createProperty(
- /*decorators*/ undefined, modifiers, name, optional ? ts.createToken(55 /* QuestionToken */) : undefined, typeNode,
- /*initializer*/ undefined));
- break;
- case 152 /* MethodSignature */:
- case 153 /* MethodDeclaration */:
- // The signature for the implementation appears as an entry in `signatures` iff
- // there is only one signature.
- // If there are overloads and an implementation signature, it appears as an
- // extra declaration that isn't a signature for `type`.
- // If there is more than one overload but no implementation signature
- // (eg: an abstract method or interface declaration), there is a 1-1
- // correspondence of declarations and signatures.
- var signatures = checker.getSignaturesOfType(type, 0 /* Call */);
- if (!ts.some(signatures)) {
- break;
- }
- if (declarations.length === 1) {
- ts.Debug.assert(signatures.length === 1);
- var signature = signatures[0];
- outputMethod(signature, modifiers, name, createStubbedMethodBody());
- break;
- }
- for (var _i = 0, signatures_8 = signatures; _i < signatures_8.length; _i++) {
- var signature = signatures_8[_i];
- // Need to ensure nodes are fresh each time so they can have different positions.
- outputMethod(signature, getSynthesizedDeepClones(modifiers), ts.getSynthesizedDeepClone(name));
- }
- if (declarations.length > signatures.length) {
- var signature = checker.getSignatureFromDeclaration(declarations[declarations.length - 1]);
- outputMethod(signature, modifiers, name, createStubbedMethodBody());
- }
- else {
- ts.Debug.assert(declarations.length === signatures.length);
- out(createMethodImplementingSignatures(signatures, name, optional, modifiers));
- }
- break;
- }
- function outputMethod(signature, modifiers, name, body) {
- var method = signatureToMethodDeclaration(checker, signature, enclosingDeclaration, modifiers, name, optional, body);
- if (method)
- out(method);
- }
- }
- function signatureToMethodDeclaration(checker, signature, enclosingDeclaration, modifiers, name, optional, body) {
- var signatureDeclaration = checker.signatureToSignatureDeclaration(signature, 153 /* MethodDeclaration */, enclosingDeclaration, 256 /* SuppressAnyReturnType */);
- if (!signatureDeclaration) {
- return undefined;
- }
- signatureDeclaration.decorators = undefined;
- signatureDeclaration.modifiers = modifiers;
- signatureDeclaration.name = name;
- signatureDeclaration.questionToken = optional ? ts.createToken(55 /* QuestionToken */) : undefined;
- signatureDeclaration.body = body;
- return signatureDeclaration;
- }
- function getSynthesizedDeepClones(nodes) {
- return nodes && ts.createNodeArray(nodes.map(ts.getSynthesizedDeepClone));
- }
- function createMethodFromCallExpression(_a, methodName, inJs, makeStatic) {
- var typeArguments = _a.typeArguments, args = _a.arguments;
- return ts.createMethod(
- /*decorators*/ undefined,
- /*modifiers*/ makeStatic ? [ts.createToken(115 /* StaticKeyword */)] : undefined,
- /*asteriskToken*/ undefined, methodName,
- /*questionToken*/ undefined,
- /*typeParameters*/ inJs ? undefined : ts.map(typeArguments, function (_, i) {
- return ts.createTypeParameterDeclaration(84 /* T */ + typeArguments.length - 1 <= 90 /* Z */ ? String.fromCharCode(84 /* T */ + i) : "T" + i);
- }),
- /*parameters*/ createDummyParameters(args.length, /*names*/ undefined, /*minArgumentCount*/ undefined, inJs),
- /*type*/ inJs ? undefined : ts.createKeywordTypeNode(119 /* AnyKeyword */), createStubbedMethodBody());
- }
- codefix.createMethodFromCallExpression = createMethodFromCallExpression;
- function createDummyParameters(argCount, names, minArgumentCount, inJs) {
- var parameters = [];
- for (var i = 0; i < argCount; i++) {
- var newParameter = ts.createParameter(
- /*decorators*/ undefined,
- /*modifiers*/ undefined,
- /*dotDotDotToken*/ undefined,
- /*name*/ names && names[i] || "arg" + i,
- /*questionToken*/ minArgumentCount !== undefined && i >= minArgumentCount ? ts.createToken(55 /* QuestionToken */) : undefined,
- /*type*/ inJs ? undefined : ts.createKeywordTypeNode(119 /* AnyKeyword */),
- /*initializer*/ undefined);
- parameters.push(newParameter);
- }
- return parameters;
- }
- function createMethodImplementingSignatures(signatures, name, optional, modifiers) {
- /** This is *a* signature with the maximal number of arguments,
- * such that if there is a "maximal" signature without rest arguments,
- * this is one of them.
- */
- var maxArgsSignature = signatures[0];
- var minArgumentCount = signatures[0].minArgumentCount;
- var someSigHasRestParameter = false;
- for (var _i = 0, signatures_9 = signatures; _i < signatures_9.length; _i++) {
- var sig = signatures_9[_i];
- minArgumentCount = Math.min(sig.minArgumentCount, minArgumentCount);
- if (sig.hasRestParameter) {
- someSigHasRestParameter = true;
- }
- if (sig.parameters.length >= maxArgsSignature.parameters.length && (!sig.hasRestParameter || maxArgsSignature.hasRestParameter)) {
- maxArgsSignature = sig;
- }
- }
- var maxNonRestArgs = maxArgsSignature.parameters.length - (maxArgsSignature.hasRestParameter ? 1 : 0);
- var maxArgsParameterSymbolNames = maxArgsSignature.parameters.map(function (symbol) { return symbol.name; });
- var parameters = createDummyParameters(maxNonRestArgs, maxArgsParameterSymbolNames, minArgumentCount, /*inJs*/ false);
- if (someSigHasRestParameter) {
- var anyArrayType = ts.createArrayTypeNode(ts.createKeywordTypeNode(119 /* AnyKeyword */));
- var restParameter = ts.createParameter(
- /*decorators*/ undefined,
- /*modifiers*/ undefined, ts.createToken(24 /* DotDotDotToken */), maxArgsParameterSymbolNames[maxNonRestArgs] || "rest",
- /*questionToken*/ maxNonRestArgs >= minArgumentCount ? ts.createToken(55 /* QuestionToken */) : undefined, anyArrayType,
- /*initializer*/ undefined);
- parameters.push(restParameter);
- }
- return createStubbedMethod(modifiers, name, optional,
- /*typeParameters*/ undefined, parameters,
- /*returnType*/ undefined);
- }
- function createStubbedMethod(modifiers, name, optional, typeParameters, parameters, returnType) {
- return ts.createMethod(
- /*decorators*/ undefined, modifiers,
- /*asteriskToken*/ undefined, name, optional ? ts.createToken(55 /* QuestionToken */) : undefined, typeParameters, parameters, returnType, createStubbedMethodBody());
- }
- function createStubbedMethodBody() {
- return ts.createBlock([ts.createThrow(ts.createNew(ts.createIdentifier("Error"),
- /*typeArguments*/ undefined, [ts.createLiteral("Method not implemented.")]))],
- /*multiline*/ true);
- }
- function createVisibilityModifier(flags) {
- if (flags & 4 /* Public */) {
- return ts.createToken(114 /* PublicKeyword */);
- }
- else if (flags & 16 /* Protected */) {
- return ts.createToken(113 /* ProtectedKeyword */);
- }
- return undefined;
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "inferFromUsage";
- var errorCodes = [
- // Variable declarations
- ts.Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_where_its_type_cannot_be_determined.code,
- // Variable uses
- ts.Diagnostics.Variable_0_implicitly_has_an_1_type.code,
- // Parameter declarations
- ts.Diagnostics.Parameter_0_implicitly_has_an_1_type.code,
- ts.Diagnostics.Rest_parameter_0_implicitly_has_an_any_type.code,
- // Get Accessor declarations
- ts.Diagnostics.Property_0_implicitly_has_type_any_because_its_get_accessor_lacks_a_return_type_annotation.code,
- ts.Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type.code,
- // Set Accessor declarations
- ts.Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation.code,
- // Property declarations
- ts.Diagnostics.Member_0_implicitly_has_an_1_type.code,
- ];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var sourceFile = context.sourceFile, program = context.program, start = context.span.start, errorCode = context.errorCode, cancellationToken = context.cancellationToken;
- if (ts.isSourceFileJavaScript(sourceFile)) {
- return undefined; // TODO: GH#20113
- }
- var token = ts.getTokenAtPosition(sourceFile, start, /*includeJsDocComment*/ false);
- var declaration;
- var changes = ts.textChanges.ChangeTracker.with(context, function (changes) { declaration = doChange(changes, sourceFile, token, errorCode, program, cancellationToken); });
- if (changes.length === 0)
- return undefined;
- var name = ts.getNameOfDeclaration(declaration).getText();
- var description = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(getDiagnostic(errorCode, token)), [name]);
- return [{ description: description, changes: changes, fixId: fixId }];
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) {
- var sourceFile = context.sourceFile, program = context.program, cancellationToken = context.cancellationToken;
- var seenFunctions = ts.createMap();
- return codefix.codeFixAll(context, errorCodes, function (changes, err) {
- doChange(changes, sourceFile, ts.getTokenAtPosition(err.file, err.start, /*includeJsDocComment*/ false), err.code, program, cancellationToken, seenFunctions);
- });
- },
- });
- function getDiagnostic(errorCode, token) {
- switch (errorCode) {
- case ts.Diagnostics.Parameter_0_implicitly_has_an_1_type.code:
- return ts.isSetAccessor(ts.getContainingFunction(token)) ? ts.Diagnostics.Infer_type_of_0_from_usage : ts.Diagnostics.Infer_parameter_types_from_usage;
- case ts.Diagnostics.Rest_parameter_0_implicitly_has_an_any_type.code:
- return ts.Diagnostics.Infer_parameter_types_from_usage;
- default:
- return ts.Diagnostics.Infer_type_of_0_from_usage;
- }
- }
- function doChange(changes, sourceFile, token, errorCode, program, cancellationToken, seenFunctions) {
- if (!isAllowedTokenKind(token.kind)) {
- return undefined;
- }
- var parent = token.parent;
- switch (errorCode) {
- // Variable and Property declarations
- case ts.Diagnostics.Member_0_implicitly_has_an_1_type.code:
- case ts.Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_where_its_type_cannot_be_determined.code:
- if (ts.isVariableDeclaration(parent) || ts.isPropertyDeclaration(parent) || ts.isPropertySignature(parent)) { // handle bad location
- annotateVariableDeclaration(changes, sourceFile, parent, program, cancellationToken);
- return parent;
- }
- return undefined;
- case ts.Diagnostics.Variable_0_implicitly_has_an_1_type.code: {
- var symbol = program.getTypeChecker().getSymbolAtLocation(token);
- if (symbol && symbol.valueDeclaration && ts.isVariableDeclaration(symbol.valueDeclaration)) {
- annotateVariableDeclaration(changes, sourceFile, symbol.valueDeclaration, program, cancellationToken);
- return symbol.valueDeclaration;
- }
- }
- }
- var containingFunction = ts.getContainingFunction(token);
- if (containingFunction === undefined) {
- return undefined;
- }
- switch (errorCode) {
- // Parameter declarations
- case ts.Diagnostics.Parameter_0_implicitly_has_an_1_type.code:
- if (ts.isSetAccessor(containingFunction)) {
- annotateSetAccessor(changes, sourceFile, containingFunction, program, cancellationToken);
- return containingFunction;
- }
- // falls through
- case ts.Diagnostics.Rest_parameter_0_implicitly_has_an_any_type.code:
- if (!seenFunctions || ts.addToSeen(seenFunctions, ts.getNodeId(containingFunction))) {
- var param = ts.cast(parent, ts.isParameter);
- annotateParameters(changes, param, containingFunction, sourceFile, program, cancellationToken);
- return param;
- }
- return undefined;
- // Get Accessor declarations
- case ts.Diagnostics.Property_0_implicitly_has_type_any_because_its_get_accessor_lacks_a_return_type_annotation.code:
- case ts.Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type.code:
- if (ts.isGetAccessor(containingFunction) && ts.isIdentifier(containingFunction.name)) {
- annotate(changes, sourceFile, containingFunction, inferTypeForVariableFromUsage(containingFunction.name, program, cancellationToken), program);
- return containingFunction;
- }
- return undefined;
- // Set Accessor declarations
- case ts.Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation.code:
- if (ts.isSetAccessor(containingFunction)) {
- annotateSetAccessor(changes, sourceFile, containingFunction, program, cancellationToken);
- return containingFunction;
- }
- return undefined;
- default:
- return ts.Debug.fail(String(errorCode));
- }
- }
- function isAllowedTokenKind(kind) {
- switch (kind) {
- case 71 /* Identifier */:
- case 24 /* DotDotDotToken */:
- case 114 /* PublicKeyword */:
- case 112 /* PrivateKeyword */:
- case 113 /* ProtectedKeyword */:
- case 132 /* ReadonlyKeyword */:
- return true;
- default:
- return false;
- }
- }
- function annotateVariableDeclaration(changes, sourceFile, declaration, program, cancellationToken) {
- if (ts.isIdentifier(declaration.name)) {
- annotate(changes, sourceFile, declaration, inferTypeForVariableFromUsage(declaration.name, program, cancellationToken), program);
- }
- }
- function isApplicableFunctionForInference(declaration) {
- switch (declaration.kind) {
- case 232 /* FunctionDeclaration */:
- case 153 /* MethodDeclaration */:
- case 154 /* Constructor */:
- return true;
- case 190 /* FunctionExpression */:
- return !!declaration.name;
- }
- return false;
- }
- function annotateParameters(changes, parameterDeclaration, containingFunction, sourceFile, program, cancellationToken) {
- if (!ts.isIdentifier(parameterDeclaration.name) || !isApplicableFunctionForInference(containingFunction)) {
- return;
- }
- var types = inferTypeForParametersFromUsage(containingFunction, sourceFile, program, cancellationToken) ||
- containingFunction.parameters.map(function (p) { return ts.isIdentifier(p.name) ? inferTypeForVariableFromUsage(p.name, program, cancellationToken) : undefined; });
- // We didn't actually find a set of type inference positions matching each parameter position
- if (!types || containingFunction.parameters.length !== types.length) {
- return;
- }
- ts.zipWith(containingFunction.parameters, types, function (parameter, type) {
- if (!parameter.type && !parameter.initializer) {
- annotate(changes, sourceFile, parameter, type, program);
- }
- });
- }
- function annotateSetAccessor(changes, sourceFile, setAccessorDeclaration, program, cancellationToken) {
- var param = ts.firstOrUndefined(setAccessorDeclaration.parameters);
- if (param && ts.isIdentifier(setAccessorDeclaration.name) && ts.isIdentifier(param.name)) {
- var type = inferTypeForVariableFromUsage(setAccessorDeclaration.name, program, cancellationToken) ||
- inferTypeForVariableFromUsage(param.name, program, cancellationToken);
- annotate(changes, sourceFile, param, type, program);
- }
- }
- function annotate(changes, sourceFile, declaration, type, program) {
- var typeNode = type && getTypeNodeIfAccessible(type, declaration, program.getTypeChecker());
- if (typeNode)
- changes.insertTypeAnnotation(sourceFile, declaration, typeNode);
- }
- function getTypeNodeIfAccessible(type, enclosingScope, checker) {
- 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,
- });
- return typeIsAccessible ? res : undefined;
- }
- function getReferences(token, program, cancellationToken) {
- // Position shouldn't matter since token is not a SourceFile.
- return ts.mapDefined(ts.FindAllReferences.getReferenceEntriesForNode(-1, token, program, program.getSourceFiles(), cancellationToken), function (entry) {
- return entry.type === "node" ? ts.tryCast(entry.node, ts.isIdentifier) : undefined;
- });
- }
- function inferTypeForVariableFromUsage(token, program, cancellationToken) {
- return InferFromReference.inferTypeFromReferences(getReferences(token, program, cancellationToken), program.getTypeChecker(), cancellationToken);
- }
- function inferTypeForParametersFromUsage(containingFunction, sourceFile, program, cancellationToken) {
- switch (containingFunction.kind) {
- case 154 /* Constructor */:
- case 190 /* FunctionExpression */:
- case 232 /* FunctionDeclaration */:
- case 153 /* MethodDeclaration */:
- var isConstructor = containingFunction.kind === 154 /* Constructor */;
- var searchToken = isConstructor ?
- ts.findChildOfKind(containingFunction, 123 /* ConstructorKeyword */, sourceFile) :
- containingFunction.name;
- if (searchToken) {
- return InferFromReference.inferTypeForParametersFromReferences(getReferences(searchToken, program, cancellationToken), containingFunction, program.getTypeChecker(), cancellationToken);
- }
- }
- }
- var InferFromReference;
- (function (InferFromReference) {
- function inferTypeFromReferences(references, checker, cancellationToken) {
- var usageContext = {};
- for (var _i = 0, references_1 = references; _i < references_1.length; _i++) {
- var reference = references_1[_i];
- cancellationToken.throwIfCancellationRequested();
- inferTypeFromContext(reference, checker, usageContext);
- }
- return getTypeFromUsageContext(usageContext, checker);
- }
- InferFromReference.inferTypeFromReferences = inferTypeFromReferences;
- function inferTypeForParametersFromReferences(references, declaration, checker, cancellationToken) {
- if (references.length === 0) {
- return undefined;
- }
- if (!declaration.parameters) {
- return undefined;
- }
- var usageContext = {};
- for (var _i = 0, references_2 = references; _i < references_2.length; _i++) {
- var reference = references_2[_i];
- cancellationToken.throwIfCancellationRequested();
- inferTypeFromContext(reference, checker, usageContext);
- }
- var isConstructor = declaration.kind === 154 /* Constructor */;
- var callContexts = isConstructor ? usageContext.constructContexts : usageContext.callContexts;
- return callContexts && declaration.parameters.map(function (parameter, parameterIndex) {
- var types = [];
- var isRest = ts.isRestParameter(parameter);
- for (var _i = 0, callContexts_1 = callContexts; _i < callContexts_1.length; _i++) {
- var callContext = callContexts_1[_i];
- if (callContext.argumentTypes.length <= parameterIndex) {
- continue;
- }
- if (isRest) {
- for (var i = parameterIndex; i < callContext.argumentTypes.length; i++) {
- types.push(checker.getBaseTypeOfLiteralType(callContext.argumentTypes[i]));
- }
- }
- else {
- types.push(checker.getBaseTypeOfLiteralType(callContext.argumentTypes[parameterIndex]));
- }
- }
- if (!types.length) {
- return undefined;
- }
- var type = checker.getWidenedType(checker.getUnionType(types, 2 /* Subtype */));
- return isRest ? checker.createArrayType(type) : type;
- });
- }
- InferFromReference.inferTypeForParametersFromReferences = inferTypeForParametersFromReferences;
- function inferTypeFromContext(node, checker, usageContext) {
- while (ts.isRightSideOfQualifiedNameOrPropertyAccess(node)) {
- node = node.parent;
- }
- switch (node.parent.kind) {
- case 197 /* PostfixUnaryExpression */:
- usageContext.isNumber = true;
- break;
- case 196 /* PrefixUnaryExpression */:
- inferTypeFromPrefixUnaryExpressionContext(node.parent, usageContext);
- break;
- case 198 /* BinaryExpression */:
- inferTypeFromBinaryExpressionContext(node, node.parent, checker, usageContext);
- break;
- case 264 /* CaseClause */:
- case 265 /* DefaultClause */:
- inferTypeFromSwitchStatementLabelContext(node.parent, checker, usageContext);
- break;
- case 185 /* CallExpression */:
- case 186 /* NewExpression */:
- if (node.parent.expression === node) {
- inferTypeFromCallExpressionContext(node.parent, checker, usageContext);
- }
- else {
- inferTypeFromContextualType(node, checker, usageContext);
- }
- break;
- case 183 /* PropertyAccessExpression */:
- inferTypeFromPropertyAccessExpressionContext(node.parent, checker, usageContext);
- break;
- case 184 /* ElementAccessExpression */:
- inferTypeFromPropertyElementExpressionContext(node.parent, node, checker, usageContext);
- break;
- default:
- return inferTypeFromContextualType(node, checker, usageContext);
- }
- }
- function inferTypeFromContextualType(node, checker, usageContext) {
- if (ts.isExpressionNode(node)) {
- addCandidateType(usageContext, checker.getContextualType(node));
- }
- }
- function inferTypeFromPrefixUnaryExpressionContext(node, usageContext) {
- switch (node.operator) {
- case 43 /* PlusPlusToken */:
- case 44 /* MinusMinusToken */:
- case 38 /* MinusToken */:
- case 52 /* TildeToken */:
- usageContext.isNumber = true;
- break;
- case 37 /* PlusToken */:
- usageContext.isNumberOrString = true;
- break;
- // case SyntaxKind.ExclamationToken:
- // no inferences here;
- }
- }
- function inferTypeFromBinaryExpressionContext(node, parent, checker, usageContext) {
- switch (parent.operatorToken.kind) {
- // ExponentiationOperator
- case 40 /* AsteriskAsteriskToken */:
- // MultiplicativeOperator
- case 39 /* AsteriskToken */:
- case 41 /* SlashToken */:
- case 42 /* PercentToken */:
- // ShiftOperator
- case 45 /* LessThanLessThanToken */:
- case 46 /* GreaterThanGreaterThanToken */:
- case 47 /* GreaterThanGreaterThanGreaterThanToken */:
- // BitwiseOperator
- case 48 /* AmpersandToken */:
- case 49 /* BarToken */:
- case 50 /* CaretToken */:
- // CompoundAssignmentOperator
- case 60 /* MinusEqualsToken */:
- case 62 /* AsteriskAsteriskEqualsToken */:
- case 61 /* AsteriskEqualsToken */:
- case 63 /* SlashEqualsToken */:
- case 64 /* PercentEqualsToken */:
- case 68 /* AmpersandEqualsToken */:
- case 69 /* BarEqualsToken */:
- case 70 /* CaretEqualsToken */:
- case 65 /* LessThanLessThanEqualsToken */:
- case 67 /* GreaterThanGreaterThanGreaterThanEqualsToken */:
- case 66 /* GreaterThanGreaterThanEqualsToken */:
- // AdditiveOperator
- case 38 /* MinusToken */:
- // RelationalOperator
- case 27 /* LessThanToken */:
- case 30 /* LessThanEqualsToken */:
- case 29 /* GreaterThanToken */:
- case 31 /* GreaterThanEqualsToken */:
- var operandType = checker.getTypeAtLocation(parent.left === node ? parent.right : parent.left);
- if (operandType.flags & 272 /* EnumLike */) {
- addCandidateType(usageContext, operandType);
- }
- else {
- usageContext.isNumber = true;
- }
- break;
- case 59 /* PlusEqualsToken */:
- case 37 /* PlusToken */:
- var otherOperandType = checker.getTypeAtLocation(parent.left === node ? parent.right : parent.left);
- if (otherOperandType.flags & 272 /* EnumLike */) {
- addCandidateType(usageContext, otherOperandType);
- }
- else if (otherOperandType.flags & 84 /* NumberLike */) {
- usageContext.isNumber = true;
- }
- else if (otherOperandType.flags & 524322 /* StringLike */) {
- usageContext.isString = true;
- }
- else {
- usageContext.isNumberOrString = true;
- }
- break;
- // AssignmentOperators
- case 58 /* EqualsToken */:
- case 32 /* EqualsEqualsToken */:
- case 34 /* EqualsEqualsEqualsToken */:
- case 35 /* ExclamationEqualsEqualsToken */:
- case 33 /* ExclamationEqualsToken */:
- addCandidateType(usageContext, checker.getTypeAtLocation(parent.left === node ? parent.right : parent.left));
- break;
- case 92 /* InKeyword */:
- if (node === parent.left) {
- usageContext.isString = true;
- }
- break;
- // LogicalOperator
- case 54 /* BarBarToken */:
- if (node === parent.left &&
- (node.parent.parent.kind === 230 /* VariableDeclaration */ || ts.isAssignmentExpression(node.parent.parent, /*excludeCompoundAssignment*/ true))) {
- // var x = x || {};
- // TODO: use getFalsyflagsOfType
- addCandidateType(usageContext, checker.getTypeAtLocation(parent.right));
- }
- break;
- case 53 /* AmpersandAmpersandToken */:
- case 26 /* CommaToken */:
- case 93 /* InstanceOfKeyword */:
- // nothing to infer here
- break;
- }
- }
- function inferTypeFromSwitchStatementLabelContext(parent, checker, usageContext) {
- addCandidateType(usageContext, checker.getTypeAtLocation(parent.parent.parent.expression));
- }
- function inferTypeFromCallExpressionContext(parent, checker, usageContext) {
- var callContext = {
- argumentTypes: [],
- returnType: {}
- };
- if (parent.arguments) {
- for (var _i = 0, _a = parent.arguments; _i < _a.length; _i++) {
- var argument = _a[_i];
- callContext.argumentTypes.push(checker.getTypeAtLocation(argument));
- }
- }
- inferTypeFromContext(parent, checker, callContext.returnType);
- if (parent.kind === 185 /* CallExpression */) {
- (usageContext.callContexts || (usageContext.callContexts = [])).push(callContext);
- }
- else {
- (usageContext.constructContexts || (usageContext.constructContexts = [])).push(callContext);
- }
- }
- function inferTypeFromPropertyAccessExpressionContext(parent, checker, usageContext) {
- var name = ts.escapeLeadingUnderscores(parent.name.text);
- if (!usageContext.properties) {
- usageContext.properties = ts.createUnderscoreEscapedMap();
- }
- var propertyUsageContext = usageContext.properties.get(name) || {};
- inferTypeFromContext(parent, checker, propertyUsageContext);
- usageContext.properties.set(name, propertyUsageContext);
- }
- function inferTypeFromPropertyElementExpressionContext(parent, node, checker, usageContext) {
- if (node === parent.argumentExpression) {
- usageContext.isNumberOrString = true;
- return;
- }
- else {
- var indexType = checker.getTypeAtLocation(parent);
- var indexUsageContext = {};
- inferTypeFromContext(parent, checker, indexUsageContext);
- if (indexType.flags & 84 /* NumberLike */) {
- usageContext.numberIndexContext = indexUsageContext;
- }
- else {
- usageContext.stringIndexContext = indexUsageContext;
- }
- }
- }
- function getTypeFromUsageContext(usageContext, checker) {
- if (usageContext.isNumberOrString && !usageContext.isNumber && !usageContext.isString) {
- return checker.getUnionType([checker.getNumberType(), checker.getStringType()]);
- }
- else if (usageContext.isNumber) {
- return checker.getNumberType();
- }
- else if (usageContext.isString) {
- return checker.getStringType();
- }
- else if (usageContext.candidateTypes) {
- return checker.getWidenedType(checker.getUnionType(ts.map(usageContext.candidateTypes, function (t) { return checker.getBaseTypeOfLiteralType(t); }), 2 /* Subtype */));
- }
- else if (usageContext.properties && hasCallContext(usageContext.properties.get("then"))) {
- var paramType = getParameterTypeFromCallContexts(0, usageContext.properties.get("then").callContexts, /*isRestParameter*/ false, checker);
- var types = paramType.getCallSignatures().map(function (c) { return c.getReturnType(); });
- return checker.createPromiseType(types.length ? checker.getUnionType(types, 2 /* Subtype */) : checker.getAnyType());
- }
- else if (usageContext.properties && hasCallContext(usageContext.properties.get("push"))) {
- return checker.createArrayType(getParameterTypeFromCallContexts(0, usageContext.properties.get("push").callContexts, /*isRestParameter*/ false, checker));
- }
- else if (usageContext.properties || usageContext.callContexts || usageContext.constructContexts || usageContext.numberIndexContext || usageContext.stringIndexContext) {
- var members_5 = ts.createUnderscoreEscapedMap();
- var callSignatures = [];
- var constructSignatures = [];
- var stringIndexInfo = void 0;
- var numberIndexInfo = void 0;
- if (usageContext.properties) {
- usageContext.properties.forEach(function (context, name) {
- var symbol = checker.createSymbol(4 /* Property */, name);
- symbol.type = getTypeFromUsageContext(context, checker) || checker.getAnyType();
- members_5.set(name, symbol);
- });
- }
- if (usageContext.callContexts) {
- for (var _i = 0, _a = usageContext.callContexts; _i < _a.length; _i++) {
- var callContext = _a[_i];
- callSignatures.push(getSignatureFromCallContext(callContext, checker));
- }
- }
- if (usageContext.constructContexts) {
- for (var _b = 0, _c = usageContext.constructContexts; _b < _c.length; _b++) {
- var constructContext = _c[_b];
- constructSignatures.push(getSignatureFromCallContext(constructContext, checker));
- }
- }
- if (usageContext.numberIndexContext) {
- numberIndexInfo = checker.createIndexInfo(getTypeFromUsageContext(usageContext.numberIndexContext, checker), /*isReadonly*/ false);
- }
- if (usageContext.stringIndexContext) {
- stringIndexInfo = checker.createIndexInfo(getTypeFromUsageContext(usageContext.stringIndexContext, checker), /*isReadonly*/ false);
- }
- return checker.createAnonymousType(/*symbol*/ undefined, members_5, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo);
- }
- else {
- return undefined;
- }
- }
- function getParameterTypeFromCallContexts(parameterIndex, callContexts, isRestParameter, checker) {
- var types = [];
- if (callContexts) {
- for (var _i = 0, callContexts_2 = callContexts; _i < callContexts_2.length; _i++) {
- var callContext = callContexts_2[_i];
- if (callContext.argumentTypes.length > parameterIndex) {
- if (isRestParameter) {
- types = ts.concatenate(types, ts.map(callContext.argumentTypes.slice(parameterIndex), function (a) { return checker.getBaseTypeOfLiteralType(a); }));
- }
- else {
- types.push(checker.getBaseTypeOfLiteralType(callContext.argumentTypes[parameterIndex]));
- }
- }
- }
- }
- if (types.length) {
- var type = checker.getWidenedType(checker.getUnionType(types, 2 /* Subtype */));
- return isRestParameter ? checker.createArrayType(type) : type;
- }
- return undefined;
- }
- function getSignatureFromCallContext(callContext, checker) {
- var parameters = [];
- for (var i = 0; i < callContext.argumentTypes.length; i++) {
- var symbol = checker.createSymbol(1 /* FunctionScopedVariable */, ts.escapeLeadingUnderscores("arg" + i));
- symbol.type = checker.getWidenedType(checker.getBaseTypeOfLiteralType(callContext.argumentTypes[i]));
- parameters.push(symbol);
- }
- var returnType = getTypeFromUsageContext(callContext.returnType, checker) || checker.getVoidType();
- return checker.createSignature(/*declaration*/ undefined, /*typeParameters*/ undefined, /*thisParameter*/ undefined, parameters, returnType, /*typePredicate*/ undefined, callContext.argumentTypes.length, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
- }
- function addCandidateType(context, type) {
- if (type && !(type.flags & 1 /* Any */) && !(type.flags & 16384 /* Never */)) {
- (context.candidateTypes || (context.candidateTypes = [])).push(type);
- }
- }
- function hasCallContext(usageContext) {
- return usageContext && usageContext.callContexts;
- }
- })(InferFromReference || (InferFromReference = {}));
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- codefix.registerCodeFix({
- errorCodes: [ts.Diagnostics.A_namespace_style_import_cannot_be_called_or_constructed_and_will_cause_a_failure_at_runtime.code],
- getCodeActions: getActionsForInvalidImport
- });
- function getActionsForInvalidImport(context) {
- var sourceFile = context.sourceFile;
- // This is the whole import statement, eg:
- // import * as Bluebird from 'bluebird';
- // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- var node = ts.getTokenAtPosition(sourceFile, context.span.start, /*includeJsDocComment*/ false).parent;
- if (!ts.isImportDeclaration(node)) {
- // No import quick fix for import calls
- return [];
- }
- return getCodeFixesForImportDeclaration(context, node);
- }
- function getCodeFixesForImportDeclaration(context, node) {
- var sourceFile = ts.getSourceFileOfNode(node);
- var namespace = ts.getNamespaceDeclarationNode(node);
- var opts = context.program.getCompilerOptions();
- var variations = [];
- // import Bluebird from "bluebird";
- variations.push(createAction(context, sourceFile, node, codefix.makeImportDeclaration(namespace.name, /*namedImports*/ undefined, node.moduleSpecifier)));
- if (ts.getEmitModuleKind(opts) === ts.ModuleKind.CommonJS) {
- // import Bluebird = require("bluebird");
- variations.push(createAction(context, sourceFile, node, ts.createImportEqualsDeclaration(
- /*decorators*/ undefined,
- /*modifiers*/ undefined, namespace.name, ts.createExternalModuleReference(node.moduleSpecifier))));
- }
- return variations;
- }
- function createAction(context, sourceFile, node, replacement) {
- // TODO: GH#21246 Should be able to use `replaceNode`, but be sure to preserve comments (see `codeFixCalledES2015Import11.ts`)
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return t.replaceRange(sourceFile, { pos: node.getStart(), end: node.end }, replacement); });
- return {
- description: ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Replace_import_with_0), [changes[0].textChanges[0].newText]),
- changes: changes,
- };
- }
- codefix.registerCodeFix({
- errorCodes: [
- ts.Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures.code,
- ts.Diagnostics.Cannot_use_new_with_an_expression_whose_type_lacks_a_call_or_construct_signature.code,
- ],
- getCodeActions: getActionsForUsageOfInvalidImport
- });
- function getActionsForUsageOfInvalidImport(context) {
- var sourceFile = context.sourceFile;
- var targetKind = ts.Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures.code === context.errorCode ? 185 /* CallExpression */ : 186 /* NewExpression */;
- var node = ts.findAncestor(ts.getTokenAtPosition(sourceFile, context.span.start, /*includeJsDocComment*/ false), function (a) { return a.kind === targetKind && a.getStart() === context.span.start && a.getEnd() === (context.span.start + context.span.length); });
- if (!node) {
- return [];
- }
- var expr = node.expression;
- var type = context.program.getTypeChecker().getTypeAtLocation(expr);
- if (!(type.symbol && type.symbol.originatingImport)) {
- return [];
- }
- var fixes = [];
- var relatedImport = type.symbol.originatingImport;
- if (!ts.isImportCall(relatedImport)) {
- ts.addRange(fixes, getCodeFixesForImportDeclaration(context, relatedImport));
- }
- fixes.push({
- description: ts.getLocaleSpecificMessage(ts.Diagnostics.Use_synthetic_default_member),
- changes: ts.textChanges.ChangeTracker.with(context, function (t) { return t.replaceNode(sourceFile, expr, ts.createPropertyAccess(expr, "default"), {}); }),
- });
- return fixes;
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixIdAddDefiniteAssignmentAssertions = "addMissingPropertyDefiniteAssignmentAssertions";
- var fixIdAddUndefinedType = "addMissingPropertyUndefinedType";
- var fixIdAddInitializer = "addMissingPropertyInitializer";
- var errorCodes = [ts.Diagnostics.Property_0_has_no_initializer_and_is_not_definitely_assigned_in_the_constructor.code];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var propertyDeclaration = getPropertyDeclaration(context.sourceFile, context.span.start);
- if (!propertyDeclaration)
- return;
- var newLineCharacter = ts.getNewLineOrDefaultFromHost(context.host, context.formatContext.options);
- var result = [
- getActionForAddMissingUndefinedType(context, propertyDeclaration),
- getActionForAddMissingDefiniteAssignmentAssertion(context, propertyDeclaration, newLineCharacter)
- ];
- ts.append(result, getActionForAddMissingInitializer(context, propertyDeclaration, newLineCharacter));
- return result;
- },
- fixIds: [fixIdAddDefiniteAssignmentAssertions, fixIdAddUndefinedType, fixIdAddInitializer],
- getAllCodeActions: function (context) {
- var newLineCharacter = ts.getNewLineOrDefaultFromHost(context.host, context.formatContext.options);
- return codefix.codeFixAll(context, errorCodes, function (changes, diag) {
- var propertyDeclaration = getPropertyDeclaration(diag.file, diag.start);
- if (!propertyDeclaration)
- return;
- switch (context.fixId) {
- case fixIdAddDefiniteAssignmentAssertions:
- addDefiniteAssignmentAssertion(changes, diag.file, propertyDeclaration, newLineCharacter);
- break;
- case fixIdAddUndefinedType:
- addUndefinedType(changes, diag.file, propertyDeclaration);
- break;
- case fixIdAddInitializer:
- var checker = context.program.getTypeChecker();
- var initializer = getInitializer(checker, propertyDeclaration);
- if (!initializer)
- return;
- addInitializer(changes, diag.file, propertyDeclaration, initializer, newLineCharacter);
- break;
- default:
- ts.Debug.fail(JSON.stringify(context.fixId));
- }
- });
- },
- });
- function getPropertyDeclaration(sourceFile, pos) {
- var token = ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false);
- return ts.isIdentifier(token) ? ts.cast(token.parent, ts.isPropertyDeclaration) : undefined;
- }
- function getActionForAddMissingDefiniteAssignmentAssertion(context, propertyDeclaration, newLineCharacter) {
- var description = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Add_definite_assignment_assertion_to_property_0), [propertyDeclaration.getText()]);
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return addDefiniteAssignmentAssertion(t, context.sourceFile, propertyDeclaration, newLineCharacter); });
- return { description: description, changes: changes, fixId: fixIdAddDefiniteAssignmentAssertions };
- }
- function addDefiniteAssignmentAssertion(changeTracker, propertyDeclarationSourceFile, propertyDeclaration, newLineCharacter) {
- var property = ts.updateProperty(propertyDeclaration, propertyDeclaration.decorators, propertyDeclaration.modifiers, propertyDeclaration.name, ts.createToken(51 /* ExclamationToken */), propertyDeclaration.type, propertyDeclaration.initializer);
- changeTracker.replaceNode(propertyDeclarationSourceFile, propertyDeclaration, property, { suffix: newLineCharacter });
- }
- function getActionForAddMissingUndefinedType(context, propertyDeclaration) {
- var description = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Add_undefined_type_to_property_0), [propertyDeclaration.name.getText()]);
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return addUndefinedType(t, context.sourceFile, propertyDeclaration); });
- return { description: description, changes: changes, fixId: fixIdAddUndefinedType };
- }
- function addUndefinedType(changeTracker, propertyDeclarationSourceFile, propertyDeclaration) {
- var undefinedTypeNode = ts.createKeywordTypeNode(140 /* UndefinedKeyword */);
- var types = ts.isUnionTypeNode(propertyDeclaration.type) ? propertyDeclaration.type.types.concat(undefinedTypeNode) : [propertyDeclaration.type, undefinedTypeNode];
- changeTracker.replaceNode(propertyDeclarationSourceFile, propertyDeclaration.type, ts.createUnionTypeNode(types));
- }
- function getActionForAddMissingInitializer(context, propertyDeclaration, newLineCharacter) {
- var checker = context.program.getTypeChecker();
- var initializer = getInitializer(checker, propertyDeclaration);
- if (!initializer)
- return undefined;
- var description = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Add_initializer_to_property_0), [propertyDeclaration.name.getText()]);
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return addInitializer(t, context.sourceFile, propertyDeclaration, initializer, newLineCharacter); });
- return { description: description, changes: changes, fixId: fixIdAddInitializer };
- }
- function addInitializer(changeTracker, propertyDeclarationSourceFile, propertyDeclaration, initializer, newLineCharacter) {
- var property = ts.updateProperty(propertyDeclaration, propertyDeclaration.decorators, propertyDeclaration.modifiers, propertyDeclaration.name, propertyDeclaration.questionToken, propertyDeclaration.type, initializer);
- changeTracker.replaceNode(propertyDeclarationSourceFile, propertyDeclaration, property, { suffix: newLineCharacter });
- }
- function getInitializer(checker, propertyDeclaration) {
- return getDefaultValueFromType(checker, checker.getTypeFromTypeNode(propertyDeclaration.type));
- }
- function getDefaultValueFromType(checker, type) {
- if (type.flags & 2 /* String */) {
- return ts.createLiteral("");
- }
- else if (type.flags & 4 /* Number */) {
- return ts.createNumericLiteral("0");
- }
- else if (type.flags & 8 /* Boolean */) {
- return ts.createFalse();
- }
- else if (type.flags & 224 /* Literal */) {
- return ts.createLiteral(type.value);
- }
- else if (type.flags & 131072 /* Union */) {
- return ts.firstDefined(type.types, function (t) { return getDefaultValueFromType(checker, t); });
- }
- else if (ts.getObjectFlags(type) & 1 /* Class */) {
- var classDeclaration = ts.getClassLikeDeclarationOfSymbol(type.symbol);
- if (!classDeclaration || ts.hasModifier(classDeclaration, 128 /* Abstract */))
- return undefined;
- var constructorDeclaration = ts.find(classDeclaration.members, function (m) { return ts.isConstructorDeclaration(m) && !!m.body; });
- if (constructorDeclaration && constructorDeclaration.parameters.length)
- return undefined;
- return ts.createNew(ts.createIdentifier(type.symbol.name), /*typeArguments*/ undefined, /*argumentsArray*/ undefined);
- }
- return undefined;
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-/* @internal */
-var ts;
-(function (ts) {
- var codefix;
- (function (codefix) {
- var fixId = "useDefaultImport";
- var errorCodes = [ts.Diagnostics.Import_may_be_converted_to_a_default_import.code];
- codefix.registerCodeFix({
- errorCodes: errorCodes,
- getCodeActions: function (context) {
- var sourceFile = context.sourceFile, start = context.span.start;
- var info = getInfo(sourceFile, start);
- if (!info)
- return undefined;
- var description = ts.getLocaleSpecificMessage(ts.Diagnostics.Convert_to_default_import);
- var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return doChange(t, sourceFile, info); });
- return [{ description: description, changes: changes, fixId: fixId }];
- },
- fixIds: [fixId],
- getAllCodeActions: function (context) { return codefix.codeFixAll(context, errorCodes, function (changes, diag) {
- var info = getInfo(diag.file, diag.start);
- if (info)
- doChange(changes, diag.file, info);
- }); },
- });
- function getInfo(sourceFile, pos) {
- var name = ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false);
- if (!ts.isIdentifier(name))
- return undefined; // bad input
- var parent = name.parent;
- if (ts.isImportEqualsDeclaration(parent) && ts.isExternalModuleReference(parent.moduleReference)) {
- return { importNode: parent, name: name, moduleSpecifier: parent.moduleReference.expression };
- }
- else if (ts.isNamespaceImport(parent)) {
- var importNode = parent.parent.parent;
- return { importNode: importNode, name: name, moduleSpecifier: importNode.moduleSpecifier };
- }
- }
- function doChange(changes, sourceFile, info) {
- changes.replaceNode(sourceFile, info.importNode, codefix.makeImportDeclaration(info.name, /*namedImports*/ undefined, info.moduleSpecifier));
- }
- })(codefix = ts.codefix || (ts.codefix = {}));
-})(ts || (ts = {}));
-///
-///
-///
-///
-///
-///
-///
-///
-///
-///
-///
-///
-///
-///
-///
-///
-///
-///
-///
-///
-///
-///
-///
-///
-///
-///
-/* @internal */
-var ts;
-(function (ts) {
- var refactor;
- (function (refactor) {
- var extractSymbol;
- (function (extractSymbol) {
- var refactorName = "Extract Symbol";
- refactor.registerRefactor(refactorName, { getAvailableActions: getAvailableActions, getEditsForAction: getEditsForAction });
- /**
- * Compute the associated code actions
- * Exported for tests.
- */
- function getAvailableActions(context) {
- var rangeToExtract = getRangeToExtract(context.file, { start: context.startPosition, length: ts.getRefactorContextLength(context) });
- var targetRange = rangeToExtract.targetRange;
- if (targetRange === undefined) {
- return undefined;
- }
- var extractions = getPossibleExtractions(targetRange, context);
- if (extractions === undefined) {
- // No extractions possible
- return undefined;
- }
- var functionActions = [];
- var usedFunctionNames = ts.createMap();
- var constantActions = [];
- var usedConstantNames = ts.createMap();
- var i = 0;
- for (var _i = 0, extractions_1 = extractions; _i < extractions_1.length; _i++) {
- var _a = extractions_1[_i], functionExtraction = _a.functionExtraction, constantExtraction = _a.constantExtraction;
- // Skip these since we don't have a way to report errors yet
- if (functionExtraction.errors.length === 0) {
- // Don't issue refactorings with duplicated names.
- // Scopes come back in "innermost first" order, so extractions will
- // preferentially go into nearer scopes
- var description = functionExtraction.description;
- if (!usedFunctionNames.has(description)) {
- usedFunctionNames.set(description, true);
- functionActions.push({
- description: description,
- name: "function_scope_" + i
- });
- }
- }
- // Skip these since we don't have a way to report errors yet
- if (constantExtraction.errors.length === 0) {
- // Don't issue refactorings with duplicated names.
- // Scopes come back in "innermost first" order, so extractions will
- // preferentially go into nearer scopes
- var description = constantExtraction.description;
- if (!usedConstantNames.has(description)) {
- usedConstantNames.set(description, true);
- constantActions.push({
- description: description,
- name: "constant_scope_" + i
- });
- }
- }
- // *do* increment i anyway because we'll look for the i-th scope
- // later when actually doing the refactoring if the user requests it
- i++;
- }
- var infos = [];
- if (functionActions.length) {
- infos.push({
- name: refactorName,
- description: ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_function),
- actions: functionActions
- });
- }
- if (constantActions.length) {
- infos.push({
- name: refactorName,
- description: ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_constant),
- actions: constantActions
- });
- }
- return infos.length ? infos : undefined;
- }
- extractSymbol.getAvailableActions = getAvailableActions;
- /* Exported for tests */
- function getEditsForAction(context, actionName) {
- var rangeToExtract = getRangeToExtract(context.file, { start: context.startPosition, length: ts.getRefactorContextLength(context) });
- var targetRange = rangeToExtract.targetRange;
- var parsedFunctionIndexMatch = /^function_scope_(\d+)$/.exec(actionName);
- if (parsedFunctionIndexMatch) {
- var index = +parsedFunctionIndexMatch[1];
- ts.Debug.assert(isFinite(index), "Expected to parse a finite number from the function scope index");
- return getFunctionExtractionAtIndex(targetRange, context, index);
- }
- var parsedConstantIndexMatch = /^constant_scope_(\d+)$/.exec(actionName);
- if (parsedConstantIndexMatch) {
- var index = +parsedConstantIndexMatch[1];
- ts.Debug.assert(isFinite(index), "Expected to parse a finite number from the constant scope index");
- return getConstantExtractionAtIndex(targetRange, context, index);
- }
- ts.Debug.fail("Unrecognized action name");
- }
- extractSymbol.getEditsForAction = getEditsForAction;
- // Move these into diagnostic messages if they become user-facing
- var Messages;
- (function (Messages) {
- function createMessage(message) {
- return { message: message, code: 0, category: ts.DiagnosticCategory.Message, key: message };
- }
- Messages.cannotExtractRange = createMessage("Cannot extract range.");
- Messages.cannotExtractImport = createMessage("Cannot extract import statement.");
- Messages.cannotExtractSuper = createMessage("Cannot extract super call.");
- Messages.cannotExtractEmpty = createMessage("Cannot extract empty range.");
- Messages.expressionExpected = createMessage("expression expected.");
- Messages.uselessConstantType = createMessage("No reason to extract constant of type.");
- Messages.statementOrExpressionExpected = createMessage("Statement or expression expected.");
- Messages.cannotExtractRangeContainingConditionalBreakOrContinueStatements = createMessage("Cannot extract range containing conditional break or continue statements.");
- Messages.cannotExtractRangeContainingConditionalReturnStatement = createMessage("Cannot extract range containing conditional return statement.");
- Messages.cannotExtractRangeContainingLabeledBreakOrContinueStatementWithTargetOutsideOfTheRange = createMessage("Cannot extract range containing labeled break or continue with target outside of the range.");
- Messages.cannotExtractRangeThatContainsWritesToReferencesLocatedOutsideOfTheTargetRangeInGenerators = createMessage("Cannot extract range containing writes to references located outside of the target range in generators.");
- Messages.typeWillNotBeVisibleInTheNewScope = createMessage("Type will not visible in the new scope.");
- Messages.functionWillNotBeVisibleInTheNewScope = createMessage("Function will not visible in the new scope.");
- Messages.cannotExtractIdentifier = createMessage("Select more than a single identifier.");
- Messages.cannotExtractExportedEntity = createMessage("Cannot extract exported declaration");
- Messages.cannotWriteInExpression = createMessage("Cannot write back side-effects when extracting an expression");
- Messages.cannotExtractReadonlyPropertyInitializerOutsideConstructor = createMessage("Cannot move initialization of read-only class property outside of the constructor");
- Messages.cannotExtractAmbientBlock = createMessage("Cannot extract code from ambient contexts");
- Messages.cannotAccessVariablesFromNestedScopes = createMessage("Cannot access variables from nested scopes");
- Messages.cannotExtractToOtherFunctionLike = createMessage("Cannot extract method to a function-like scope that is not a function");
- Messages.cannotExtractToJSClass = createMessage("Cannot extract constant to a class scope in JS");
- Messages.cannotExtractToExpressionArrowFunction = createMessage("Cannot extract constant to an arrow function without a block");
- })(Messages = extractSymbol.Messages || (extractSymbol.Messages = {}));
- var RangeFacts;
- (function (RangeFacts) {
- RangeFacts[RangeFacts["None"] = 0] = "None";
- RangeFacts[RangeFacts["HasReturn"] = 1] = "HasReturn";
- RangeFacts[RangeFacts["IsGenerator"] = 2] = "IsGenerator";
- RangeFacts[RangeFacts["IsAsyncFunction"] = 4] = "IsAsyncFunction";
- RangeFacts[RangeFacts["UsesThis"] = 8] = "UsesThis";
- /**
- * The range is in a function which needs the 'static' modifier in a class
- */
- RangeFacts[RangeFacts["InStaticRegion"] = 16] = "InStaticRegion";
- })(RangeFacts || (RangeFacts = {}));
- /**
- * getRangeToExtract takes a span inside a text file and returns either an expression or an array
- * of statements representing the minimum set of nodes needed to extract the entire span. This
- * process may fail, in which case a set of errors is returned instead (these are currently
- * not shown to the user, but can be used by us diagnostically)
- */
- // exported only for tests
- function getRangeToExtract(sourceFile, span) {
- var length = span.length;
- if (length === 0) {
- return { errors: [ts.createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractEmpty)] };
- }
- // Walk up starting from the the start position until we find a non-SourceFile node that subsumes the selected span.
- // This may fail (e.g. you select two statements in the root of a source file)
- var start = getParentNodeInSpan(ts.getTokenAtPosition(sourceFile, span.start, /*includeJsDocComment*/ false), sourceFile, span);
- // Do the same for the ending position
- var end = getParentNodeInSpan(ts.findTokenOnLeftOfPosition(sourceFile, ts.textSpanEnd(span)), sourceFile, span);
- var declarations = [];
- // We'll modify these flags as we walk the tree to collect data
- // about what things need to be done as part of the extraction.
- var rangeFacts = RangeFacts.None;
- if (!start || !end) {
- // cannot find either start or end node
- return { errors: [ts.createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractRange)] };
- }
- if (start.parent !== end.parent) {
- // start and end nodes belong to different subtrees
- return { errors: [ts.createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractRange)] };
- }
- if (start !== end) {
- // start and end should be statements and parent should be either block or a source file
- if (!isBlockLike(start.parent)) {
- return { errors: [ts.createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractRange)] };
- }
- var statements = [];
- for (var _i = 0, _a = start.parent.statements; _i < _a.length; _i++) {
- var statement = _a[_i];
- if (statement === start || statements.length) {
- var errors_1 = checkNode(statement);
- if (errors_1) {
- return { errors: errors_1 };
- }
- statements.push(statement);
- }
- if (statement === end) {
- break;
- }
- }
- if (!statements.length) {
- // https://github.com/Microsoft/TypeScript/issues/20559
- // Ranges like [|case 1: break;|] will fail to populate `statements` because
- // they will never find `start` in `start.parent.statements`.
- // Consider: We could support ranges like [|case 1:|] by refining them to just
- // the expression.
- return { errors: [ts.createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractRange)] };
- }
- return { targetRange: { range: statements, facts: rangeFacts, declarations: declarations } };
- }
- if (ts.isReturnStatement(start) && !start.expression) {
- // Makes no sense to extract an expression-less return statement.
- return { errors: [ts.createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractRange)] };
- }
- // We have a single node (start)
- var node = refineNode(start);
- var errors = checkRootNode(node) || checkNode(node);
- if (errors) {
- return { errors: errors };
- }
- return { targetRange: { range: getStatementOrExpressionRange(node), facts: rangeFacts, declarations: declarations } };
- /**
- * Attempt to refine the extraction node (generally, by shrinking it) to produce better results.
- * @param node The unrefined extraction node.
- */
- function refineNode(node) {
- if (ts.isReturnStatement(node)) {
- if (node.expression) {
- return node.expression;
- }
- }
- else if (ts.isVariableStatement(node)) {
- var numInitializers = 0;
- var lastInitializer = void 0;
- for (var _i = 0, _a = node.declarationList.declarations; _i < _a.length; _i++) {
- var declaration = _a[_i];
- if (declaration.initializer) {
- numInitializers++;
- lastInitializer = declaration.initializer;
- }
- }
- if (numInitializers === 1) {
- return lastInitializer;
- }
- // No special handling if there are multiple initializers.
- }
- else if (ts.isVariableDeclaration(node)) {
- if (node.initializer) {
- return node.initializer;
- }
- }
- return node;
- }
- function checkRootNode(node) {
- if (ts.isIdentifier(ts.isExpressionStatement(node) ? node.expression : node)) {
- return [ts.createDiagnosticForNode(node, Messages.cannotExtractIdentifier)];
- }
- return undefined;
- }
- function checkForStaticContext(nodeToCheck, containingClass) {
- var current = nodeToCheck;
- while (current !== containingClass) {
- if (current.kind === 151 /* PropertyDeclaration */) {
- if (ts.hasModifier(current, 32 /* Static */)) {
- rangeFacts |= RangeFacts.InStaticRegion;
- }
- break;
- }
- else if (current.kind === 148 /* Parameter */) {
- var ctorOrMethod = ts.getContainingFunction(current);
- if (ctorOrMethod.kind === 154 /* Constructor */) {
- rangeFacts |= RangeFacts.InStaticRegion;
- }
- break;
- }
- else if (current.kind === 153 /* MethodDeclaration */) {
- if (ts.hasModifier(current, 32 /* Static */)) {
- rangeFacts |= RangeFacts.InStaticRegion;
- }
- }
- current = current.parent;
- }
- }
- // Verifies whether we can actually extract this node or not.
- function checkNode(nodeToCheck) {
- var PermittedJumps;
- (function (PermittedJumps) {
- PermittedJumps[PermittedJumps["None"] = 0] = "None";
- PermittedJumps[PermittedJumps["Break"] = 1] = "Break";
- PermittedJumps[PermittedJumps["Continue"] = 2] = "Continue";
- PermittedJumps[PermittedJumps["Return"] = 4] = "Return";
- })(PermittedJumps || (PermittedJumps = {}));
- // We believe it's true because the node is from the (unmodified) tree.
- ts.Debug.assert(nodeToCheck.pos <= nodeToCheck.end, "This failure could trigger https://github.com/Microsoft/TypeScript/issues/20809");
- // For understanding how skipTrivia functioned:
- ts.Debug.assert(!ts.positionIsSynthesized(nodeToCheck.pos), "This failure could trigger https://github.com/Microsoft/TypeScript/issues/20809");
- if (!ts.isStatement(nodeToCheck) && !(ts.isExpressionNode(nodeToCheck) && isExtractableExpression(nodeToCheck))) {
- return [ts.createDiagnosticForNode(nodeToCheck, Messages.statementOrExpressionExpected)];
- }
- if (nodeToCheck.flags & 2097152 /* Ambient */) {
- return [ts.createDiagnosticForNode(nodeToCheck, Messages.cannotExtractAmbientBlock)];
- }
- // If we're in a class, see whether we're in a static region (static property initializer, static method, class constructor parameter default)
- var containingClass = ts.getContainingClass(nodeToCheck);
- if (containingClass) {
- checkForStaticContext(nodeToCheck, containingClass);
- }
- var errors;
- var permittedJumps = 4 /* Return */;
- var seenLabels;
- visit(nodeToCheck);
- return errors;
- function visit(node) {
- if (errors) {
- // already found an error - can stop now
- return true;
- }
- if (ts.isDeclaration(node)) {
- var declaringNode = (node.kind === 230 /* VariableDeclaration */) ? node.parent.parent : node;
- if (ts.hasModifier(declaringNode, 1 /* Export */)) {
- (errors || (errors = [])).push(ts.createDiagnosticForNode(node, Messages.cannotExtractExportedEntity));
- return true;
- }
- declarations.push(node.symbol);
- }
- // Some things can't be extracted in certain situations
- switch (node.kind) {
- case 242 /* ImportDeclaration */:
- (errors || (errors = [])).push(ts.createDiagnosticForNode(node, Messages.cannotExtractImport));
- return true;
- case 97 /* SuperKeyword */:
- // For a super *constructor call*, we have to be extracting the entire class,
- // but a super *method call* simply implies a 'this' reference
- if (node.parent.kind === 185 /* CallExpression */) {
- // Super constructor call
- var containingClass_1 = ts.getContainingClass(node);
- if (containingClass_1.pos < span.start || containingClass_1.end >= (span.start + span.length)) {
- (errors || (errors = [])).push(ts.createDiagnosticForNode(node, Messages.cannotExtractSuper));
- return true;
- }
- }
- else {
- rangeFacts |= RangeFacts.UsesThis;
- }
- break;
- }
- if (!node || ts.isFunctionLikeDeclaration(node) || ts.isClassLike(node)) {
- switch (node.kind) {
- case 232 /* FunctionDeclaration */:
- case 233 /* ClassDeclaration */:
- if (ts.isSourceFile(node.parent) && node.parent.externalModuleIndicator === undefined) {
- // You cannot extract global declarations
- (errors || (errors = [])).push(ts.createDiagnosticForNode(node, Messages.functionWillNotBeVisibleInTheNewScope));
- }
- break;
- }
- // do not dive into functions or classes
- return false;
- }
- var savedPermittedJumps = permittedJumps;
- switch (node.kind) {
- case 215 /* IfStatement */:
- permittedJumps = 0 /* None */;
- break;
- case 228 /* TryStatement */:
- // forbid all jumps inside try blocks
- permittedJumps = 0 /* None */;
- break;
- case 211 /* Block */:
- if (node.parent && node.parent.kind === 228 /* TryStatement */ && node.parent.finallyBlock === node) {
- // allow unconditional returns from finally blocks
- permittedJumps = 4 /* Return */;
- }
- break;
- case 264 /* CaseClause */:
- // allow unlabeled break inside case clauses
- permittedJumps |= 1 /* Break */;
- break;
- default:
- if (ts.isIterationStatement(node, /*lookInLabeledStatements*/ false)) {
- // allow unlabeled break/continue inside loops
- permittedJumps |= 1 /* Break */ | 2 /* Continue */;
- }
- break;
- }
- switch (node.kind) {
- case 173 /* ThisType */:
- case 99 /* ThisKeyword */:
- rangeFacts |= RangeFacts.UsesThis;
- break;
- case 226 /* LabeledStatement */:
- {
- var label = node.label;
- (seenLabels || (seenLabels = [])).push(label.escapedText);
- ts.forEachChild(node, visit);
- seenLabels.pop();
- break;
- }
- case 222 /* BreakStatement */:
- case 221 /* ContinueStatement */:
- {
- var label = node.label;
- if (label) {
- if (!ts.contains(seenLabels, label.escapedText)) {
- // attempts to jump to label that is not in range to be extracted
- (errors || (errors = [])).push(ts.createDiagnosticForNode(node, Messages.cannotExtractRangeContainingLabeledBreakOrContinueStatementWithTargetOutsideOfTheRange));
- }
- }
- else {
- if (!(permittedJumps & (node.kind === 222 /* BreakStatement */ ? 1 /* Break */ : 2 /* Continue */))) {
- // attempt to break or continue in a forbidden context
- (errors || (errors = [])).push(ts.createDiagnosticForNode(node, Messages.cannotExtractRangeContainingConditionalBreakOrContinueStatements));
- }
- }
- break;
- }
- case 195 /* AwaitExpression */:
- rangeFacts |= RangeFacts.IsAsyncFunction;
- break;
- case 201 /* YieldExpression */:
- rangeFacts |= RangeFacts.IsGenerator;
- break;
- case 223 /* ReturnStatement */:
- if (permittedJumps & 4 /* Return */) {
- rangeFacts |= RangeFacts.HasReturn;
- }
- else {
- (errors || (errors = [])).push(ts.createDiagnosticForNode(node, Messages.cannotExtractRangeContainingConditionalReturnStatement));
- }
- break;
- default:
- ts.forEachChild(node, visit);
- break;
- }
- permittedJumps = savedPermittedJumps;
- }
- }
- }
- extractSymbol.getRangeToExtract = getRangeToExtract;
- function getStatementOrExpressionRange(node) {
- if (ts.isStatement(node)) {
- return [node];
- }
- else if (ts.isExpressionNode(node)) {
- // If our selection is the expression in an ExpressionStatement, expand
- // the selection to include the enclosing Statement (this stops us
- // from trying to care about the return value of the extracted function
- // and eliminates double semicolon insertion in certain scenarios)
- return ts.isExpressionStatement(node.parent) ? [node.parent] : node;
- }
- return undefined;
- }
- function isScope(node) {
- return ts.isFunctionLikeDeclaration(node) || ts.isSourceFile(node) || ts.isModuleBlock(node) || ts.isClassLike(node);
- }
- /**
- * Computes possible places we could extract the function into. For example,
- * you may be able to extract into a class method *or* local closure *or* namespace function,
- * depending on what's in the extracted body.
- */
- function collectEnclosingScopes(range) {
- var current = isReadonlyArray(range.range) ? ts.first(range.range) : range.range;
- if (range.facts & RangeFacts.UsesThis) {
- // if range uses this as keyword or as type inside the class then it can only be extracted to a method of the containing class
- var containingClass = ts.getContainingClass(current);
- if (containingClass) {
- var containingFunction = ts.findAncestor(current, ts.isFunctionLikeDeclaration);
- return containingFunction
- ? [containingFunction, containingClass]
- : [containingClass];
- }
- }
- var scopes = [];
- while (true) {
- current = current.parent;
- // A function parameter's initializer is actually in the outer scope, not the function declaration
- if (current.kind === 148 /* Parameter */) {
- // Skip all the way to the outer scope of the function that declared this parameter
- current = ts.findAncestor(current, function (parent) { return ts.isFunctionLikeDeclaration(parent); }).parent;
- }
- // We want to find the nearest parent where we can place an "equivalent" sibling to the node we're extracting out of.
- // Walk up to the closest parent of a place where we can logically put a sibling:
- // * Function declaration
- // * Class declaration or expression
- // * Module/namespace or source file
- if (isScope(current)) {
- scopes.push(current);
- if (current.kind === 272 /* SourceFile */) {
- return scopes;
- }
- }
- }
- }
- function getFunctionExtractionAtIndex(targetRange, context, requestedChangesIndex) {
- var _a = getPossibleExtractionsWorker(targetRange, context), scopes = _a.scopes, _b = _a.readsAndWrites, target = _b.target, usagesPerScope = _b.usagesPerScope, functionErrorsPerScope = _b.functionErrorsPerScope, exposedVariableDeclarations = _b.exposedVariableDeclarations;
- ts.Debug.assert(!functionErrorsPerScope[requestedChangesIndex].length, "The extraction went missing? How?");
- context.cancellationToken.throwIfCancellationRequested();
- return extractFunctionInScope(target, scopes[requestedChangesIndex], usagesPerScope[requestedChangesIndex], exposedVariableDeclarations, targetRange, context);
- }
- function getConstantExtractionAtIndex(targetRange, context, requestedChangesIndex) {
- var _a = getPossibleExtractionsWorker(targetRange, context), scopes = _a.scopes, _b = _a.readsAndWrites, target = _b.target, usagesPerScope = _b.usagesPerScope, constantErrorsPerScope = _b.constantErrorsPerScope, exposedVariableDeclarations = _b.exposedVariableDeclarations;
- ts.Debug.assert(!constantErrorsPerScope[requestedChangesIndex].length, "The extraction went missing? How?");
- ts.Debug.assert(exposedVariableDeclarations.length === 0, "Extract constant accepted a range containing a variable declaration?");
- context.cancellationToken.throwIfCancellationRequested();
- var expression = ts.isExpression(target)
- ? target
- : target.statements[0].expression;
- return extractConstantInScope(expression, scopes[requestedChangesIndex], usagesPerScope[requestedChangesIndex], targetRange.facts, context);
- }
- /**
- * Given a piece of text to extract ('targetRange'), computes a list of possible extractions.
- * Each returned ExtractResultForScope corresponds to a possible target scope and is either a set of changes
- * or an error explaining why we can't extract into that scope.
- */
- function getPossibleExtractions(targetRange, context) {
- var _a = getPossibleExtractionsWorker(targetRange, context), scopes = _a.scopes, _b = _a.readsAndWrites, functionErrorsPerScope = _b.functionErrorsPerScope, constantErrorsPerScope = _b.constantErrorsPerScope;
- // Need the inner type annotation to avoid https://github.com/Microsoft/TypeScript/issues/7547
- var extractions = scopes.map(function (scope, i) {
- var functionDescriptionPart = getDescriptionForFunctionInScope(scope);
- var constantDescriptionPart = getDescriptionForConstantInScope(scope);
- var scopeDescription = ts.isFunctionLikeDeclaration(scope)
- ? getDescriptionForFunctionLikeDeclaration(scope)
- : ts.isClassLike(scope)
- ? getDescriptionForClassLikeDeclaration(scope)
- : getDescriptionForModuleLikeDeclaration(scope);
- var functionDescription;
- var constantDescription;
- if (scopeDescription === 1 /* Global */) {
- functionDescription = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_0_in_1_scope), [functionDescriptionPart, "global"]);
- constantDescription = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_0_in_1_scope), [constantDescriptionPart, "global"]);
- }
- else if (scopeDescription === 0 /* Module */) {
- functionDescription = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_0_in_1_scope), [functionDescriptionPart, "module"]);
- constantDescription = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_0_in_1_scope), [constantDescriptionPart, "module"]);
- }
- else {
- functionDescription = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_0_in_1), [functionDescriptionPart, scopeDescription]);
- constantDescription = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_0_in_1), [constantDescriptionPart, scopeDescription]);
- }
- // Customize the phrasing for the innermost scope to increase clarity.
- if (i === 0 && !ts.isClassLike(scope)) {
- constantDescription = ts.formatStringFromArgs(ts.getLocaleSpecificMessage(ts.Diagnostics.Extract_to_0_in_enclosing_scope), [constantDescriptionPart]);
- }
- return {
- functionExtraction: {
- description: functionDescription,
- errors: functionErrorsPerScope[i],
- },
- constantExtraction: {
- description: constantDescription,
- errors: constantErrorsPerScope[i],
- },
- };
- });
- return extractions;
- }
- function getPossibleExtractionsWorker(targetRange, context) {
- var sourceFile = context.file;
- var scopes = collectEnclosingScopes(targetRange);
- var enclosingTextRange = getEnclosingTextRange(targetRange, sourceFile);
- var readsAndWrites = collectReadsAndWrites(targetRange, scopes, enclosingTextRange, sourceFile, context.program.getTypeChecker(), context.cancellationToken);
- return { scopes: scopes, readsAndWrites: readsAndWrites };
- }
- function getDescriptionForFunctionInScope(scope) {
- return ts.isFunctionLikeDeclaration(scope)
- ? "inner function"
- : ts.isClassLike(scope)
- ? "method"
- : "function";
- }
- function getDescriptionForConstantInScope(scope) {
- return ts.isClassLike(scope)
- ? "readonly field"
- : "constant";
- }
- function getDescriptionForFunctionLikeDeclaration(scope) {
- switch (scope.kind) {
- case 154 /* Constructor */:
- return "constructor";
- case 190 /* FunctionExpression */:
- case 232 /* FunctionDeclaration */:
- return scope.name
- ? "function '" + scope.name.text + "'"
- : "anonymous function";
- case 191 /* ArrowFunction */:
- return "arrow function";
- case 153 /* MethodDeclaration */:
- return "method '" + scope.name.getText();
- case 155 /* GetAccessor */:
- return "'get " + scope.name.getText() + "'";
- case 156 /* SetAccessor */:
- return "'set " + scope.name.getText() + "'";
- default:
- ts.Debug.assertNever(scope);
- }
- }
- function getDescriptionForClassLikeDeclaration(scope) {
- return scope.kind === 233 /* ClassDeclaration */
- ? scope.name ? "class '" + scope.name.text + "'" : "anonymous class declaration"
- : scope.name ? "class expression '" + scope.name.text + "'" : "anonymous class expression";
- }
- function getDescriptionForModuleLikeDeclaration(scope) {
- return scope.kind === 238 /* ModuleBlock */
- ? "namespace '" + scope.parent.name.getText() + "'"
- : scope.externalModuleIndicator ? 0 /* Module */ : 1 /* Global */;
- }
- var SpecialScope;
- (function (SpecialScope) {
- SpecialScope[SpecialScope["Module"] = 0] = "Module";
- SpecialScope[SpecialScope["Global"] = 1] = "Global";
- })(SpecialScope || (SpecialScope = {}));
- function getUniqueName(baseName, fileText) {
- var nameText = baseName;
- for (var i = 1; ts.stringContains(fileText, nameText); i++) {
- nameText = baseName + "_" + i;
- }
- return nameText;
- }
- /**
- * Result of 'extractRange' operation for a specific scope.
- * Stores either a list of changes that should be applied to extract a range or a list of errors
- */
- function extractFunctionInScope(node, scope, _a, exposedVariableDeclarations, range, context) {
- var usagesInScope = _a.usages, typeParameterUsages = _a.typeParameterUsages, substitutions = _a.substitutions;
- var checker = context.program.getTypeChecker();
- // Make a unique name for the extracted function
- var file = scope.getSourceFile();
- var functionNameText = getUniqueName(ts.isClassLike(scope) ? "newMethod" : "newFunction", file.text);
- var isJS = ts.isInJavaScriptFile(scope);
- var functionName = ts.createIdentifier(functionNameText);
- var returnType;
- var parameters = [];
- var callArguments = [];
- var writes;
- usagesInScope.forEach(function (usage, name) {
- var typeNode;
- if (!isJS) {
- var type = checker.getTypeOfSymbolAtLocation(usage.symbol, usage.node);
- // Widen the type so we don't emit nonsense annotations like "function fn(x: 3) {"
- type = checker.getBaseTypeOfLiteralType(type);
- typeNode = checker.typeToTypeNode(type, scope, 1 /* NoTruncation */);
- }
- var paramDecl = ts.createParameter(
- /*decorators*/ undefined,
- /*modifiers*/ undefined,
- /*dotDotDotToken*/ undefined,
- /*name*/ name,
- /*questionToken*/ undefined, typeNode);
- parameters.push(paramDecl);
- if (usage.usage === 2 /* Write */) {
- (writes || (writes = [])).push(usage);
- }
- callArguments.push(ts.createIdentifier(name));
- });
- var typeParametersAndDeclarations = ts.arrayFrom(typeParameterUsages.values()).map(function (type) { return ({ type: type, declaration: getFirstDeclaration(type) }); });
- var sortedTypeParametersAndDeclarations = typeParametersAndDeclarations.sort(compareTypesByDeclarationOrder);
- var typeParameters = sortedTypeParametersAndDeclarations.length === 0
- ? undefined
- : sortedTypeParametersAndDeclarations.map(function (t) { return t.declaration; });
- // Strictly speaking, we should check whether each name actually binds to the appropriate type
- // parameter. In cases of shadowing, they may not.
- var callTypeArguments = typeParameters !== undefined
- ? typeParameters.map(function (decl) { return ts.createTypeReferenceNode(decl.name, /*typeArguments*/ undefined); })
- : undefined;
- // Provide explicit return types for contextually-typed functions
- // to avoid problems when there are literal types present
- if (ts.isExpression(node) && !isJS) {
- var contextualType = checker.getContextualType(node);
- returnType = checker.typeToTypeNode(contextualType, scope, 1 /* NoTruncation */);
- }
- var _b = transformFunctionBody(node, exposedVariableDeclarations, writes, substitutions, !!(range.facts & RangeFacts.HasReturn)), body = _b.body, returnValueProperty = _b.returnValueProperty;
- ts.suppressLeadingAndTrailingTrivia(body);
- var newFunction;
- if (ts.isClassLike(scope)) {
- // always create private method in TypeScript files
- var modifiers = isJS ? [] : [ts.createToken(112 /* PrivateKeyword */)];
- if (range.facts & RangeFacts.InStaticRegion) {
- modifiers.push(ts.createToken(115 /* StaticKeyword */));
- }
- if (range.facts & RangeFacts.IsAsyncFunction) {
- modifiers.push(ts.createToken(120 /* AsyncKeyword */));
- }
- newFunction = ts.createMethod(
- /*decorators*/ undefined, modifiers.length ? modifiers : undefined, range.facts & RangeFacts.IsGenerator ? ts.createToken(39 /* AsteriskToken */) : undefined, functionName,
- /*questionToken*/ undefined, typeParameters, parameters, returnType, body);
- }
- else {
- newFunction = ts.createFunctionDeclaration(
- /*decorators*/ undefined, range.facts & RangeFacts.IsAsyncFunction ? [ts.createToken(120 /* AsyncKeyword */)] : undefined, range.facts & RangeFacts.IsGenerator ? ts.createToken(39 /* AsteriskToken */) : undefined, functionName, typeParameters, parameters, returnType, body);
- }
- var changeTracker = ts.textChanges.ChangeTracker.fromContext(context);
- var minInsertionPos = (isReadonlyArray(range.range) ? ts.last(range.range) : range.range).end;
- var nodeToInsertBefore = getNodeToInsertFunctionBefore(minInsertionPos, scope);
- if (nodeToInsertBefore) {
- changeTracker.insertNodeBefore(context.file, nodeToInsertBefore, newFunction, /*blankLineBetween*/ true);
- }
- else {
- changeTracker.insertNodeAtEndOfScope(context.file, scope, newFunction);
- }
- var newNodes = [];
- // replace range with function call
- var called = getCalledExpression(scope, range, functionNameText);
- var call = ts.createCall(called, callTypeArguments, // Note that no attempt is made to take advantage of type argument inference
- callArguments);
- if (range.facts & RangeFacts.IsGenerator) {
- call = ts.createYield(ts.createToken(39 /* AsteriskToken */), call);
- }
- if (range.facts & RangeFacts.IsAsyncFunction) {
- call = ts.createAwait(call);
- }
- if (exposedVariableDeclarations.length && !writes) {
- // No need to mix declarations and writes.
- // How could any variables be exposed if there's a return statement?
- ts.Debug.assert(!returnValueProperty);
- ts.Debug.assert(!(range.facts & RangeFacts.HasReturn));
- if (exposedVariableDeclarations.length === 1) {
- // Declaring exactly one variable: let x = newFunction();
- var variableDeclaration = exposedVariableDeclarations[0];
- newNodes.push(ts.createVariableStatement(
- /*modifiers*/ undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(ts.getSynthesizedDeepClone(variableDeclaration.name), /*type*/ ts.getSynthesizedDeepClone(variableDeclaration.type), /*initializer*/ call)], // TODO (acasey): test binding patterns
- variableDeclaration.parent.flags)));
- }
- else {
- // Declaring multiple variables / return properties:
- // let {x, y} = newFunction();
- var bindingElements = [];
- var typeElements = [];
- var commonNodeFlags = exposedVariableDeclarations[0].parent.flags;
- var sawExplicitType = false;
- for (var _i = 0, exposedVariableDeclarations_1 = exposedVariableDeclarations; _i < exposedVariableDeclarations_1.length; _i++) {
- var variableDeclaration = exposedVariableDeclarations_1[_i];
- bindingElements.push(ts.createBindingElement(
- /*dotDotDotToken*/ undefined,
- /*propertyName*/ undefined,
- /*name*/ ts.getSynthesizedDeepClone(variableDeclaration.name)));
- // Being returned through an object literal will have widened the type.
- var variableType = checker.typeToTypeNode(checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(variableDeclaration)), scope, 1 /* NoTruncation */);
- typeElements.push(ts.createPropertySignature(
- /*modifiers*/ undefined,
- /*name*/ variableDeclaration.symbol.name,
- /*questionToken*/ undefined,
- /*type*/ variableType,
- /*initializer*/ undefined));
- sawExplicitType = sawExplicitType || variableDeclaration.type !== undefined;
- commonNodeFlags = commonNodeFlags & variableDeclaration.parent.flags;
- }
- var typeLiteral = sawExplicitType ? ts.createTypeLiteralNode(typeElements) : undefined;
- if (typeLiteral) {
- ts.setEmitFlags(typeLiteral, 1 /* SingleLine */);
- }
- newNodes.push(ts.createVariableStatement(
- /*modifiers*/ undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(ts.createObjectBindingPattern(bindingElements),
- /*type*/ typeLiteral,
- /*initializer*/ call)], commonNodeFlags)));
- }
- }
- else if (exposedVariableDeclarations.length || writes) {
- if (exposedVariableDeclarations.length) {
- // CONSIDER: we're going to create one statement per variable, but we could actually preserve their original grouping.
- for (var _c = 0, exposedVariableDeclarations_2 = exposedVariableDeclarations; _c < exposedVariableDeclarations_2.length; _c++) {
- var variableDeclaration = exposedVariableDeclarations_2[_c];
- var flags = variableDeclaration.parent.flags;
- if (flags & 2 /* Const */) {
- flags = (flags & ~2 /* Const */) | 1 /* Let */;
- }
- newNodes.push(ts.createVariableStatement(
- /*modifiers*/ undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(variableDeclaration.symbol.name, getTypeDeepCloneUnionUndefined(variableDeclaration.type))], flags)));
- }
- }
- if (returnValueProperty) {
- // has both writes and return, need to create variable declaration to hold return value;
- newNodes.push(ts.createVariableStatement(
- /*modifiers*/ undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(returnValueProperty, getTypeDeepCloneUnionUndefined(returnType))], 1 /* Let */)));
- }
- var assignments = getPropertyAssignmentsForWritesAndVariableDeclarations(exposedVariableDeclarations, writes);
- if (returnValueProperty) {
- assignments.unshift(ts.createShorthandPropertyAssignment(returnValueProperty));
- }
- // propagate writes back
- if (assignments.length === 1) {
- // We would only have introduced a return value property if there had been
- // other assignments to make.
- ts.Debug.assert(!returnValueProperty);
- newNodes.push(ts.createStatement(ts.createAssignment(assignments[0].name, call)));
- if (range.facts & RangeFacts.HasReturn) {
- newNodes.push(ts.createReturn());
- }
- }
- else {
- // emit e.g.
- // { a, b, __return } = newFunction(a, b);
- // return __return;
- newNodes.push(ts.createStatement(ts.createAssignment(ts.createObjectLiteral(assignments), call)));
- if (returnValueProperty) {
- newNodes.push(ts.createReturn(ts.createIdentifier(returnValueProperty)));
- }
- }
- }
- else {
- if (range.facts & RangeFacts.HasReturn) {
- newNodes.push(ts.createReturn(call));
- }
- else if (isReadonlyArray(range.range)) {
- newNodes.push(ts.createStatement(call));
- }
- else {
- newNodes.push(call);
- }
- }
- if (isReadonlyArray(range.range)) {
- changeTracker.replaceNodeRangeWithNodes(context.file, ts.first(range.range), ts.last(range.range), newNodes);
- }
- else {
- changeTracker.replaceNodeWithNodes(context.file, range.range, newNodes);
- }
- var edits = changeTracker.getChanges();
- var renameRange = isReadonlyArray(range.range) ? ts.first(range.range) : range.range;
- var renameFilename = renameRange.getSourceFile().fileName;
- var renameLocation = getRenameLocation(edits, renameFilename, functionNameText, /*isDeclaredBeforeUse*/ false);
- return { renameFilename: renameFilename, renameLocation: renameLocation, edits: edits };
- function getTypeDeepCloneUnionUndefined(typeNode) {
- if (typeNode === undefined) {
- return undefined;
- }
- var clone = ts.getSynthesizedDeepClone(typeNode);
- var withoutParens = clone;
- while (ts.isParenthesizedTypeNode(withoutParens)) {
- withoutParens = withoutParens.type;
- }
- return ts.isUnionTypeNode(withoutParens) && ts.find(withoutParens.types, function (t) { return t.kind === 140 /* UndefinedKeyword */; })
- ? clone
- : ts.createUnionTypeNode([clone, ts.createKeywordTypeNode(140 /* UndefinedKeyword */)]);
- }
- }
- /**
- * Result of 'extractRange' operation for a specific scope.
- * Stores either a list of changes that should be applied to extract a range or a list of errors
- */
- function extractConstantInScope(node, scope, _a, rangeFacts, context) {
- var substitutions = _a.substitutions;
- var checker = context.program.getTypeChecker();
- // Make a unique name for the extracted variable
- var file = scope.getSourceFile();
- var localNameText = getUniqueName(ts.isClassLike(scope) ? "newProperty" : "newLocal", file.text);
- var isJS = ts.isInJavaScriptFile(scope);
- var variableType = isJS || !checker.isContextSensitive(node)
- ? undefined
- : checker.typeToTypeNode(checker.getContextualType(node), scope, 1 /* NoTruncation */);
- var initializer = transformConstantInitializer(node, substitutions);
- ts.suppressLeadingAndTrailingTrivia(initializer);
- var changeTracker = ts.textChanges.ChangeTracker.fromContext(context);
- if (ts.isClassLike(scope)) {
- ts.Debug.assert(!isJS); // See CannotExtractToJSClass
- var modifiers = [];
- modifiers.push(ts.createToken(112 /* PrivateKeyword */));
- if (rangeFacts & RangeFacts.InStaticRegion) {
- modifiers.push(ts.createToken(115 /* StaticKeyword */));
- }
- modifiers.push(ts.createToken(132 /* ReadonlyKeyword */));
- var newVariable = ts.createProperty(
- /*decorators*/ undefined, modifiers, localNameText,
- /*questionToken*/ undefined, variableType, initializer);
- var localReference = ts.createPropertyAccess(rangeFacts & RangeFacts.InStaticRegion
- ? ts.createIdentifier(scope.name.getText())
- : ts.createThis(), ts.createIdentifier(localNameText));
- // Declare
- var maxInsertionPos = node.pos;
- var nodeToInsertBefore = getNodeToInsertPropertyBefore(maxInsertionPos, scope);
- changeTracker.insertNodeBefore(context.file, nodeToInsertBefore, newVariable, /*blankLineBetween*/ true);
- // Consume
- changeTracker.replaceNode(context.file, node, localReference, ts.textChanges.useNonAdjustedPositions);
- }
- else {
- var newVariableDeclaration = ts.createVariableDeclaration(localNameText, variableType, initializer);
- // If the node is part of an initializer in a list of variable declarations, insert a new
- // variable declaration into the list (in case it depends on earlier ones).
- // CONSIDER: If the declaration list isn't const, we might want to split it into multiple
- // lists so that the newly extracted one can be const.
- var oldVariableDeclaration = getContainingVariableDeclarationIfInList(node, scope);
- if (oldVariableDeclaration) {
- // Declare
- // CONSIDER: could detect that each is on a separate line (See `extractConstant_VariableList_MultipleLines` in `extractConstants.ts`)
- changeTracker.insertNodeBefore(context.file, oldVariableDeclaration, newVariableDeclaration);
- // Consume
- var localReference = ts.createIdentifier(localNameText);
- changeTracker.replaceNode(context.file, node, localReference, ts.textChanges.useNonAdjustedPositions);
- }
- else if (node.parent.kind === 214 /* ExpressionStatement */ && scope === ts.findAncestor(node, isScope)) {
- // If the parent is an expression statement and the target scope is the immediately enclosing one,
- // replace the statement with the declaration.
- var newVariableStatement = ts.createVariableStatement(
- /*modifiers*/ undefined, ts.createVariableDeclarationList([newVariableDeclaration], 2 /* Const */));
- changeTracker.replaceNode(context.file, node.parent, newVariableStatement, ts.textChanges.useNonAdjustedPositions);
- }
- else {
- var newVariableStatement = ts.createVariableStatement(
- /*modifiers*/ undefined, ts.createVariableDeclarationList([newVariableDeclaration], 2 /* Const */));
- // Declare
- var nodeToInsertBefore = getNodeToInsertConstantBefore(node, scope);
- if (nodeToInsertBefore.pos === 0) {
- changeTracker.insertNodeAtTopOfFile(context.file, newVariableStatement, /*blankLineBetween*/ false);
- }
- else {
- changeTracker.insertNodeBefore(context.file, nodeToInsertBefore, newVariableStatement, /*blankLineBetween*/ false);
- }
- // Consume
- if (node.parent.kind === 214 /* ExpressionStatement */) {
- // If the parent is an expression statement, delete it.
- changeTracker.deleteNode(context.file, node.parent, ts.textChanges.useNonAdjustedPositions);
- }
- else {
- var localReference = ts.createIdentifier(localNameText);
- changeTracker.replaceNode(context.file, node, localReference, ts.textChanges.useNonAdjustedPositions);
- }
- }
- }
- var edits = changeTracker.getChanges();
- var renameFilename = node.getSourceFile().fileName;
- var renameLocation = getRenameLocation(edits, renameFilename, localNameText, /*isDeclaredBeforeUse*/ true);
- return { renameFilename: renameFilename, renameLocation: renameLocation, edits: edits };
- }
- function getContainingVariableDeclarationIfInList(node, scope) {
- var prevNode;
- while (node !== undefined && node !== scope) {
- if (ts.isVariableDeclaration(node) &&
- node.initializer === prevNode &&
- ts.isVariableDeclarationList(node.parent) &&
- node.parent.declarations.length > 1) {
- return node;
- }
- prevNode = node;
- node = node.parent;
- }
- }
- /**
- * @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, functionNameText, isDeclaredBeforeUse) {
- 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_3 = textChanges_2; _b < textChanges_3.length; _b++) {
- var change = textChanges_3[_b];
- var span_14 = change.span, newText = change.newText;
- var index = newText.indexOf(functionNameText);
- if (index !== -1) {
- lastPos = span_14.start + delta + index;
- // If the reference comes first, return immediately.
- if (!isDeclaredBeforeUse) {
- return lastPos;
- }
- }
- delta += newText.length - span_14.length;
- }
- }
- // If the declaration comes first, return the position of the last occurrence.
- ts.Debug.assert(isDeclaredBeforeUse);
- ts.Debug.assert(lastPos >= 0);
- return lastPos;
- }
- function getFirstDeclaration(type) {
- var firstDeclaration;
- var symbol = type.symbol;
- if (symbol && symbol.declarations) {
- for (var _i = 0, _a = symbol.declarations; _i < _a.length; _i++) {
- var declaration = _a[_i];
- if (firstDeclaration === undefined || declaration.pos < firstDeclaration.pos) {
- firstDeclaration = declaration;
- }
- }
- }
- return firstDeclaration;
- }
- function compareTypesByDeclarationOrder(_a, _b) {
- var type1 = _a.type, declaration1 = _a.declaration;
- var type2 = _b.type, declaration2 = _b.declaration;
- return ts.compareProperties(declaration1, declaration2, "pos", ts.compareValues)
- || ts.compareStringsCaseSensitive(type1.symbol ? type1.symbol.getName() : "", type2.symbol ? type2.symbol.getName() : "")
- || ts.compareValues(type1.id, type2.id);
- }
- function getCalledExpression(scope, range, functionNameText) {
- var functionReference = ts.createIdentifier(functionNameText);
- if (ts.isClassLike(scope)) {
- var lhs = range.facts & RangeFacts.InStaticRegion ? ts.createIdentifier(scope.name.text) : ts.createThis();
- return ts.createPropertyAccess(lhs, functionReference);
- }
- else {
- return functionReference;
- }
- }
- function transformFunctionBody(body, exposedVariableDeclarations, writes, substitutions, hasReturn) {
- var hasWritesOrVariableDeclarations = writes !== undefined || exposedVariableDeclarations.length > 0;
- if (ts.isBlock(body) && !hasWritesOrVariableDeclarations && substitutions.size === 0) {
- // already block, no declarations or writes to propagate back, no substitutions - can use node as is
- return { body: ts.createBlock(body.statements, /*multLine*/ true), returnValueProperty: undefined };
- }
- var returnValueProperty;
- var ignoreReturns = false;
- var statements = ts.createNodeArray(ts.isBlock(body) ? body.statements.slice(0) : [ts.isStatement(body) ? body : ts.createReturn(body)]);
- // rewrite body if either there are writes that should be propagated back via return statements or there are substitutions
- if (hasWritesOrVariableDeclarations || substitutions.size) {
- var rewrittenStatements = ts.visitNodes(statements, visitor).slice();
- if (hasWritesOrVariableDeclarations && !hasReturn && ts.isStatement(body)) {
- // add return at the end to propagate writes back in case if control flow falls out of the function body
- // it is ok to know that range has at least one return since it we only allow unconditional returns
- var assignments = getPropertyAssignmentsForWritesAndVariableDeclarations(exposedVariableDeclarations, writes);
- if (assignments.length === 1) {
- rewrittenStatements.push(ts.createReturn(assignments[0].name));
- }
- else {
- rewrittenStatements.push(ts.createReturn(ts.createObjectLiteral(assignments)));
- }
- }
- return { body: ts.createBlock(rewrittenStatements, /*multiLine*/ true), returnValueProperty: returnValueProperty };
- }
- else {
- return { body: ts.createBlock(statements, /*multiLine*/ true), returnValueProperty: undefined };
- }
- function visitor(node) {
- if (!ignoreReturns && node.kind === 223 /* ReturnStatement */ && hasWritesOrVariableDeclarations) {
- var assignments = getPropertyAssignmentsForWritesAndVariableDeclarations(exposedVariableDeclarations, writes);
- if (node.expression) {
- if (!returnValueProperty) {
- returnValueProperty = "__return";
- }
- assignments.unshift(ts.createPropertyAssignment(returnValueProperty, ts.visitNode(node.expression, visitor)));
- }
- if (assignments.length === 1) {
- return ts.createReturn(assignments[0].name);
- }
- else {
- return ts.createReturn(ts.createObjectLiteral(assignments));
- }
- }
- else {
- var oldIgnoreReturns = ignoreReturns;
- ignoreReturns = ignoreReturns || ts.isFunctionLikeDeclaration(node) || ts.isClassLike(node);
- var substitution = substitutions.get(ts.getNodeId(node).toString());
- var result = substitution ? ts.getSynthesizedDeepClone(substitution) : ts.visitEachChild(node, visitor, ts.nullTransformationContext);
- ignoreReturns = oldIgnoreReturns;
- return result;
- }
- }
- }
- function transformConstantInitializer(initializer, substitutions) {
- return substitutions.size
- ? visitor(initializer)
- : initializer;
- function visitor(node) {
- var substitution = substitutions.get(ts.getNodeId(node).toString());
- return substitution ? ts.getSynthesizedDeepClone(substitution) : ts.visitEachChild(node, visitor, ts.nullTransformationContext);
- }
- }
- function getStatementsOrClassElements(scope) {
- if (ts.isFunctionLikeDeclaration(scope)) {
- var body = scope.body;
- if (ts.isBlock(body)) {
- return body.statements;
- }
- }
- else if (ts.isModuleBlock(scope) || ts.isSourceFile(scope)) {
- return scope.statements;
- }
- else if (ts.isClassLike(scope)) {
- return scope.members;
- }
- else {
- ts.assertTypeIsNever(scope);
- }
- return ts.emptyArray;
- }
- /**
- * If `scope` contains a function after `minPos`, then return the first such function.
- * Otherwise, return `undefined`.
- */
- function getNodeToInsertFunctionBefore(minPos, scope) {
- return ts.find(getStatementsOrClassElements(scope), function (child) {
- return child.pos >= minPos && ts.isFunctionLikeDeclaration(child) && !ts.isConstructorDeclaration(child);
- });
- }
- function getNodeToInsertPropertyBefore(maxPos, scope) {
- var members = scope.members;
- ts.Debug.assert(members.length > 0); // There must be at least one child, since we extracted from one.
- var prevMember;
- var allProperties = true;
- for (var _i = 0, members_6 = members; _i < members_6.length; _i++) {
- var member = members_6[_i];
- if (member.pos > maxPos) {
- return prevMember || members[0];
- }
- if (allProperties && !ts.isPropertyDeclaration(member)) {
- // If it is non-vacuously true that all preceding members are properties,
- // insert before the current member (i.e. at the end of the list of properties).
- if (prevMember !== undefined) {
- return member;
- }
- allProperties = false;
- }
- prevMember = member;
- }
- ts.Debug.assert(prevMember !== undefined); // If the loop didn't return, then it did set prevMember.
- return prevMember;
- }
- function getNodeToInsertConstantBefore(node, scope) {
- ts.Debug.assert(!ts.isClassLike(scope));
- var prevScope;
- for (var curr = node; curr !== scope; curr = curr.parent) {
- if (isScope(curr)) {
- prevScope = curr;
- }
- }
- for (var curr = (prevScope || node).parent;; curr = curr.parent) {
- if (isBlockLike(curr)) {
- var prevStatement = void 0;
- for (var _i = 0, _a = curr.statements; _i < _a.length; _i++) {
- var statement = _a[_i];
- if (statement.pos > node.pos) {
- break;
- }
- prevStatement = statement;
- }
- if (!prevStatement && ts.isCaseClause(curr)) {
- // We must have been in the expression of the case clause.
- ts.Debug.assert(ts.isSwitchStatement(curr.parent.parent));
- return curr.parent.parent;
- }
- // There must be at least one statement since we started in one.
- ts.Debug.assert(prevStatement !== undefined);
- return prevStatement;
- }
- if (curr === scope) {
- ts.Debug.fail("Didn't encounter a block-like before encountering scope");
- break;
- }
- }
- }
- function getPropertyAssignmentsForWritesAndVariableDeclarations(exposedVariableDeclarations, writes) {
- var variableAssignments = ts.map(exposedVariableDeclarations, function (v) { return ts.createShorthandPropertyAssignment(v.symbol.name); });
- var writeAssignments = ts.map(writes, function (w) { return ts.createShorthandPropertyAssignment(w.symbol.name); });
- return variableAssignments === undefined
- ? writeAssignments
- : writeAssignments === undefined
- ? variableAssignments
- : variableAssignments.concat(writeAssignments);
- }
- function isReadonlyArray(v) {
- return ts.isArray(v);
- }
- /**
- * Produces a range that spans the entirety of nodes, given a selection
- * that might start/end in the middle of nodes.
- *
- * For example, when the user makes a selection like this
- * v---v
- * var someThing = foo + bar;
- * this returns ^-------^
- */
- function getEnclosingTextRange(targetRange, sourceFile) {
- return isReadonlyArray(targetRange.range)
- ? { pos: ts.first(targetRange.range).getStart(sourceFile), end: ts.last(targetRange.range).getEnd() }
- : targetRange.range;
- }
- var Usage;
- (function (Usage) {
- // value should be passed to extracted method
- Usage[Usage["Read"] = 1] = "Read";
- // value should be passed to extracted method and propagated back
- Usage[Usage["Write"] = 2] = "Write";
- })(Usage || (Usage = {}));
- function collectReadsAndWrites(targetRange, scopes, enclosingTextRange, sourceFile, checker, cancellationToken) {
- var allTypeParameterUsages = ts.createMap(); // Key is type ID
- var usagesPerScope = [];
- var substitutionsPerScope = [];
- var functionErrorsPerScope = [];
- var constantErrorsPerScope = [];
- var visibleDeclarationsInExtractedRange = [];
- var exposedVariableSymbolSet = ts.createMap(); // Key is symbol ID
- var exposedVariableDeclarations = [];
- var firstExposedNonVariableDeclaration;
- var expression = !isReadonlyArray(targetRange.range)
- ? targetRange.range
- : targetRange.range.length === 1 && ts.isExpressionStatement(targetRange.range[0])
- ? targetRange.range[0].expression
- : undefined;
- var expressionDiagnostic;
- if (expression === undefined) {
- var statements = targetRange.range;
- var start = ts.first(statements).getStart();
- var end = ts.last(statements).end;
- expressionDiagnostic = ts.createFileDiagnostic(sourceFile, start, end - start, Messages.expressionExpected);
- }
- else if (checker.getTypeAtLocation(expression).flags & (2048 /* Void */ | 16384 /* Never */)) {
- expressionDiagnostic = ts.createDiagnosticForNode(expression, Messages.uselessConstantType);
- }
- // initialize results
- for (var _i = 0, scopes_1 = scopes; _i < scopes_1.length; _i++) {
- var scope = scopes_1[_i];
- usagesPerScope.push({ usages: ts.createMap(), typeParameterUsages: ts.createMap(), substitutions: ts.createMap() });
- substitutionsPerScope.push(ts.createMap());
- functionErrorsPerScope.push(ts.isFunctionLikeDeclaration(scope) && scope.kind !== 232 /* FunctionDeclaration */
- ? [ts.createDiagnosticForNode(scope, Messages.cannotExtractToOtherFunctionLike)]
- : []);
- var constantErrors = [];
- if (expressionDiagnostic) {
- constantErrors.push(expressionDiagnostic);
- }
- if (ts.isClassLike(scope) && ts.isInJavaScriptFile(scope)) {
- constantErrors.push(ts.createDiagnosticForNode(scope, Messages.cannotExtractToJSClass));
- }
- if (ts.isArrowFunction(scope) && !ts.isBlock(scope.body)) {
- // TODO (https://github.com/Microsoft/TypeScript/issues/18924): allow this
- constantErrors.push(ts.createDiagnosticForNode(scope, Messages.cannotExtractToExpressionArrowFunction));
- }
- constantErrorsPerScope.push(constantErrors);
- }
- var seenUsages = ts.createMap();
- var target = isReadonlyArray(targetRange.range) ? ts.createBlock(targetRange.range) : targetRange.range;
- var unmodifiedNode = isReadonlyArray(targetRange.range) ? ts.first(targetRange.range) : targetRange.range;
- var inGenericContext = isInGenericContext(unmodifiedNode);
- collectUsages(target);
- // Unfortunately, this code takes advantage of the knowledge that the generated method
- // will use the contextual type of an expression as the return type of the extracted
- // method (and will therefore "use" all the types involved).
- if (inGenericContext && !isReadonlyArray(targetRange.range)) {
- var contextualType = checker.getContextualType(targetRange.range);
- recordTypeParameterUsages(contextualType);
- }
- if (allTypeParameterUsages.size > 0) {
- var seenTypeParameterUsages = ts.createMap(); // Key is type ID
- var i_1 = 0;
- for (var curr = unmodifiedNode; curr !== undefined && i_1 < scopes.length; curr = curr.parent) {
- if (curr === scopes[i_1]) {
- // Copy current contents of seenTypeParameterUsages into scope.
- seenTypeParameterUsages.forEach(function (typeParameter, id) {
- usagesPerScope[i_1].typeParameterUsages.set(id, typeParameter);
- });
- i_1++;
- }
- // Note that we add the current node's type parameters *after* updating the corresponding scope.
- if (ts.isDeclarationWithTypeParameters(curr) && curr.typeParameters) {
- for (var _a = 0, _b = curr.typeParameters; _a < _b.length; _a++) {
- var typeParameterDecl = _b[_a];
- var typeParameter = checker.getTypeAtLocation(typeParameterDecl);
- if (allTypeParameterUsages.has(typeParameter.id.toString())) {
- seenTypeParameterUsages.set(typeParameter.id.toString(), typeParameter);
- }
- }
- }
- }
- // If we didn't get through all the scopes, then there were some that weren't in our
- // parent chain (impossible at time of writing). A conservative solution would be to
- // copy allTypeParameterUsages into all remaining scopes.
- ts.Debug.assert(i_1 === scopes.length);
- }
- // If there are any declarations in the extracted block that are used in the same enclosing
- // lexical scope, we can't move the extraction "up" as those declarations will become unreachable
- if (visibleDeclarationsInExtractedRange.length) {
- var containingLexicalScopeOfExtraction = ts.isBlockScope(scopes[0], scopes[0].parent)
- ? scopes[0]
- : ts.getEnclosingBlockScopeContainer(scopes[0]);
- ts.forEachChild(containingLexicalScopeOfExtraction, checkForUsedDeclarations);
- }
- var _loop_11 = function (i) {
- var scopeUsages = usagesPerScope[i];
- // Special case: in the innermost scope, all usages are available.
- // (The computed value reflects the value at the top-level of the scope, but the
- // local will actually be declared at the same level as the extracted expression).
- if (i > 0 && (scopeUsages.usages.size > 0 || scopeUsages.typeParameterUsages.size > 0)) {
- var errorNode = isReadonlyArray(targetRange.range) ? targetRange.range[0] : targetRange.range;
- constantErrorsPerScope[i].push(ts.createDiagnosticForNode(errorNode, Messages.cannotAccessVariablesFromNestedScopes));
- }
- var hasWrite = false;
- var readonlyClassPropertyWrite;
- usagesPerScope[i].usages.forEach(function (value) {
- if (value.usage === 2 /* Write */) {
- hasWrite = true;
- if (value.symbol.flags & 106500 /* ClassMember */ &&
- value.symbol.valueDeclaration &&
- ts.hasModifier(value.symbol.valueDeclaration, 64 /* Readonly */)) {
- readonlyClassPropertyWrite = value.symbol.valueDeclaration;
- }
- }
- });
- // If an expression was extracted, then there shouldn't have been any variable declarations.
- ts.Debug.assert(isReadonlyArray(targetRange.range) || exposedVariableDeclarations.length === 0);
- if (hasWrite && !isReadonlyArray(targetRange.range)) {
- var diag = ts.createDiagnosticForNode(targetRange.range, Messages.cannotWriteInExpression);
- functionErrorsPerScope[i].push(diag);
- constantErrorsPerScope[i].push(diag);
- }
- else if (readonlyClassPropertyWrite && i > 0) {
- var diag = ts.createDiagnosticForNode(readonlyClassPropertyWrite, Messages.cannotExtractReadonlyPropertyInitializerOutsideConstructor);
- functionErrorsPerScope[i].push(diag);
- constantErrorsPerScope[i].push(diag);
- }
- else if (firstExposedNonVariableDeclaration) {
- var diag = ts.createDiagnosticForNode(firstExposedNonVariableDeclaration, Messages.cannotExtractExportedEntity);
- functionErrorsPerScope[i].push(diag);
- constantErrorsPerScope[i].push(diag);
- }
- };
- for (var i = 0; i < scopes.length; i++) {
- _loop_11(i);
- }
- return { target: target, usagesPerScope: usagesPerScope, functionErrorsPerScope: functionErrorsPerScope, constantErrorsPerScope: constantErrorsPerScope, exposedVariableDeclarations: exposedVariableDeclarations };
- function hasTypeParameters(node) {
- return ts.isDeclarationWithTypeParameters(node) &&
- node.typeParameters !== undefined &&
- node.typeParameters.length > 0;
- }
- function isInGenericContext(node) {
- for (; node; node = node.parent) {
- if (hasTypeParameters(node)) {
- return true;
- }
- }
- return false;
- }
- function recordTypeParameterUsages(type) {
- // PERF: This is potentially very expensive. `type` could be a library type with
- // a lot of properties, each of which the walker will visit. Unfortunately, the
- // solution isn't as trivial as filtering to user types because of (e.g.) Array.
- var symbolWalker = checker.getSymbolWalker(function () { return (cancellationToken.throwIfCancellationRequested(), true); });
- var visitedTypes = symbolWalker.walkType(type).visitedTypes;
- for (var _i = 0, visitedTypes_1 = visitedTypes; _i < visitedTypes_1.length; _i++) {
- var visitedType = visitedTypes_1[_i];
- if (visitedType.flags & 32768 /* TypeParameter */) {
- allTypeParameterUsages.set(visitedType.id.toString(), visitedType);
- }
- }
- }
- function collectUsages(node, valueUsage) {
- if (valueUsage === void 0) { valueUsage = 1 /* Read */; }
- if (inGenericContext) {
- var type = checker.getTypeAtLocation(node);
- recordTypeParameterUsages(type);
- }
- if (ts.isDeclaration(node) && node.symbol) {
- visibleDeclarationsInExtractedRange.push(node);
- }
- if (ts.isAssignmentExpression(node)) {
- // use 'write' as default usage for values
- collectUsages(node.left, 2 /* Write */);
- collectUsages(node.right);
- }
- else if (ts.isUnaryExpressionWithWrite(node)) {
- collectUsages(node.operand, 2 /* Write */);
- }
- else if (ts.isPropertyAccessExpression(node) || ts.isElementAccessExpression(node)) {
- // use 'write' as default usage for values
- ts.forEachChild(node, collectUsages);
- }
- else if (ts.isIdentifier(node)) {
- if (!node.parent) {
- return;
- }
- if (ts.isQualifiedName(node.parent) && node !== node.parent.left) {
- return;
- }
- if (ts.isPropertyAccessExpression(node.parent) && node !== node.parent.expression) {
- return;
- }
- recordUsage(node, valueUsage, /*isTypeNode*/ ts.isPartOfTypeNode(node));
- }
- else {
- ts.forEachChild(node, collectUsages);
- }
- }
- function recordUsage(n, usage, isTypeNode) {
- var symbolId = recordUsagebySymbol(n, usage, isTypeNode);
- if (symbolId) {
- for (var i = 0; i < scopes.length; i++) {
- // push substitution from map to map to simplify rewriting
- var substitution = substitutionsPerScope[i].get(symbolId);
- if (substitution) {
- usagesPerScope[i].substitutions.set(ts.getNodeId(n).toString(), substitution);
- }
- }
- }
- }
- function recordUsagebySymbol(identifier, usage, isTypeName) {
- var symbol = getSymbolReferencedByIdentifier(identifier);
- if (!symbol) {
- // cannot find symbol - do nothing
- return undefined;
- }
- var symbolId = ts.getSymbolId(symbol).toString();
- var lastUsage = seenUsages.get(symbolId);
- // there are two kinds of value usages
- // - reads - if range contains a read from the value located outside of the range then value should be passed as a parameter
- // - writes - if range contains a write to a value located outside the range the value should be passed as a parameter and
- // returned as a return value
- // 'write' case is a superset of 'read' so if we already have processed 'write' of some symbol there is not need to handle 'read'
- // since all information is already recorded
- if (lastUsage && lastUsage >= usage) {
- return symbolId;
- }
- seenUsages.set(symbolId, usage);
- if (lastUsage) {
- // if we get here this means that we are trying to handle 'write' and 'read' was already processed
- // walk scopes and update existing records.
- for (var _i = 0, usagesPerScope_1 = usagesPerScope; _i < usagesPerScope_1.length; _i++) {
- var perScope = usagesPerScope_1[_i];
- var prevEntry = perScope.usages.get(identifier.text);
- if (prevEntry) {
- perScope.usages.set(identifier.text, { usage: usage, symbol: symbol, node: identifier });
- }
- }
- return symbolId;
- }
- // find first declaration in this file
- var decls = symbol.getDeclarations();
- var declInFile = decls && ts.find(decls, function (d) { return d.getSourceFile() === sourceFile; });
- if (!declInFile) {
- return undefined;
- }
- if (ts.rangeContainsStartEnd(enclosingTextRange, declInFile.getStart(), declInFile.end)) {
- // declaration is located in range to be extracted - do nothing
- return undefined;
- }
- if (targetRange.facts & RangeFacts.IsGenerator && usage === 2 /* Write */) {
- // this is write to a reference located outside of the target scope and range is extracted into generator
- // currently this is unsupported scenario
- var diag = ts.createDiagnosticForNode(identifier, Messages.cannotExtractRangeThatContainsWritesToReferencesLocatedOutsideOfTheTargetRangeInGenerators);
- for (var _a = 0, functionErrorsPerScope_1 = functionErrorsPerScope; _a < functionErrorsPerScope_1.length; _a++) {
- var errors = functionErrorsPerScope_1[_a];
- errors.push(diag);
- }
- for (var _b = 0, constantErrorsPerScope_1 = constantErrorsPerScope; _b < constantErrorsPerScope_1.length; _b++) {
- var errors = constantErrorsPerScope_1[_b];
- errors.push(diag);
- }
- }
- for (var i = 0; i < scopes.length; i++) {
- var scope = scopes[i];
- var resolvedSymbol = checker.resolveName(symbol.name, scope, symbol.flags, /*excludeGlobals*/ false);
- if (resolvedSymbol === symbol) {
- continue;
- }
- if (!substitutionsPerScope[i].has(symbolId)) {
- var substitution = tryReplaceWithQualifiedNameOrPropertyAccess(symbol.exportSymbol || symbol, scope, isTypeName);
- if (substitution) {
- substitutionsPerScope[i].set(symbolId, substitution);
- }
- else if (isTypeName) {
- // If the symbol is a type parameter that won't be in scope, we'll pass it as a type argument
- // so there's no problem.
- if (!(symbol.flags & 262144 /* TypeParameter */)) {
- var diag = ts.createDiagnosticForNode(identifier, Messages.typeWillNotBeVisibleInTheNewScope);
- functionErrorsPerScope[i].push(diag);
- constantErrorsPerScope[i].push(diag);
- }
- }
- else {
- usagesPerScope[i].usages.set(identifier.text, { usage: usage, symbol: symbol, node: identifier });
- }
- }
- }
- return symbolId;
- }
- function checkForUsedDeclarations(node) {
- // If this node is entirely within the original extraction range, we don't need to do anything.
- if (node === targetRange.range || (isReadonlyArray(targetRange.range) && targetRange.range.indexOf(node) >= 0)) {
- return;
- }
- // Otherwise check and recurse.
- var sym = ts.isIdentifier(node)
- ? getSymbolReferencedByIdentifier(node)
- : checker.getSymbolAtLocation(node);
- if (sym) {
- var decl = ts.find(visibleDeclarationsInExtractedRange, function (d) { return d.symbol === sym; });
- if (decl) {
- if (ts.isVariableDeclaration(decl)) {
- var idString = decl.symbol.id.toString();
- if (!exposedVariableSymbolSet.has(idString)) {
- exposedVariableDeclarations.push(decl);
- exposedVariableSymbolSet.set(idString, true);
- }
- }
- else {
- // CONSIDER: this includes binding elements, which we could
- // expose in the same way as variables.
- firstExposedNonVariableDeclaration = firstExposedNonVariableDeclaration || decl;
- }
- }
- }
- ts.forEachChild(node, checkForUsedDeclarations);
- }
- /**
- * Return the symbol referenced by an identifier (even if it declares a different symbol).
- */
- function getSymbolReferencedByIdentifier(identifier) {
- // If the identifier is both a property name and its value, we're only interested in its value
- // (since the name is a declaration and will be included in the extracted range).
- return identifier.parent && ts.isShorthandPropertyAssignment(identifier.parent) && identifier.parent.name === identifier
- ? checker.getShorthandAssignmentValueSymbol(identifier.parent)
- : checker.getSymbolAtLocation(identifier);
- }
- function tryReplaceWithQualifiedNameOrPropertyAccess(symbol, scopeDecl, isTypeNode) {
- if (!symbol) {
- return undefined;
- }
- var decls = symbol.getDeclarations();
- if (decls && decls.some(function (d) { return d.parent === scopeDecl; })) {
- return ts.createIdentifier(symbol.name);
- }
- var prefix = tryReplaceWithQualifiedNameOrPropertyAccess(symbol.parent, scopeDecl, isTypeNode);
- if (prefix === undefined) {
- return undefined;
- }
- return isTypeNode
- ? ts.createQualifiedName(prefix, ts.createIdentifier(symbol.name))
- : ts.createPropertyAccess(prefix, symbol.name);
- }
- }
- 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;
- }
- }
- function spanContainsNode(span, node, file) {
- return ts.textSpanContainsPosition(span, node.getStart(file)) &&
- node.getEnd() <= ts.textSpanEnd(span);
- }
- /**
- * Computes whether or not a node represents an expression in a position where it could
- * be extracted.
- * The isExpression() in utilities.ts returns some false positives we need to handle,
- * such as `import x from 'y'` -- the 'y' is a StringLiteral but is *not* an expression
- * in the sense of something that you could extract on
- */
- function isExtractableExpression(node) {
- switch (node.parent.kind) {
- case 271 /* EnumMember */:
- return false;
- }
- switch (node.kind) {
- case 9 /* StringLiteral */:
- return node.parent.kind !== 242 /* ImportDeclaration */ &&
- node.parent.kind !== 246 /* ImportSpecifier */;
- case 202 /* SpreadElement */:
- case 178 /* ObjectBindingPattern */:
- case 180 /* BindingElement */:
- return false;
- case 71 /* Identifier */:
- return node.parent.kind !== 180 /* BindingElement */ &&
- node.parent.kind !== 246 /* ImportSpecifier */ &&
- node.parent.kind !== 250 /* ExportSpecifier */;
- }
- return true;
- }
- function isBlockLike(node) {
- switch (node.kind) {
- case 211 /* Block */:
- case 272 /* SourceFile */:
- case 238 /* ModuleBlock */:
- case 264 /* CaseClause */:
- return true;
- default:
- return false;
- }
- }
- })(extractSymbol = refactor.extractSymbol || (refactor.extractSymbol = {}));
- })(refactor = ts.refactor || (ts.refactor = {}));
-})(ts || (ts = {}));
-///
-///
-///
-///
-///
-///
-///
-///
-///
-///
-///
-///
-///
-///
-///
-///
-///
-///
-///
-///
-///
-///
-///
-///
-///
-///
-///
-///
-///
-///
-///
-///
-var ts;
-(function (ts) {
- /** The version of the language service API */
- ts.servicesVersion = "0.7";
- function createNode(kind, pos, end, parent) {
- var node = ts.isNodeKind(kind) ? new NodeObject(kind, pos, end) :
- kind === 71 /* Identifier */ ? new IdentifierObject(71 /* Identifier */, pos, end) :
- new TokenObject(kind, pos, end);
- node.parent = parent;
- node.flags = parent.flags & 6387712 /* ContextFlags */;
- return node;
- }
- var NodeObject = /** @class */ (function () {
- function NodeObject(kind, pos, end) {
- this.pos = pos;
- this.end = end;
- this.flags = 0 /* None */;
- this.transformFlags = undefined;
- this.parent = undefined;
- this.kind = kind;
- }
- NodeObject.prototype.assertHasRealPosition = function (message) {
- // tslint:disable-next-line:debug-assert
- ts.Debug.assert(!ts.positionIsSynthesized(this.pos) && !ts.positionIsSynthesized(this.end), message || "Node must have a real position for this operation");
- };
- NodeObject.prototype.getSourceFile = function () {
- return ts.getSourceFileOfNode(this);
- };
- NodeObject.prototype.getStart = function (sourceFile, includeJsDocComment) {
- this.assertHasRealPosition();
- return ts.getTokenPosOfNode(this, sourceFile, includeJsDocComment);
- };
- NodeObject.prototype.getFullStart = function () {
- this.assertHasRealPosition();
- return this.pos;
- };
- NodeObject.prototype.getEnd = function () {
- this.assertHasRealPosition();
- return this.end;
- };
- NodeObject.prototype.getWidth = function (sourceFile) {
- this.assertHasRealPosition();
- return this.getEnd() - this.getStart(sourceFile);
- };
- NodeObject.prototype.getFullWidth = function () {
- this.assertHasRealPosition();
- return this.end - this.pos;
- };
- NodeObject.prototype.getLeadingTriviaWidth = function (sourceFile) {
- this.assertHasRealPosition();
- return this.getStart(sourceFile) - this.pos;
- };
- NodeObject.prototype.getFullText = function (sourceFile) {
- this.assertHasRealPosition();
- return (sourceFile || this.getSourceFile()).text.substring(this.pos, this.end);
- };
- NodeObject.prototype.getText = function (sourceFile) {
- this.assertHasRealPosition();
- if (!sourceFile) {
- sourceFile = this.getSourceFile();
- }
- return sourceFile.text.substring(this.getStart(sourceFile), this.getEnd());
- };
- NodeObject.prototype.addSyntheticNodes = function (nodes, pos, end) {
- ts.scanner.setTextPos(pos);
- while (pos < end) {
- var token = ts.scanner.scan();
- var textPos = ts.scanner.getTextPos();
- if (textPos <= end) {
- if (token === 71 /* Identifier */) {
- ts.Debug.fail("Did not expect " + ts.Debug.showSyntaxKind(this) + " to have an Identifier in its trivia");
- }
- nodes.push(createNode(token, pos, textPos, this));
- }
- pos = textPos;
- if (token === 1 /* EndOfFileToken */) {
- break;
- }
- }
- return pos;
- };
- NodeObject.prototype.createSyntaxList = function (nodes) {
- var list = createNode(293 /* SyntaxList */, nodes.pos, nodes.end, this);
- list._children = [];
- var pos = nodes.pos;
- for (var _i = 0, nodes_9 = nodes; _i < nodes_9.length; _i++) {
- var node = nodes_9[_i];
- if (pos < node.pos) {
- pos = this.addSyntheticNodes(list._children, pos, node.pos);
- }
- list._children.push(node);
- pos = node.end;
- }
- if (pos < nodes.end) {
- this.addSyntheticNodes(list._children, pos, nodes.end);
- }
- return list;
- };
- NodeObject.prototype.createChildren = function (sourceFile) {
- var _this = this;
- if (!ts.isNodeKind(this.kind)) {
- this._children = ts.emptyArray;
- return;
- }
- if (ts.isJSDocCommentContainingNode(this)) {
- /** Don't add trivia for "tokens" since this is in a comment. */
- var children_4 = [];
- this.forEachChild(function (child) { children_4.push(child); });
- this._children = children_4;
- return;
- }
- var children = [];
- ts.scanner.setText((sourceFile || this.getSourceFile()).text);
- var pos = this.pos;
- var processNode = function (node) {
- pos = _this.addSyntheticNodes(children, pos, node.pos);
- children.push(node);
- pos = node.end;
- };
- var processNodes = function (nodes) {
- if (pos < nodes.pos) {
- pos = _this.addSyntheticNodes(children, pos, nodes.pos);
- }
- children.push(_this.createSyntaxList(nodes));
- pos = nodes.end;
- };
- // jsDocComments need to be the first children
- if (this.jsDoc) {
- for (var _i = 0, _a = this.jsDoc; _i < _a.length; _i++) {
- var jsDocComment = _a[_i];
- processNode(jsDocComment);
- }
- }
- // For syntactic classifications, all trivia are classcified together, including jsdoc comments.
- // For that to work, the jsdoc comments should still be the leading trivia of the first child.
- // Restoring the scanner position ensures that.
- pos = this.pos;
- ts.forEachChild(this, processNode, processNodes);
- if (pos < this.end) {
- this.addSyntheticNodes(children, pos, this.end);
- }
- ts.scanner.setText(undefined);
- this._children = children;
- };
- NodeObject.prototype.getChildCount = function (sourceFile) {
- this.assertHasRealPosition();
- if (!this._children)
- this.createChildren(sourceFile);
- return this._children.length;
- };
- NodeObject.prototype.getChildAt = function (index, sourceFile) {
- this.assertHasRealPosition();
- if (!this._children)
- this.createChildren(sourceFile);
- return this._children[index];
- };
- NodeObject.prototype.getChildren = function (sourceFile) {
- this.assertHasRealPosition("Node without a real position cannot be scanned and thus has no token nodes - use forEachChild and collect the result if that's fine");
- if (!this._children)
- this.createChildren(sourceFile);
- return this._children;
- };
- NodeObject.prototype.getFirstToken = function (sourceFile) {
- this.assertHasRealPosition();
- var children = this.getChildren(sourceFile);
- if (!children.length) {
- return undefined;
- }
- var child = ts.find(children, function (kid) { return kid.kind < 274 /* FirstJSDocNode */ || kid.kind > 292 /* LastJSDocNode */; });
- return child.kind < 145 /* FirstNode */ ?
- child :
- child.getFirstToken(sourceFile);
- };
- NodeObject.prototype.getLastToken = function (sourceFile) {
- this.assertHasRealPosition();
- var children = this.getChildren(sourceFile);
- var child = ts.lastOrUndefined(children);
- if (!child) {
- return undefined;
- }
- return child.kind < 145 /* FirstNode */ ? child : child.getLastToken(sourceFile);
- };
- NodeObject.prototype.forEachChild = function (cbNode, cbNodeArray) {
- return ts.forEachChild(this, cbNode, cbNodeArray);
- };
- return NodeObject;
- }());
- var TokenOrIdentifierObject = /** @class */ (function () {
- function TokenOrIdentifierObject(pos, end) {
- // Set properties in same order as NodeObject
- this.pos = pos;
- this.end = end;
- this.flags = 0 /* None */;
- this.parent = undefined;
- }
- TokenOrIdentifierObject.prototype.getSourceFile = function () {
- return ts.getSourceFileOfNode(this);
- };
- TokenOrIdentifierObject.prototype.getStart = function (sourceFile, includeJsDocComment) {
- return ts.getTokenPosOfNode(this, sourceFile, includeJsDocComment);
- };
- TokenOrIdentifierObject.prototype.getFullStart = function () {
- return this.pos;
- };
- TokenOrIdentifierObject.prototype.getEnd = function () {
- return this.end;
- };
- TokenOrIdentifierObject.prototype.getWidth = function (sourceFile) {
- return this.getEnd() - this.getStart(sourceFile);
- };
- TokenOrIdentifierObject.prototype.getFullWidth = function () {
- return this.end - this.pos;
- };
- TokenOrIdentifierObject.prototype.getLeadingTriviaWidth = function (sourceFile) {
- return this.getStart(sourceFile) - this.pos;
- };
- TokenOrIdentifierObject.prototype.getFullText = function (sourceFile) {
- return (sourceFile || this.getSourceFile()).text.substring(this.pos, this.end);
- };
- TokenOrIdentifierObject.prototype.getText = function (sourceFile) {
- if (!sourceFile) {
- sourceFile = this.getSourceFile();
- }
- return sourceFile.text.substring(this.getStart(sourceFile), this.getEnd());
- };
- TokenOrIdentifierObject.prototype.getChildCount = function () {
- return 0;
- };
- TokenOrIdentifierObject.prototype.getChildAt = function () {
- return undefined;
- };
- TokenOrIdentifierObject.prototype.getChildren = function () {
- return ts.emptyArray;
- };
- TokenOrIdentifierObject.prototype.getFirstToken = function () {
- return undefined;
- };
- TokenOrIdentifierObject.prototype.getLastToken = function () {
- return undefined;
- };
- TokenOrIdentifierObject.prototype.forEachChild = function () {
- return undefined;
- };
- return TokenOrIdentifierObject;
- }());
- var SymbolObject = /** @class */ (function () {
- function SymbolObject(flags, name) {
- this.flags = flags;
- this.escapedName = name;
- }
- SymbolObject.prototype.getFlags = function () {
- return this.flags;
- };
- Object.defineProperty(SymbolObject.prototype, "name", {
- get: function () {
- return ts.symbolName(this);
- },
- enumerable: true,
- configurable: true
- });
- SymbolObject.prototype.getEscapedName = function () {
- return this.escapedName;
- };
- SymbolObject.prototype.getName = function () {
- return this.name;
- };
- SymbolObject.prototype.getDeclarations = function () {
- return this.declarations;
- };
- SymbolObject.prototype.getDocumentationComment = function (checker) {
- if (this.documentationComment === undefined) {
- if (this.declarations) {
- this.documentationComment = ts.JsDoc.getJsDocCommentsFromDeclarations(this.declarations);
- if (this.documentationComment.length === 0 || this.declarations.some(hasJSDocInheritDocTag)) {
- if (checker) {
- for (var _i = 0, _a = this.declarations; _i < _a.length; _i++) {
- var declaration = _a[_i];
- var inheritedDocs = findInheritedJSDocComments(declaration, this.getName(), checker);
- if (inheritedDocs.length > 0) {
- if (this.documentationComment.length > 0) {
- inheritedDocs.push(ts.lineBreakPart());
- }
- this.documentationComment = ts.concatenate(inheritedDocs, this.documentationComment);
- break;
- }
- }
- }
- }
- }
- else {
- this.documentationComment = [];
- }
- }
- return this.documentationComment;
- };
- SymbolObject.prototype.getJsDocTags = function () {
- if (this.tags === undefined) {
- this.tags = ts.JsDoc.getJsDocTagsFromDeclarations(this.declarations);
- }
- return this.tags;
- };
- return SymbolObject;
- }());
- var TokenObject = /** @class */ (function (_super) {
- __extends(TokenObject, _super);
- function TokenObject(kind, pos, end) {
- var _this = _super.call(this, pos, end) || this;
- _this.kind = kind;
- return _this;
- }
- return TokenObject;
- }(TokenOrIdentifierObject));
- var IdentifierObject = /** @class */ (function (_super) {
- __extends(IdentifierObject, _super);
- function IdentifierObject(_kind, pos, end) {
- return _super.call(this, pos, end) || this;
- }
- Object.defineProperty(IdentifierObject.prototype, "text", {
- get: function () {
- return ts.idText(this);
- },
- enumerable: true,
- configurable: true
- });
- return IdentifierObject;
- }(TokenOrIdentifierObject));
- IdentifierObject.prototype.kind = 71 /* Identifier */;
- var TypeObject = /** @class */ (function () {
- function TypeObject(checker, flags) {
- this.checker = checker;
- this.flags = flags;
- }
- TypeObject.prototype.getFlags = function () {
- return this.flags;
- };
- TypeObject.prototype.getSymbol = function () {
- return this.symbol;
- };
- TypeObject.prototype.getProperties = function () {
- return this.checker.getPropertiesOfType(this);
- };
- TypeObject.prototype.getProperty = function (propertyName) {
- return this.checker.getPropertyOfType(this, propertyName);
- };
- TypeObject.prototype.getApparentProperties = function () {
- return this.checker.getAugmentedPropertiesOfType(this);
- };
- TypeObject.prototype.getCallSignatures = function () {
- return this.checker.getSignaturesOfType(this, 0 /* Call */);
- };
- TypeObject.prototype.getConstructSignatures = function () {
- return this.checker.getSignaturesOfType(this, 1 /* Construct */);
- };
- TypeObject.prototype.getStringIndexType = function () {
- return this.checker.getIndexTypeOfType(this, 0 /* String */);
- };
- TypeObject.prototype.getNumberIndexType = function () {
- return this.checker.getIndexTypeOfType(this, 1 /* Number */);
- };
- TypeObject.prototype.getBaseTypes = function () {
- return this.flags & 65536 /* Object */ && this.objectFlags & (1 /* Class */ | 2 /* Interface */)
- ? this.checker.getBaseTypes(this)
- : undefined;
- };
- TypeObject.prototype.getNonNullableType = function () {
- return this.checker.getNonNullableType(this);
- };
- TypeObject.prototype.getConstraint = function () {
- return this.checker.getBaseConstraintOfType(this);
- };
- TypeObject.prototype.getDefault = function () {
- return this.checker.getDefaultFromTypeParameter(this);
- };
- return TypeObject;
- }());
- var SignatureObject = /** @class */ (function () {
- function SignatureObject(checker) {
- this.checker = checker;
- }
- SignatureObject.prototype.getDeclaration = function () {
- return this.declaration;
- };
- SignatureObject.prototype.getTypeParameters = function () {
- return this.typeParameters;
- };
- SignatureObject.prototype.getParameters = function () {
- return this.parameters;
- };
- SignatureObject.prototype.getReturnType = function () {
- return this.checker.getReturnTypeOfSignature(this);
- };
- SignatureObject.prototype.getDocumentationComment = function () {
- if (this.documentationComment === undefined) {
- if (this.declaration) {
- this.documentationComment = ts.JsDoc.getJsDocCommentsFromDeclarations([this.declaration]);
- if (this.documentationComment.length === 0 || hasJSDocInheritDocTag(this.declaration)) {
- var inheritedDocs = findInheritedJSDocComments(this.declaration, this.declaration.symbol.getName(), this.checker);
- if (this.documentationComment.length > 0) {
- inheritedDocs.push(ts.lineBreakPart());
- }
- this.documentationComment = ts.concatenate(inheritedDocs, this.documentationComment);
- }
- }
- else {
- this.documentationComment = [];
- }
- }
- return this.documentationComment;
- };
- SignatureObject.prototype.getJsDocTags = function () {
- if (this.jsDocTags === undefined) {
- this.jsDocTags = this.declaration ? ts.JsDoc.getJsDocTagsFromDeclarations([this.declaration]) : [];
- }
- return this.jsDocTags;
- };
- return SignatureObject;
- }());
- /**
- * Returns whether or not the given node has a JSDoc "inheritDoc" tag on it.
- * @param node the Node in question.
- * @returns `true` if `node` has a JSDoc "inheritDoc" tag on it, otherwise `false`.
- */
- function hasJSDocInheritDocTag(node) {
- return ts.getJSDocTags(node).some(function (tag) { return tag.tagName.text === "inheritDoc"; });
- }
- /**
- * Attempts to find JSDoc comments for possibly-inherited properties. Checks superclasses then traverses
- * implemented interfaces until a symbol is found with the same name and with documentation.
- * @param declaration The possibly-inherited declaration to find comments for.
- * @param propertyName The name of the possibly-inherited property.
- * @param typeChecker A TypeChecker, used to find inherited properties.
- * @returns A filled array of documentation comments if any were found, otherwise an empty array.
- */
- function findInheritedJSDocComments(declaration, propertyName, typeChecker) {
- var foundDocs = false;
- return ts.flatMap(getAllSuperTypeNodes(declaration), function (superTypeNode) {
- if (foundDocs) {
- return ts.emptyArray;
- }
- var superType = typeChecker.getTypeAtLocation(superTypeNode);
- if (!superType) {
- return ts.emptyArray;
- }
- var baseProperty = typeChecker.getPropertyOfType(superType, propertyName);
- if (!baseProperty) {
- return ts.emptyArray;
- }
- var inheritedDocs = baseProperty.getDocumentationComment(typeChecker);
- foundDocs = inheritedDocs.length > 0;
- return inheritedDocs;
- });
- }
- /**
- * Finds and returns the `TypeNode` for all super classes and implemented interfaces given a declaration.
- * @param declaration The possibly-inherited declaration.
- * @returns A filled array of `TypeNode`s containing all super classes and implemented interfaces if any exist, otherwise an empty array.
- */
- function getAllSuperTypeNodes(declaration) {
- var container = declaration.parent;
- if (!container || (!ts.isClassDeclaration(container) && !ts.isInterfaceDeclaration(container))) {
- return ts.emptyArray;
- }
- var extended = ts.getClassExtendsHeritageClauseElement(container);
- var types = extended ? [extended] : ts.emptyArray;
- return ts.isClassLike(container) ? ts.concatenate(types, ts.getClassImplementsHeritageClauseElements(container)) : types;
- }
- var SourceFileObject = /** @class */ (function (_super) {
- __extends(SourceFileObject, _super);
- function SourceFileObject(kind, pos, end) {
- return _super.call(this, kind, pos, end) || this;
- }
- SourceFileObject.prototype.update = function (newText, textChangeRange) {
- return ts.updateSourceFile(this, newText, textChangeRange);
- };
- SourceFileObject.prototype.getLineAndCharacterOfPosition = function (position) {
- return ts.getLineAndCharacterOfPosition(this, position);
- };
- SourceFileObject.prototype.getLineStarts = function () {
- return ts.getLineStarts(this);
- };
- SourceFileObject.prototype.getPositionOfLineAndCharacter = function (line, character) {
- return ts.getPositionOfLineAndCharacter(this, line, character);
- };
- SourceFileObject.prototype.getLineEndOfPosition = function (pos) {
- var line = this.getLineAndCharacterOfPosition(pos).line;
- var lineStarts = this.getLineStarts();
- var lastCharPos;
- if (line + 1 >= lineStarts.length) {
- lastCharPos = this.getEnd();
- }
- if (!lastCharPos) {
- lastCharPos = lineStarts[line + 1] - 1;
- }
- var fullText = this.getFullText();
- // if the new line is "\r\n", we should return the last non-new-line-character position
- return fullText[lastCharPos] === "\n" && fullText[lastCharPos - 1] === "\r" ? lastCharPos - 1 : lastCharPos;
- };
- SourceFileObject.prototype.getNamedDeclarations = function () {
- if (!this.namedDeclarations) {
- this.namedDeclarations = this.computeNamedDeclarations();
- }
- return this.namedDeclarations;
- };
- SourceFileObject.prototype.computeNamedDeclarations = function () {
- var result = ts.createMultiMap();
- ts.forEachChild(this, visit);
- return result;
- function addDeclaration(declaration) {
- var name = getDeclarationName(declaration);
- if (name) {
- result.add(name, declaration);
- }
- }
- function getDeclarations(name) {
- var declarations = result.get(name);
- if (!declarations) {
- result.set(name, declarations = []);
- }
- return declarations;
- }
- function getDeclarationName(declaration) {
- var name = ts.getNameOfDeclaration(declaration);
- return name && (ts.isPropertyNameLiteral(name) ? ts.getTextOfIdentifierOrLiteral(name) :
- name.kind === 146 /* ComputedPropertyName */ && ts.isPropertyAccessExpression(name.expression) ? name.expression.name.text : undefined);
- }
- function visit(node) {
- switch (node.kind) {
- case 232 /* FunctionDeclaration */:
- case 190 /* FunctionExpression */:
- case 153 /* MethodDeclaration */:
- case 152 /* MethodSignature */:
- var functionDeclaration = node;
- var declarationName = getDeclarationName(functionDeclaration);
- if (declarationName) {
- var declarations = getDeclarations(declarationName);
- var lastDeclaration = ts.lastOrUndefined(declarations);
- // Check whether this declaration belongs to an "overload group".
- if (lastDeclaration && functionDeclaration.parent === lastDeclaration.parent && functionDeclaration.symbol === lastDeclaration.symbol) {
- // Overwrite the last declaration if it was an overload
- // and this one is an implementation.
- if (functionDeclaration.body && !lastDeclaration.body) {
- declarations[declarations.length - 1] = functionDeclaration;
- }
- }
- else {
- declarations.push(functionDeclaration);
- }
- }
- ts.forEachChild(node, visit);
- break;
- case 233 /* ClassDeclaration */:
- case 203 /* ClassExpression */:
- case 234 /* InterfaceDeclaration */:
- case 235 /* TypeAliasDeclaration */:
- case 236 /* EnumDeclaration */:
- case 237 /* ModuleDeclaration */:
- case 241 /* ImportEqualsDeclaration */:
- case 250 /* ExportSpecifier */:
- case 246 /* ImportSpecifier */:
- case 243 /* ImportClause */:
- case 244 /* NamespaceImport */:
- case 155 /* GetAccessor */:
- case 156 /* SetAccessor */:
- case 165 /* TypeLiteral */:
- addDeclaration(node);
- ts.forEachChild(node, visit);
- break;
- case 148 /* Parameter */:
- // Only consider parameter properties
- if (!ts.hasModifier(node, 92 /* ParameterPropertyModifier */)) {
- break;
- }
- // falls through
- case 230 /* VariableDeclaration */:
- case 180 /* BindingElement */: {
- var decl = node;
- if (ts.isBindingPattern(decl.name)) {
- ts.forEachChild(decl.name, visit);
- break;
- }
- if (decl.initializer) {
- visit(decl.initializer);
- }
- }
- // falls through
- case 271 /* EnumMember */:
- case 151 /* PropertyDeclaration */:
- case 150 /* PropertySignature */:
- addDeclaration(node);
- break;
- case 248 /* ExportDeclaration */:
- // Handle named exports case e.g.:
- // export {a, b as B} from "mod";
- if (node.exportClause) {
- ts.forEach(node.exportClause.elements, visit);
- }
- break;
- case 242 /* ImportDeclaration */:
- var importClause = node.importClause;
- if (importClause) {
- // Handle default import case e.g.:
- // import d from "mod";
- if (importClause.name) {
- addDeclaration(importClause);
- }
- // Handle named bindings in imports e.g.:
- // import * as NS from "mod";
- // import {a, b as B} from "mod";
- if (importClause.namedBindings) {
- if (importClause.namedBindings.kind === 244 /* NamespaceImport */) {
- addDeclaration(importClause.namedBindings);
- }
- else {
- ts.forEach(importClause.namedBindings.elements, visit);
- }
- }
- }
- break;
- case 198 /* BinaryExpression */:
- if (ts.getSpecialPropertyAssignmentKind(node) !== 0 /* None */) {
- addDeclaration(node);
- }
- // falls through
- default:
- ts.forEachChild(node, visit);
- }
- }
- };
- return SourceFileObject;
- }(NodeObject));
- var SourceMapSourceObject = /** @class */ (function () {
- function SourceMapSourceObject(fileName, text, skipTrivia) {
- this.fileName = fileName;
- this.text = text;
- this.skipTrivia = skipTrivia;
- }
- SourceMapSourceObject.prototype.getLineAndCharacterOfPosition = function (pos) {
- return ts.getLineAndCharacterOfPosition(this, pos);
- };
- return SourceMapSourceObject;
- }());
- function getServicesObjectAllocator() {
- return {
- getNodeConstructor: function () { return NodeObject; },
- getTokenConstructor: function () { return TokenObject; },
- getIdentifierConstructor: function () { return IdentifierObject; },
- getSourceFileConstructor: function () { return SourceFileObject; },
- getSymbolConstructor: function () { return SymbolObject; },
- getTypeConstructor: function () { return TypeObject; },
- getSignatureConstructor: function () { return SignatureObject; },
- getSourceMapSourceConstructor: function () { return SourceMapSourceObject; },
- };
- }
- function toEditorSettings(optionsAsMap) {
- var allPropertiesAreCamelCased = true;
- for (var key in optionsAsMap) {
- if (ts.hasProperty(optionsAsMap, key) && !isCamelCase(key)) {
- allPropertiesAreCamelCased = false;
- break;
- }
- }
- if (allPropertiesAreCamelCased) {
- return optionsAsMap;
- }
- var settings = {};
- for (var key in optionsAsMap) {
- if (ts.hasProperty(optionsAsMap, key)) {
- var newKey = isCamelCase(key) ? key : key.charAt(0).toLowerCase() + key.substr(1);
- settings[newKey] = optionsAsMap[key];
- }
- }
- return settings;
- }
- ts.toEditorSettings = toEditorSettings;
- function isCamelCase(s) {
- return !s.length || s.charAt(0) === s.charAt(0).toLowerCase();
- }
- function displayPartsToString(displayParts) {
- if (displayParts) {
- return ts.map(displayParts, function (displayPart) { return displayPart.text; }).join("");
- }
- return "";
- }
- ts.displayPartsToString = displayPartsToString;
- function getDefaultCompilerOptions() {
- // Always default to "ScriptTarget.ES5" for the language service
- return {
- target: 1 /* ES5 */,
- jsx: 1 /* Preserve */
- };
- }
- ts.getDefaultCompilerOptions = getDefaultCompilerOptions;
- function getSupportedCodeFixes() {
- return ts.codefix.getSupportedErrorCodes();
- }
- ts.getSupportedCodeFixes = getSupportedCodeFixes;
- // Cache host information about script Should be refreshed
- // at each language service public entry point, since we don't know when
- // the set of scripts handled by the host changes.
- var HostCache = /** @class */ (function () {
- function HostCache(host, getCanonicalFileName) {
- this.host = host;
- // script id => script index
- this.currentDirectory = host.getCurrentDirectory();
- this.fileNameToEntry = ts.createMap();
- // Initialize the list with the root file names
- var rootFileNames = host.getScriptFileNames();
- for (var _i = 0, rootFileNames_1 = rootFileNames; _i < rootFileNames_1.length; _i++) {
- var fileName = rootFileNames_1[_i];
- this.createEntry(fileName, ts.toPath(fileName, this.currentDirectory, getCanonicalFileName));
- }
- // store the compilation settings
- this._compilationSettings = host.getCompilationSettings() || getDefaultCompilerOptions();
- }
- HostCache.prototype.compilationSettings = function () {
- return this._compilationSettings;
- };
- HostCache.prototype.createEntry = function (fileName, path) {
- var entry;
- var scriptSnapshot = this.host.getScriptSnapshot(fileName);
- if (scriptSnapshot) {
- entry = {
- hostFileName: fileName,
- version: this.host.getScriptVersion(fileName),
- scriptSnapshot: scriptSnapshot,
- scriptKind: ts.getScriptKind(fileName, this.host)
- };
- }
- else {
- entry = fileName;
- }
- this.fileNameToEntry.set(path, entry);
- return entry;
- };
- HostCache.prototype.getEntryByPath = function (path) {
- return this.fileNameToEntry.get(path);
- };
- HostCache.prototype.getHostFileInformation = function (path) {
- var entry = this.fileNameToEntry.get(path);
- return !ts.isString(entry) ? entry : undefined;
- };
- HostCache.prototype.getOrCreateEntryByPath = function (fileName, path) {
- var info = this.getEntryByPath(path) || this.createEntry(fileName, path);
- return ts.isString(info) ? undefined : info;
- };
- HostCache.prototype.getRootFileNames = function () {
- return ts.arrayFrom(this.fileNameToEntry.values(), function (entry) {
- return ts.isString(entry) ? entry : entry.hostFileName;
- });
- };
- HostCache.prototype.getVersion = function (path) {
- var file = this.getHostFileInformation(path);
- return file && file.version;
- };
- HostCache.prototype.getScriptSnapshot = function (path) {
- var file = this.getHostFileInformation(path);
- return file && file.scriptSnapshot;
- };
- return HostCache;
- }());
- var SyntaxTreeCache = /** @class */ (function () {
- function SyntaxTreeCache(host) {
- this.host = host;
- }
- SyntaxTreeCache.prototype.getCurrentSourceFile = function (fileName) {
- var scriptSnapshot = this.host.getScriptSnapshot(fileName);
- if (!scriptSnapshot) {
- // The host does not know about this file.
- throw new Error("Could not find file: '" + fileName + "'.");
- }
- var scriptKind = ts.getScriptKind(fileName, this.host);
- var version = this.host.getScriptVersion(fileName);
- var sourceFile;
- if (this.currentFileName !== fileName) {
- // This is a new file, just parse it
- sourceFile = createLanguageServiceSourceFile(fileName, scriptSnapshot, 6 /* Latest */, version, /*setNodeParents*/ true, scriptKind);
- }
- else if (this.currentFileVersion !== version) {
- // This is the same file, just a newer version. Incrementally parse the file.
- var editRange = scriptSnapshot.getChangeRange(this.currentFileScriptSnapshot);
- sourceFile = updateLanguageServiceSourceFile(this.currentSourceFile, scriptSnapshot, version, editRange);
- }
- if (sourceFile) {
- // All done, ensure state is up to date
- this.currentFileVersion = version;
- this.currentFileName = fileName;
- this.currentFileScriptSnapshot = scriptSnapshot;
- this.currentSourceFile = sourceFile;
- }
- return this.currentSourceFile;
- };
- return SyntaxTreeCache;
- }());
- function setSourceFileFields(sourceFile, scriptSnapshot, version) {
- sourceFile.version = version;
- sourceFile.scriptSnapshot = scriptSnapshot;
- }
- function createLanguageServiceSourceFile(fileName, scriptSnapshot, scriptTarget, version, setNodeParents, scriptKind) {
- var sourceFile = ts.createSourceFile(fileName, ts.getSnapshotText(scriptSnapshot), scriptTarget, setNodeParents, scriptKind);
- setSourceFileFields(sourceFile, scriptSnapshot, version);
- return sourceFile;
- }
- ts.createLanguageServiceSourceFile = createLanguageServiceSourceFile;
- ts.disableIncrementalParsing = false;
- function updateLanguageServiceSourceFile(sourceFile, scriptSnapshot, version, textChangeRange, aggressiveChecks) {
- // If we were given a text change range, and our version or open-ness changed, then
- // incrementally parse this file.
- if (textChangeRange) {
- if (version !== sourceFile.version) {
- // Once incremental parsing is ready, then just call into this function.
- if (!ts.disableIncrementalParsing) {
- var newText = void 0;
- // grab the fragment from the beginning of the original text to the beginning of the span
- var prefix = textChangeRange.span.start !== 0
- ? sourceFile.text.substr(0, textChangeRange.span.start)
- : "";
- // grab the fragment from the end of the span till the end of the original text
- var suffix = ts.textSpanEnd(textChangeRange.span) !== sourceFile.text.length
- ? sourceFile.text.substr(ts.textSpanEnd(textChangeRange.span))
- : "";
- if (textChangeRange.newLength === 0) {
- // edit was a deletion - just combine prefix and suffix
- newText = prefix && suffix ? prefix + suffix : prefix || suffix;
- }
- else {
- // it was actual edit, fetch the fragment of new text that correspond to new span
- var changedText = scriptSnapshot.getText(textChangeRange.span.start, textChangeRange.span.start + textChangeRange.newLength);
- // combine prefix, changed text and suffix
- newText = prefix && suffix
- ? prefix + changedText + suffix
- : prefix
- ? (prefix + changedText)
- : (changedText + suffix);
- }
- var newSourceFile = ts.updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks);
- setSourceFileFields(newSourceFile, scriptSnapshot, version);
- // after incremental parsing nameTable might not be up-to-date
- // drop it so it can be lazily recreated later
- newSourceFile.nameTable = undefined;
- // dispose all resources held by old script snapshot
- if (sourceFile !== newSourceFile && sourceFile.scriptSnapshot) {
- if (sourceFile.scriptSnapshot.dispose) {
- sourceFile.scriptSnapshot.dispose();
- }
- sourceFile.scriptSnapshot = undefined;
- }
- return newSourceFile;
- }
- }
- }
- // Otherwise, just create a new source file.
- return createLanguageServiceSourceFile(sourceFile.fileName, scriptSnapshot, sourceFile.languageVersion, version, /*setNodeParents*/ true, sourceFile.scriptKind);
- }
- ts.updateLanguageServiceSourceFile = updateLanguageServiceSourceFile;
- var CancellationTokenObject = /** @class */ (function () {
- function CancellationTokenObject(cancellationToken) {
- this.cancellationToken = cancellationToken;
- }
- CancellationTokenObject.prototype.isCancellationRequested = function () {
- return this.cancellationToken && this.cancellationToken.isCancellationRequested();
- };
- CancellationTokenObject.prototype.throwIfCancellationRequested = function () {
- if (this.isCancellationRequested()) {
- throw new ts.OperationCanceledException();
- }
- };
- return CancellationTokenObject;
- }());
- /* @internal */
- /** A cancellation that throttles calls to the host */
- var ThrottledCancellationToken = /** @class */ (function () {
- function ThrottledCancellationToken(hostCancellationToken, throttleWaitMilliseconds) {
- if (throttleWaitMilliseconds === void 0) { throttleWaitMilliseconds = 20; }
- this.hostCancellationToken = hostCancellationToken;
- this.throttleWaitMilliseconds = throttleWaitMilliseconds;
- // Store when we last tried to cancel. Checking cancellation can be expensive (as we have
- // to marshall over to the host layer). So we only bother actually checking once enough
- // time has passed.
- this.lastCancellationCheckTime = 0;
- }
- ThrottledCancellationToken.prototype.isCancellationRequested = function () {
- var time = ts.timestamp();
- var duration = Math.abs(time - this.lastCancellationCheckTime);
- if (duration >= this.throttleWaitMilliseconds) {
- // Check no more than once every throttle wait milliseconds
- this.lastCancellationCheckTime = time;
- return this.hostCancellationToken.isCancellationRequested();
- }
- return false;
- };
- ThrottledCancellationToken.prototype.throwIfCancellationRequested = function () {
- if (this.isCancellationRequested()) {
- throw new ts.OperationCanceledException();
- }
- };
- return ThrottledCancellationToken;
- }());
- ts.ThrottledCancellationToken = ThrottledCancellationToken;
- function createLanguageService(host, documentRegistry) {
- if (documentRegistry === void 0) { documentRegistry = ts.createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames(), host.getCurrentDirectory()); }
- var syntaxTreeCache = new SyntaxTreeCache(host);
- var program;
- var lastProjectVersion;
- var lastTypesRootVersion = 0;
- var useCaseSensitivefileNames = host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames();
- var cancellationToken = new CancellationTokenObject(host.getCancellationToken && host.getCancellationToken());
- var currentDirectory = host.getCurrentDirectory();
- // Check if the localized messages json is set, otherwise query the host for it
- if (!ts.localizedDiagnosticMessages && host.getLocalizedDiagnosticMessages) {
- ts.localizedDiagnosticMessages = host.getLocalizedDiagnosticMessages();
- }
- function log(message) {
- if (host.log) {
- host.log(message);
- }
- }
- var getCanonicalFileName = ts.createGetCanonicalFileName(useCaseSensitivefileNames);
- function getValidSourceFile(fileName) {
- var sourceFile = program.getSourceFile(fileName);
- if (!sourceFile) {
- throw new Error("Could not find file: '" + fileName + "'.");
- }
- return sourceFile;
- }
- function synchronizeHostData() {
- // perform fast check if host supports it
- if (host.getProjectVersion) {
- var hostProjectVersion = host.getProjectVersion();
- if (hostProjectVersion) {
- if (lastProjectVersion === hostProjectVersion && !host.hasChangedAutomaticTypeDirectiveNames) {
- return;
- }
- lastProjectVersion = hostProjectVersion;
- }
- }
- var typeRootsVersion = host.getTypeRootsVersion ? host.getTypeRootsVersion() : 0;
- if (lastTypesRootVersion !== typeRootsVersion) {
- log("TypeRoots version has changed; provide new program");
- program = undefined;
- lastTypesRootVersion = typeRootsVersion;
- }
- // Get a fresh cache of the host information
- var hostCache = new HostCache(host, getCanonicalFileName);
- var rootFileNames = hostCache.getRootFileNames();
- var hasInvalidatedResolution = host.hasInvalidatedResolution || ts.returnFalse;
- // If the program is already up-to-date, we can reuse it
- if (ts.isProgramUptoDate(program, rootFileNames, hostCache.compilationSettings(), function (path) { return hostCache.getVersion(path); }, fileExists, hasInvalidatedResolution, host.hasChangedAutomaticTypeDirectiveNames)) {
- return;
- }
- // IMPORTANT - It is critical from this moment onward that we do not check
- // cancellation tokens. We are about to mutate source files from a previous program
- // instance. If we cancel midway through, we may end up in an inconsistent state where
- // the program points to old source files that have been invalidated because of
- // incremental parsing.
- var newSettings = hostCache.compilationSettings();
- // Now create a new compiler
- var compilerHost = {
- getSourceFile: getOrCreateSourceFile,
- getSourceFileByPath: getOrCreateSourceFileByPath,
- getCancellationToken: function () { return cancellationToken; },
- getCanonicalFileName: getCanonicalFileName,
- useCaseSensitiveFileNames: function () { return useCaseSensitivefileNames; },
- getNewLine: function () { return ts.getNewLineCharacter(newSettings, function () { return ts.getNewLineOrDefaultFromHost(host); }); },
- getDefaultLibFileName: function (options) { return host.getDefaultLibFileName(options); },
- writeFile: ts.noop,
- getCurrentDirectory: function () { return currentDirectory; },
- fileExists: fileExists,
- readFile: function (fileName) {
- // stub missing host functionality
- var path = ts.toPath(fileName, currentDirectory, getCanonicalFileName);
- var entry = hostCache.getEntryByPath(path);
- if (entry) {
- return ts.isString(entry) ? undefined : ts.getSnapshotText(entry.scriptSnapshot);
- }
- return host.readFile && host.readFile(fileName);
- },
- realpath: host.realpath && (function (path) { return host.realpath(path); }),
- directoryExists: function (directoryName) {
- return ts.directoryProbablyExists(directoryName, host);
- },
- getDirectories: function (path) {
- return host.getDirectories ? host.getDirectories(path) : [];
- },
- onReleaseOldSourceFile: onReleaseOldSourceFile,
- hasInvalidatedResolution: hasInvalidatedResolution,
- hasChangedAutomaticTypeDirectiveNames: host.hasChangedAutomaticTypeDirectiveNames
- };
- if (host.trace) {
- compilerHost.trace = function (message) { return host.trace(message); };
- }
- if (host.resolveModuleNames) {
- compilerHost.resolveModuleNames = function (moduleNames, containingFile, reusedNames) { return host.resolveModuleNames(moduleNames, containingFile, reusedNames); };
- }
- if (host.resolveTypeReferenceDirectives) {
- compilerHost.resolveTypeReferenceDirectives = function (typeReferenceDirectiveNames, containingFile) {
- return host.resolveTypeReferenceDirectives(typeReferenceDirectiveNames, containingFile);
- };
- }
- var documentRegistryBucketKey = documentRegistry.getKeyForCompilationSettings(newSettings);
- program = ts.createProgram(rootFileNames, newSettings, compilerHost, program);
- // hostCache is captured in the closure for 'getOrCreateSourceFile' but it should not be used past this point.
- // It needs to be cleared to allow all collected snapshots to be released
- hostCache = undefined;
- // Make sure all the nodes in the program are both bound, and have their parent
- // pointers set property.
- program.getTypeChecker();
- return;
- function fileExists(fileName) {
- var path = ts.toPath(fileName, currentDirectory, getCanonicalFileName);
- var entry = hostCache.getEntryByPath(path);
- return entry ?
- !ts.isString(entry) :
- (host.fileExists && host.fileExists(fileName));
- }
- // Release any files we have acquired in the old program but are
- // not part of the new program.
- function onReleaseOldSourceFile(oldSourceFile, oldOptions) {
- var oldSettingsKey = documentRegistry.getKeyForCompilationSettings(oldOptions);
- documentRegistry.releaseDocumentWithKey(oldSourceFile.path, oldSettingsKey);
- }
- function getOrCreateSourceFile(fileName, languageVersion, onError, shouldCreateNewSourceFile) {
- return getOrCreateSourceFileByPath(fileName, ts.toPath(fileName, currentDirectory, getCanonicalFileName), languageVersion, onError, shouldCreateNewSourceFile);
- }
- function getOrCreateSourceFileByPath(fileName, path, _languageVersion, _onError, shouldCreateNewSourceFile) {
- ts.Debug.assert(hostCache !== undefined);
- // The program is asking for this file, check first if the host can locate it.
- // If the host can not locate the file, then it does not exist. return undefined
- // to the program to allow reporting of errors for missing files.
- var hostFileInformation = hostCache.getOrCreateEntryByPath(fileName, path);
- if (!hostFileInformation) {
- return undefined;
- }
- // Check if the language version has changed since we last created a program; if they are the same,
- // it is safe to reuse the sourceFiles; if not, then the shape of the AST can change, and the oldSourceFile
- // can not be reused. we have to dump all syntax trees and create new ones.
- if (!shouldCreateNewSourceFile) {
- // Check if the old program had this file already
- var oldSourceFile = program && program.getSourceFileByPath(path);
- if (oldSourceFile) {
- // We already had a source file for this file name. Go to the registry to
- // ensure that we get the right up to date version of it. We need this to
- // address the following race-condition. Specifically, say we have the following:
- //
- // LS1
- // \
- // DocumentRegistry
- // /
- // LS2
- //
- // Each LS has a reference to file 'foo.ts' at version 1. LS2 then updates
- // it's version of 'foo.ts' to version 2. This will cause LS2 and the
- // DocumentRegistry to have version 2 of the document. HOwever, LS1 will
- // have version 1. And *importantly* this source file will be *corrupt*.
- // The act of creating version 2 of the file irrevocably damages the version
- // 1 file.
- //
- // So, later when we call into LS1, we need to make sure that it doesn't use
- // it's source file any more, and instead defers to DocumentRegistry to get
- // either version 1, version 2 (or some other version) depending on what the
- // host says should be used.
- // We do not support the scenario where a host can modify a registered
- // file's script kind, i.e. in one project some file is treated as ".ts"
- // and in another as ".js"
- ts.Debug.assertEqual(hostFileInformation.scriptKind, oldSourceFile.scriptKind, "Registered script kind should match new script kind.", path);
- return documentRegistry.updateDocumentWithKey(fileName, path, newSettings, documentRegistryBucketKey, hostFileInformation.scriptSnapshot, hostFileInformation.version, hostFileInformation.scriptKind);
- }
- // We didn't already have the file. Fall through and acquire it from the registry.
- }
- // Could not find this file in the old program, create a new SourceFile for it.
- return documentRegistry.acquireDocumentWithKey(fileName, path, newSettings, documentRegistryBucketKey, hostFileInformation.scriptSnapshot, hostFileInformation.version, hostFileInformation.scriptKind);
- }
- }
- function getProgram() {
- synchronizeHostData();
- return program;
- }
- function cleanupSemanticCache() {
- program = undefined;
- }
- function dispose() {
- if (program) {
- ts.forEach(program.getSourceFiles(), function (f) {
- return documentRegistry.releaseDocument(f.fileName, program.getCompilerOptions());
- });
- program = undefined;
- }
- host = undefined;
- }
- /// Diagnostics
- function getSyntacticDiagnostics(fileName) {
- synchronizeHostData();
- return program.getSyntacticDiagnostics(getValidSourceFile(fileName), cancellationToken).slice();
- }
- /**
- * getSemanticDiagnostics return array of Diagnostics. If '-d' is not enabled, only report semantic errors
- * If '-d' enabled, report both semantic and emitter errors
- */
- function getSemanticDiagnostics(fileName) {
- synchronizeHostData();
- var targetSourceFile = getValidSourceFile(fileName);
- // Only perform the action per file regardless of '-out' flag as LanguageServiceHost is expected to call this function per file.
- // Therefore only get diagnostics for given file.
- var semanticDiagnostics = program.getSemanticDiagnostics(targetSourceFile, cancellationToken);
- if (!program.getCompilerOptions().declaration) {
- return semanticDiagnostics.slice();
- }
- // If '-d' is enabled, check for emitter error. One example of emitter error is export class implements non-export interface
- var declarationDiagnostics = program.getDeclarationDiagnostics(targetSourceFile, cancellationToken);
- return semanticDiagnostics.concat(declarationDiagnostics);
- }
- function getSuggestionDiagnostics(fileName) {
- synchronizeHostData();
- return ts.computeSuggestionDiagnostics(getValidSourceFile(fileName), program);
- }
- function getCompilerOptionsDiagnostics() {
- synchronizeHostData();
- return program.getOptionsDiagnostics(cancellationToken).concat(program.getGlobalDiagnostics(cancellationToken));
- }
- function getCompletionsAtPosition(fileName, position, options) {
- if (options === void 0) { options = { includeExternalModuleExports: false, includeInsertTextCompletions: false }; }
- synchronizeHostData();
- return ts.Completions.getCompletionsAtPosition(host, program.getTypeChecker(), log, program.getCompilerOptions(), getValidSourceFile(fileName), position, program.getSourceFiles(), options);
- }
- function getCompletionEntryDetails(fileName, position, name, formattingOptions, source) {
- synchronizeHostData();
- return ts.Completions.getCompletionEntryDetails(program, log, program.getCompilerOptions(), getValidSourceFile(fileName), position, { name: name, source: source }, program.getSourceFiles(), host, formattingOptions && ts.formatting.getFormatContext(formattingOptions), getCanonicalFileName);
- }
- function getCompletionEntrySymbol(fileName, position, name, source) {
- synchronizeHostData();
- return ts.Completions.getCompletionEntrySymbol(program.getTypeChecker(), log, program.getCompilerOptions(), getValidSourceFile(fileName), position, { name: name, source: source }, program.getSourceFiles());
- }
- function getQuickInfoAtPosition(fileName, position) {
- synchronizeHostData();
- var sourceFile = getValidSourceFile(fileName);
- var node = ts.getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ true);
- if (node === sourceFile) {
- // Avoid giving quickInfo for the sourceFile as a whole.
- return undefined;
- }
- var typeChecker = program.getTypeChecker();
- var symbol = getSymbolAtLocationForQuickInfo(node, typeChecker);
- if (!symbol || typeChecker.isUnknownSymbol(symbol)) {
- // Try getting just type at this position and show
- switch (node.kind) {
- case 71 /* Identifier */:
- if (ts.isLabelName(node)) {
- // Type here will be 'any', avoid displaying this.
- return undefined;
- }
- // falls through
- case 183 /* PropertyAccessExpression */:
- case 145 /* QualifiedName */:
- case 99 /* ThisKeyword */:
- case 173 /* ThisType */:
- case 97 /* SuperKeyword */:
- // For the identifiers/this/super etc get the type at position
- var type = typeChecker.getTypeAtLocation(node);
- return type && {
- kind: "" /* unknown */,
- kindModifiers: "" /* none */,
- textSpan: ts.createTextSpanFromNode(node, sourceFile),
- displayParts: ts.typeToDisplayParts(typeChecker, type, ts.getContainerNode(node)),
- documentation: type.symbol ? type.symbol.getDocumentationComment(typeChecker) : undefined,
- tags: type.symbol ? type.symbol.getJsDocTags() : undefined
- };
- }
- return undefined;
- }
- var _a = ts.SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker, symbol, sourceFile, ts.getContainerNode(node), node), symbolKind = _a.symbolKind, displayParts = _a.displayParts, documentation = _a.documentation, tags = _a.tags;
- return {
- kind: symbolKind,
- kindModifiers: ts.SymbolDisplay.getSymbolModifiers(symbol),
- textSpan: ts.createTextSpanFromNode(node, sourceFile),
- displayParts: displayParts,
- documentation: documentation,
- tags: tags,
- };
- }
- function getSymbolAtLocationForQuickInfo(node, checker) {
- if ((ts.isIdentifier(node) || ts.isStringLiteral(node))
- && ts.isPropertyAssignment(node.parent)
- && node.parent.name === node) {
- var type = checker.getContextualType(node.parent.parent);
- var property = type && checker.getPropertyOfType(type, ts.getTextOfIdentifierOrLiteral(node));
- if (property) {
- return property;
- }
- }
- return checker.getSymbolAtLocation(node);
- }
- /// Goto definition
- function getDefinitionAtPosition(fileName, position) {
- synchronizeHostData();
- return ts.GoToDefinition.getDefinitionAtPosition(program, getValidSourceFile(fileName), position);
- }
- function getDefinitionAndBoundSpan(fileName, position) {
- synchronizeHostData();
- return ts.GoToDefinition.getDefinitionAndBoundSpan(program, getValidSourceFile(fileName), position);
- }
- function getTypeDefinitionAtPosition(fileName, position) {
- synchronizeHostData();
- return ts.GoToDefinition.getTypeDefinitionAtPosition(program.getTypeChecker(), getValidSourceFile(fileName), position);
- }
- /// Goto implementation
- function getImplementationAtPosition(fileName, position) {
- synchronizeHostData();
- return ts.FindAllReferences.getImplementationsAtPosition(program, cancellationToken, program.getSourceFiles(), getValidSourceFile(fileName), position);
- }
- /// References and Occurrences
- function getOccurrencesAtPosition(fileName, position) {
- var canonicalFileName = getCanonicalFileName(ts.normalizeSlashes(fileName));
- return ts.flatMap(getDocumentHighlights(fileName, position, [fileName]), function (entry) { return entry.highlightSpans.map(function (highlightSpan) {
- ts.Debug.assert(getCanonicalFileName(ts.normalizeSlashes(entry.fileName)) === canonicalFileName); // Get occurrences only supports reporting occurrences for the file queried.
- return {
- fileName: entry.fileName,
- textSpan: highlightSpan.textSpan,
- isWriteAccess: highlightSpan.kind === "writtenReference" /* writtenReference */,
- isDefinition: false,
- isInString: highlightSpan.isInString,
- };
- }); });
- }
- function getDocumentHighlights(fileName, position, filesToSearch) {
- synchronizeHostData();
- var sourceFilesToSearch = ts.map(filesToSearch, function (f) { return ts.Debug.assertDefined(program.getSourceFile(f)); });
- var sourceFile = getValidSourceFile(fileName);
- return ts.DocumentHighlights.getDocumentHighlights(program, cancellationToken, sourceFile, position, sourceFilesToSearch);
- }
- function findRenameLocations(fileName, position, findInStrings, findInComments) {
- return getReferences(fileName, position, { findInStrings: findInStrings, findInComments: findInComments, isForRename: true });
- }
- function getReferencesAtPosition(fileName, position) {
- return getReferences(fileName, position);
- }
- function getReferences(fileName, position, options) {
- synchronizeHostData();
- // Exclude default library when renaming as commonly user don't want to change that file.
- var sourceFiles = [];
- if (options && options.isForRename) {
- for (var _i = 0, _a = program.getSourceFiles(); _i < _a.length; _i++) {
- var sourceFile = _a[_i];
- if (!program.isSourceFileDefaultLibrary(sourceFile)) {
- sourceFiles.push(sourceFile);
- }
- }
- }
- else {
- sourceFiles = program.getSourceFiles().slice();
- }
- return ts.FindAllReferences.findReferencedEntries(program, cancellationToken, sourceFiles, getValidSourceFile(fileName), position, options);
- }
- function findReferences(fileName, position) {
- synchronizeHostData();
- return ts.FindAllReferences.findReferencedSymbols(program, cancellationToken, program.getSourceFiles(), getValidSourceFile(fileName), position);
- }
- /// NavigateTo
- function getNavigateToItems(searchValue, maxResultCount, fileName, excludeDtsFiles) {
- synchronizeHostData();
- var sourceFiles = fileName ? [getValidSourceFile(fileName)] : program.getSourceFiles();
- return ts.NavigateTo.getNavigateToItems(sourceFiles, program.getTypeChecker(), cancellationToken, searchValue, maxResultCount, excludeDtsFiles);
- }
- function getEmitOutput(fileName, emitOnlyDtsFiles) {
- synchronizeHostData();
- var sourceFile = getValidSourceFile(fileName);
- var customTransformers = host.getCustomTransformers && host.getCustomTransformers();
- return ts.getFileEmitOutput(program, sourceFile, emitOnlyDtsFiles, cancellationToken, customTransformers);
- }
- // Signature help
- /**
- * This is a semantic operation.
- */
- function getSignatureHelpItems(fileName, position) {
- synchronizeHostData();
- var sourceFile = getValidSourceFile(fileName);
- return ts.SignatureHelp.getSignatureHelpItems(program, sourceFile, position, cancellationToken);
- }
- /// Syntactic features
- function getNonBoundSourceFile(fileName) {
- return syntaxTreeCache.getCurrentSourceFile(fileName);
- }
- function getSourceFile(fileName) {
- return getNonBoundSourceFile(fileName);
- }
- function getNameOrDottedNameSpan(fileName, startPos, _endPos) {
- var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
- // Get node at the location
- var node = ts.getTouchingPropertyName(sourceFile, startPos, /*includeJsDocComment*/ false);
- if (node === sourceFile) {
- return;
- }
- switch (node.kind) {
- case 183 /* PropertyAccessExpression */:
- case 145 /* QualifiedName */:
- case 9 /* StringLiteral */:
- case 86 /* FalseKeyword */:
- case 101 /* TrueKeyword */:
- case 95 /* NullKeyword */:
- case 97 /* SuperKeyword */:
- case 99 /* ThisKeyword */:
- case 173 /* ThisType */:
- case 71 /* Identifier */:
- break;
- // Cant create the text span
- default:
- return;
- }
- var nodeForStartPos = node;
- while (true) {
- if (ts.isRightSideOfPropertyAccess(nodeForStartPos) || ts.isRightSideOfQualifiedName(nodeForStartPos)) {
- // If on the span is in right side of the the property or qualified name, return the span from the qualified name pos to end of this node
- nodeForStartPos = nodeForStartPos.parent;
- }
- else if (ts.isNameOfModuleDeclaration(nodeForStartPos)) {
- // If this is name of a module declarations, check if this is right side of dotted module name
- // If parent of the module declaration which is parent of this node is module declaration and its body is the module declaration that this node is name of
- // Then this name is name from dotted module
- if (nodeForStartPos.parent.parent.kind === 237 /* ModuleDeclaration */ &&
- nodeForStartPos.parent.parent.body === nodeForStartPos.parent) {
- // Use parent module declarations name for start pos
- nodeForStartPos = nodeForStartPos.parent.parent.name;
- }
- else {
- // We have to use this name for start pos
- break;
- }
- }
- else {
- // Is not a member expression so we have found the node for start pos
- break;
- }
- }
- return ts.createTextSpanFromBounds(nodeForStartPos.getStart(), node.getEnd());
- }
- function getBreakpointStatementAtPosition(fileName, position) {
- // doesn't use compiler - no need to synchronize with host
- var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
- return ts.BreakpointResolver.spanInSourceFileAtLocation(sourceFile, position);
- }
- function getNavigationBarItems(fileName) {
- return ts.NavigationBar.getNavigationBarItems(syntaxTreeCache.getCurrentSourceFile(fileName), cancellationToken);
- }
- function getNavigationTree(fileName) {
- return ts.NavigationBar.getNavigationTree(syntaxTreeCache.getCurrentSourceFile(fileName), cancellationToken);
- }
- function isTsOrTsxFile(fileName) {
- var kind = ts.getScriptKind(fileName, host);
- return kind === 3 /* TS */ || kind === 4 /* TSX */;
- }
- function getSemanticClassifications(fileName, span) {
- if (!isTsOrTsxFile(fileName)) {
- // do not run semantic classification on non-ts-or-tsx files
- return [];
- }
- synchronizeHostData();
- return ts.getSemanticClassifications(program.getTypeChecker(), cancellationToken, getValidSourceFile(fileName), program.getClassifiableNames(), span);
- }
- function getEncodedSemanticClassifications(fileName, span) {
- if (!isTsOrTsxFile(fileName)) {
- // do not run semantic classification on non-ts-or-tsx files
- return { spans: [], endOfLineState: 0 /* None */ };
- }
- synchronizeHostData();
- return ts.getEncodedSemanticClassifications(program.getTypeChecker(), cancellationToken, getValidSourceFile(fileName), program.getClassifiableNames(), span);
- }
- function getSyntacticClassifications(fileName, span) {
- // doesn't use compiler - no need to synchronize with host
- return ts.getSyntacticClassifications(cancellationToken, syntaxTreeCache.getCurrentSourceFile(fileName), span);
- }
- function getEncodedSyntacticClassifications(fileName, span) {
- // doesn't use compiler - no need to synchronize with host
- return ts.getEncodedSyntacticClassifications(cancellationToken, syntaxTreeCache.getCurrentSourceFile(fileName), span);
- }
- function getOutliningSpans(fileName) {
- // doesn't use compiler - no need to synchronize with host
- var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
- return ts.OutliningElementsCollector.collectElements(sourceFile, cancellationToken);
- }
- var braceMatching = ts.createMapFromTemplate((_a = {},
- _a[17 /* OpenBraceToken */] = 18 /* CloseBraceToken */,
- _a[19 /* OpenParenToken */] = 20 /* CloseParenToken */,
- _a[21 /* OpenBracketToken */] = 22 /* CloseBracketToken */,
- _a[29 /* GreaterThanToken */] = 27 /* LessThanToken */,
- _a));
- braceMatching.forEach(function (value, key) { return braceMatching.set(value.toString(), Number(key)); });
- function getBraceMatchingAtPosition(fileName, position) {
- var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
- var token = ts.getTouchingToken(sourceFile, position, /*includeJsDocComment*/ false);
- var matchKind = token.getStart(sourceFile) === position ? braceMatching.get(token.kind.toString()) : undefined;
- var match = matchKind && ts.findChildOfKind(token.parent, matchKind, sourceFile);
- // We want to order the braces when we return the result.
- return match ? [ts.createTextSpanFromNode(token, sourceFile), ts.createTextSpanFromNode(match, sourceFile)].sort(function (a, b) { return a.start - b.start; }) : ts.emptyArray;
- }
- function getIndentationAtPosition(fileName, position, editorOptions) {
- var start = ts.timestamp();
- var settings = toEditorSettings(editorOptions);
- var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
- log("getIndentationAtPosition: getCurrentSourceFile: " + (ts.timestamp() - start));
- start = ts.timestamp();
- var result = ts.formatting.SmartIndenter.getIndentation(position, sourceFile, settings);
- log("getIndentationAtPosition: computeIndentation : " + (ts.timestamp() - start));
- return result;
- }
- function getFormattingEditsForRange(fileName, start, end, options) {
- var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
- return ts.formatting.formatSelection(start, end, sourceFile, ts.formatting.getFormatContext(toEditorSettings(options)));
- }
- function getFormattingEditsForDocument(fileName, options) {
- return ts.formatting.formatDocument(syntaxTreeCache.getCurrentSourceFile(fileName), ts.formatting.getFormatContext(toEditorSettings(options)));
- }
- function getFormattingEditsAfterKeystroke(fileName, position, key, options) {
- var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
- var formatContext = ts.formatting.getFormatContext(toEditorSettings(options));
- if (!ts.isInComment(sourceFile, position)) {
- switch (key) {
- case "{":
- return ts.formatting.formatOnOpeningCurly(position, sourceFile, formatContext);
- case "}":
- return ts.formatting.formatOnClosingCurly(position, sourceFile, formatContext);
- case ";":
- return ts.formatting.formatOnSemicolon(position, sourceFile, formatContext);
- case "\n":
- return ts.formatting.formatOnEnter(position, sourceFile, formatContext);
- }
- }
- return [];
- }
- function getCodeFixesAtPosition(fileName, start, end, errorCodes, formatOptions) {
- synchronizeHostData();
- var sourceFile = getValidSourceFile(fileName);
- var span = ts.createTextSpanFromBounds(start, end);
- var formatContext = ts.formatting.getFormatContext(formatOptions);
- return ts.flatMap(ts.deduplicate(errorCodes, ts.equateValues, ts.compareValues), function (errorCode) {
- cancellationToken.throwIfCancellationRequested();
- return ts.codefix.getFixes({ errorCode: errorCode, sourceFile: sourceFile, span: span, program: program, host: host, cancellationToken: cancellationToken, formatContext: formatContext });
- });
- }
- function getCombinedCodeFix(scope, fixId, formatOptions) {
- synchronizeHostData();
- ts.Debug.assert(scope.type === "file");
- var sourceFile = getValidSourceFile(scope.fileName);
- var formatContext = ts.formatting.getFormatContext(formatOptions);
- return ts.codefix.getAllFixes({ fixId: fixId, sourceFile: sourceFile, program: program, host: host, cancellationToken: cancellationToken, formatContext: formatContext });
- }
- function organizeImports(scope, formatOptions) {
- synchronizeHostData();
- ts.Debug.assert(scope.type === "file");
- var sourceFile = getValidSourceFile(scope.fileName);
- var formatContext = ts.formatting.getFormatContext(formatOptions);
- return ts.OrganizeImports.organizeImports(sourceFile, formatContext, host, program);
- }
- function applyCodeActionCommand(fileName, actionOrUndefined) {
- var action = typeof fileName === "string" ? actionOrUndefined : fileName;
- return ts.isArray(action) ? Promise.all(action.map(applySingleCodeActionCommand)) : applySingleCodeActionCommand(action);
- }
- function applySingleCodeActionCommand(action) {
- switch (action.type) {
- case "install package":
- return host.installPackage
- ? host.installPackage({ fileName: ts.toPath(action.file, currentDirectory, getCanonicalFileName), packageName: action.packageName })
- : Promise.reject("Host does not implement `installPackage`");
- default:
- ts.Debug.fail();
- // TODO: Debug.assertNever(action); will only work if there is more than one type.
- }
- }
- function getDocCommentTemplateAtPosition(fileName, position) {
- return ts.JsDoc.getDocCommentTemplateAtPosition(ts.getNewLineOrDefaultFromHost(host), syntaxTreeCache.getCurrentSourceFile(fileName), position);
- }
- function isValidBraceCompletionAtPosition(fileName, position, openingBrace) {
- // '<' is currently not supported, figuring out if we're in a Generic Type vs. a comparison is too
- // expensive to do during typing scenarios
- // i.e. whether we're dealing with:
- // var x = new foo<| ( with class foo{} )
- // or
- // var y = 3 <|
- if (openingBrace === 60 /* lessThan */) {
- return false;
- }
- var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
- // Check if in a context where we don't want to perform any insertion
- if (ts.isInString(sourceFile, position)) {
- return false;
- }
- if (ts.isInsideJsxElementOrAttribute(sourceFile, position)) {
- return openingBrace === 123 /* openBrace */;
- }
- if (ts.isInTemplateString(sourceFile, position)) {
- return false;
- }
- switch (openingBrace) {
- case 39 /* singleQuote */:
- case 34 /* doubleQuote */:
- case 96 /* backtick */:
- return !ts.isInComment(sourceFile, position);
- }
- return true;
- }
- function getSpanOfEnclosingComment(fileName, position, onlyMultiLine) {
- var sourceFile = syntaxTreeCache.getCurrentSourceFile(fileName);
- var range = ts.formatting.getRangeOfEnclosingComment(sourceFile, position, onlyMultiLine);
- return range && ts.createTextSpanFromRange(range);
- }
- function getTodoComments(fileName, descriptors) {
- // Note: while getting todo comments seems like a syntactic operation, we actually
- // treat it as a semantic operation here. This is because we expect our host to call
- // this on every single file. If we treat this syntactically, then that will cause
- // us to populate and throw away the tree in our syntax tree cache for each file. By
- // treating this as a semantic operation, we can access any tree without throwing
- // anything away.
- synchronizeHostData();
- var sourceFile = getValidSourceFile(fileName);
- cancellationToken.throwIfCancellationRequested();
- var fileContents = sourceFile.text;
- var result = [];
- // Exclude node_modules files as we don't want to show the todos of external libraries.
- if (descriptors.length > 0 && !isNodeModulesFile(sourceFile.fileName)) {
- var regExp = getTodoCommentsRegExp();
- var matchArray = void 0;
- while (matchArray = regExp.exec(fileContents)) {
- cancellationToken.throwIfCancellationRequested();
- // If we got a match, here is what the match array will look like. Say the source text is:
- //
- // " // hack 1"
- //
- // The result array with the regexp: will be:
- //
- // ["// hack 1", "// ", "hack 1", undefined, "hack"]
- //
- // Here are the relevant capture groups:
- // 0) The full match for the entire regexp.
- // 1) The preamble to the message portion.
- // 2) The message portion.
- // 3...N) The descriptor that was matched - by index. 'undefined' for each
- // descriptor that didn't match. an actual value if it did match.
- //
- // i.e. 'undefined' in position 3 above means TODO(jason) didn't match.
- // "hack" in position 4 means HACK did match.
- var firstDescriptorCaptureIndex = 3;
- ts.Debug.assert(matchArray.length === descriptors.length + firstDescriptorCaptureIndex);
- var preamble = matchArray[1];
- var matchPosition = matchArray.index + preamble.length;
- // OK, we have found a match in the file. This is only an acceptable match if
- // it is contained within a comment.
- if (!ts.isInComment(sourceFile, matchPosition)) {
- continue;
- }
- var descriptor = void 0;
- for (var i = 0; i < descriptors.length; i++) {
- if (matchArray[i + firstDescriptorCaptureIndex]) {
- descriptor = descriptors[i];
- }
- }
- ts.Debug.assert(descriptor !== undefined);
- // We don't want to match something like 'TODOBY', so we make sure a non
- // letter/digit follows the match.
- if (isLetterOrDigit(fileContents.charCodeAt(matchPosition + descriptor.text.length))) {
- continue;
- }
- var message = matchArray[2];
- result.push({ descriptor: descriptor, message: message, position: matchPosition });
- }
- }
- return result;
- function escapeRegExp(str) {
- return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
- }
- function getTodoCommentsRegExp() {
- // NOTE: `?:` means 'non-capture group'. It allows us to have groups without having to
- // filter them out later in the final result array.
- // TODO comments can appear in one of the following forms:
- //
- // 1) // TODO or /////////// TODO
- //
- // 2) /* TODO or /********** TODO
- //
- // 3) /*
- // * TODO
- // */
- //
- // The following three regexps are used to match the start of the text up to the TODO
- // comment portion.
- var singleLineCommentStart = /(?:\/\/+\s*)/.source;
- var multiLineCommentStart = /(?:\/\*+\s*)/.source;
- var anyNumberOfSpacesAndAsterisksAtStartOfLine = /(?:^(?:\s|\*)*)/.source;
- // Match any of the above three TODO comment start regexps.
- // Note that the outermost group *is* a capture group. We want to capture the preamble
- // so that we can determine the starting position of the TODO comment match.
- var preamble = "(" + anyNumberOfSpacesAndAsterisksAtStartOfLine + "|" + singleLineCommentStart + "|" + multiLineCommentStart + ")";
- // Takes the descriptors and forms a regexp that matches them as if they were literals.
- // For example, if the descriptors are "TODO(jason)" and "HACK", then this will be:
- //
- // (?:(TODO\(jason\))|(HACK))
- //
- // Note that the outermost group is *not* a capture group, but the innermost groups
- // *are* capture groups. By capturing the inner literals we can determine after
- // matching which descriptor we are dealing with.
- var literals = "(?:" + ts.map(descriptors, function (d) { return "(" + escapeRegExp(d.text) + ")"; }).join("|") + ")";
- // After matching a descriptor literal, the following regexp matches the rest of the
- // text up to the end of the line (or */).
- var endOfLineOrEndOfComment = /(?:$|\*\/)/.source;
- var messageRemainder = /(?:.*?)/.source;
- // This is the portion of the match we'll return as part of the TODO comment result. We
- // match the literal portion up to the end of the line or end of comment.
- var messagePortion = "(" + literals + messageRemainder + ")";
- var regExpString = preamble + messagePortion + endOfLineOrEndOfComment;
- // The final regexp will look like this:
- // /((?:\/\/+\s*)|(?:\/\*+\s*)|(?:^(?:\s|\*)*))((?:(TODO\(jason\))|(HACK))(?:.*?))(?:$|\*\/)/gim
- // The flags of the regexp are important here.
- // 'g' is so that we are doing a global search and can find matches several times
- // in the input.
- //
- // 'i' is for case insensitivity (We do this to match C# TODO comment code).
- //
- // 'm' is so we can find matches in a multi-line input.
- return new RegExp(regExpString, "gim");
- }
- function isLetterOrDigit(char) {
- return (char >= 97 /* a */ && char <= 122 /* z */) ||
- (char >= 65 /* A */ && char <= 90 /* Z */) ||
- (char >= 48 /* _0 */ && char <= 57 /* _9 */);
- }
- function isNodeModulesFile(path) {
- return ts.stringContains(path, "/node_modules/");
- }
- }
- function getRenameInfo(fileName, position) {
- synchronizeHostData();
- var defaultLibFileName = host.getDefaultLibFileName(host.getCompilationSettings());
- return ts.Rename.getRenameInfo(program.getTypeChecker(), defaultLibFileName, getCanonicalFileName, getValidSourceFile(fileName), position);
- }
- function getRefactorContext(file, positionOrRange, formatOptions) {
- var _a = typeof positionOrRange === "number" ? [positionOrRange, undefined] : [positionOrRange.pos, positionOrRange.end], startPosition = _a[0], endPosition = _a[1];
- return {
- file: file,
- startPosition: startPosition,
- endPosition: endPosition,
- program: getProgram(),
- host: host,
- formatContext: ts.formatting.getFormatContext(formatOptions),
- cancellationToken: cancellationToken,
- };
- }
- function getApplicableRefactors(fileName, positionOrRange) {
- synchronizeHostData();
- var file = getValidSourceFile(fileName);
- return ts.refactor.getApplicableRefactors(getRefactorContext(file, positionOrRange));
- }
- function getEditsForRefactor(fileName, formatOptions, positionOrRange, refactorName, actionName) {
- synchronizeHostData();
- var file = getValidSourceFile(fileName);
- return ts.refactor.getEditsForRefactor(getRefactorContext(file, positionOrRange, formatOptions), refactorName, actionName);
- }
- return {
- dispose: dispose,
- cleanupSemanticCache: cleanupSemanticCache,
- getSyntacticDiagnostics: getSyntacticDiagnostics,
- getSemanticDiagnostics: getSemanticDiagnostics,
- getSuggestionDiagnostics: getSuggestionDiagnostics,
- getCompilerOptionsDiagnostics: getCompilerOptionsDiagnostics,
- getSyntacticClassifications: getSyntacticClassifications,
- getSemanticClassifications: getSemanticClassifications,
- getEncodedSyntacticClassifications: getEncodedSyntacticClassifications,
- getEncodedSemanticClassifications: getEncodedSemanticClassifications,
- getCompletionsAtPosition: getCompletionsAtPosition,
- getCompletionEntryDetails: getCompletionEntryDetails,
- getCompletionEntrySymbol: getCompletionEntrySymbol,
- getSignatureHelpItems: getSignatureHelpItems,
- getQuickInfoAtPosition: getQuickInfoAtPosition,
- getDefinitionAtPosition: getDefinitionAtPosition,
- getDefinitionAndBoundSpan: getDefinitionAndBoundSpan,
- getImplementationAtPosition: getImplementationAtPosition,
- getTypeDefinitionAtPosition: getTypeDefinitionAtPosition,
- getReferencesAtPosition: getReferencesAtPosition,
- findReferences: findReferences,
- getOccurrencesAtPosition: getOccurrencesAtPosition,
- getDocumentHighlights: getDocumentHighlights,
- getNameOrDottedNameSpan: getNameOrDottedNameSpan,
- getBreakpointStatementAtPosition: getBreakpointStatementAtPosition,
- getNavigateToItems: getNavigateToItems,
- getRenameInfo: getRenameInfo,
- findRenameLocations: findRenameLocations,
- getNavigationBarItems: getNavigationBarItems,
- getNavigationTree: getNavigationTree,
- getOutliningSpans: getOutliningSpans,
- getTodoComments: getTodoComments,
- getBraceMatchingAtPosition: getBraceMatchingAtPosition,
- getIndentationAtPosition: getIndentationAtPosition,
- getFormattingEditsForRange: getFormattingEditsForRange,
- getFormattingEditsForDocument: getFormattingEditsForDocument,
- getFormattingEditsAfterKeystroke: getFormattingEditsAfterKeystroke,
- getDocCommentTemplateAtPosition: getDocCommentTemplateAtPosition,
- isValidBraceCompletionAtPosition: isValidBraceCompletionAtPosition,
- getSpanOfEnclosingComment: getSpanOfEnclosingComment,
- getCodeFixesAtPosition: getCodeFixesAtPosition,
- getCombinedCodeFix: getCombinedCodeFix,
- applyCodeActionCommand: applyCodeActionCommand,
- organizeImports: organizeImports,
- getEmitOutput: getEmitOutput,
- getNonBoundSourceFile: getNonBoundSourceFile,
- getSourceFile: getSourceFile,
- getProgram: getProgram,
- getApplicableRefactors: getApplicableRefactors,
- getEditsForRefactor: getEditsForRefactor,
- };
- var _a;
- }
- ts.createLanguageService = createLanguageService;
- /* @internal */
- /** Names in the name table are escaped, so an identifier `__foo` will have a name table entry `___foo`. */
- function getNameTable(sourceFile) {
- if (!sourceFile.nameTable) {
- initializeNameTable(sourceFile);
- }
- return sourceFile.nameTable;
- }
- ts.getNameTable = getNameTable;
- function initializeNameTable(sourceFile) {
- var nameTable = sourceFile.nameTable = ts.createUnderscoreEscapedMap();
- sourceFile.forEachChild(function walk(node) {
- if (ts.isIdentifier(node) && node.escapedText || ts.isStringOrNumericLiteral(node) && literalIsName(node)) {
- var text = ts.getEscapedTextOfIdentifierOrLiteral(node);
- nameTable.set(text, nameTable.get(text) === undefined ? node.pos : -1);
- }
- ts.forEachChild(node, walk);
- if (ts.hasJSDocNodes(node)) {
- for (var _i = 0, _a = node.jsDoc; _i < _a.length; _i++) {
- var jsDoc = _a[_i];
- ts.forEachChild(jsDoc, walk);
- }
- }
- });
- }
- /**
- * We want to store any numbers/strings if they were a name that could be
- * related to a declaration. So, if we have 'import x = require("something")'
- * then we want 'something' to be in the name table. Similarly, if we have
- * "a['propname']" then we want to store "propname" in the name table.
- */
- function literalIsName(node) {
- return ts.isDeclarationName(node) ||
- node.parent.kind === 252 /* ExternalModuleReference */ ||
- isArgumentOfElementAccessExpression(node) ||
- ts.isLiteralComputedPropertyDeclarationName(node);
- }
- /**
- * Returns the containing object literal property declaration given a possible name node, e.g. "a" in x = { "a": 1 }
- */
- /* @internal */
- function getContainingObjectLiteralElement(node) {
- switch (node.kind) {
- case 9 /* StringLiteral */:
- case 8 /* NumericLiteral */:
- if (node.parent.kind === 146 /* ComputedPropertyName */) {
- return ts.isObjectLiteralElement(node.parent.parent) ? node.parent.parent : undefined;
- }
- // falls through
- case 71 /* Identifier */:
- return ts.isObjectLiteralElement(node.parent) &&
- (node.parent.parent.kind === 182 /* ObjectLiteralExpression */ || node.parent.parent.kind === 261 /* JsxAttributes */) &&
- node.parent.name === node ? node.parent : undefined;
- }
- return undefined;
- }
- ts.getContainingObjectLiteralElement = getContainingObjectLiteralElement;
- /* @internal */
- function getPropertySymbolsFromContextualType(typeChecker, node) {
- var objectLiteral = node.parent;
- var contextualType = typeChecker.getContextualType(objectLiteral);
- return getPropertySymbolsFromType(contextualType, node.name);
- }
- ts.getPropertySymbolsFromContextualType = getPropertySymbolsFromContextualType;
- /* @internal */
- function getPropertySymbolsFromType(type, propName) {
- var name = ts.unescapeLeadingUnderscores(ts.getTextOfPropertyName(propName));
- if (name && type) {
- var result_6 = [];
- var symbol = type.getProperty(name);
- if (type.flags & 131072 /* Union */) {
- ts.forEach(type.types, function (t) {
- var symbol = t.getProperty(name);
- if (symbol) {
- result_6.push(symbol);
- }
- });
- return result_6;
- }
- if (symbol) {
- result_6.push(symbol);
- return result_6;
- }
- }
- return undefined;
- }
- ts.getPropertySymbolsFromType = getPropertySymbolsFromType;
- function isArgumentOfElementAccessExpression(node) {
- return node &&
- node.parent &&
- node.parent.kind === 184 /* ElementAccessExpression */ &&
- node.parent.argumentExpression === node;
- }
- /**
- * Get the path of the default library files (lib.d.ts) as distributed with the typescript
- * node package.
- * The functionality is not supported if the ts module is consumed outside of a node module.
- */
- function getDefaultLibFilePath(options) {
- // Check __dirname is defined and that we are on a node.js system.
- if (typeof __dirname !== "undefined") {
- return __dirname + ts.directorySeparator + ts.getDefaultLibFileName(options);
- }
- throw new Error("getDefaultLibFilePath is only supported when consumed as a node module. ");
- }
- ts.getDefaultLibFilePath = getDefaultLibFilePath;
- ts.objectAllocator = getServicesObjectAllocator();
-})(ts || (ts = {}));
-// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0.
-// See LICENSE.txt in the project root for complete license information.
-///
-/* @internal */
-var ts;
-(function (ts) {
- var BreakpointResolver;
- (function (BreakpointResolver) {
- /**
- * Get the breakpoint span in given sourceFile
- */
- function spanInSourceFileAtLocation(sourceFile, position) {
- // Cannot set breakpoint in dts file
- if (sourceFile.isDeclarationFile) {
- return undefined;
- }
- var tokenAtLocation = ts.getTokenAtPosition(sourceFile, position, /*includeJsDocComment*/ false);
- var lineOfPosition = sourceFile.getLineAndCharacterOfPosition(position).line;
- if (sourceFile.getLineAndCharacterOfPosition(tokenAtLocation.getStart(sourceFile)).line > lineOfPosition) {
- // Get previous token if the token is returned starts on new line
- // eg: let x =10; |--- cursor is here
- // let y = 10;
- // token at position will return let keyword on second line as the token but we would like to use
- // token on same line if trailing trivia (comments or white spaces on same line) part of the last token on that line
- tokenAtLocation = ts.findPrecedingToken(tokenAtLocation.pos, sourceFile);
- // It's a blank line
- if (!tokenAtLocation || sourceFile.getLineAndCharacterOfPosition(tokenAtLocation.getEnd()).line !== lineOfPosition) {
- return undefined;
- }
- }
- // Cannot set breakpoint in ambient declarations
- if (tokenAtLocation.flags & 2097152 /* Ambient */) {
- return undefined;
- }
- // Get the span in the node based on its syntax
- return spanInNode(tokenAtLocation);
- function textSpan(startNode, endNode) {
- var start = startNode.decorators ?
- ts.skipTrivia(sourceFile.text, startNode.decorators.end) :
- startNode.getStart(sourceFile);
- return ts.createTextSpanFromBounds(start, (endNode || startNode).getEnd());
- }
- function textSpanEndingAtNextToken(startNode, previousTokenToFindNextEndToken) {
- return textSpan(startNode, ts.findNextToken(previousTokenToFindNextEndToken, previousTokenToFindNextEndToken.parent));
- }
- function spanInNodeIfStartsOnSameLine(node, otherwiseOnNode) {
- if (node && lineOfPosition === sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line) {
- return spanInNode(node);
- }
- return spanInNode(otherwiseOnNode);
- }
- function spanInNodeArray(nodeArray) {
- return ts.createTextSpanFromBounds(ts.skipTrivia(sourceFile.text, nodeArray.pos), nodeArray.end);
- }
- function spanInPreviousNode(node) {
- return spanInNode(ts.findPrecedingToken(node.pos, sourceFile));
- }
- function spanInNextNode(node) {
- return spanInNode(ts.findNextToken(node, node.parent));
- }
- function spanInNode(node) {
- if (node) {
- switch (node.kind) {
- case 212 /* VariableStatement */:
- // Span on first variable declaration
- return spanInVariableDeclaration(node.declarationList.declarations[0]);
- case 230 /* VariableDeclaration */:
- case 151 /* PropertyDeclaration */:
- case 150 /* PropertySignature */:
- return spanInVariableDeclaration(node);
- case 148 /* Parameter */:
- return spanInParameterDeclaration(node);
- case 232 /* FunctionDeclaration */:
- case 153 /* MethodDeclaration */:
- case 152 /* MethodSignature */:
- case 155 /* GetAccessor */:
- case 156 /* SetAccessor */:
- case 154 /* Constructor */:
- case 190 /* FunctionExpression */:
- case 191 /* ArrowFunction */:
- return spanInFunctionDeclaration(node);
- case 211 /* Block */:
- if (ts.isFunctionBlock(node)) {
- return spanInFunctionBlock(node);
- }
- // falls through
- case 238 /* ModuleBlock */:
- return spanInBlock(node);
- case 267 /* CatchClause */:
- return spanInBlock(node.block);
- case 214 /* ExpressionStatement */:
- // span on the expression
- return textSpan(node.expression);
- case 223 /* ReturnStatement */:
- // span on return keyword and expression if present
- return textSpan(node.getChildAt(0), node.expression);
- case 217 /* WhileStatement */:
- // Span on while(...)
- return textSpanEndingAtNextToken(node, node.expression);
- case 216 /* DoStatement */:
- // span in statement of the do statement
- return spanInNode(node.statement);
- case 229 /* DebuggerStatement */:
- // span on debugger keyword
- return textSpan(node.getChildAt(0));
- case 215 /* IfStatement */:
- // set on if(..) span
- return textSpanEndingAtNextToken(node, node.expression);
- case 226 /* LabeledStatement */:
- // span in statement
- return spanInNode(node.statement);
- case 222 /* BreakStatement */:
- case 221 /* ContinueStatement */:
- // On break or continue keyword and label if present
- return textSpan(node.getChildAt(0), node.label);
- case 218 /* ForStatement */:
- return spanInForStatement(node);
- case 219 /* ForInStatement */:
- // span of for (a in ...)
- return textSpanEndingAtNextToken(node, node.expression);
- case 220 /* ForOfStatement */:
- // span in initializer
- return spanInInitializerOfForLike(node);
- case 225 /* SwitchStatement */:
- // span on switch(...)
- return textSpanEndingAtNextToken(node, node.expression);
- case 264 /* CaseClause */:
- case 265 /* DefaultClause */:
- // span in first statement of the clause
- return spanInNode(node.statements[0]);
- case 228 /* TryStatement */:
- // span in try block
- return spanInBlock(node.tryBlock);
- case 227 /* ThrowStatement */:
- // span in throw ...
- return textSpan(node, node.expression);
- case 247 /* ExportAssignment */:
- // span on export = id
- return textSpan(node, node.expression);
- case 241 /* ImportEqualsDeclaration */:
- // import statement without including semicolon
- return textSpan(node, node.moduleReference);
- case 242 /* ImportDeclaration */:
- // import statement without including semicolon
- return textSpan(node, node.moduleSpecifier);
- case 248 /* ExportDeclaration */:
- // import statement without including semicolon
- return textSpan(node, node.moduleSpecifier);
- case 237 /* ModuleDeclaration */:
- // span on complete module if it is instantiated
- if (ts.getModuleInstanceState(node) !== 1 /* Instantiated */) {
- return undefined;
- }
- // falls through
- case 233 /* ClassDeclaration */:
- case 236 /* EnumDeclaration */:
- case 271 /* EnumMember */:
- case 180 /* BindingElement */:
- // span on complete node
- return textSpan(node);
- case 224 /* WithStatement */:
- // span in statement
- return spanInNode(node.statement);
- case 149 /* Decorator */:
- return spanInNodeArray(node.parent.decorators);
- case 178 /* ObjectBindingPattern */:
- case 179 /* ArrayBindingPattern */:
- return spanInBindingPattern(node);
- // No breakpoint in interface, type alias
- case 234 /* InterfaceDeclaration */:
- case 235 /* TypeAliasDeclaration */:
- return undefined;
- // Tokens:
- case 25 /* SemicolonToken */:
- case 1 /* EndOfFileToken */:
- return spanInNodeIfStartsOnSameLine(ts.findPrecedingToken(node.pos, sourceFile));
- case 26 /* CommaToken */:
- return spanInPreviousNode(node);
- case 17 /* OpenBraceToken */:
- return spanInOpenBraceToken(node);
- case 18 /* CloseBraceToken */:
- return spanInCloseBraceToken(node);
- case 22 /* CloseBracketToken */:
- return spanInCloseBracketToken(node);
- case 19 /* OpenParenToken */:
- return spanInOpenParenToken(node);
- case 20 /* CloseParenToken */:
- return spanInCloseParenToken(node);
- case 56 /* ColonToken */:
- return spanInColonToken(node);
- case 29 /* GreaterThanToken */:
- case 27 /* LessThanToken */:
- return spanInGreaterThanOrLessThanToken(node);
- // Keywords:
- case 106 /* WhileKeyword */:
- return spanInWhileKeyword(node);
- case 82 /* ElseKeyword */:
- case 74 /* CatchKeyword */:
- case 87 /* FinallyKeyword */:
- return spanInNextNode(node);
- case 144 /* OfKeyword */:
- return spanInOfKeyword(node);
- default:
- // Destructuring pattern in destructuring assignment
- // [a, b, c] of
- // [a, b, c] = expression
- if (ts.isArrayLiteralOrObjectLiteralDestructuringPattern(node)) {
- return spanInArrayLiteralOrObjectLiteralDestructuringPattern(node);
- }
- // Set breakpoint on identifier element of destructuring pattern
- // `a` or `...c` or `d: x` from
- // `[a, b, ...c]` or `{ a, b }` or `{ d: x }` from destructuring pattern
- if ((node.kind === 71 /* Identifier */ ||
- node.kind === 202 /* SpreadElement */ ||
- node.kind === 268 /* PropertyAssignment */ ||
- node.kind === 269 /* ShorthandPropertyAssignment */) &&
- ts.isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent)) {
- return textSpan(node);
- }
- if (node.kind === 198 /* BinaryExpression */) {
- var _a = node, left = _a.left, operatorToken = _a.operatorToken;
- // Set breakpoint in destructuring pattern if its destructuring assignment
- // [a, b, c] or {a, b, c} of
- // [a, b, c] = expression or
- // {a, b, c} = expression
- if (ts.isArrayLiteralOrObjectLiteralDestructuringPattern(left)) {
- return spanInArrayLiteralOrObjectLiteralDestructuringPattern(left);
- }
- if (operatorToken.kind === 58 /* EqualsToken */ && ts.isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent)) {
- // Set breakpoint on assignment expression element of destructuring pattern
- // a = expression of
- // [a = expression, b, c] = someExpression or
- // { a = expression, b, c } = someExpression
- return textSpan(node);
- }
- if (operatorToken.kind === 26 /* CommaToken */) {
- return spanInNode(left);
- }
- }
- if (ts.isExpressionNode(node)) {
- switch (node.parent.kind) {
- case 216 /* DoStatement */:
- // Set span as if on while keyword
- return spanInPreviousNode(node);
- case 149 /* Decorator */:
- // Set breakpoint on the decorator emit
- return spanInNode(node.parent);
- case 218 /* ForStatement */:
- case 220 /* ForOfStatement */:
- return textSpan(node);
- case 198 /* BinaryExpression */:
- if (node.parent.operatorToken.kind === 26 /* CommaToken */) {
- // If this is a comma expression, the breakpoint is possible in this expression
- return textSpan(node);
- }
- break;
- case 191 /* ArrowFunction */:
- if (node.parent.body === node) {
- // If this is body of arrow function, it is allowed to have the breakpoint
- return textSpan(node);
- }
- break;
- }
- }
- switch (node.parent.kind) {
- case 268 /* PropertyAssignment */:
- // If this is name of property assignment, set breakpoint in the initializer
- if (node.parent.name === node &&
- !ts.isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent.parent)) {
- return spanInNode(node.parent.initializer);
- }
- break;
- case 188 /* TypeAssertionExpression */:
- // Breakpoint in type assertion goes to its operand
- if (node.parent.type === node) {
- return spanInNextNode(node.parent.type);
- }
- break;
- case 230 /* VariableDeclaration */:
- case 148 /* Parameter */: {
- // initializer of variable/parameter declaration go to previous node
- var _b = node.parent, initializer = _b.initializer, type = _b.type;
- if (initializer === node || type === node || ts.isAssignmentOperator(node.kind)) {
- return spanInPreviousNode(node);
- }
- break;
- }
- case 198 /* BinaryExpression */: {
- var left = node.parent.left;
- if (ts.isArrayLiteralOrObjectLiteralDestructuringPattern(left) && node !== left) {
- // If initializer of destructuring assignment move to previous token
- return spanInPreviousNode(node);
- }
- break;
- }
- default:
- // return type of function go to previous token
- if (ts.isFunctionLike(node.parent) && node.parent.type === node) {
- return spanInPreviousNode(node);
- }
- }
- // Default go to parent to set the breakpoint
- return spanInNode(node.parent);
- }
- }
- function textSpanFromVariableDeclaration(variableDeclaration) {
- if (ts.isVariableDeclarationList(variableDeclaration.parent) && variableDeclaration.parent.declarations[0] === variableDeclaration) {
- // First declaration - include let keyword
- return textSpan(ts.findPrecedingToken(variableDeclaration.pos, sourceFile, variableDeclaration.parent), variableDeclaration);
- }
- else {
- // Span only on this declaration
- return textSpan(variableDeclaration);
- }
- }
- function spanInVariableDeclaration(variableDeclaration) {
- // If declaration of for in statement, just set the span in parent
- if (variableDeclaration.parent.parent.kind === 219 /* ForInStatement */) {
- return spanInNode(variableDeclaration.parent.parent);
- }
- // If this is a destructuring pattern, set breakpoint in binding pattern
- if (ts.isBindingPattern(variableDeclaration.name)) {
- return spanInBindingPattern(variableDeclaration.name);
- }
- // Breakpoint is possible in variableDeclaration only if there is initialization
- // or its declaration from 'for of'
- if (variableDeclaration.initializer ||
- ts.hasModifier(variableDeclaration, 1 /* Export */) ||
- variableDeclaration.parent.parent.kind === 220 /* ForOfStatement */) {
- return textSpanFromVariableDeclaration(variableDeclaration);
- }
- if (ts.isVariableDeclarationList(variableDeclaration.parent) &&
- variableDeclaration.parent.declarations[0] !== variableDeclaration) {
- // If we cannot set breakpoint on this declaration, set it on previous one
- // Because the variable declaration may be binding pattern and
- // we would like to set breakpoint in last binding element if that's the case,
- // use preceding token instead
- return spanInNode(ts.findPrecedingToken(variableDeclaration.pos, sourceFile, variableDeclaration.parent));
- }
- }
- function canHaveSpanInParameterDeclaration(parameter) {
- // Breakpoint is possible on parameter only if it has initializer, is a rest parameter, or has public or private modifier
- return !!parameter.initializer || parameter.dotDotDotToken !== undefined ||
- ts.hasModifier(parameter, 4 /* Public */ | 8 /* Private */);
- }
- function spanInParameterDeclaration(parameter) {
- if (ts.isBindingPattern(parameter.name)) {
- // Set breakpoint in binding pattern
- return spanInBindingPattern(parameter.name);
- }
- else if (canHaveSpanInParameterDeclaration(parameter)) {
- return textSpan(parameter);
- }
- else {
- var functionDeclaration = parameter.parent;
- var indexOfParameter = functionDeclaration.parameters.indexOf(parameter);
- ts.Debug.assert(indexOfParameter !== -1);
- if (indexOfParameter !== 0) {
- // Not a first parameter, go to previous parameter
- return spanInParameterDeclaration(functionDeclaration.parameters[indexOfParameter - 1]);
- }
- else {
- // Set breakpoint in the function declaration body
- return spanInNode(functionDeclaration.body);
- }
- }
- }
- function canFunctionHaveSpanInWholeDeclaration(functionDeclaration) {
- return ts.hasModifier(functionDeclaration, 1 /* Export */) ||
- (functionDeclaration.parent.kind === 233 /* ClassDeclaration */ && functionDeclaration.kind !== 154 /* Constructor */);
- }
- function spanInFunctionDeclaration(functionDeclaration) {
- // No breakpoints in the function signature
- if (!functionDeclaration.body) {
- return undefined;
- }
- if (canFunctionHaveSpanInWholeDeclaration(functionDeclaration)) {
- // Set the span on whole function declaration
- return textSpan(functionDeclaration);
- }
- // Set span in function body
- return spanInNode(functionDeclaration.body);
- }
- function spanInFunctionBlock(block) {
- var nodeForSpanInBlock = block.statements.length ? block.statements[0] : block.getLastToken();
- if (canFunctionHaveSpanInWholeDeclaration(block.parent)) {
- return spanInNodeIfStartsOnSameLine(block.parent, nodeForSpanInBlock);
- }
- return spanInNode(nodeForSpanInBlock);
- }
- function spanInBlock(block) {
- switch (block.parent.kind) {
- case 237 /* ModuleDeclaration */:
- if (ts.getModuleInstanceState(block.parent) !== 1 /* Instantiated */) {
- return undefined;
- }
- // falls through
- // Set on parent if on same line otherwise on first statement
- case 217 /* WhileStatement */:
- case 215 /* IfStatement */:
- case 219 /* ForInStatement */:
- return spanInNodeIfStartsOnSameLine(block.parent, block.statements[0]);
- // Set span on previous token if it starts on same line otherwise on the first statement of the block
- case 218 /* ForStatement */:
- case 220 /* ForOfStatement */:
- return spanInNodeIfStartsOnSameLine(ts.findPrecedingToken(block.pos, sourceFile, block.parent), block.statements[0]);
- }
- // Default action is to set on first statement
- return spanInNode(block.statements[0]);
- }
- function spanInInitializerOfForLike(forLikeStatement) {
- if (forLikeStatement.initializer.kind === 231 /* VariableDeclarationList */) {
- // Declaration list - set breakpoint in first declaration
- var variableDeclarationList = forLikeStatement.initializer;
- if (variableDeclarationList.declarations.length > 0) {
- return spanInNode(variableDeclarationList.declarations[0]);
- }
- }
- else {
- // Expression - set breakpoint in it
- return spanInNode(forLikeStatement.initializer);
- }
- }
- function spanInForStatement(forStatement) {
- if (forStatement.initializer) {
- return spanInInitializerOfForLike(forStatement);
- }
- if (forStatement.condition) {
- return textSpan(forStatement.condition);
- }
- if (forStatement.incrementor) {
- return textSpan(forStatement.incrementor);
- }
- }
- function spanInBindingPattern(bindingPattern) {
- // Set breakpoint in first binding element
- var firstBindingElement = ts.forEach(bindingPattern.elements, function (element) { return element.kind !== 204 /* OmittedExpression */ ? element : undefined; });
- if (firstBindingElement) {
- return spanInNode(firstBindingElement);
- }
- // Empty binding pattern of binding element, set breakpoint on binding element
- if (bindingPattern.parent.kind === 180 /* BindingElement */) {
- return textSpan(bindingPattern.parent);
- }
- // Variable declaration is used as the span
- return textSpanFromVariableDeclaration(bindingPattern.parent);
- }
- function spanInArrayLiteralOrObjectLiteralDestructuringPattern(node) {
- ts.Debug.assert(node.kind !== 179 /* ArrayBindingPattern */ && node.kind !== 178 /* ObjectBindingPattern */);
- var elements = node.kind === 181 /* ArrayLiteralExpression */ ? node.elements : node.properties;
- var firstBindingElement = ts.forEach(elements, function (element) { return element.kind !== 204 /* OmittedExpression */ ? element : undefined; });
- if (firstBindingElement) {
- return spanInNode(firstBindingElement);
- }
- // Could be ArrayLiteral from destructuring assignment or
- // just nested element in another destructuring assignment
- // set breakpoint on assignment when parent is destructuring assignment
- // Otherwise set breakpoint for this element
- return textSpan(node.parent.kind === 198 /* BinaryExpression */ ? node.parent : node);
- }
- // Tokens:
- function spanInOpenBraceToken(node) {
- switch (node.parent.kind) {
- case 236 /* EnumDeclaration */:
- var enumDeclaration = node.parent;
- return spanInNodeIfStartsOnSameLine(ts.findPrecedingToken(node.pos, sourceFile, node.parent), enumDeclaration.members.length ? enumDeclaration.members[0] : enumDeclaration.getLastToken(sourceFile));
- case 233 /* ClassDeclaration */:
- var classDeclaration = node.parent;
- return spanInNodeIfStartsOnSameLine(ts.findPrecedingToken(node.pos, sourceFile, node.parent), classDeclaration.members.length ? classDeclaration.members[0] : classDeclaration.getLastToken(sourceFile));
- case 239 /* CaseBlock */:
- return spanInNodeIfStartsOnSameLine(node.parent.parent, node.parent.clauses[0]);
- }
- // Default to parent node
- return spanInNode(node.parent);
- }
- function spanInCloseBraceToken(node) {
- switch (node.parent.kind) {
- case 238 /* ModuleBlock */:
- // If this is not an instantiated module block, no bp span
- if (ts.getModuleInstanceState(node.parent.parent) !== 1 /* Instantiated */) {
- return undefined;
- }
- // falls through
- case 236 /* EnumDeclaration */:
- case 233 /* ClassDeclaration */:
- // Span on close brace token
- return textSpan(node);
- case 211 /* Block */:
- if (ts.isFunctionBlock(node.parent)) {
- // Span on close brace token
- return textSpan(node);
- }
- // falls through
- case 267 /* CatchClause */:
- return spanInNode(ts.lastOrUndefined(node.parent.statements));
- case 239 /* CaseBlock */:
- // breakpoint in last statement of the last clause
- var caseBlock = node.parent;
- var lastClause = ts.lastOrUndefined(caseBlock.clauses);
- if (lastClause) {
- return spanInNode(ts.lastOrUndefined(lastClause.statements));
- }
- return undefined;
- case 178 /* ObjectBindingPattern */:
- // Breakpoint in last binding element or binding pattern if it contains no elements
- var bindingPattern = node.parent;
- return spanInNode(ts.lastOrUndefined(bindingPattern.elements) || bindingPattern);
- // Default to parent node
- default:
- if (ts.isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent)) {
- // Breakpoint in last binding element or binding pattern if it contains no elements
- var objectLiteral = node.parent;
- return textSpan(ts.lastOrUndefined(objectLiteral.properties) || objectLiteral);
- }
- return spanInNode(node.parent);
- }
- }
- function spanInCloseBracketToken(node) {
- switch (node.parent.kind) {
- case 179 /* ArrayBindingPattern */:
- // Breakpoint in last binding element or binding pattern if it contains no elements
- var bindingPattern = node.parent;
- return textSpan(ts.lastOrUndefined(bindingPattern.elements) || bindingPattern);
- default:
- if (ts.isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent)) {
- // Breakpoint in last binding element or binding pattern if it contains no elements
- var arrayLiteral = node.parent;
- return textSpan(ts.lastOrUndefined(arrayLiteral.elements) || arrayLiteral);
- }
- // Default to parent node
- return spanInNode(node.parent);
- }
- }
- function spanInOpenParenToken(node) {
- if (node.parent.kind === 216 /* DoStatement */ || // Go to while keyword and do action instead
- node.parent.kind === 185 /* CallExpression */ ||
- node.parent.kind === 186 /* NewExpression */) {
- return spanInPreviousNode(node);
- }
- if (node.parent.kind === 189 /* ParenthesizedExpression */) {
- return spanInNextNode(node);
- }
- // Default to parent node
- return spanInNode(node.parent);
- }
- function spanInCloseParenToken(node) {
- // Is this close paren token of parameter list, set span in previous token
- switch (node.parent.kind) {
- case 190 /* FunctionExpression */:
- case 232 /* FunctionDeclaration */:
- case 191 /* ArrowFunction */:
- case 153 /* MethodDeclaration */:
- case 152 /* MethodSignature */:
- case 155 /* GetAccessor */:
- case 156 /* SetAccessor */:
- case 154 /* Constructor */:
- case 217 /* WhileStatement */:
- case 216 /* DoStatement */:
- case 218 /* ForStatement */:
- case 220 /* ForOfStatement */:
- case 185 /* CallExpression */:
- case 186 /* NewExpression */:
- case 189 /* ParenthesizedExpression */:
- return spanInPreviousNode(node);
- // Default to parent node
- default:
- return spanInNode(node.parent);
- }
- }
- function spanInColonToken(node) {
- // Is this : specifying return annotation of the function declaration
- if (ts.isFunctionLike(node.parent) ||
- node.parent.kind === 268 /* PropertyAssignment */ ||
- node.parent.kind === 148 /* Parameter */) {
- return spanInPreviousNode(node);
- }
- return spanInNode(node.parent);
- }
- function spanInGreaterThanOrLessThanToken(node) {
- if (node.parent.kind === 188 /* TypeAssertionExpression */) {
- return spanInNextNode(node);
- }
- return spanInNode(node.parent);
- }
- function spanInWhileKeyword(node) {
- if (node.parent.kind === 216 /* DoStatement */) {
- // Set span on while expression
- return textSpanEndingAtNextToken(node, node.parent.expression);
- }
- // Default to parent node
- return spanInNode(node.parent);
- }
- function spanInOfKeyword(node) {
- if (node.parent.kind === 220 /* ForOfStatement */) {
- // Set using next token
- return spanInNextNode(node);
- }
- // Default to parent node
- return spanInNode(node.parent);
- }
- }
- }
- BreakpointResolver.spanInSourceFileAtLocation = spanInSourceFileAtLocation;
- })(BreakpointResolver = ts.BreakpointResolver || (ts.BreakpointResolver = {}));
-})(ts || (ts = {}));
-///
-///
-var ts;
-(function (ts) {
- /**
- * Transform one or more nodes using the supplied transformers.
- * @param source A single `Node` or an array of `Node` objects.
- * @param transformers An array of `TransformerFactory` callbacks used to process the transformation.
- * @param compilerOptions Optional compiler options.
- */
- function transform(source, transformers, compilerOptions) {
- var diagnostics = [];
- compilerOptions = ts.fixupCompilerOptions(compilerOptions, diagnostics);
- var nodes = ts.isArray(source) ? source : [source];
- var result = ts.transformNodes(/*resolver*/ undefined, /*emitHost*/ undefined, compilerOptions, nodes, transformers, /*allowDtsFiles*/ true);
- result.diagnostics = ts.concatenate(result.diagnostics, diagnostics);
- return result;
- }
- ts.transform = transform;
-})(ts || (ts = {}));
-//
-// Copyright (c) Microsoft Corporation. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-///
-/* @internal */
-var debugObjectHost = (function () { return this; })();
-// We need to use 'null' to interface with the managed side.
-/* tslint:disable:no-null-keyword */
-/* tslint:disable:no-in-operator */
-/* @internal */
-var ts;
-(function (ts) {
- function logInternalError(logger, err) {
- if (logger) {
- logger.log("*INTERNAL ERROR* - Exception in typescript services: " + err.message);
- }
- }
- var ScriptSnapshotShimAdapter = /** @class */ (function () {
- function ScriptSnapshotShimAdapter(scriptSnapshotShim) {
- this.scriptSnapshotShim = scriptSnapshotShim;
- }
- ScriptSnapshotShimAdapter.prototype.getText = function (start, end) {
- return this.scriptSnapshotShim.getText(start, end);
- };
- ScriptSnapshotShimAdapter.prototype.getLength = function () {
- return this.scriptSnapshotShim.getLength();
- };
- ScriptSnapshotShimAdapter.prototype.getChangeRange = function (oldSnapshot) {
- var oldSnapshotShim = oldSnapshot;
- var encoded = this.scriptSnapshotShim.getChangeRange(oldSnapshotShim.scriptSnapshotShim);
- if (encoded === null) {
- return null;
- }
- var decoded = JSON.parse(encoded);
- return ts.createTextChangeRange(ts.createTextSpan(decoded.span.start, decoded.span.length), decoded.newLength);
- };
- ScriptSnapshotShimAdapter.prototype.dispose = function () {
- // if scriptSnapshotShim is a COM object then property check becomes method call with no arguments
- // 'in' does not have this effect
- if ("dispose" in this.scriptSnapshotShim) {
- this.scriptSnapshotShim.dispose();
- }
- };
- return ScriptSnapshotShimAdapter;
- }());
- var LanguageServiceShimHostAdapter = /** @class */ (function () {
- function LanguageServiceShimHostAdapter(shimHost) {
- var _this = this;
- this.shimHost = shimHost;
- this.loggingEnabled = false;
- this.tracingEnabled = false;
- // if shimHost is a COM object then property check will become method call with no arguments.
- // 'in' does not have this effect.
- if ("getModuleResolutionsForFile" in this.shimHost) {
- this.resolveModuleNames = function (moduleNames, containingFile) {
- var resolutionsInFile = JSON.parse(_this.shimHost.getModuleResolutionsForFile(containingFile));
- return ts.map(moduleNames, function (name) {
- var result = ts.getProperty(resolutionsInFile, name);
- return result ? { resolvedFileName: result, extension: ts.extensionFromPath(result), isExternalLibraryImport: false } : undefined;
- });
- };
- }
- if ("directoryExists" in this.shimHost) {
- this.directoryExists = function (directoryName) { return _this.shimHost.directoryExists(directoryName); };
- }
- if ("getTypeReferenceDirectiveResolutionsForFile" in this.shimHost) {
- this.resolveTypeReferenceDirectives = function (typeDirectiveNames, containingFile) {
- var typeDirectivesForFile = JSON.parse(_this.shimHost.getTypeReferenceDirectiveResolutionsForFile(containingFile));
- return ts.map(typeDirectiveNames, function (name) { return ts.getProperty(typeDirectivesForFile, name); });
- };
- }
- }
- LanguageServiceShimHostAdapter.prototype.log = function (s) {
- if (this.loggingEnabled) {
- this.shimHost.log(s);
- }
- };
- LanguageServiceShimHostAdapter.prototype.trace = function (s) {
- if (this.tracingEnabled) {
- this.shimHost.trace(s);
- }
- };
- LanguageServiceShimHostAdapter.prototype.error = function (s) {
- this.shimHost.error(s);
- };
- LanguageServiceShimHostAdapter.prototype.getProjectVersion = function () {
- if (!this.shimHost.getProjectVersion) {
- // shimmed host does not support getProjectVersion
- return undefined;
- }
- return this.shimHost.getProjectVersion();
- };
- LanguageServiceShimHostAdapter.prototype.getTypeRootsVersion = function () {
- if (!this.shimHost.getTypeRootsVersion) {
- return 0;
- }
- return this.shimHost.getTypeRootsVersion();
- };
- LanguageServiceShimHostAdapter.prototype.useCaseSensitiveFileNames = function () {
- return this.shimHost.useCaseSensitiveFileNames ? this.shimHost.useCaseSensitiveFileNames() : false;
- };
- LanguageServiceShimHostAdapter.prototype.getCompilationSettings = function () {
- var settingsJson = this.shimHost.getCompilationSettings();
- if (settingsJson === null || settingsJson === "") {
- throw Error("LanguageServiceShimHostAdapter.getCompilationSettings: empty compilationSettings");
- }
- var compilerOptions = JSON.parse(settingsJson);
- // permit language service to handle all files (filtering should be performed on the host side)
- compilerOptions.allowNonTsExtensions = true;
- return compilerOptions;
- };
- LanguageServiceShimHostAdapter.prototype.getScriptFileNames = function () {
- var encoded = this.shimHost.getScriptFileNames();
- return this.files = JSON.parse(encoded);
- };
- LanguageServiceShimHostAdapter.prototype.getScriptSnapshot = function (fileName) {
- var scriptSnapshot = this.shimHost.getScriptSnapshot(fileName);
- return scriptSnapshot && new ScriptSnapshotShimAdapter(scriptSnapshot);
- };
- LanguageServiceShimHostAdapter.prototype.getScriptKind = function (fileName) {
- if ("getScriptKind" in this.shimHost) {
- return this.shimHost.getScriptKind(fileName);
- }
- else {
- return 0 /* Unknown */;
- }
- };
- LanguageServiceShimHostAdapter.prototype.getScriptVersion = function (fileName) {
- return this.shimHost.getScriptVersion(fileName);
- };
- LanguageServiceShimHostAdapter.prototype.getLocalizedDiagnosticMessages = function () {
- var diagnosticMessagesJson = this.shimHost.getLocalizedDiagnosticMessages();
- if (diagnosticMessagesJson === null || diagnosticMessagesJson === "") {
- return null;
- }
- try {
- return JSON.parse(diagnosticMessagesJson);
- }
- catch (e) {
- this.log(e.description || "diagnosticMessages.generated.json has invalid JSON format");
- return null;
- }
- };
- LanguageServiceShimHostAdapter.prototype.getCancellationToken = function () {
- var hostCancellationToken = this.shimHost.getCancellationToken();
- return new ts.ThrottledCancellationToken(hostCancellationToken);
- };
- LanguageServiceShimHostAdapter.prototype.getCurrentDirectory = function () {
- return this.shimHost.getCurrentDirectory();
- };
- LanguageServiceShimHostAdapter.prototype.getDirectories = function (path) {
- return JSON.parse(this.shimHost.getDirectories(path));
- };
- LanguageServiceShimHostAdapter.prototype.getDefaultLibFileName = function (options) {
- return this.shimHost.getDefaultLibFileName(JSON.stringify(options));
- };
- LanguageServiceShimHostAdapter.prototype.readDirectory = function (path, extensions, exclude, include, depth) {
- var pattern = ts.getFileMatcherPatterns(path, exclude, include, this.shimHost.useCaseSensitiveFileNames(), this.shimHost.getCurrentDirectory());
- return JSON.parse(this.shimHost.readDirectory(path, JSON.stringify(extensions), JSON.stringify(pattern.basePaths), pattern.excludePattern, pattern.includeFilePattern, pattern.includeDirectoryPattern, depth));
- };
- LanguageServiceShimHostAdapter.prototype.readFile = function (path, encoding) {
- return this.shimHost.readFile(path, encoding);
- };
- LanguageServiceShimHostAdapter.prototype.fileExists = function (path) {
- return this.shimHost.fileExists(path);
- };
- return LanguageServiceShimHostAdapter;
- }());
- ts.LanguageServiceShimHostAdapter = LanguageServiceShimHostAdapter;
- var CoreServicesShimHostAdapter = /** @class */ (function () {
- function CoreServicesShimHostAdapter(shimHost) {
- var _this = this;
- this.shimHost = shimHost;
- this.useCaseSensitiveFileNames = this.shimHost.useCaseSensitiveFileNames ? this.shimHost.useCaseSensitiveFileNames() : false;
- if ("directoryExists" in this.shimHost) {
- this.directoryExists = function (directoryName) { return _this.shimHost.directoryExists(directoryName); };
- }
- if ("realpath" in this.shimHost) {
- this.realpath = function (path) { return _this.shimHost.realpath(path); };
- }
- }
- CoreServicesShimHostAdapter.prototype.readDirectory = function (rootDir, extensions, exclude, include, depth) {
- var pattern = ts.getFileMatcherPatterns(rootDir, exclude, include, this.shimHost.useCaseSensitiveFileNames(), this.shimHost.getCurrentDirectory());
- return JSON.parse(this.shimHost.readDirectory(rootDir, JSON.stringify(extensions), JSON.stringify(pattern.basePaths), pattern.excludePattern, pattern.includeFilePattern, pattern.includeDirectoryPattern, depth));
- };
- CoreServicesShimHostAdapter.prototype.fileExists = function (fileName) {
- return this.shimHost.fileExists(fileName);
- };
- CoreServicesShimHostAdapter.prototype.readFile = function (fileName) {
- return this.shimHost.readFile(fileName);
- };
- CoreServicesShimHostAdapter.prototype.getDirectories = function (path) {
- return JSON.parse(this.shimHost.getDirectories(path));
- };
- return CoreServicesShimHostAdapter;
- }());
- ts.CoreServicesShimHostAdapter = CoreServicesShimHostAdapter;
- function simpleForwardCall(logger, actionDescription, action, logPerformance) {
- var start;
- if (logPerformance) {
- logger.log(actionDescription);
- start = ts.timestamp();
- }
- var result = action();
- if (logPerformance) {
- var end = ts.timestamp();
- logger.log(actionDescription + " completed in " + (end - start) + " msec");
- if (ts.isString(result)) {
- var str = result;
- if (str.length > 128) {
- str = str.substring(0, 128) + "...";
- }
- logger.log(" result.length=" + str.length + ", result='" + JSON.stringify(str) + "'");
- }
- }
- return result;
- }
- function forwardJSONCall(logger, actionDescription, action, logPerformance) {
- return forwardCall(logger, actionDescription, /*returnJson*/ true, action, logPerformance);
- }
- function forwardCall(logger, actionDescription, returnJson, action, logPerformance) {
- try {
- var result = simpleForwardCall(logger, actionDescription, action, logPerformance);
- return returnJson ? JSON.stringify({ result: result }) : result;
- }
- catch (err) {
- if (err instanceof ts.OperationCanceledException) {
- return JSON.stringify({ canceled: true });
- }
- logInternalError(logger, err);
- err.description = actionDescription;
- return JSON.stringify({ error: err });
- }
- }
- var ShimBase = /** @class */ (function () {
- function ShimBase(factory) {
- this.factory = factory;
- factory.registerShim(this);
- }
- ShimBase.prototype.dispose = function (_dummy) {
- this.factory.unregisterShim(this);
- };
- return ShimBase;
- }());
- function realizeDiagnostics(diagnostics, newLine) {
- return diagnostics.map(function (d) { return realizeDiagnostic(d, newLine); });
- }
- ts.realizeDiagnostics = realizeDiagnostics;
- function realizeDiagnostic(diagnostic, newLine) {
- return {
- message: ts.flattenDiagnosticMessageText(diagnostic.messageText, newLine),
- start: diagnostic.start,
- length: diagnostic.length,
- category: ts.diagnosticCategoryName(diagnostic),
- code: diagnostic.code
- };
- }
- var LanguageServiceShimObject = /** @class */ (function (_super) {
- __extends(LanguageServiceShimObject, _super);
- function LanguageServiceShimObject(factory, host, languageService) {
- var _this = _super.call(this, factory) || this;
- _this.host = host;
- _this.languageService = languageService;
- _this.logPerformance = false;
- _this.logger = _this.host;
- return _this;
- }
- LanguageServiceShimObject.prototype.forwardJSONCall = function (actionDescription, action) {
- return forwardJSONCall(this.logger, actionDescription, action, this.logPerformance);
- };
- /// DISPOSE
- /**
- * Ensure (almost) deterministic release of internal Javascript resources when
- * some external native objects holds onto us (e.g. Com/Interop).
- */
- LanguageServiceShimObject.prototype.dispose = function (dummy) {
- this.logger.log("dispose()");
- this.languageService.dispose();
- this.languageService = null;
- // force a GC
- if (debugObjectHost && debugObjectHost.CollectGarbage) {
- debugObjectHost.CollectGarbage();
- this.logger.log("CollectGarbage()");
- }
- this.logger = null;
- _super.prototype.dispose.call(this, dummy);
- };
- /// REFRESH
- /**
- * Update the list of scripts known to the compiler
- */
- LanguageServiceShimObject.prototype.refresh = function (throwOnError) {
- this.forwardJSONCall("refresh(" + throwOnError + ")", function () { return null; });
- };
- LanguageServiceShimObject.prototype.cleanupSemanticCache = function () {
- var _this = this;
- this.forwardJSONCall("cleanupSemanticCache()", function () {
- _this.languageService.cleanupSemanticCache();
- return null;
- });
- };
- LanguageServiceShimObject.prototype.realizeDiagnostics = function (diagnostics) {
- var newLine = ts.getNewLineOrDefaultFromHost(this.host);
- return realizeDiagnostics(diagnostics, newLine);
- };
- LanguageServiceShimObject.prototype.getSyntacticClassifications = function (fileName, start, length) {
- var _this = this;
- return this.forwardJSONCall("getSyntacticClassifications('" + fileName + "', " + start + ", " + length + ")", function () { return _this.languageService.getSyntacticClassifications(fileName, ts.createTextSpan(start, length)); });
- };
- LanguageServiceShimObject.prototype.getSemanticClassifications = function (fileName, start, length) {
- var _this = this;
- return this.forwardJSONCall("getSemanticClassifications('" + fileName + "', " + start + ", " + length + ")", function () { return _this.languageService.getSemanticClassifications(fileName, ts.createTextSpan(start, length)); });
- };
- LanguageServiceShimObject.prototype.getEncodedSyntacticClassifications = function (fileName, start, length) {
- var _this = this;
- return this.forwardJSONCall("getEncodedSyntacticClassifications('" + fileName + "', " + start + ", " + length + ")",
- // directly serialize the spans out to a string. This is much faster to decode
- // on the managed side versus a full JSON array.
- function () { return convertClassifications(_this.languageService.getEncodedSyntacticClassifications(fileName, ts.createTextSpan(start, length))); });
- };
- LanguageServiceShimObject.prototype.getEncodedSemanticClassifications = function (fileName, start, length) {
- var _this = this;
- return this.forwardJSONCall("getEncodedSemanticClassifications('" + fileName + "', " + start + ", " + length + ")",
- // directly serialize the spans out to a string. This is much faster to decode
- // on the managed side versus a full JSON array.
- function () { return convertClassifications(_this.languageService.getEncodedSemanticClassifications(fileName, ts.createTextSpan(start, length))); });
- };
- LanguageServiceShimObject.prototype.getSyntacticDiagnostics = function (fileName) {
- var _this = this;
- return this.forwardJSONCall("getSyntacticDiagnostics('" + fileName + "')", function () {
- var diagnostics = _this.languageService.getSyntacticDiagnostics(fileName);
- return _this.realizeDiagnostics(diagnostics);
- });
- };
- LanguageServiceShimObject.prototype.getSemanticDiagnostics = function (fileName) {
- var _this = this;
- return this.forwardJSONCall("getSemanticDiagnostics('" + fileName + "')", function () {
- var diagnostics = _this.languageService.getSemanticDiagnostics(fileName);
- return _this.realizeDiagnostics(diagnostics);
- });
- };
- LanguageServiceShimObject.prototype.getSuggestionDiagnostics = function (fileName) {
- var _this = this;
- return this.forwardJSONCall("getSuggestionDiagnostics('" + fileName + "')", function () { return _this.realizeDiagnostics(_this.languageService.getSuggestionDiagnostics(fileName)); });
- };
- LanguageServiceShimObject.prototype.getCompilerOptionsDiagnostics = function () {
- var _this = this;
- return this.forwardJSONCall("getCompilerOptionsDiagnostics()", function () {
- var diagnostics = _this.languageService.getCompilerOptionsDiagnostics();
- return _this.realizeDiagnostics(diagnostics);
- });
- };
- /// QUICKINFO
- /**
- * Computes a string representation of the type at the requested position
- * in the active file.
- */
- LanguageServiceShimObject.prototype.getQuickInfoAtPosition = function (fileName, position) {
- var _this = this;
- return this.forwardJSONCall("getQuickInfoAtPosition('" + fileName + "', " + position + ")", function () { return _this.languageService.getQuickInfoAtPosition(fileName, position); });
- };
- /// NAMEORDOTTEDNAMESPAN
- /**
- * Computes span information of the name or dotted name at the requested position
- * in the active file.
- */
- LanguageServiceShimObject.prototype.getNameOrDottedNameSpan = function (fileName, startPos, endPos) {
- var _this = this;
- return this.forwardJSONCall("getNameOrDottedNameSpan('" + fileName + "', " + startPos + ", " + endPos + ")", function () { return _this.languageService.getNameOrDottedNameSpan(fileName, startPos, endPos); });
- };
- /**
- * STATEMENTSPAN
- * Computes span information of statement at the requested position in the active file.
- */
- LanguageServiceShimObject.prototype.getBreakpointStatementAtPosition = function (fileName, position) {
- var _this = this;
- return this.forwardJSONCall("getBreakpointStatementAtPosition('" + fileName + "', " + position + ")", function () { return _this.languageService.getBreakpointStatementAtPosition(fileName, position); });
- };
- /// SIGNATUREHELP
- LanguageServiceShimObject.prototype.getSignatureHelpItems = function (fileName, position) {
- var _this = this;
- return this.forwardJSONCall("getSignatureHelpItems('" + fileName + "', " + position + ")", function () { return _this.languageService.getSignatureHelpItems(fileName, position); });
- };
- /// GOTO DEFINITION
- /**
- * Computes the definition location and file for the symbol
- * at the requested position.
- */
- LanguageServiceShimObject.prototype.getDefinitionAtPosition = function (fileName, position) {
- var _this = this;
- return this.forwardJSONCall("getDefinitionAtPosition('" + fileName + "', " + position + ")", function () { return _this.languageService.getDefinitionAtPosition(fileName, position); });
- };
- /**
- * Computes the definition location and file for the symbol
- * at the requested position.
- */
- LanguageServiceShimObject.prototype.getDefinitionAndBoundSpan = function (fileName, position) {
- var _this = this;
- return this.forwardJSONCall("getDefinitionAndBoundSpan('" + fileName + "', " + position + ")", function () { return _this.languageService.getDefinitionAndBoundSpan(fileName, position); });
- };
- /// GOTO Type
- /**
- * Computes the definition location of the type of the symbol
- * at the requested position.
- */
- LanguageServiceShimObject.prototype.getTypeDefinitionAtPosition = function (fileName, position) {
- var _this = this;
- return this.forwardJSONCall("getTypeDefinitionAtPosition('" + fileName + "', " + position + ")", function () { return _this.languageService.getTypeDefinitionAtPosition(fileName, position); });
- };
- /// GOTO Implementation
- /**
- * Computes the implementation location of the symbol
- * at the requested position.
- */
- LanguageServiceShimObject.prototype.getImplementationAtPosition = function (fileName, position) {
- var _this = this;
- return this.forwardJSONCall("getImplementationAtPosition('" + fileName + "', " + position + ")", function () { return _this.languageService.getImplementationAtPosition(fileName, position); });
- };
- LanguageServiceShimObject.prototype.getRenameInfo = function (fileName, position) {
- var _this = this;
- return this.forwardJSONCall("getRenameInfo('" + fileName + "', " + position + ")", function () { return _this.languageService.getRenameInfo(fileName, position); });
- };
- LanguageServiceShimObject.prototype.findRenameLocations = function (fileName, position, findInStrings, findInComments) {
- var _this = this;
- return this.forwardJSONCall("findRenameLocations('" + fileName + "', " + position + ", " + findInStrings + ", " + findInComments + ")", function () { return _this.languageService.findRenameLocations(fileName, position, findInStrings, findInComments); });
- };
- /// GET BRACE MATCHING
- LanguageServiceShimObject.prototype.getBraceMatchingAtPosition = function (fileName, position) {
- var _this = this;
- return this.forwardJSONCall("getBraceMatchingAtPosition('" + fileName + "', " + position + ")", function () { return _this.languageService.getBraceMatchingAtPosition(fileName, position); });
- };
- LanguageServiceShimObject.prototype.isValidBraceCompletionAtPosition = function (fileName, position, openingBrace) {
- var _this = this;
- return this.forwardJSONCall("isValidBraceCompletionAtPosition('" + fileName + "', " + position + ", " + openingBrace + ")", function () { return _this.languageService.isValidBraceCompletionAtPosition(fileName, position, openingBrace); });
- };
- LanguageServiceShimObject.prototype.getSpanOfEnclosingComment = function (fileName, position, onlyMultiLine) {
- var _this = this;
- return this.forwardJSONCall("getSpanOfEnclosingComment('" + fileName + "', " + position + ")", function () { return _this.languageService.getSpanOfEnclosingComment(fileName, position, onlyMultiLine); });
- };
- /// GET SMART INDENT
- LanguageServiceShimObject.prototype.getIndentationAtPosition = function (fileName, position, options /*Services.EditorOptions*/) {
- var _this = this;
- return this.forwardJSONCall("getIndentationAtPosition('" + fileName + "', " + position + ")", function () {
- var localOptions = JSON.parse(options);
- return _this.languageService.getIndentationAtPosition(fileName, position, localOptions);
- });
- };
- /// GET REFERENCES
- LanguageServiceShimObject.prototype.getReferencesAtPosition = function (fileName, position) {
- var _this = this;
- return this.forwardJSONCall("getReferencesAtPosition('" + fileName + "', " + position + ")", function () { return _this.languageService.getReferencesAtPosition(fileName, position); });
- };
- LanguageServiceShimObject.prototype.findReferences = function (fileName, position) {
- var _this = this;
- return this.forwardJSONCall("findReferences('" + fileName + "', " + position + ")", function () { return _this.languageService.findReferences(fileName, position); });
- };
- LanguageServiceShimObject.prototype.getOccurrencesAtPosition = function (fileName, position) {
- var _this = this;
- return this.forwardJSONCall("getOccurrencesAtPosition('" + fileName + "', " + position + ")", function () { return _this.languageService.getOccurrencesAtPosition(fileName, position); });
- };
- LanguageServiceShimObject.prototype.getDocumentHighlights = function (fileName, position, filesToSearch) {
- var _this = this;
- return this.forwardJSONCall("getDocumentHighlights('" + fileName + "', " + position + ")", function () {
- var results = _this.languageService.getDocumentHighlights(fileName, position, JSON.parse(filesToSearch));
- // workaround for VS document highlighting issue - keep only items from the initial file
- var normalizedName = ts.normalizeSlashes(fileName).toLowerCase();
- return ts.filter(results, function (r) { return ts.normalizeSlashes(r.fileName).toLowerCase() === normalizedName; });
- });
- };
- /// COMPLETION LISTS
- /**
- * Get a string based representation of the completions
- * to provide at the given source position and providing a member completion
- * list if requested.
- */
- LanguageServiceShimObject.prototype.getCompletionsAtPosition = function (fileName, position, options) {
- var _this = this;
- return this.forwardJSONCall("getCompletionsAtPosition('" + fileName + "', " + position + ", " + options + ")", function () { return _this.languageService.getCompletionsAtPosition(fileName, position, options); });
- };
- /** Get a string based representation of a completion list entry details */
- LanguageServiceShimObject.prototype.getCompletionEntryDetails = function (fileName, position, entryName, options, source) {
- var _this = this;
- return this.forwardJSONCall("getCompletionEntryDetails('" + fileName + "', " + position + ", '" + entryName + "')", function () {
- var localOptions = options === undefined ? undefined : JSON.parse(options);
- return _this.languageService.getCompletionEntryDetails(fileName, position, entryName, localOptions, source);
- });
- };
- LanguageServiceShimObject.prototype.getFormattingEditsForRange = function (fileName, start, end, options /*Services.FormatCodeOptions*/) {
- var _this = this;
- return this.forwardJSONCall("getFormattingEditsForRange('" + fileName + "', " + start + ", " + end + ")", function () {
- var localOptions = JSON.parse(options);
- return _this.languageService.getFormattingEditsForRange(fileName, start, end, localOptions);
- });
- };
- LanguageServiceShimObject.prototype.getFormattingEditsForDocument = function (fileName, options /*Services.FormatCodeOptions*/) {
- var _this = this;
- return this.forwardJSONCall("getFormattingEditsForDocument('" + fileName + "')", function () {
- var localOptions = JSON.parse(options);
- return _this.languageService.getFormattingEditsForDocument(fileName, localOptions);
- });
- };
- LanguageServiceShimObject.prototype.getFormattingEditsAfterKeystroke = function (fileName, position, key, options /*Services.FormatCodeOptions*/) {
- var _this = this;
- return this.forwardJSONCall("getFormattingEditsAfterKeystroke('" + fileName + "', " + position + ", '" + key + "')", function () {
- var localOptions = JSON.parse(options);
- return _this.languageService.getFormattingEditsAfterKeystroke(fileName, position, key, localOptions);
- });
- };
- LanguageServiceShimObject.prototype.getDocCommentTemplateAtPosition = function (fileName, position) {
- var _this = this;
- return this.forwardJSONCall("getDocCommentTemplateAtPosition('" + fileName + "', " + position + ")", function () { return _this.languageService.getDocCommentTemplateAtPosition(fileName, position); });
- };
- /// NAVIGATE TO
- /** Return a list of symbols that are interesting to navigate to */
- LanguageServiceShimObject.prototype.getNavigateToItems = function (searchValue, maxResultCount, fileName) {
- var _this = this;
- return this.forwardJSONCall("getNavigateToItems('" + searchValue + "', " + maxResultCount + ", " + fileName + ")", function () { return _this.languageService.getNavigateToItems(searchValue, maxResultCount, fileName); });
- };
- LanguageServiceShimObject.prototype.getNavigationBarItems = function (fileName) {
- var _this = this;
- return this.forwardJSONCall("getNavigationBarItems('" + fileName + "')", function () { return _this.languageService.getNavigationBarItems(fileName); });
- };
- LanguageServiceShimObject.prototype.getNavigationTree = function (fileName) {
- var _this = this;
- return this.forwardJSONCall("getNavigationTree('" + fileName + "')", function () { return _this.languageService.getNavigationTree(fileName); });
- };
- LanguageServiceShimObject.prototype.getOutliningSpans = function (fileName) {
- var _this = this;
- return this.forwardJSONCall("getOutliningSpans('" + fileName + "')", function () { return _this.languageService.getOutliningSpans(fileName); });
- };
- LanguageServiceShimObject.prototype.getTodoComments = function (fileName, descriptors) {
- var _this = this;
- return this.forwardJSONCall("getTodoComments('" + fileName + "')", function () { return _this.languageService.getTodoComments(fileName, JSON.parse(descriptors)); });
- };
- /// Emit
- LanguageServiceShimObject.prototype.getEmitOutput = function (fileName) {
- var _this = this;
- return this.forwardJSONCall("getEmitOutput('" + fileName + "')", function () { return _this.languageService.getEmitOutput(fileName); });
- };
- LanguageServiceShimObject.prototype.getEmitOutputObject = function (fileName) {
- var _this = this;
- return forwardCall(this.logger, "getEmitOutput('" + fileName + "')",
- /*returnJson*/ false, function () { return _this.languageService.getEmitOutput(fileName); }, this.logPerformance);
- };
- return LanguageServiceShimObject;
- }(ShimBase));
- function convertClassifications(classifications) {
- return { spans: classifications.spans.join(","), endOfLineState: classifications.endOfLineState };
- }
- var ClassifierShimObject = /** @class */ (function (_super) {
- __extends(ClassifierShimObject, _super);
- function ClassifierShimObject(factory, logger) {
- var _this = _super.call(this, factory) || this;
- _this.logger = logger;
- _this.logPerformance = false;
- _this.classifier = ts.createClassifier();
- return _this;
- }
- ClassifierShimObject.prototype.getEncodedLexicalClassifications = function (text, lexState, syntacticClassifierAbsent) {
- var _this = this;
- return forwardJSONCall(this.logger, "getEncodedLexicalClassifications", function () { return convertClassifications(_this.classifier.getEncodedLexicalClassifications(text, lexState, syntacticClassifierAbsent)); }, this.logPerformance);
- };
- /// COLORIZATION
- ClassifierShimObject.prototype.getClassificationsForLine = function (text, lexState, classifyKeywordsInGenerics) {
- var classification = this.classifier.getClassificationsForLine(text, lexState, classifyKeywordsInGenerics);
- var result = "";
- for (var _i = 0, _a = classification.entries; _i < _a.length; _i++) {
- var item = _a[_i];
- result += item.length + "\n";
- result += item.classification + "\n";
- }
- result += classification.finalLexState;
- return result;
- };
- return ClassifierShimObject;
- }(ShimBase));
- var CoreServicesShimObject = /** @class */ (function (_super) {
- __extends(CoreServicesShimObject, _super);
- function CoreServicesShimObject(factory, logger, host) {
- var _this = _super.call(this, factory) || this;
- _this.logger = logger;
- _this.host = host;
- _this.logPerformance = false;
- return _this;
- }
- CoreServicesShimObject.prototype.forwardJSONCall = function (actionDescription, action) {
- return forwardJSONCall(this.logger, actionDescription, action, this.logPerformance);
- };
- CoreServicesShimObject.prototype.resolveModuleName = function (fileName, moduleName, compilerOptionsJson) {
- var _this = this;
- return this.forwardJSONCall("resolveModuleName('" + fileName + "')", function () {
- var compilerOptions = JSON.parse(compilerOptionsJson);
- var result = ts.resolveModuleName(moduleName, ts.normalizeSlashes(fileName), compilerOptions, _this.host);
- var resolvedFileName = result.resolvedModule ? result.resolvedModule.resolvedFileName : undefined;
- if (result.resolvedModule && result.resolvedModule.extension !== ".ts" /* Ts */ && result.resolvedModule.extension !== ".tsx" /* Tsx */ && result.resolvedModule.extension !== ".d.ts" /* Dts */) {
- resolvedFileName = undefined;
- }
- return {
- resolvedFileName: resolvedFileName,
- failedLookupLocations: result.failedLookupLocations
- };
- });
- };
- CoreServicesShimObject.prototype.resolveTypeReferenceDirective = function (fileName, typeReferenceDirective, compilerOptionsJson) {
- var _this = this;
- return this.forwardJSONCall("resolveTypeReferenceDirective(" + fileName + ")", function () {
- var compilerOptions = JSON.parse(compilerOptionsJson);
- var result = ts.resolveTypeReferenceDirective(typeReferenceDirective, ts.normalizeSlashes(fileName), compilerOptions, _this.host);
- return {
- resolvedFileName: result.resolvedTypeReferenceDirective ? result.resolvedTypeReferenceDirective.resolvedFileName : undefined,
- primary: result.resolvedTypeReferenceDirective ? result.resolvedTypeReferenceDirective.primary : true,
- failedLookupLocations: result.failedLookupLocations
- };
- });
- };
- CoreServicesShimObject.prototype.getPreProcessedFileInfo = function (fileName, sourceTextSnapshot) {
- var _this = this;
- return this.forwardJSONCall("getPreProcessedFileInfo('" + fileName + "')", function () {
- // for now treat files as JavaScript
- var result = ts.preProcessFile(ts.getSnapshotText(sourceTextSnapshot), /* readImportFiles */ true, /* detectJavaScriptImports */ true);
- return {
- referencedFiles: _this.convertFileReferences(result.referencedFiles),
- importedFiles: _this.convertFileReferences(result.importedFiles),
- ambientExternalModules: result.ambientExternalModules,
- isLibFile: result.isLibFile,
- typeReferenceDirectives: _this.convertFileReferences(result.typeReferenceDirectives)
- };
- });
- };
- CoreServicesShimObject.prototype.getAutomaticTypeDirectiveNames = function (compilerOptionsJson) {
- var _this = this;
- return this.forwardJSONCall("getAutomaticTypeDirectiveNames('" + compilerOptionsJson + "')", function () {
- var compilerOptions = JSON.parse(compilerOptionsJson);
- return ts.getAutomaticTypeDirectiveNames(compilerOptions, _this.host);
- });
- };
- CoreServicesShimObject.prototype.convertFileReferences = function (refs) {
- if (!refs) {
- return undefined;
- }
- var result = [];
- for (var _i = 0, refs_2 = refs; _i < refs_2.length; _i++) {
- var ref = refs_2[_i];
- result.push({
- path: ts.normalizeSlashes(ref.fileName),
- position: ref.pos,
- length: ref.end - ref.pos
- });
- }
- return result;
- };
- CoreServicesShimObject.prototype.getTSConfigFileInfo = function (fileName, sourceTextSnapshot) {
- var _this = this;
- return this.forwardJSONCall("getTSConfigFileInfo('" + fileName + "')", function () {
- var result = ts.parseJsonText(fileName, ts.getSnapshotText(sourceTextSnapshot));
- var normalizedFileName = ts.normalizeSlashes(fileName);
- var configFile = ts.parseJsonSourceFileConfigFileContent(result, _this.host, ts.getDirectoryPath(normalizedFileName), /*existingOptions*/ {}, normalizedFileName);
- return {
- options: configFile.options,
- typeAcquisition: configFile.typeAcquisition,
- files: configFile.fileNames,
- raw: configFile.raw,
- errors: realizeDiagnostics(result.parseDiagnostics.concat(configFile.errors), "\r\n")
- };
- });
- };
- CoreServicesShimObject.prototype.getDefaultCompilationSettings = function () {
- return this.forwardJSONCall("getDefaultCompilationSettings()", function () { return ts.getDefaultCompilerOptions(); });
- };
- CoreServicesShimObject.prototype.discoverTypings = function (discoverTypingsJson) {
- var _this = this;
- var getCanonicalFileName = ts.createGetCanonicalFileName(/*useCaseSensitivefileNames:*/ false);
- return this.forwardJSONCall("discoverTypings()", function () {
- var info = JSON.parse(discoverTypingsJson);
- if (_this.safeList === undefined) {
- _this.safeList = ts.JsTyping.loadSafeList(_this.host, ts.toPath(info.safeListPath, info.safeListPath, getCanonicalFileName));
- }
- return ts.JsTyping.discoverTypings(_this.host, function (msg) { return _this.logger.log(msg); }, info.fileNames, ts.toPath(info.projectRootPath, info.projectRootPath, getCanonicalFileName), _this.safeList, info.packageNameToTypingLocation, info.typeAcquisition, info.unresolvedImports, info.typesRegistry);
- });
- };
- return CoreServicesShimObject;
- }(ShimBase));
- var TypeScriptServicesFactory = /** @class */ (function () {
- function TypeScriptServicesFactory() {
- this._shims = [];
- }
- /*
- * Returns script API version.
- */
- TypeScriptServicesFactory.prototype.getServicesVersion = function () {
- return ts.servicesVersion;
- };
- TypeScriptServicesFactory.prototype.createLanguageServiceShim = function (host) {
- try {
- if (this.documentRegistry === undefined) {
- this.documentRegistry = ts.createDocumentRegistry(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames(), host.getCurrentDirectory());
- }
- var hostAdapter = new LanguageServiceShimHostAdapter(host);
- var languageService = ts.createLanguageService(hostAdapter, this.documentRegistry);
- return new LanguageServiceShimObject(this, host, languageService);
- }
- catch (err) {
- logInternalError(host, err);
- throw err;
- }
- };
- TypeScriptServicesFactory.prototype.createClassifierShim = function (logger) {
- try {
- return new ClassifierShimObject(this, logger);
- }
- catch (err) {
- logInternalError(logger, err);
- throw err;
- }
- };
- TypeScriptServicesFactory.prototype.createCoreServicesShim = function (host) {
- try {
- var adapter = new CoreServicesShimHostAdapter(host);
- return new CoreServicesShimObject(this, host, adapter);
- }
- catch (err) {
- logInternalError(host, err);
- throw err;
- }
- };
- TypeScriptServicesFactory.prototype.close = function () {
- // Forget all the registered shims
- ts.clear(this._shims);
- this.documentRegistry = undefined;
- };
- TypeScriptServicesFactory.prototype.registerShim = function (shim) {
- this._shims.push(shim);
- };
- TypeScriptServicesFactory.prototype.unregisterShim = function (shim) {
- for (var i = 0; i < this._shims.length; i++) {
- if (this._shims[i] === shim) {
- delete this._shims[i];
- return;
- }
- }
- throw new Error("Invalid operation");
- };
- return TypeScriptServicesFactory;
- }());
- ts.TypeScriptServicesFactory = TypeScriptServicesFactory;
- if (typeof module !== "undefined" && module.exports) {
- module.exports = ts;
- }
-})(ts || (ts = {}));
-/* tslint:enable:no-in-operator */
-/* tslint:enable:no-null */
-/// TODO: this is used by VS, clean this up on both sides of the interface
-/* @internal */
-var TypeScript;
-(function (TypeScript) {
- var Services;
- (function (Services) {
- Services.TypeScriptServicesFactory = ts.TypeScriptServicesFactory;
- })(Services = TypeScript.Services || (TypeScript.Services = {}));
-})(TypeScript || (TypeScript = {}));
-// 'toolsVersion' gets consumed by the managed side, so it's not unused.
-// TODO: it should be moved into a namespace though.
-/* @internal */
-var toolsVersion = ts.versionMajorMinor;