diff --git a/lib/tsc.js b/lib/tsc.js index ef23d59ebc3..4dbe3f4cf31 100644 --- a/lib/tsc.js +++ b/lib/tsc.js @@ -21387,11 +21387,11 @@ var ts; } var visitedSymbolTables = []; return forEachSymbolTableInScope(enclosingDeclaration, getAccessibleSymbolChainFromSymbolTable); - function getAccessibleSymbolChainFromSymbolTable(symbols) { + function getAccessibleSymbolChainFromSymbolTable(symbols, ignoreQualification) { if (!ts.pushIfUnique(visitedSymbolTables, symbols)) { return undefined; } - var result = trySymbolTable(symbols); + var result = trySymbolTable(symbols, ignoreQualification); visitedSymbolTables.pop(); return result; } @@ -21399,16 +21399,16 @@ var ts; return !needsQualification(symbolFromSymbolTable, enclosingDeclaration, meaning) || !!getAccessibleSymbolChain(symbolFromSymbolTable.parent, enclosingDeclaration, getQualifiedLeftMeaning(meaning), useOnlyExternalAliasing); } - function isAccessible(symbolFromSymbolTable, resolvedAliasSymbol) { + function isAccessible(symbolFromSymbolTable, resolvedAliasSymbol, ignoreQualification) { return symbol === (resolvedAliasSymbol || symbolFromSymbolTable) && !ts.some(symbolFromSymbolTable.declarations, hasExternalModuleSymbol) && - canQualifySymbol(symbolFromSymbolTable, meaning); + (ignoreQualification || canQualifySymbol(symbolFromSymbolTable, meaning)); } function isUMDExportSymbol(symbol) { return symbol && symbol.declarations && symbol.declarations[0] && ts.isNamespaceExportDeclaration(symbol.declarations[0]); } - function trySymbolTable(symbols) { - if (isAccessible(symbols.get(symbol.escapedName))) { + function trySymbolTable(symbols, ignoreQualification) { + if (isAccessible(symbols.get(symbol.escapedName), undefined, ignoreQualification)) { return [symbol]; } return ts.forEachEntry(symbols, function (symbolFromSymbolTable) { @@ -21417,11 +21417,11 @@ var ts; && !(isUMDExportSymbol(symbolFromSymbolTable) && enclosingDeclaration && ts.isExternalModule(ts.getSourceFileOfNode(enclosingDeclaration))) && (!useOnlyExternalAliasing || ts.some(symbolFromSymbolTable.declarations, ts.isExternalModuleImportEqualsDeclaration))) { var resolvedImportedSymbol = resolveAlias(symbolFromSymbolTable); - if (isAccessible(symbolFromSymbolTable, resolvedImportedSymbol)) { + if (isAccessible(symbolFromSymbolTable, resolvedImportedSymbol, ignoreQualification)) { return [symbolFromSymbolTable]; } var candidateTable = getExportsOfSymbol(resolvedImportedSymbol); - var accessibleSymbolsFromExports = candidateTable && getAccessibleSymbolChainFromSymbolTable(candidateTable); + var accessibleSymbolsFromExports = candidateTable && getAccessibleSymbolChainFromSymbolTable(candidateTable, true); if (accessibleSymbolsFromExports && canQualifySymbol(symbolFromSymbolTable, getQualifiedLeftMeaning(meaning))) { return [symbolFromSymbolTable].concat(accessibleSymbolsFromExports); } @@ -47176,7 +47176,7 @@ var ts; return ts.visitEachChild(node, visitor, context); } function visitLabeledStatement(node) { - if (enclosingFunctionFlags & 2 && enclosingFunctionFlags & 1) { + if (enclosingFunctionFlags & 2) { var statement = ts.unwrapInnermostStatementOfLabel(node); if (statement.kind === 217 && statement.awaitModifier) { return visitForOfStatement(statement, node); @@ -61711,13 +61711,13 @@ var ts; var host = system; host.onConfigFileDiagnostic = reportDiagnostic; host.onUnRecoverableConfigFileDiagnostic = function (diagnostic) { return reportUnrecoverableDiagnostic(ts.sys, reportDiagnostic, diagnostic); }; - var result = parseConfigFile(configFileName, optionsToExtend, host); + var result = getParsedCommandLineOfConfigFile(configFileName, optionsToExtend, host); host.onConfigFileDiagnostic = undefined; host.onUnRecoverableConfigFileDiagnostic = undefined; return result; } ts.parseConfigFileWithSystem = parseConfigFileWithSystem; - function parseConfigFile(configFileName, optionsToExtend, host) { + function getParsedCommandLineOfConfigFile(configFileName, optionsToExtend, host) { var configFileText; try { configFileText = host.readFile(configFileName); @@ -61739,7 +61739,7 @@ var ts; configParseResult.errors.forEach(function (diagnostic) { return host.onConfigFileDiagnostic(diagnostic); }); return configParseResult; } - ts.parseConfigFile = parseConfigFile; + ts.getParsedCommandLineOfConfigFile = getParsedCommandLineOfConfigFile; function emitFilesAndReportErrors(program, reportDiagnostic, writeFileName) { var diagnostics = program.getSyntacticDiagnostics().slice(); var reportSemanticDiagnostics = false; @@ -62146,7 +62146,7 @@ var ts; watchConfigFileWildCardDirectories(); } function parseConfigFile() { - var configParseResult = ts.parseConfigFile(configFileName, optionsToExtendForConfigFile, parseConfigFileHost); + var configParseResult = ts.getParsedCommandLineOfConfigFile(configFileName, optionsToExtendForConfigFile, parseConfigFileHost); rootFileNames = configParseResult.fileNames; compilerOptions = configParseResult.options; configFileSpecs = configParseResult.configFileSpecs; diff --git a/lib/tsserver.js b/lib/tsserver.js index a1cfb09ddd8..551d431c29f 100644 --- a/lib/tsserver.js +++ b/lib/tsserver.js @@ -22780,11 +22780,11 @@ var ts; } var visitedSymbolTables = []; return forEachSymbolTableInScope(enclosingDeclaration, getAccessibleSymbolChainFromSymbolTable); - function getAccessibleSymbolChainFromSymbolTable(symbols) { + function getAccessibleSymbolChainFromSymbolTable(symbols, ignoreQualification) { if (!ts.pushIfUnique(visitedSymbolTables, symbols)) { return undefined; } - var result = trySymbolTable(symbols); + var result = trySymbolTable(symbols, ignoreQualification); visitedSymbolTables.pop(); return result; } @@ -22792,16 +22792,16 @@ var ts; return !needsQualification(symbolFromSymbolTable, enclosingDeclaration, meaning) || !!getAccessibleSymbolChain(symbolFromSymbolTable.parent, enclosingDeclaration, getQualifiedLeftMeaning(meaning), useOnlyExternalAliasing); } - function isAccessible(symbolFromSymbolTable, resolvedAliasSymbol) { + function isAccessible(symbolFromSymbolTable, resolvedAliasSymbol, ignoreQualification) { return symbol === (resolvedAliasSymbol || symbolFromSymbolTable) && !ts.some(symbolFromSymbolTable.declarations, hasExternalModuleSymbol) && - canQualifySymbol(symbolFromSymbolTable, meaning); + (ignoreQualification || canQualifySymbol(symbolFromSymbolTable, meaning)); } function isUMDExportSymbol(symbol) { return symbol && symbol.declarations && symbol.declarations[0] && ts.isNamespaceExportDeclaration(symbol.declarations[0]); } - function trySymbolTable(symbols) { - if (isAccessible(symbols.get(symbol.escapedName))) { + function trySymbolTable(symbols, ignoreQualification) { + if (isAccessible(symbols.get(symbol.escapedName), undefined, ignoreQualification)) { return [symbol]; } return ts.forEachEntry(symbols, function (symbolFromSymbolTable) { @@ -22810,11 +22810,11 @@ var ts; && !(isUMDExportSymbol(symbolFromSymbolTable) && enclosingDeclaration && ts.isExternalModule(ts.getSourceFileOfNode(enclosingDeclaration))) && (!useOnlyExternalAliasing || ts.some(symbolFromSymbolTable.declarations, ts.isExternalModuleImportEqualsDeclaration))) { var resolvedImportedSymbol = resolveAlias(symbolFromSymbolTable); - if (isAccessible(symbolFromSymbolTable, resolvedImportedSymbol)) { + if (isAccessible(symbolFromSymbolTable, resolvedImportedSymbol, ignoreQualification)) { return [symbolFromSymbolTable]; } var candidateTable = getExportsOfSymbol(resolvedImportedSymbol); - var accessibleSymbolsFromExports = candidateTable && getAccessibleSymbolChainFromSymbolTable(candidateTable); + var accessibleSymbolsFromExports = candidateTable && getAccessibleSymbolChainFromSymbolTable(candidateTable, true); if (accessibleSymbolsFromExports && canQualifySymbol(symbolFromSymbolTable, getQualifiedLeftMeaning(meaning))) { return [symbolFromSymbolTable].concat(accessibleSymbolsFromExports); } @@ -48632,7 +48632,7 @@ var ts; return ts.visitEachChild(node, visitor, context); } function visitLabeledStatement(node) { - if (enclosingFunctionFlags & 2 && enclosingFunctionFlags & 1) { + if (enclosingFunctionFlags & 2) { var statement = ts.unwrapInnermostStatementOfLabel(node); if (statement.kind === 217 && statement.awaitModifier) { return visitForOfStatement(statement, node); @@ -64859,12 +64859,16 @@ var ts; ts.typeKeywords = [ 119, 122, + 127, 130, + 95, 133, 134, 136, 137, 105, + 139, + 140, ]; function isTypeKeyword(kind) { return ts.contains(ts.typeKeywords, kind); @@ -66804,6 +66808,7 @@ var ts; KeywordCompletionFilters[KeywordCompletionFilters["ClassElementKeywords"] = 1] = "ClassElementKeywords"; KeywordCompletionFilters[KeywordCompletionFilters["ConstructorParameterKeywords"] = 2] = "ConstructorParameterKeywords"; KeywordCompletionFilters[KeywordCompletionFilters["FunctionLikeBodyKeywords"] = 3] = "FunctionLikeBodyKeywords"; + KeywordCompletionFilters[KeywordCompletionFilters["TypeKeywords"] = 4] = "TypeKeywords"; })(KeywordCompletionFilters || (KeywordCompletionFilters = {})); function getCompletionsAtPosition(host, typeChecker, log, compilerOptions, sourceFile, position, allSourceFiles, options) { if (ts.isInReferenceComment(sourceFile, position)) { @@ -66842,7 +66847,7 @@ var ts; return { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, entries: entries }; } function completionInfoFromData(sourceFile, typeChecker, compilerOptions, log, completionData, includeInsertTextCompletions) { - var symbols = completionData.symbols, completionKind = completionData.completionKind, isNewIdentifierLocation = completionData.isNewIdentifierLocation, location = completionData.location, propertyAccessToConvert = completionData.propertyAccessToConvert, keywordFilters = completionData.keywordFilters, symbolToOriginInfoMap = completionData.symbolToOriginInfoMap, recommendedCompletion = completionData.recommendedCompletion; + var symbols = completionData.symbols, completionKind = completionData.completionKind, isNewIdentifierLocation = completionData.isNewIdentifierLocation, location = completionData.location, propertyAccessToConvert = completionData.propertyAccessToConvert, keywordFilters = completionData.keywordFilters, symbolToOriginInfoMap = completionData.symbolToOriginInfoMap, recommendedCompletion = completionData.recommendedCompletion, isJsxInitializer = completionData.isJsxInitializer; if (sourceFile.languageVariant === 1 && location && location.parent && ts.isJsxClosingElement(location.parent)) { var tagName = location.parent.parent.openingElement.tagName; return { isGlobalCompletion: false, isMemberCompletion: true, isNewIdentifierLocation: false, @@ -66855,14 +66860,14 @@ var ts; } var entries = []; if (ts.isSourceFileJavaScript(sourceFile)) { - var uniqueNames = getCompletionEntriesFromSymbols(symbols, entries, location, sourceFile, typeChecker, compilerOptions.target, log, completionKind, includeInsertTextCompletions, propertyAccessToConvert, recommendedCompletion, symbolToOriginInfoMap); + 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) { return undefined; } - getCompletionEntriesFromSymbols(symbols, entries, location, sourceFile, typeChecker, compilerOptions.target, log, completionKind, includeInsertTextCompletions, propertyAccessToConvert, recommendedCompletion, symbolToOriginInfoMap); + getCompletionEntriesFromSymbols(symbols, entries, location, sourceFile, typeChecker, compilerOptions.target, log, completionKind, includeInsertTextCompletions, propertyAccessToConvert, isJsxInitializer, recommendedCompletion, symbolToOriginInfoMap); } var isMemberCompletion = isMemberCompletionKind(completionKind); if (keywordFilters !== 0 || !isMemberCompletion) { @@ -66896,23 +66901,30 @@ var ts; } }); } - function createCompletionEntry(symbol, location, sourceFile, typeChecker, target, kind, origin, recommendedCompletion, propertyAccessToConvert, includeInsertTextCompletions) { + 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; - if (needsConvertPropertyAccess && !includeInsertTextCompletions) { - return undefined; - } var insertText; var replacementSpan; - if (kind === 1 && origin && origin.type === "this-type") { - insertText = needsConvertPropertyAccess ? "this[\"" + name + "\"]" : "this." + name; + if (includeInsertTextCompletions) { + if (origin && origin.type === "this-type") { + insertText = needsConvertPropertyAccess ? "this[\"" + name + "\"]" : "this." + name; + } + else if (needsConvertPropertyAccess) { + insertText = "[\"" + name + "\"]"; + replacementSpan = ts.createTextSpanFromBounds(ts.findChildOfKind(propertyAccessToConvert, 23, sourceFile).getStart(sourceFile), propertyAccessToConvert.name.end); + } + if (isJsxInitializer) { + if (insertText === undefined) + insertText = name; + insertText = "{" + insertText + "}"; + } } - else if (needsConvertPropertyAccess) { - insertText = "[\"" + name + "\"]"; - replacementSpan = ts.createTextSpanFromBounds(ts.findChildOfKind(propertyAccessToConvert, 23, sourceFile).getStart(sourceFile), propertyAccessToConvert.name.end); + if (insertText !== undefined && !includeInsertTextCompletions) { + return undefined; } return { name: name, @@ -66936,13 +66948,13 @@ var ts; 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, recommendedCompletion, symbolToOriginInfoMap) { + function getCompletionEntriesFromSymbols(symbols, entries, location, sourceFile, typeChecker, target, log, kind, includeInsertTextCompletions, propertyAccessToConvert, isJsxInitializer, recommendedCompletion, symbolToOriginInfoMap) { var start = ts.timestamp(); 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, includeInsertTextCompletions); + var entry = createCompletionEntry(symbol, location, sourceFile, typeChecker, target, kind, origin, recommendedCompletion, propertyAccessToConvert, isJsxInitializer, includeInsertTextCompletions); if (!entry) { continue; } @@ -67119,11 +67131,11 @@ var ts; if (completionData.kind !== 0) { return { type: "request", request: completionData }; } - var symbols = completionData.symbols, location = completionData.location, completionKind = completionData.completionKind, symbolToOriginInfoMap = completionData.symbolToOriginInfoMap, previousToken = completionData.previousToken; + var symbols = completionData.symbols, location = completionData.location, completionKind = completionData.completionKind, symbolToOriginInfoMap = completionData.symbolToOriginInfoMap, previousToken = completionData.previousToken, isJsxInitializer = completionData.isJsxInitializer; 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 } : undefined; + 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) { @@ -67158,7 +67170,7 @@ var ts; return { name: name, kindModifiers: kindModifiers, kind: symbolKind, displayParts: displayParts, documentation: documentation, tags: tags, codeActions: codeActions, source: sourceDisplay }; } case "none": { - if (ts.some(getKeywordCompletions(0), function (c) { return c.name === name; })) { + if (allKeywordsCompletions().some(function (c) { return c.name === name; })) { return { name: name, kind: "keyword", @@ -67345,6 +67357,7 @@ var ts; var isRightOfDot = false; var isRightOfOpenTag = false; var isStartingCloseTag = false; + var isJsxInitializer = false; var location = ts.getTouchingPropertyName(sourceFile, position, insideJsDocTagTypeExpression); if (contextToken) { if (isCompletionListBlocker(contextToken)) { @@ -67390,6 +67403,9 @@ var ts; location = contextToken; } break; + case 257: + isJsxInitializer = previousToken.kind === 58; + break; } } } @@ -67427,7 +67443,7 @@ var ts; } log("getCompletionData: Semantic work: " + (ts.timestamp() - semanticStart)); var recommendedCompletion = previousToken && getRecommendedCompletion(previousToken, typeChecker); - return { kind: 0, symbols: symbols, completionKind: completionKind, propertyAccessToConvert: propertyAccessToConvert, isNewIdentifierLocation: isNewIdentifierLocation, location: location, keywordFilters: keywordFilters, symbolToOriginInfoMap: symbolToOriginInfoMap, recommendedCompletion: recommendedCompletion, previousToken: previousToken }; + return { kind: 0, symbols: symbols, completionKind: completionKind, propertyAccessToConvert: propertyAccessToConvert, isNewIdentifierLocation: isNewIdentifierLocation, location: location, keywordFilters: keywordFilters, symbolToOriginInfoMap: symbolToOriginInfoMap, recommendedCompletion: recommendedCompletion, previousToken: previousToken, isJsxInitializer: isJsxInitializer }; function isTagWithTypeExpression(tag) { switch (tag.kind) { case 284: @@ -67561,20 +67577,19 @@ var ts; } } function filterGlobalCompletion(symbols) { + var isTypeCompletion = insideJsDocTagTypeExpression || !isContextTokenValueLocation(contextToken) && (ts.isPartOfTypeNode(location) || isContextTokenTypeLocation(contextToken)); + if (isTypeCompletion) + keywordFilters = 4; ts.filterMutate(symbols, function (symbol) { if (!ts.isSourceFile(location)) { if (ts.isExportAssignment(location.parent)) { return true; } - if (symbol && symbol.flags & 2097152) { - symbol = typeChecker.getAliasedSymbol(symbol); - } + symbol = ts.skipAlias(symbol, typeChecker); if (ts.isInRightSideOfInternalImportEqualsDeclaration(location)) { return !!(symbol.flags & 1920); } - if (insideJsDocTagTypeExpression || - (!isContextTokenValueLocation(contextToken) && - (ts.isPartOfTypeNode(location) || isContextTokenTypeLocation(contextToken)))) { + if (isTypeCompletion) { return symbolCanBeReferencedAtTypeLocation(symbol); } } @@ -67602,6 +67617,7 @@ var ts; return parentKind === 203; } } + return false; } function symbolCanBeReferencedAtTypeLocation(symbol) { symbol = symbol.exportSymbol || symbol; @@ -68215,12 +68231,12 @@ var ts; if (ts.isIdentifierText(name, target)) return validIdentiferResult; switch (kind) { - case 5: case 3: return undefined; case 0: return { name: JSON.stringify(name), needsConvertPropertyAccess: false }; case 2: + case 5: case 1: return name.charCodeAt(0) === 32 ? undefined : { name: name, needsConvertPropertyAccess: true }; case 4: @@ -68230,43 +68246,36 @@ var ts; } } var _keywordCompletions = []; - function getKeywordCompletions(keywordFilter) { - var completions = _keywordCompletions[keywordFilter]; - if (completions) { - return completions; + var allKeywordsCompletions = ts.memoize(function () { + var res = []; + for (var i = 72; i <= 143; i++) { + res.push({ + name: ts.tokenToString(i), + kind: "keyword", + kindModifiers: "", + sortText: "0" + }); } - return _keywordCompletions[keywordFilter] = generateKeywordCompletions(keywordFilter); - function generateKeywordCompletions(keywordFilter) { + return res; + }); + function getKeywordCompletions(keywordFilter) { + return _keywordCompletions[keywordFilter] || (_keywordCompletions[keywordFilter] = allKeywordsCompletions().filter(function (entry) { + var kind = ts.stringToToken(entry.name); switch (keywordFilter) { case 0: - return getAllKeywordCompletions(); + return kind !== 139; case 1: - return getFilteredKeywordCompletions(isClassMemberCompletionKeywordText); + return isClassMemberCompletionKeyword(kind); case 2: - return getFilteredKeywordCompletions(isConstructorParameterCompletionKeywordText); + return isConstructorParameterCompletionKeyword(kind); case 3: - return getFilteredKeywordCompletions(isFunctionLikeBodyCompletionKeywordText); + return isFunctionLikeBodyCompletionKeyword(kind); + case 4: + return ts.isTypeKeyword(kind); default: - ts.Debug.assertNever(keywordFilter); + return ts.Debug.assertNever(keywordFilter); } - } - function getAllKeywordCompletions() { - var allKeywordsCompletions = []; - for (var i = 72; i <= 143; i++) { - if (i === 139) - continue; - allKeywordsCompletions.push({ - name: ts.tokenToString(i), - kind: "keyword", - kindModifiers: "", - sortText: "0" - }); - } - return allKeywordsCompletions; - } - function getFilteredKeywordCompletions(filterFn) { - return ts.filter(getKeywordCompletions(0), function (entry) { return filterFn(entry.name); }); - } + })); } function isClassMemberCompletionKeyword(kind) { switch (kind) { @@ -68309,13 +68318,11 @@ var ts; case 117: case 125: case 135: + case 139: return false; } return true; } - function isFunctionLikeBodyCompletionKeywordText(text) { - return isFunctionLikeBodyCompletionKeyword(ts.stringToToken(text)); - } function isEqualityOperatorKind(kind) { switch (kind) { case 34: @@ -78287,7 +78294,7 @@ var ts; return [relativePath]; } var pathFromSourceToBaseUrl = getRelativePath(baseUrl, sourceDirectory, getCanonicalFileName); - var relativeFirst = getRelativePathNParents(pathFromSourceToBaseUrl) < getRelativePathNParents(relativePath); + var relativeFirst = getRelativePathNParents(relativePath) < getRelativePathNParents(pathFromSourceToBaseUrl); return relativeFirst ? [relativePath, importRelativeToBaseUrl] : [importRelativeToBaseUrl, relativePath]; }); }); @@ -80528,6 +80535,9 @@ var ts; break; } } + if (!statements.length) { + return { errors: [ts.createFileDiagnostic(sourceFile, span.start, length, Messages.cannotExtractRange)] }; + } return { targetRange: { range: statements, facts: rangeFacts, declarations: declarations } }; } if (ts.isReturnStatement(start) && !start.expression) { @@ -84646,7 +84656,7 @@ var ts; }()); server.TextStorage = TextStorage; function isDynamicFileName(fileName) { - return ts.getBaseFileName(fileName)[0] === "^"; + return fileName[0] === "^" || ts.getBaseFileName(fileName)[0] === "^"; } server.isDynamicFileName = isDynamicFileName; var ScriptInfo = (function () { @@ -87493,7 +87503,7 @@ var ts; ts.Debug.assert(info.isOrphan()); var project = this.getOrCreateInferredProjectForProjectRootPathIfEnabled(info, projectRootPath) || this.getOrCreateSingleInferredProjectIfEnabled() || - this.createInferredProject(ts.getDirectoryPath(info.path)); + this.createInferredProject(info.isDynamic ? this.currentDirectory : ts.getDirectoryPath(info.path)); project.addRoot(info); project.updateGraph(); if (!this.useSingleInferredProject && !project.projectRootPath) { @@ -88014,7 +88024,7 @@ var ts; }); }; ProjectService.prototype.getOrCreateInferredProjectForProjectRootPathIfEnabled = function (info, projectRootPath) { - if (!this.useInferredProjectPerProjectRoot) { + if (info.isDynamic || !this.useInferredProjectPerProjectRoot) { return undefined; } if (projectRootPath) { diff --git a/lib/tsserverlibrary.js b/lib/tsserverlibrary.js index 7967ba04fc4..ad86c98e6ee 100644 --- a/lib/tsserverlibrary.js +++ b/lib/tsserverlibrary.js @@ -28604,11 +28604,14 @@ var ts; } var visitedSymbolTables = []; return forEachSymbolTableInScope(enclosingDeclaration, getAccessibleSymbolChainFromSymbolTable); - function getAccessibleSymbolChainFromSymbolTable(symbols) { + /** + * @param {ignoreQualification} boolean Set when a symbol is being looked for through the exports of another symbol (meaning we have a route to qualify it already) + */ + function getAccessibleSymbolChainFromSymbolTable(symbols, ignoreQualification) { if (!ts.pushIfUnique(visitedSymbolTables, symbols)) { return undefined; } - var result = trySymbolTable(symbols); + var result = trySymbolTable(symbols, ignoreQualification); visitedSymbolTables.pop(); return result; } @@ -28618,20 +28621,20 @@ var ts; // If symbol needs qualification, make sure that parent is accessible, if it is then this symbol is accessible too !!getAccessibleSymbolChain(symbolFromSymbolTable.parent, enclosingDeclaration, getQualifiedLeftMeaning(meaning), useOnlyExternalAliasing); } - function isAccessible(symbolFromSymbolTable, resolvedAliasSymbol) { + function isAccessible(symbolFromSymbolTable, resolvedAliasSymbol, ignoreQualification) { return symbol === (resolvedAliasSymbol || symbolFromSymbolTable) && // if the symbolFromSymbolTable is not external module (it could be if it was determined as ambient external module and would be in globals table) // and if symbolFromSymbolTable or alias resolution matches the symbol, // check the symbol can be qualified, it is only then this symbol is accessible !ts.some(symbolFromSymbolTable.declarations, hasExternalModuleSymbol) && - canQualifySymbol(symbolFromSymbolTable, meaning); + (ignoreQualification || canQualifySymbol(symbolFromSymbolTable, meaning)); } function isUMDExportSymbol(symbol) { return symbol && symbol.declarations && symbol.declarations[0] && ts.isNamespaceExportDeclaration(symbol.declarations[0]); } - function trySymbolTable(symbols) { + function trySymbolTable(symbols, ignoreQualification) { // If symbol is directly available by its name in the symbol table - if (isAccessible(symbols.get(symbol.escapedName))) { + if (isAccessible(symbols.get(symbol.escapedName), /*resolvedAliasSymbol*/ undefined, ignoreQualification)) { return [symbol]; } // Check if symbol is any of the alias @@ -28642,13 +28645,13 @@ var ts; // If `!useOnlyExternalAliasing`, we can use any type of alias to get the name && (!useOnlyExternalAliasing || ts.some(symbolFromSymbolTable.declarations, ts.isExternalModuleImportEqualsDeclaration))) { var resolvedImportedSymbol = resolveAlias(symbolFromSymbolTable); - if (isAccessible(symbolFromSymbolTable, resolvedImportedSymbol)) { + if (isAccessible(symbolFromSymbolTable, resolvedImportedSymbol, ignoreQualification)) { return [symbolFromSymbolTable]; } // Look in the exported members, if we can find accessibleSymbolChain, symbol is accessible using this chain // but only if the symbolFromSymbolTable can be qualified var candidateTable = getExportsOfSymbol(resolvedImportedSymbol); - var accessibleSymbolsFromExports = candidateTable && getAccessibleSymbolChainFromSymbolTable(candidateTable); + var accessibleSymbolsFromExports = candidateTable && getAccessibleSymbolChainFromSymbolTable(candidateTable, /*ignoreQualification*/ true); if (accessibleSymbolsFromExports && canQualifySymbol(symbolFromSymbolTable, getQualifiedLeftMeaning(meaning))) { return [symbolFromSymbolTable].concat(accessibleSymbolsFromExports); } @@ -59861,7 +59864,7 @@ var ts; return ts.visitEachChild(node, visitor, context); } function visitLabeledStatement(node) { - if (enclosingFunctionFlags & 2 /* Async */ && enclosingFunctionFlags & 1 /* Generator */) { + if (enclosingFunctionFlags & 2 /* Async */) { var statement = ts.unwrapInnermostStatementOfLabel(node); if (statement.kind === 217 /* ForOfStatement */ && statement.awaitModifier) { return visitForOfStatement(statement, node); @@ -78658,12 +78661,16 @@ var ts; ts.typeKeywords = [ 119 /* AnyKeyword */, 122 /* BooleanKeyword */, + 127 /* KeyOfKeyword */, 130 /* NeverKeyword */, + 95 /* NullKeyword */, 133 /* NumberKeyword */, 134 /* ObjectKeyword */, 136 /* StringKeyword */, 137 /* SymbolKeyword */, 105 /* VoidKeyword */, + 139 /* UndefinedKeyword */, + 140 /* UniqueKeyword */, ]; function isTypeKeyword(kind) { return ts.contains(ts.typeKeywords, kind); @@ -80956,7 +80963,8 @@ var ts; KeywordCompletionFilters[KeywordCompletionFilters["None"] = 0] = "None"; KeywordCompletionFilters[KeywordCompletionFilters["ClassElementKeywords"] = 1] = "ClassElementKeywords"; KeywordCompletionFilters[KeywordCompletionFilters["ConstructorParameterKeywords"] = 2] = "ConstructorParameterKeywords"; - KeywordCompletionFilters[KeywordCompletionFilters["FunctionLikeBodyKeywords"] = 3] = "FunctionLikeBodyKeywords"; // Keywords at function like body + KeywordCompletionFilters[KeywordCompletionFilters["FunctionLikeBodyKeywords"] = 3] = "FunctionLikeBodyKeywords"; + KeywordCompletionFilters[KeywordCompletionFilters["TypeKeywords"] = 4] = "TypeKeywords"; })(KeywordCompletionFilters || (KeywordCompletionFilters = {})); function getCompletionsAtPosition(host, typeChecker, log, compilerOptions, sourceFile, position, allSourceFiles, options) { if (ts.isInReferenceComment(sourceFile, position)) { @@ -80997,7 +81005,7 @@ var ts; return { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, entries: entries }; } function completionInfoFromData(sourceFile, typeChecker, compilerOptions, log, completionData, includeInsertTextCompletions) { - var symbols = completionData.symbols, completionKind = completionData.completionKind, isNewIdentifierLocation = completionData.isNewIdentifierLocation, location = completionData.location, propertyAccessToConvert = completionData.propertyAccessToConvert, keywordFilters = completionData.keywordFilters, symbolToOriginInfoMap = completionData.symbolToOriginInfoMap, recommendedCompletion = completionData.recommendedCompletion; + var symbols = completionData.symbols, completionKind = completionData.completionKind, isNewIdentifierLocation = completionData.isNewIdentifierLocation, location = completionData.location, propertyAccessToConvert = completionData.propertyAccessToConvert, keywordFilters = completionData.keywordFilters, symbolToOriginInfoMap = completionData.symbolToOriginInfoMap, recommendedCompletion = completionData.recommendedCompletion, isJsxInitializer = completionData.isJsxInitializer; if (sourceFile.languageVariant === 1 /* JSX */ && location && location.parent && ts.isJsxClosingElement(location.parent)) { // In the TypeScript JSX element, if such element is not defined. When users query for completion at closing tag, // instead of simply giving unknown value, the completion will return the tag-name of an associated opening-element. @@ -81015,14 +81023,14 @@ var ts; } var entries = []; if (ts.isSourceFileJavaScript(sourceFile)) { - var uniqueNames = getCompletionEntriesFromSymbols(symbols, entries, location, sourceFile, typeChecker, compilerOptions.target, log, completionKind, includeInsertTextCompletions, propertyAccessToConvert, recommendedCompletion, symbolToOriginInfoMap); + 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, recommendedCompletion, symbolToOriginInfoMap); + 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 @@ -81061,24 +81069,31 @@ var ts; } }); } - function createCompletionEntry(symbol, location, sourceFile, typeChecker, target, kind, origin, recommendedCompletion, propertyAccessToConvert, includeInsertTextCompletions) { + 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; - if (needsConvertPropertyAccess && !includeInsertTextCompletions) { - return undefined; - } var insertText; var replacementSpan; - if (kind === 1 /* Global */ && origin && origin.type === "this-type") { - insertText = needsConvertPropertyAccess ? "this[\"" + name + "\"]" : "this." + name; + if (includeInsertTextCompletions) { + if (origin && origin.type === "this-type") { + insertText = needsConvertPropertyAccess ? "this[\"" + name + "\"]" : "this." + name; + } + else if (needsConvertPropertyAccess) { + // TODO: GH#20619 Use configured quote style + insertText = "[\"" + name + "\"]"; + replacementSpan = ts.createTextSpanFromBounds(ts.findChildOfKind(propertyAccessToConvert, 23 /* DotToken */, sourceFile).getStart(sourceFile), propertyAccessToConvert.name.end); + } + if (isJsxInitializer) { + if (insertText === undefined) + insertText = name; + insertText = "{" + insertText + "}"; + } } - else if (needsConvertPropertyAccess) { - // TODO: GH#20619 Use configured quote style - insertText = "[\"" + name + "\"]"; - replacementSpan = ts.createTextSpanFromBounds(ts.findChildOfKind(propertyAccessToConvert, 23 /* DotToken */, sourceFile).getStart(sourceFile), propertyAccessToConvert.name.end); + 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 @@ -81109,7 +81124,7 @@ var ts; 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, recommendedCompletion, symbolToOriginInfoMap) { + 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. @@ -81119,7 +81134,7 @@ var ts; 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, includeInsertTextCompletions); + var entry = createCompletionEntry(symbol, location, sourceFile, typeChecker, target, kind, origin, recommendedCompletion, propertyAccessToConvert, isJsxInitializer, includeInsertTextCompletions); if (!entry) { continue; } @@ -81337,7 +81352,7 @@ var ts; 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; + 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 @@ -81345,7 +81360,7 @@ var ts; 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 } : undefined; + 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) { @@ -81383,7 +81398,7 @@ var ts; } case "none": { // Didn't find a symbol with this name. See if we can find a keyword instead. - if (ts.some(getKeywordCompletions(0 /* None */), function (c) { return c.name === name; })) { + if (allKeywordsCompletions().some(function (c) { return c.name === name; })) { return { name: name, kind: "keyword" /* keyword */, @@ -81453,6 +81468,7 @@ var ts; var CompletionKind; (function (CompletionKind) { CompletionKind[CompletionKind["ObjectPropertyDeclaration"] = 0] = "ObjectPropertyDeclaration"; + /** Note that sometimes we access completions from global scope, but use "None" instead of this. See isGlobalCompletionScope. */ CompletionKind[CompletionKind["Global"] = 1] = "Global"; CompletionKind[CompletionKind["PropertyAccess"] = 2] = "PropertyAccess"; CompletionKind[CompletionKind["MemberLike"] = 3] = "MemberLike"; @@ -81605,6 +81621,7 @@ var ts; 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 @@ -81658,6 +81675,9 @@ var ts; location = contextToken; } break; + case 257 /* JsxAttribute */: + isJsxInitializer = previousToken.kind === 58 /* EqualsToken */; + break; } } } @@ -81698,7 +81718,7 @@ var ts; } log("getCompletionData: Semantic work: " + (ts.timestamp() - semanticStart)); var recommendedCompletion = previousToken && getRecommendedCompletion(previousToken, typeChecker); - return { kind: 0 /* Data */, symbols: symbols, completionKind: completionKind, propertyAccessToConvert: propertyAccessToConvert, isNewIdentifierLocation: isNewIdentifierLocation, location: location, keywordFilters: keywordFilters, symbolToOriginInfoMap: symbolToOriginInfoMap, recommendedCompletion: recommendedCompletion, previousToken: previousToken }; + return { kind: 0 /* Data */, symbols: symbols, completionKind: completionKind, propertyAccessToConvert: propertyAccessToConvert, isNewIdentifierLocation: isNewIdentifierLocation, location: location, keywordFilters: keywordFilters, symbolToOriginInfoMap: symbolToOriginInfoMap, recommendedCompletion: recommendedCompletion, previousToken: previousToken, isJsxInitializer: isJsxInitializer }; function isTagWithTypeExpression(tag) { switch (tag.kind) { case 284 /* JSDocParameterTag */: @@ -81876,23 +81896,21 @@ var ts; } } function filterGlobalCompletion(symbols) { + var isTypeCompletion = insideJsDocTagTypeExpression || !isContextTokenValueLocation(contextToken) && (ts.isPartOfTypeNode(location) || isContextTokenTypeLocation(contextToken)); + if (isTypeCompletion) + 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; } - // This is an alias, follow what it aliases - if (symbol && symbol.flags & 2097152 /* Alias */) { - symbol = typeChecker.getAliasedSymbol(symbol); - } + 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 (insideJsDocTagTypeExpression || - (!isContextTokenValueLocation(contextToken) && - (ts.isPartOfTypeNode(location) || isContextTokenTypeLocation(contextToken)))) { + if (isTypeCompletion) { // Its a type, but you can reach it by namespace.type as well return symbolCanBeReferencedAtTypeLocation(symbol); } @@ -81922,6 +81940,7 @@ var ts; return parentKind === 203 /* AsExpression */; } } + return false; } function symbolCanBeReferencedAtTypeLocation(symbol) { symbol = symbol.exportSymbol || symbol; @@ -82695,13 +82714,13 @@ var ts; if (ts.isIdentifierText(name, target)) return validIdentiferResult; switch (kind) { - case 5 /* None */: case 3 /* MemberLike */: return undefined; case 0 /* ObjectPropertyDeclaration */: // TODO: GH#18169 return { name: JSON.stringify(name), needsConvertPropertyAccess: false }; case 2 /* PropertyAccess */: + case 5 /* None */: case 1 /* Global */: // 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 }; @@ -82713,44 +82732,37 @@ var ts; } // A cache of completion entries for keywords, these do not change between sessions var _keywordCompletions = []; - function getKeywordCompletions(keywordFilter) { - var completions = _keywordCompletions[keywordFilter]; - if (completions) { - return completions; + var allKeywordsCompletions = ts.memoize(function () { + var res = []; + for (var i = 72 /* FirstKeyword */; i <= 143 /* LastKeyword */; i++) { + res.push({ + name: ts.tokenToString(i), + kind: "keyword" /* keyword */, + kindModifiers: "" /* none */, + sortText: "0" + }); } - return _keywordCompletions[keywordFilter] = generateKeywordCompletions(keywordFilter); - function generateKeywordCompletions(keywordFilter) { + 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 */: - return getAllKeywordCompletions(); + // "undefined" is a global variable, so don't need a keyword completion for it. + return kind !== 139 /* UndefinedKeyword */; case 1 /* ClassElementKeywords */: - return getFilteredKeywordCompletions(isClassMemberCompletionKeywordText); + return isClassMemberCompletionKeyword(kind); case 2 /* ConstructorParameterKeywords */: - return getFilteredKeywordCompletions(isConstructorParameterCompletionKeywordText); + return isConstructorParameterCompletionKeyword(kind); case 3 /* FunctionLikeBodyKeywords */: - return getFilteredKeywordCompletions(isFunctionLikeBodyCompletionKeywordText); + return isFunctionLikeBodyCompletionKeyword(kind); + case 4 /* TypeKeywords */: + return ts.isTypeKeyword(kind); default: - ts.Debug.assertNever(keywordFilter); + return ts.Debug.assertNever(keywordFilter); } - } - function getAllKeywordCompletions() { - var allKeywordsCompletions = []; - for (var i = 72 /* FirstKeyword */; i <= 143 /* LastKeyword */; i++) { - // "undefined" is a global variable, so don't need a keyword completion for it. - if (i === 139 /* UndefinedKeyword */) - continue; - allKeywordsCompletions.push({ - name: ts.tokenToString(i), - kind: "keyword" /* keyword */, - kindModifiers: "" /* none */, - sortText: "0" - }); - } - return allKeywordsCompletions; - } - function getFilteredKeywordCompletions(filterFn) { - return ts.filter(getKeywordCompletions(0 /* None */), function (entry) { return filterFn(entry.name); }); - } + })); } function isClassMemberCompletionKeyword(kind) { switch (kind) { @@ -82793,13 +82805,11 @@ var ts; case 117 /* AbstractKeyword */: case 125 /* GetKeyword */: case 135 /* SetKeyword */: + case 139 /* UndefinedKeyword */: return false; } return true; } - function isFunctionLikeBodyCompletionKeywordText(text) { - return isFunctionLikeBodyCompletionKeyword(ts.stringToToken(text)); - } function isEqualityOperatorKind(kind) { switch (kind) { case 34 /* EqualsEqualsEqualsToken */: @@ -94411,7 +94421,7 @@ var ts; 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(pathFromSourceToBaseUrl) < getRelativePathNParents(relativePath); + var relativeFirst = getRelativePathNParents(relativePath) < getRelativePathNParents(pathFromSourceToBaseUrl); return relativeFirst ? [relativePath, importRelativeToBaseUrl] : [importRelativeToBaseUrl, relativePath]; }); }); @@ -96928,6 +96938,14 @@ var ts; 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) { @@ -103556,7 +103574,7 @@ var ts; server.TextStorage = TextStorage; /*@internal*/ function isDynamicFileName(fileName) { - return ts.getBaseFileName(fileName)[0] === "^"; + return fileName[0] === "^" || ts.getBaseFileName(fileName)[0] === "^"; } server.isDynamicFileName = isDynamicFileName; var ScriptInfo = /** @class */ (function () { @@ -106917,7 +106935,7 @@ var ts; ts.Debug.assert(info.isOrphan()); var project = this.getOrCreateInferredProjectForProjectRootPathIfEnabled(info, projectRootPath) || this.getOrCreateSingleInferredProjectIfEnabled() || - this.createInferredProject(ts.getDirectoryPath(info.path)); + this.createInferredProject(info.isDynamic ? this.currentDirectory : ts.getDirectoryPath(info.path)); project.addRoot(info); project.updateGraph(); if (!this.useSingleInferredProject && !project.projectRootPath) { @@ -107566,7 +107584,7 @@ var ts; }); }; ProjectService.prototype.getOrCreateInferredProjectForProjectRootPathIfEnabled = function (info, projectRootPath) { - if (!this.useInferredProjectPerProjectRoot) { + if (info.isDynamic || !this.useInferredProjectPerProjectRoot) { return undefined; } if (projectRootPath) { diff --git a/lib/typescript.js b/lib/typescript.js index 4c73d04ba23..6858f786ede 100644 --- a/lib/typescript.js +++ b/lib/typescript.js @@ -26564,11 +26564,14 @@ var ts; } var visitedSymbolTables = []; return forEachSymbolTableInScope(enclosingDeclaration, getAccessibleSymbolChainFromSymbolTable); - function getAccessibleSymbolChainFromSymbolTable(symbols) { + /** + * @param {ignoreQualification} boolean Set when a symbol is being looked for through the exports of another symbol (meaning we have a route to qualify it already) + */ + function getAccessibleSymbolChainFromSymbolTable(symbols, ignoreQualification) { if (!ts.pushIfUnique(visitedSymbolTables, symbols)) { return undefined; } - var result = trySymbolTable(symbols); + var result = trySymbolTable(symbols, ignoreQualification); visitedSymbolTables.pop(); return result; } @@ -26578,20 +26581,20 @@ var ts; // If symbol needs qualification, make sure that parent is accessible, if it is then this symbol is accessible too !!getAccessibleSymbolChain(symbolFromSymbolTable.parent, enclosingDeclaration, getQualifiedLeftMeaning(meaning), useOnlyExternalAliasing); } - function isAccessible(symbolFromSymbolTable, resolvedAliasSymbol) { + function isAccessible(symbolFromSymbolTable, resolvedAliasSymbol, ignoreQualification) { return symbol === (resolvedAliasSymbol || symbolFromSymbolTable) && // if the symbolFromSymbolTable is not external module (it could be if it was determined as ambient external module and would be in globals table) // and if symbolFromSymbolTable or alias resolution matches the symbol, // check the symbol can be qualified, it is only then this symbol is accessible !ts.some(symbolFromSymbolTable.declarations, hasExternalModuleSymbol) && - canQualifySymbol(symbolFromSymbolTable, meaning); + (ignoreQualification || canQualifySymbol(symbolFromSymbolTable, meaning)); } function isUMDExportSymbol(symbol) { return symbol && symbol.declarations && symbol.declarations[0] && ts.isNamespaceExportDeclaration(symbol.declarations[0]); } - function trySymbolTable(symbols) { + function trySymbolTable(symbols, ignoreQualification) { // If symbol is directly available by its name in the symbol table - if (isAccessible(symbols.get(symbol.escapedName))) { + if (isAccessible(symbols.get(symbol.escapedName), /*resolvedAliasSymbol*/ undefined, ignoreQualification)) { return [symbol]; } // Check if symbol is any of the alias @@ -26602,13 +26605,13 @@ var ts; // If `!useOnlyExternalAliasing`, we can use any type of alias to get the name && (!useOnlyExternalAliasing || ts.some(symbolFromSymbolTable.declarations, ts.isExternalModuleImportEqualsDeclaration))) { var resolvedImportedSymbol = resolveAlias(symbolFromSymbolTable); - if (isAccessible(symbolFromSymbolTable, resolvedImportedSymbol)) { + if (isAccessible(symbolFromSymbolTable, resolvedImportedSymbol, ignoreQualification)) { return [symbolFromSymbolTable]; } // Look in the exported members, if we can find accessibleSymbolChain, symbol is accessible using this chain // but only if the symbolFromSymbolTable can be qualified var candidateTable = getExportsOfSymbol(resolvedImportedSymbol); - var accessibleSymbolsFromExports = candidateTable && getAccessibleSymbolChainFromSymbolTable(candidateTable); + var accessibleSymbolsFromExports = candidateTable && getAccessibleSymbolChainFromSymbolTable(candidateTable, /*ignoreQualification*/ true); if (accessibleSymbolsFromExports && canQualifySymbol(symbolFromSymbolTable, getQualifiedLeftMeaning(meaning))) { return [symbolFromSymbolTable].concat(accessibleSymbolsFromExports); } @@ -57821,7 +57824,7 @@ var ts; return ts.visitEachChild(node, visitor, context); } function visitLabeledStatement(node) { - if (enclosingFunctionFlags & 2 /* Async */ && enclosingFunctionFlags & 1 /* Generator */) { + if (enclosingFunctionFlags & 2 /* Async */) { var statement = ts.unwrapInnermostStatementOfLabel(node); if (statement.kind === 217 /* ForOfStatement */ && statement.awaitModifier) { return visitForOfStatement(statement, node); @@ -76976,7 +76979,7 @@ var ts; var host = system; host.onConfigFileDiagnostic = reportDiagnostic; host.onUnRecoverableConfigFileDiagnostic = function (diagnostic) { return reportUnrecoverableDiagnostic(ts.sys, reportDiagnostic, diagnostic); }; - var result = parseConfigFile(configFileName, optionsToExtend, host); + var result = getParsedCommandLineOfConfigFile(configFileName, optionsToExtend, host); host.onConfigFileDiagnostic = undefined; host.onUnRecoverableConfigFileDiagnostic = undefined; return result; @@ -76985,7 +76988,7 @@ var ts; /** * Reads the config file, reports errors if any and exits if the config file cannot be found */ - function parseConfigFile(configFileName, optionsToExtend, host) { + function getParsedCommandLineOfConfigFile(configFileName, optionsToExtend, host) { var configFileText; try { configFileText = host.readFile(configFileName); @@ -77007,7 +77010,7 @@ var ts; configParseResult.errors.forEach(function (diagnostic) { return host.onConfigFileDiagnostic(diagnostic); }); return configParseResult; } - ts.parseConfigFile = parseConfigFile; + ts.getParsedCommandLineOfConfigFile = getParsedCommandLineOfConfigFile; /** * Helper that emit files, report diagnostics and lists emitted and/or source files depending on compiler options */ @@ -77464,7 +77467,7 @@ var ts; watchConfigFileWildCardDirectories(); } function parseConfigFile() { - var configParseResult = ts.parseConfigFile(configFileName, optionsToExtendForConfigFile, parseConfigFileHost); + var configParseResult = ts.getParsedCommandLineOfConfigFile(configFileName, optionsToExtendForConfigFile, parseConfigFileHost); rootFileNames = configParseResult.fileNames; compilerOptions = configParseResult.options; configFileSpecs = configParseResult.configFileSpecs; @@ -80820,12 +80823,16 @@ var ts; ts.typeKeywords = [ 119 /* AnyKeyword */, 122 /* BooleanKeyword */, + 127 /* KeyOfKeyword */, 130 /* NeverKeyword */, + 95 /* NullKeyword */, 133 /* NumberKeyword */, 134 /* ObjectKeyword */, 136 /* StringKeyword */, 137 /* SymbolKeyword */, 105 /* VoidKeyword */, + 139 /* UndefinedKeyword */, + 140 /* UniqueKeyword */, ]; function isTypeKeyword(kind) { return ts.contains(ts.typeKeywords, kind); @@ -82513,7 +82520,8 @@ var ts; KeywordCompletionFilters[KeywordCompletionFilters["None"] = 0] = "None"; KeywordCompletionFilters[KeywordCompletionFilters["ClassElementKeywords"] = 1] = "ClassElementKeywords"; KeywordCompletionFilters[KeywordCompletionFilters["ConstructorParameterKeywords"] = 2] = "ConstructorParameterKeywords"; - KeywordCompletionFilters[KeywordCompletionFilters["FunctionLikeBodyKeywords"] = 3] = "FunctionLikeBodyKeywords"; // Keywords at function like body + KeywordCompletionFilters[KeywordCompletionFilters["FunctionLikeBodyKeywords"] = 3] = "FunctionLikeBodyKeywords"; + KeywordCompletionFilters[KeywordCompletionFilters["TypeKeywords"] = 4] = "TypeKeywords"; })(KeywordCompletionFilters || (KeywordCompletionFilters = {})); function getCompletionsAtPosition(host, typeChecker, log, compilerOptions, sourceFile, position, allSourceFiles, options) { if (ts.isInReferenceComment(sourceFile, position)) { @@ -82554,7 +82562,7 @@ var ts; return { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, entries: entries }; } function completionInfoFromData(sourceFile, typeChecker, compilerOptions, log, completionData, includeInsertTextCompletions) { - var symbols = completionData.symbols, completionKind = completionData.completionKind, isNewIdentifierLocation = completionData.isNewIdentifierLocation, location = completionData.location, propertyAccessToConvert = completionData.propertyAccessToConvert, keywordFilters = completionData.keywordFilters, symbolToOriginInfoMap = completionData.symbolToOriginInfoMap, recommendedCompletion = completionData.recommendedCompletion; + var symbols = completionData.symbols, completionKind = completionData.completionKind, isNewIdentifierLocation = completionData.isNewIdentifierLocation, location = completionData.location, propertyAccessToConvert = completionData.propertyAccessToConvert, keywordFilters = completionData.keywordFilters, symbolToOriginInfoMap = completionData.symbolToOriginInfoMap, recommendedCompletion = completionData.recommendedCompletion, isJsxInitializer = completionData.isJsxInitializer; if (sourceFile.languageVariant === 1 /* JSX */ && location && location.parent && ts.isJsxClosingElement(location.parent)) { // In the TypeScript JSX element, if such element is not defined. When users query for completion at closing tag, // instead of simply giving unknown value, the completion will return the tag-name of an associated opening-element. @@ -82572,14 +82580,14 @@ var ts; } var entries = []; if (ts.isSourceFileJavaScript(sourceFile)) { - var uniqueNames = getCompletionEntriesFromSymbols(symbols, entries, location, sourceFile, typeChecker, compilerOptions.target, log, completionKind, includeInsertTextCompletions, propertyAccessToConvert, recommendedCompletion, symbolToOriginInfoMap); + 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, recommendedCompletion, symbolToOriginInfoMap); + 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 @@ -82618,24 +82626,31 @@ var ts; } }); } - function createCompletionEntry(symbol, location, sourceFile, typeChecker, target, kind, origin, recommendedCompletion, propertyAccessToConvert, includeInsertTextCompletions) { + 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; - if (needsConvertPropertyAccess && !includeInsertTextCompletions) { - return undefined; - } var insertText; var replacementSpan; - if (kind === 1 /* Global */ && origin && origin.type === "this-type") { - insertText = needsConvertPropertyAccess ? "this[\"" + name + "\"]" : "this." + name; + if (includeInsertTextCompletions) { + if (origin && origin.type === "this-type") { + insertText = needsConvertPropertyAccess ? "this[\"" + name + "\"]" : "this." + name; + } + else if (needsConvertPropertyAccess) { + // TODO: GH#20619 Use configured quote style + insertText = "[\"" + name + "\"]"; + replacementSpan = ts.createTextSpanFromBounds(ts.findChildOfKind(propertyAccessToConvert, 23 /* DotToken */, sourceFile).getStart(sourceFile), propertyAccessToConvert.name.end); + } + if (isJsxInitializer) { + if (insertText === undefined) + insertText = name; + insertText = "{" + insertText + "}"; + } } - else if (needsConvertPropertyAccess) { - // TODO: GH#20619 Use configured quote style - insertText = "[\"" + name + "\"]"; - replacementSpan = ts.createTextSpanFromBounds(ts.findChildOfKind(propertyAccessToConvert, 23 /* DotToken */, sourceFile).getStart(sourceFile), propertyAccessToConvert.name.end); + 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 @@ -82666,7 +82681,7 @@ var ts; 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, recommendedCompletion, symbolToOriginInfoMap) { + 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. @@ -82676,7 +82691,7 @@ var ts; 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, includeInsertTextCompletions); + var entry = createCompletionEntry(symbol, location, sourceFile, typeChecker, target, kind, origin, recommendedCompletion, propertyAccessToConvert, isJsxInitializer, includeInsertTextCompletions); if (!entry) { continue; } @@ -82894,7 +82909,7 @@ var ts; 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; + 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 @@ -82902,7 +82917,7 @@ var ts; 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 } : undefined; + 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) { @@ -82940,7 +82955,7 @@ var ts; } case "none": { // Didn't find a symbol with this name. See if we can find a keyword instead. - if (ts.some(getKeywordCompletions(0 /* None */), function (c) { return c.name === name; })) { + if (allKeywordsCompletions().some(function (c) { return c.name === name; })) { return { name: name, kind: "keyword" /* keyword */, @@ -83010,6 +83025,7 @@ var ts; var CompletionKind; (function (CompletionKind) { CompletionKind[CompletionKind["ObjectPropertyDeclaration"] = 0] = "ObjectPropertyDeclaration"; + /** Note that sometimes we access completions from global scope, but use "None" instead of this. See isGlobalCompletionScope. */ CompletionKind[CompletionKind["Global"] = 1] = "Global"; CompletionKind[CompletionKind["PropertyAccess"] = 2] = "PropertyAccess"; CompletionKind[CompletionKind["MemberLike"] = 3] = "MemberLike"; @@ -83162,6 +83178,7 @@ var ts; 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 @@ -83215,6 +83232,9 @@ var ts; location = contextToken; } break; + case 257 /* JsxAttribute */: + isJsxInitializer = previousToken.kind === 58 /* EqualsToken */; + break; } } } @@ -83255,7 +83275,7 @@ var ts; } log("getCompletionData: Semantic work: " + (ts.timestamp() - semanticStart)); var recommendedCompletion = previousToken && getRecommendedCompletion(previousToken, typeChecker); - return { kind: 0 /* Data */, symbols: symbols, completionKind: completionKind, propertyAccessToConvert: propertyAccessToConvert, isNewIdentifierLocation: isNewIdentifierLocation, location: location, keywordFilters: keywordFilters, symbolToOriginInfoMap: symbolToOriginInfoMap, recommendedCompletion: recommendedCompletion, previousToken: previousToken }; + return { kind: 0 /* Data */, symbols: symbols, completionKind: completionKind, propertyAccessToConvert: propertyAccessToConvert, isNewIdentifierLocation: isNewIdentifierLocation, location: location, keywordFilters: keywordFilters, symbolToOriginInfoMap: symbolToOriginInfoMap, recommendedCompletion: recommendedCompletion, previousToken: previousToken, isJsxInitializer: isJsxInitializer }; function isTagWithTypeExpression(tag) { switch (tag.kind) { case 284 /* JSDocParameterTag */: @@ -83433,23 +83453,21 @@ var ts; } } function filterGlobalCompletion(symbols) { + var isTypeCompletion = insideJsDocTagTypeExpression || !isContextTokenValueLocation(contextToken) && (ts.isPartOfTypeNode(location) || isContextTokenTypeLocation(contextToken)); + if (isTypeCompletion) + 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; } - // This is an alias, follow what it aliases - if (symbol && symbol.flags & 2097152 /* Alias */) { - symbol = typeChecker.getAliasedSymbol(symbol); - } + 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 (insideJsDocTagTypeExpression || - (!isContextTokenValueLocation(contextToken) && - (ts.isPartOfTypeNode(location) || isContextTokenTypeLocation(contextToken)))) { + if (isTypeCompletion) { // Its a type, but you can reach it by namespace.type as well return symbolCanBeReferencedAtTypeLocation(symbol); } @@ -83479,6 +83497,7 @@ var ts; return parentKind === 203 /* AsExpression */; } } + return false; } function symbolCanBeReferencedAtTypeLocation(symbol) { symbol = symbol.exportSymbol || symbol; @@ -84252,13 +84271,13 @@ var ts; if (ts.isIdentifierText(name, target)) return validIdentiferResult; switch (kind) { - case 5 /* None */: case 3 /* MemberLike */: return undefined; case 0 /* ObjectPropertyDeclaration */: // TODO: GH#18169 return { name: JSON.stringify(name), needsConvertPropertyAccess: false }; case 2 /* PropertyAccess */: + case 5 /* None */: case 1 /* Global */: // 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 }; @@ -84270,44 +84289,37 @@ var ts; } // A cache of completion entries for keywords, these do not change between sessions var _keywordCompletions = []; - function getKeywordCompletions(keywordFilter) { - var completions = _keywordCompletions[keywordFilter]; - if (completions) { - return completions; + var allKeywordsCompletions = ts.memoize(function () { + var res = []; + for (var i = 72 /* FirstKeyword */; i <= 143 /* LastKeyword */; i++) { + res.push({ + name: ts.tokenToString(i), + kind: "keyword" /* keyword */, + kindModifiers: "" /* none */, + sortText: "0" + }); } - return _keywordCompletions[keywordFilter] = generateKeywordCompletions(keywordFilter); - function generateKeywordCompletions(keywordFilter) { + 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 */: - return getAllKeywordCompletions(); + // "undefined" is a global variable, so don't need a keyword completion for it. + return kind !== 139 /* UndefinedKeyword */; case 1 /* ClassElementKeywords */: - return getFilteredKeywordCompletions(isClassMemberCompletionKeywordText); + return isClassMemberCompletionKeyword(kind); case 2 /* ConstructorParameterKeywords */: - return getFilteredKeywordCompletions(isConstructorParameterCompletionKeywordText); + return isConstructorParameterCompletionKeyword(kind); case 3 /* FunctionLikeBodyKeywords */: - return getFilteredKeywordCompletions(isFunctionLikeBodyCompletionKeywordText); + return isFunctionLikeBodyCompletionKeyword(kind); + case 4 /* TypeKeywords */: + return ts.isTypeKeyword(kind); default: - ts.Debug.assertNever(keywordFilter); + return ts.Debug.assertNever(keywordFilter); } - } - function getAllKeywordCompletions() { - var allKeywordsCompletions = []; - for (var i = 72 /* FirstKeyword */; i <= 143 /* LastKeyword */; i++) { - // "undefined" is a global variable, so don't need a keyword completion for it. - if (i === 139 /* UndefinedKeyword */) - continue; - allKeywordsCompletions.push({ - name: ts.tokenToString(i), - kind: "keyword" /* keyword */, - kindModifiers: "" /* none */, - sortText: "0" - }); - } - return allKeywordsCompletions; - } - function getFilteredKeywordCompletions(filterFn) { - return ts.filter(getKeywordCompletions(0 /* None */), function (entry) { return filterFn(entry.name); }); - } + })); } function isClassMemberCompletionKeyword(kind) { switch (kind) { @@ -84350,13 +84362,11 @@ var ts; case 117 /* AbstractKeyword */: case 125 /* GetKeyword */: case 135 /* SetKeyword */: + case 139 /* UndefinedKeyword */: return false; } return true; } - function isFunctionLikeBodyCompletionKeywordText(text) { - return isFunctionLikeBodyCompletionKeyword(ts.stringToToken(text)); - } function isEqualityOperatorKind(kind) { switch (kind) { case 34 /* EqualsEqualsEqualsToken */: @@ -95968,7 +95978,7 @@ var ts; 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(pathFromSourceToBaseUrl) < getRelativePathNParents(relativePath); + var relativeFirst = getRelativePathNParents(relativePath) < getRelativePathNParents(pathFromSourceToBaseUrl); return relativeFirst ? [relativePath, importRelativeToBaseUrl] : [importRelativeToBaseUrl, relativePath]; }); }); @@ -98485,6 +98495,14 @@ var ts; 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) { diff --git a/lib/typescriptServices.js b/lib/typescriptServices.js index 4c73d04ba23..6858f786ede 100644 --- a/lib/typescriptServices.js +++ b/lib/typescriptServices.js @@ -26564,11 +26564,14 @@ var ts; } var visitedSymbolTables = []; return forEachSymbolTableInScope(enclosingDeclaration, getAccessibleSymbolChainFromSymbolTable); - function getAccessibleSymbolChainFromSymbolTable(symbols) { + /** + * @param {ignoreQualification} boolean Set when a symbol is being looked for through the exports of another symbol (meaning we have a route to qualify it already) + */ + function getAccessibleSymbolChainFromSymbolTable(symbols, ignoreQualification) { if (!ts.pushIfUnique(visitedSymbolTables, symbols)) { return undefined; } - var result = trySymbolTable(symbols); + var result = trySymbolTable(symbols, ignoreQualification); visitedSymbolTables.pop(); return result; } @@ -26578,20 +26581,20 @@ var ts; // If symbol needs qualification, make sure that parent is accessible, if it is then this symbol is accessible too !!getAccessibleSymbolChain(symbolFromSymbolTable.parent, enclosingDeclaration, getQualifiedLeftMeaning(meaning), useOnlyExternalAliasing); } - function isAccessible(symbolFromSymbolTable, resolvedAliasSymbol) { + function isAccessible(symbolFromSymbolTable, resolvedAliasSymbol, ignoreQualification) { return symbol === (resolvedAliasSymbol || symbolFromSymbolTable) && // if the symbolFromSymbolTable is not external module (it could be if it was determined as ambient external module and would be in globals table) // and if symbolFromSymbolTable or alias resolution matches the symbol, // check the symbol can be qualified, it is only then this symbol is accessible !ts.some(symbolFromSymbolTable.declarations, hasExternalModuleSymbol) && - canQualifySymbol(symbolFromSymbolTable, meaning); + (ignoreQualification || canQualifySymbol(symbolFromSymbolTable, meaning)); } function isUMDExportSymbol(symbol) { return symbol && symbol.declarations && symbol.declarations[0] && ts.isNamespaceExportDeclaration(symbol.declarations[0]); } - function trySymbolTable(symbols) { + function trySymbolTable(symbols, ignoreQualification) { // If symbol is directly available by its name in the symbol table - if (isAccessible(symbols.get(symbol.escapedName))) { + if (isAccessible(symbols.get(symbol.escapedName), /*resolvedAliasSymbol*/ undefined, ignoreQualification)) { return [symbol]; } // Check if symbol is any of the alias @@ -26602,13 +26605,13 @@ var ts; // If `!useOnlyExternalAliasing`, we can use any type of alias to get the name && (!useOnlyExternalAliasing || ts.some(symbolFromSymbolTable.declarations, ts.isExternalModuleImportEqualsDeclaration))) { var resolvedImportedSymbol = resolveAlias(symbolFromSymbolTable); - if (isAccessible(symbolFromSymbolTable, resolvedImportedSymbol)) { + if (isAccessible(symbolFromSymbolTable, resolvedImportedSymbol, ignoreQualification)) { return [symbolFromSymbolTable]; } // Look in the exported members, if we can find accessibleSymbolChain, symbol is accessible using this chain // but only if the symbolFromSymbolTable can be qualified var candidateTable = getExportsOfSymbol(resolvedImportedSymbol); - var accessibleSymbolsFromExports = candidateTable && getAccessibleSymbolChainFromSymbolTable(candidateTable); + var accessibleSymbolsFromExports = candidateTable && getAccessibleSymbolChainFromSymbolTable(candidateTable, /*ignoreQualification*/ true); if (accessibleSymbolsFromExports && canQualifySymbol(symbolFromSymbolTable, getQualifiedLeftMeaning(meaning))) { return [symbolFromSymbolTable].concat(accessibleSymbolsFromExports); } @@ -57821,7 +57824,7 @@ var ts; return ts.visitEachChild(node, visitor, context); } function visitLabeledStatement(node) { - if (enclosingFunctionFlags & 2 /* Async */ && enclosingFunctionFlags & 1 /* Generator */) { + if (enclosingFunctionFlags & 2 /* Async */) { var statement = ts.unwrapInnermostStatementOfLabel(node); if (statement.kind === 217 /* ForOfStatement */ && statement.awaitModifier) { return visitForOfStatement(statement, node); @@ -76976,7 +76979,7 @@ var ts; var host = system; host.onConfigFileDiagnostic = reportDiagnostic; host.onUnRecoverableConfigFileDiagnostic = function (diagnostic) { return reportUnrecoverableDiagnostic(ts.sys, reportDiagnostic, diagnostic); }; - var result = parseConfigFile(configFileName, optionsToExtend, host); + var result = getParsedCommandLineOfConfigFile(configFileName, optionsToExtend, host); host.onConfigFileDiagnostic = undefined; host.onUnRecoverableConfigFileDiagnostic = undefined; return result; @@ -76985,7 +76988,7 @@ var ts; /** * Reads the config file, reports errors if any and exits if the config file cannot be found */ - function parseConfigFile(configFileName, optionsToExtend, host) { + function getParsedCommandLineOfConfigFile(configFileName, optionsToExtend, host) { var configFileText; try { configFileText = host.readFile(configFileName); @@ -77007,7 +77010,7 @@ var ts; configParseResult.errors.forEach(function (diagnostic) { return host.onConfigFileDiagnostic(diagnostic); }); return configParseResult; } - ts.parseConfigFile = parseConfigFile; + ts.getParsedCommandLineOfConfigFile = getParsedCommandLineOfConfigFile; /** * Helper that emit files, report diagnostics and lists emitted and/or source files depending on compiler options */ @@ -77464,7 +77467,7 @@ var ts; watchConfigFileWildCardDirectories(); } function parseConfigFile() { - var configParseResult = ts.parseConfigFile(configFileName, optionsToExtendForConfigFile, parseConfigFileHost); + var configParseResult = ts.getParsedCommandLineOfConfigFile(configFileName, optionsToExtendForConfigFile, parseConfigFileHost); rootFileNames = configParseResult.fileNames; compilerOptions = configParseResult.options; configFileSpecs = configParseResult.configFileSpecs; @@ -80820,12 +80823,16 @@ var ts; ts.typeKeywords = [ 119 /* AnyKeyword */, 122 /* BooleanKeyword */, + 127 /* KeyOfKeyword */, 130 /* NeverKeyword */, + 95 /* NullKeyword */, 133 /* NumberKeyword */, 134 /* ObjectKeyword */, 136 /* StringKeyword */, 137 /* SymbolKeyword */, 105 /* VoidKeyword */, + 139 /* UndefinedKeyword */, + 140 /* UniqueKeyword */, ]; function isTypeKeyword(kind) { return ts.contains(ts.typeKeywords, kind); @@ -82513,7 +82520,8 @@ var ts; KeywordCompletionFilters[KeywordCompletionFilters["None"] = 0] = "None"; KeywordCompletionFilters[KeywordCompletionFilters["ClassElementKeywords"] = 1] = "ClassElementKeywords"; KeywordCompletionFilters[KeywordCompletionFilters["ConstructorParameterKeywords"] = 2] = "ConstructorParameterKeywords"; - KeywordCompletionFilters[KeywordCompletionFilters["FunctionLikeBodyKeywords"] = 3] = "FunctionLikeBodyKeywords"; // Keywords at function like body + KeywordCompletionFilters[KeywordCompletionFilters["FunctionLikeBodyKeywords"] = 3] = "FunctionLikeBodyKeywords"; + KeywordCompletionFilters[KeywordCompletionFilters["TypeKeywords"] = 4] = "TypeKeywords"; })(KeywordCompletionFilters || (KeywordCompletionFilters = {})); function getCompletionsAtPosition(host, typeChecker, log, compilerOptions, sourceFile, position, allSourceFiles, options) { if (ts.isInReferenceComment(sourceFile, position)) { @@ -82554,7 +82562,7 @@ var ts; return { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, entries: entries }; } function completionInfoFromData(sourceFile, typeChecker, compilerOptions, log, completionData, includeInsertTextCompletions) { - var symbols = completionData.symbols, completionKind = completionData.completionKind, isNewIdentifierLocation = completionData.isNewIdentifierLocation, location = completionData.location, propertyAccessToConvert = completionData.propertyAccessToConvert, keywordFilters = completionData.keywordFilters, symbolToOriginInfoMap = completionData.symbolToOriginInfoMap, recommendedCompletion = completionData.recommendedCompletion; + var symbols = completionData.symbols, completionKind = completionData.completionKind, isNewIdentifierLocation = completionData.isNewIdentifierLocation, location = completionData.location, propertyAccessToConvert = completionData.propertyAccessToConvert, keywordFilters = completionData.keywordFilters, symbolToOriginInfoMap = completionData.symbolToOriginInfoMap, recommendedCompletion = completionData.recommendedCompletion, isJsxInitializer = completionData.isJsxInitializer; if (sourceFile.languageVariant === 1 /* JSX */ && location && location.parent && ts.isJsxClosingElement(location.parent)) { // In the TypeScript JSX element, if such element is not defined. When users query for completion at closing tag, // instead of simply giving unknown value, the completion will return the tag-name of an associated opening-element. @@ -82572,14 +82580,14 @@ var ts; } var entries = []; if (ts.isSourceFileJavaScript(sourceFile)) { - var uniqueNames = getCompletionEntriesFromSymbols(symbols, entries, location, sourceFile, typeChecker, compilerOptions.target, log, completionKind, includeInsertTextCompletions, propertyAccessToConvert, recommendedCompletion, symbolToOriginInfoMap); + 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, recommendedCompletion, symbolToOriginInfoMap); + 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 @@ -82618,24 +82626,31 @@ var ts; } }); } - function createCompletionEntry(symbol, location, sourceFile, typeChecker, target, kind, origin, recommendedCompletion, propertyAccessToConvert, includeInsertTextCompletions) { + 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; - if (needsConvertPropertyAccess && !includeInsertTextCompletions) { - return undefined; - } var insertText; var replacementSpan; - if (kind === 1 /* Global */ && origin && origin.type === "this-type") { - insertText = needsConvertPropertyAccess ? "this[\"" + name + "\"]" : "this." + name; + if (includeInsertTextCompletions) { + if (origin && origin.type === "this-type") { + insertText = needsConvertPropertyAccess ? "this[\"" + name + "\"]" : "this." + name; + } + else if (needsConvertPropertyAccess) { + // TODO: GH#20619 Use configured quote style + insertText = "[\"" + name + "\"]"; + replacementSpan = ts.createTextSpanFromBounds(ts.findChildOfKind(propertyAccessToConvert, 23 /* DotToken */, sourceFile).getStart(sourceFile), propertyAccessToConvert.name.end); + } + if (isJsxInitializer) { + if (insertText === undefined) + insertText = name; + insertText = "{" + insertText + "}"; + } } - else if (needsConvertPropertyAccess) { - // TODO: GH#20619 Use configured quote style - insertText = "[\"" + name + "\"]"; - replacementSpan = ts.createTextSpanFromBounds(ts.findChildOfKind(propertyAccessToConvert, 23 /* DotToken */, sourceFile).getStart(sourceFile), propertyAccessToConvert.name.end); + 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 @@ -82666,7 +82681,7 @@ var ts; 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, recommendedCompletion, symbolToOriginInfoMap) { + 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. @@ -82676,7 +82691,7 @@ var ts; 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, includeInsertTextCompletions); + var entry = createCompletionEntry(symbol, location, sourceFile, typeChecker, target, kind, origin, recommendedCompletion, propertyAccessToConvert, isJsxInitializer, includeInsertTextCompletions); if (!entry) { continue; } @@ -82894,7 +82909,7 @@ var ts; 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; + 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 @@ -82902,7 +82917,7 @@ var ts; 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 } : undefined; + 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) { @@ -82940,7 +82955,7 @@ var ts; } case "none": { // Didn't find a symbol with this name. See if we can find a keyword instead. - if (ts.some(getKeywordCompletions(0 /* None */), function (c) { return c.name === name; })) { + if (allKeywordsCompletions().some(function (c) { return c.name === name; })) { return { name: name, kind: "keyword" /* keyword */, @@ -83010,6 +83025,7 @@ var ts; var CompletionKind; (function (CompletionKind) { CompletionKind[CompletionKind["ObjectPropertyDeclaration"] = 0] = "ObjectPropertyDeclaration"; + /** Note that sometimes we access completions from global scope, but use "None" instead of this. See isGlobalCompletionScope. */ CompletionKind[CompletionKind["Global"] = 1] = "Global"; CompletionKind[CompletionKind["PropertyAccess"] = 2] = "PropertyAccess"; CompletionKind[CompletionKind["MemberLike"] = 3] = "MemberLike"; @@ -83162,6 +83178,7 @@ var ts; 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 @@ -83215,6 +83232,9 @@ var ts; location = contextToken; } break; + case 257 /* JsxAttribute */: + isJsxInitializer = previousToken.kind === 58 /* EqualsToken */; + break; } } } @@ -83255,7 +83275,7 @@ var ts; } log("getCompletionData: Semantic work: " + (ts.timestamp() - semanticStart)); var recommendedCompletion = previousToken && getRecommendedCompletion(previousToken, typeChecker); - return { kind: 0 /* Data */, symbols: symbols, completionKind: completionKind, propertyAccessToConvert: propertyAccessToConvert, isNewIdentifierLocation: isNewIdentifierLocation, location: location, keywordFilters: keywordFilters, symbolToOriginInfoMap: symbolToOriginInfoMap, recommendedCompletion: recommendedCompletion, previousToken: previousToken }; + return { kind: 0 /* Data */, symbols: symbols, completionKind: completionKind, propertyAccessToConvert: propertyAccessToConvert, isNewIdentifierLocation: isNewIdentifierLocation, location: location, keywordFilters: keywordFilters, symbolToOriginInfoMap: symbolToOriginInfoMap, recommendedCompletion: recommendedCompletion, previousToken: previousToken, isJsxInitializer: isJsxInitializer }; function isTagWithTypeExpression(tag) { switch (tag.kind) { case 284 /* JSDocParameterTag */: @@ -83433,23 +83453,21 @@ var ts; } } function filterGlobalCompletion(symbols) { + var isTypeCompletion = insideJsDocTagTypeExpression || !isContextTokenValueLocation(contextToken) && (ts.isPartOfTypeNode(location) || isContextTokenTypeLocation(contextToken)); + if (isTypeCompletion) + 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; } - // This is an alias, follow what it aliases - if (symbol && symbol.flags & 2097152 /* Alias */) { - symbol = typeChecker.getAliasedSymbol(symbol); - } + 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 (insideJsDocTagTypeExpression || - (!isContextTokenValueLocation(contextToken) && - (ts.isPartOfTypeNode(location) || isContextTokenTypeLocation(contextToken)))) { + if (isTypeCompletion) { // Its a type, but you can reach it by namespace.type as well return symbolCanBeReferencedAtTypeLocation(symbol); } @@ -83479,6 +83497,7 @@ var ts; return parentKind === 203 /* AsExpression */; } } + return false; } function symbolCanBeReferencedAtTypeLocation(symbol) { symbol = symbol.exportSymbol || symbol; @@ -84252,13 +84271,13 @@ var ts; if (ts.isIdentifierText(name, target)) return validIdentiferResult; switch (kind) { - case 5 /* None */: case 3 /* MemberLike */: return undefined; case 0 /* ObjectPropertyDeclaration */: // TODO: GH#18169 return { name: JSON.stringify(name), needsConvertPropertyAccess: false }; case 2 /* PropertyAccess */: + case 5 /* None */: case 1 /* Global */: // 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 }; @@ -84270,44 +84289,37 @@ var ts; } // A cache of completion entries for keywords, these do not change between sessions var _keywordCompletions = []; - function getKeywordCompletions(keywordFilter) { - var completions = _keywordCompletions[keywordFilter]; - if (completions) { - return completions; + var allKeywordsCompletions = ts.memoize(function () { + var res = []; + for (var i = 72 /* FirstKeyword */; i <= 143 /* LastKeyword */; i++) { + res.push({ + name: ts.tokenToString(i), + kind: "keyword" /* keyword */, + kindModifiers: "" /* none */, + sortText: "0" + }); } - return _keywordCompletions[keywordFilter] = generateKeywordCompletions(keywordFilter); - function generateKeywordCompletions(keywordFilter) { + 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 */: - return getAllKeywordCompletions(); + // "undefined" is a global variable, so don't need a keyword completion for it. + return kind !== 139 /* UndefinedKeyword */; case 1 /* ClassElementKeywords */: - return getFilteredKeywordCompletions(isClassMemberCompletionKeywordText); + return isClassMemberCompletionKeyword(kind); case 2 /* ConstructorParameterKeywords */: - return getFilteredKeywordCompletions(isConstructorParameterCompletionKeywordText); + return isConstructorParameterCompletionKeyword(kind); case 3 /* FunctionLikeBodyKeywords */: - return getFilteredKeywordCompletions(isFunctionLikeBodyCompletionKeywordText); + return isFunctionLikeBodyCompletionKeyword(kind); + case 4 /* TypeKeywords */: + return ts.isTypeKeyword(kind); default: - ts.Debug.assertNever(keywordFilter); + return ts.Debug.assertNever(keywordFilter); } - } - function getAllKeywordCompletions() { - var allKeywordsCompletions = []; - for (var i = 72 /* FirstKeyword */; i <= 143 /* LastKeyword */; i++) { - // "undefined" is a global variable, so don't need a keyword completion for it. - if (i === 139 /* UndefinedKeyword */) - continue; - allKeywordsCompletions.push({ - name: ts.tokenToString(i), - kind: "keyword" /* keyword */, - kindModifiers: "" /* none */, - sortText: "0" - }); - } - return allKeywordsCompletions; - } - function getFilteredKeywordCompletions(filterFn) { - return ts.filter(getKeywordCompletions(0 /* None */), function (entry) { return filterFn(entry.name); }); - } + })); } function isClassMemberCompletionKeyword(kind) { switch (kind) { @@ -84350,13 +84362,11 @@ var ts; case 117 /* AbstractKeyword */: case 125 /* GetKeyword */: case 135 /* SetKeyword */: + case 139 /* UndefinedKeyword */: return false; } return true; } - function isFunctionLikeBodyCompletionKeywordText(text) { - return isFunctionLikeBodyCompletionKeyword(ts.stringToToken(text)); - } function isEqualityOperatorKind(kind) { switch (kind) { case 34 /* EqualsEqualsEqualsToken */: @@ -95968,7 +95978,7 @@ var ts; 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(pathFromSourceToBaseUrl) < getRelativePathNParents(relativePath); + var relativeFirst = getRelativePathNParents(relativePath) < getRelativePathNParents(pathFromSourceToBaseUrl); return relativeFirst ? [relativePath, importRelativeToBaseUrl] : [importRelativeToBaseUrl, relativePath]; }); }); @@ -98485,6 +98495,14 @@ var ts; 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) {