diff --git a/.gitignore b/.gitignore index 40c473d13dd..19d96d0b046 100644 --- a/.gitignore +++ b/.gitignore @@ -67,3 +67,4 @@ tests/cases/user/*/**/*.d.ts !tests/cases/user/zone.js/ !tests/cases/user/bignumber.js/ !tests/cases/user/discord.js/ +tests/baselines/reference/dt \ No newline at end of file diff --git a/lib/typescript.d.ts b/lib/typescript.d.ts index b6598e9f617..815cc7bf24a 100644 --- a/lib/typescript.d.ts +++ b/lib/typescript.d.ts @@ -4487,9 +4487,9 @@ declare namespace ts { * @param compilationSettings Some compilation settings like target affects the * shape of a the resulting SourceFile. This allows the DocumentRegistry to store * multiple copies of the same file for different compilation settings. - * @parm scriptSnapshot Text of the file. Only used if the file was not found + * @param scriptSnapshot Text of the file. Only used if the file was not found * in the registry and a new one was created. - * @parm version Current version of the file. Only used if the file was not found + * @param version Current version of the file. Only used if the file was not found * in the registry and a new one was created. */ acquireDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile; diff --git a/lib/typescriptServices.d.ts b/lib/typescriptServices.d.ts index 4bce953f667..cbf7ad062d2 100644 --- a/lib/typescriptServices.d.ts +++ b/lib/typescriptServices.d.ts @@ -4487,9 +4487,9 @@ declare namespace ts { * @param compilationSettings Some compilation settings like target affects the * shape of a the resulting SourceFile. This allows the DocumentRegistry to store * multiple copies of the same file for different compilation settings. - * @parm scriptSnapshot Text of the file. Only used if the file was not found + * @param scriptSnapshot Text of the file. Only used if the file was not found * in the registry and a new one was created. - * @parm version Current version of the file. Only used if the file was not found + * @param version Current version of the file. Only used if the file was not found * in the registry and a new one was created. */ acquireDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile; diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a282e9d3a68..bb1e26ede8b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -251,6 +251,7 @@ namespace ts { getSuggestionForNonexistentProperty: (node, type) => getSuggestionForNonexistentProperty(node, type), getSuggestionForNonexistentSymbol: (location, name, meaning) => getSuggestionForNonexistentSymbol(location, escapeLeadingUnderscores(name), meaning), getBaseConstraintOfType, + getDefaultFromTypeParameter: type => type && type.flags & TypeFlags.TypeParameter ? getDefaultFromTypeParameter(type as TypeParameter) : undefined, resolveName(name, location, meaning) { return resolveName(location, escapeLeadingUnderscores(name), meaning, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false); }, @@ -4054,15 +4055,15 @@ namespace ts { } } - function collectLinkedAliases(node: Identifier): Node[] { + function collectLinkedAliases(node: Identifier, setVisibility?: boolean): Node[] | undefined { let exportSymbol: Symbol; if (node.parent && node.parent.kind === SyntaxKind.ExportAssignment) { - exportSymbol = resolveName(node.parent, node.escapedText, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias, Diagnostics.Cannot_find_name_0, node, /*isUse*/ false); + exportSymbol = resolveName(node, node.escapedText, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias, /*nameNotFoundMessage*/ undefined, node, /*isUse*/ false); } else if (node.parent.kind === SyntaxKind.ExportSpecifier) { exportSymbol = getTargetOfExportSpecifier(node.parent, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias); } - const result: Node[] = []; + let result: Node[]; if (exportSymbol) { buildVisibleNodeList(exportSymbol.declarations); } @@ -4070,9 +4071,14 @@ namespace ts { function buildVisibleNodeList(declarations: Declaration[]) { forEach(declarations, declaration => { - getNodeLinks(declaration).isVisible = true; const resultNode = getAnyImportSyntax(declaration) || declaration; - pushIfUnique(result, resultNode); + if (setVisibility) { + getNodeLinks(declaration).isVisible = true; + } + else { + result = result || []; + pushIfUnique(result, resultNode); + } if (isInternalModuleImportEqualsDeclaration(declaration)) { // Add the referenced top container visible @@ -4231,7 +4237,7 @@ namespace ts { /** Return the inferred type for a binding element */ function getTypeForBindingElement(declaration: BindingElement): Type { const pattern = declaration.parent; - const parentType = getTypeForBindingElementParent(pattern.parent); + let parentType = getTypeForBindingElementParent(pattern.parent); // If parent has the unknown (error) type, then so does this binding element if (parentType === unknownType) { return unknownType; @@ -4273,6 +4279,10 @@ namespace ts { // or otherwise the type of the string index signature. const text = getTextOfPropertyName(name); + // Relax null check on ambient destructuring parameters, since the parameters have no implementation and are just documentation + if (strictNullChecks && declaration.flags & NodeFlags.Ambient && isParameterDeclaration(declaration)) { + parentType = getNonNullableType(parentType); + } const declaredType = getTypeOfPropertyOfType(parentType, text); type = declaredType && getFlowTypeOfReference(declaration, declaredType) || isNumericLiteralName(text) && getIndexTypeOfType(parentType, IndexKind.Number) || @@ -15746,61 +15756,95 @@ namespace ts { * except for candidates: * * With no name * * Whose meaning doesn't match the `meaning` parameter. - * * Whose length differs from the target name by more than 0.3 of the length of the name. + * * Whose length differs from the target name by more than 0.34 of the length of the name. * * Whose levenshtein distance is more than 0.4 of the length of the name * (0.4 allows 1 substitution/transposition for every 5 characters, * and 1 insertion/deletion at 3 characters) - * Names longer than 30 characters don't get suggestions because Levenshtein distance is an n**2 algorithm. */ function getSpellingSuggestionForName(name: string, symbols: Symbol[], meaning: SymbolFlags): Symbol | undefined { - const worstDistance = name.length * 0.4; - const maximumLengthDifference = Math.min(3, name.length * 0.34); - let bestDistance = Number.MAX_VALUE; - let bestCandidate = undefined; + const maximumLengthDifference = Math.min(2, Math.floor(name.length * 0.34)); + let bestDistance = Math.floor(name.length * 0.4) + 1; // If the best result isn't better than this, don't bother. + let bestCandidate: Symbol | undefined; let justCheckExactMatches = false; - if (name.length > 30) { - return undefined; - } - name = name.toLowerCase(); + const nameLowerCase = name.toLowerCase(); for (const candidate of symbols) { - let candidateName = symbolName(candidate); - if (candidate.flags & meaning && - candidateName && - Math.abs(candidateName.length - name.length) < maximumLengthDifference) { - candidateName = candidateName.toLowerCase(); - if (candidateName === name) { - return candidate; - } - if (justCheckExactMatches) { - continue; - } - if (candidateName.length < 3 || - name.length < 3 || - candidateName === "eval" || - candidateName === "intl" || - candidateName === "undefined" || - candidateName === "map" || - candidateName === "nan" || - candidateName === "set") { - continue; - } - const distance = levenshtein(name, candidateName); - if (distance > worstDistance) { - continue; - } - if (distance < 3) { - justCheckExactMatches = true; - bestCandidate = candidate; - } - else if (distance < bestDistance) { - bestDistance = distance; - bestCandidate = candidate; - } + const candidateName = symbolName(candidate); + if (!(candidate.flags & meaning && Math.abs(candidateName.length - nameLowerCase.length) <= maximumLengthDifference)) { + continue; + } + const candidateNameLowerCase = candidateName.toLowerCase(); + if (candidateNameLowerCase === nameLowerCase) { + return candidate; + } + if (justCheckExactMatches) { + continue; + } + if (candidateName.length < 3) { + // Don't bother, user would have noticed a 2-character name having an extra character + continue; + } + // Only care about a result better than the best so far. + const distance = levenshteinWithMax(nameLowerCase, candidateNameLowerCase, bestDistance - 1); + if (distance === undefined) { + continue; + } + if (distance < 3) { + justCheckExactMatches = true; + bestCandidate = candidate; + } + else { + Debug.assert(distance < bestDistance); // Else `levenshteinWithMax` should return undefined + bestDistance = distance; + bestCandidate = candidate; } } return bestCandidate; } + function levenshteinWithMax(s1: string, s2: string, max: number): number | undefined { + let previous = new Array(s2.length + 1); + let current = new Array(s2.length + 1); + /** Represents any value > max. We don't care about the particular value. */ + const big = max + 1; + + for (let i = 0; i <= s2.length; i++) { + previous[i] = i; + } + + for (let i = 1; i <= s1.length; i++) { + const c1 = s1.charCodeAt(i - 1); + const minJ = i > max ? i - max : 1; + const maxJ = s2.length > max + i ? max + i : s2.length; + current[0] = i; + /** Smallest value of the matrix in the ith column. */ + let colMin = i; + for (let j = 1; j < minJ; j++) { + current[j] = big; + } + for (let j = minJ; j <= maxJ; j++) { + const dist = c1 === s2.charCodeAt(j - 1) + ? previous[j - 1] + : Math.min(/*delete*/ previous[j] + 1, /*insert*/ current[j - 1] + 1, /*substitute*/ previous[j - 1] + 2); + current[j] = dist; + colMin = Math.min(colMin, dist); + } + for (let j = maxJ + 1; j <= s2.length; j++) { + current[j] = big; + } + if (colMin > max) { + // Give up -- everything in this column is > max and it can't get better in future columns. + return undefined; + } + + const temp = previous; + previous = current; + current = temp; + } + + const res = previous[s2.length]; + return res > max ? undefined : res; + } + function markPropertyAsReferenced(prop: Symbol, nodeForCheckWriteOnly: Node | undefined, isThisAccess: boolean) { if (prop && noUnusedIdentifiers && @@ -23335,6 +23379,9 @@ namespace ts { function checkExportSpecifier(node: ExportSpecifier) { checkAliasSymbol(node); + if (compilerOptions.declaration) { + collectLinkedAliases(node.propertyName || node.name, /*setVisibility*/ true); + } if (!(node.parent.parent).moduleSpecifier) { const exportedName = node.propertyName || node.name; // find immediate value referenced by exported name (SymbolFlags.Alias is set so we don't chase down aliases) @@ -23372,6 +23419,10 @@ namespace ts { } if (node.expression.kind === SyntaxKind.Identifier) { markExportAsReferenced(node); + + if (compilerOptions.declaration) { + collectLinkedAliases(node.expression as Identifier, /*setVisibility*/ true); + } } else { checkExpressionCached(node.expression); @@ -26243,14 +26294,17 @@ namespace ts { } function checkGrammarConstructorTypeParameters(node: ConstructorDeclaration) { - if (node.typeParameters) { - return grammarErrorAtPos(node, node.typeParameters.pos, node.typeParameters.end - node.typeParameters.pos, Diagnostics.Type_parameters_cannot_appear_on_a_constructor_declaration); + const typeParameters = getEffectiveTypeParameterDeclarations(node); + if (typeParameters) { + const { pos, end } = isNodeArray(typeParameters) ? typeParameters : first(typeParameters); + return grammarErrorAtPos(node, pos, end - pos, Diagnostics.Type_parameters_cannot_appear_on_a_constructor_declaration); } } function checkGrammarConstructorTypeAnnotation(node: ConstructorDeclaration) { - if (node.type) { - return grammarErrorOnNode(node.type, Diagnostics.Type_annotation_cannot_appear_on_a_constructor_declaration); + const type = getEffectiveReturnTypeNode(node); + if (type) { + return grammarErrorOnNode(type, Diagnostics.Type_annotation_cannot_appear_on_a_constructor_declaration); } } diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index ebd2985dd45..dc76e0ddf50 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -1249,10 +1249,18 @@ namespace ts { writeLine(); } + function bindingNameContainsVisibleBindingElement(node: BindingName): boolean { + return !!node && isBindingPattern(node) && some(node.elements, elem => !isOmittedExpression(elem) && isVariableDeclarationVisible(elem)); + } + + function isVariableDeclarationVisible(node: VariableDeclaration | BindingElement) { + return resolver.isDeclarationVisible(node) || bindingNameContainsVisibleBindingElement(node.name); + } + function emitVariableDeclaration(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration) { // If we are emitting property it isn't moduleElement and hence we already know it needs to be emitted // so there is no check needed to see if declaration is visible - if (node.kind !== SyntaxKind.VariableDeclaration || resolver.isDeclarationVisible(node)) { + if (node.kind !== SyntaxKind.VariableDeclaration || isVariableDeclarationVisible(node)) { if (isBindingPattern(node.name)) { emitBindingPattern(node.name); } @@ -1324,14 +1332,14 @@ namespace ts { } function emitBindingPattern(bindingPattern: BindingPattern) { - // Only select non-omitted expression from the bindingPattern's elements. + // Only select visible, non-omitted expression from the bindingPattern's elements. // We have to do this to avoid emitting trailing commas. // For example: // original: var [, c,,] = [ 2,3,4] // emitted: declare var c: number; // instead of declare var c:number, ; const elements: Node[] = []; for (const element of bindingPattern.elements) { - if (element.kind !== SyntaxKind.OmittedExpression) { + if (element.kind !== SyntaxKind.OmittedExpression && isVariableDeclarationVisible(element)) { elements.push(element); } } @@ -1371,7 +1379,7 @@ namespace ts { } function isVariableStatementVisible(node: VariableStatement) { - return forEach(node.declarationList.declarations, varDeclaration => resolver.isDeclarationVisible(varDeclaration)); + return forEach(node.declarationList.declarations, varDeclaration => isVariableDeclarationVisible(varDeclaration)); } function writeVariableStatement(node: VariableStatement) { @@ -1390,7 +1398,7 @@ namespace ts { else { write("var "); } - emitCommaList(node.declarationList.declarations, emitVariableDeclaration, resolver.isDeclarationVisible); + emitCommaList(node.declarationList.declarations, emitVariableDeclaration, isVariableDeclarationVisible); write(";"); writeLine(); } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 09319589da7..cd65bf945f4 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3766,7 +3766,7 @@ "category": "Error", "code": 90010 }, - "Import '{0}' from \"{1}\".": { + "Import '{0}' from module \"{1}\".": { "category": "Message", "code": 90013 }, @@ -3886,13 +3886,5 @@ "Install '{0}'": { "category": "Message", "code": 95014 - }, - "Import '{0}' = require(\"{1}\").": { - "category": "Message", - "code": 95015 - }, - "Import * as '{0}' from \"{1}\".": { - "category": "Message", - "code": 95016 } } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index b13aaac792f..cb28be4677a 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -3281,7 +3281,7 @@ namespace ts { // Check for "(xxx yyy", where xxx is a modifier and yyy is an identifier. This // isn't actually allowed, but we want to treat it as a lambda so we can provide // a good error message. - if (isModifierKind(second) && lookAhead(nextTokenIsIdentifier)) { + if (isModifierKind(second) && second !== SyntaxKind.AsyncKeyword && lookAhead(nextTokenIsIdentifier)) { return Tristate.True; } @@ -3298,7 +3298,7 @@ namespace ts { return Tristate.True; case SyntaxKind.QuestionToken: nextToken(); - // If we have "(a?:" or "(a?," or "(a?=" or "(a?)" then it is definitely a lamnda. + // If we have "(a?:" or "(a?," or "(a?=" or "(a?)" then it is definitely a lambda. if (token() === SyntaxKind.ColonToken || token() === SyntaxKind.CommaToken || token() === SyntaxKind.EqualsToken || token() === SyntaxKind.CloseParenToken) { return Tristate.True; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 9979139a913..68029b2f5e3 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2771,7 +2771,8 @@ namespace ts { getApparentType(type: Type): Type; getSuggestionForNonexistentProperty(node: Identifier, containingType: Type): string | undefined; getSuggestionForNonexistentSymbol(location: Node, name: string, meaning: SymbolFlags): string | undefined; - /* @internal */ getBaseConstraintOfType(type: Type): Type | undefined; + getBaseConstraintOfType(type: Type): Type | undefined; + getDefaultFromTypeParameter(type: Type): Type | undefined; /* @internal */ getAnyType(): Type; /* @internal */ getStringType(): Type; @@ -3575,15 +3576,17 @@ namespace ts { export interface TypeVariable extends Type { /* @internal */ - resolvedBaseConstraint: Type; + resolvedBaseConstraint?: Type; /* @internal */ - resolvedIndexType: IndexType; + resolvedIndexType?: IndexType; } // Type parameters (TypeFlags.TypeParameter) export interface TypeParameter extends TypeVariable { /** Retrieve using getConstraintFromTypeParameter */ - constraint: Type; // Constraint + /* @internal */ + constraint?: Type; // Constraint + /* @internal */ default?: Type; /* @internal */ target?: TypeParameter; // Instantiation target diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index ac152e4023a..80ca3bbdfad 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1463,7 +1463,7 @@ namespace ts { /// Given a BinaryExpression, returns SpecialPropertyAssignmentKind for the various kinds of property /// assignments we treat as special in the binder - export function getSpecialPropertyAssignmentKind(expr: ts.BinaryExpression): SpecialPropertyAssignmentKind { + export function getSpecialPropertyAssignmentKind(expr: BinaryExpression): SpecialPropertyAssignmentKind { if (!isInJavaScriptFile(expr)) { return SpecialPropertyAssignmentKind.None; } @@ -1615,15 +1615,15 @@ namespace ts { function getJSDocCommentsAndTagsWorker(node: Node): void { const parent = node.parent; + if (parent && (parent.kind === SyntaxKind.PropertyAssignment || getNestedModuleDeclaration(parent))) { + getJSDocCommentsAndTagsWorker(parent); + } // Try to recognize this pattern when node is initializer of variable declaration and JSDoc comments are on containing variable statement. // /** // * @param {number} name // * @returns {number} // */ // var x = function(name) { return name.length; } - if (parent && (parent.kind === SyntaxKind.PropertyAssignment || parent.kind === SyntaxKind.ExpressionStatement || getNestedModuleDeclaration(parent))) { - getJSDocCommentsAndTagsWorker(parent); - } if (parent && parent.parent && (getSingleVariableOfVariableStatement(parent.parent, node) || getSourceOfAssignment(parent.parent))) { getJSDocCommentsAndTagsWorker(parent.parent); @@ -1631,6 +1631,10 @@ namespace ts { if (parent && parent.parent && parent.parent.parent && getSingleInitializerOfVariableStatement(parent.parent.parent, node)) { getJSDocCommentsAndTagsWorker(parent.parent.parent); } + if (isBinaryExpression(node) && getSpecialPropertyAssignmentKind(node) !== SpecialPropertyAssignmentKind.None || + node.kind === SyntaxKind.PropertyAccessExpression && node.parent && node.parent.kind === SyntaxKind.ExpressionStatement) { + getJSDocCommentsAndTagsWorker(parent); + } // Pull parameter comments from declaring function as well if (node.kind === SyntaxKind.Parameter) { @@ -3521,29 +3525,6 @@ namespace ts { return 0; } - export function levenshtein(s1: string, s2: string): number { - let previous: number[] = new Array(s2.length + 1); - let current: number[] = new Array(s2.length + 1); - for (let i = 0; i < s2.length + 1; i++) { - previous[i] = i; - current[i] = -1; - } - for (let i = 1; i < s1.length + 1; i++) { - current[0] = i; - for (let j = 1; j < s2.length + 1; j++) { - current[j] = Math.min( - previous[j] + 1, - current[j - 1] + 1, - previous[j - 1] + (s1[i - 1] === s2[j - 1] ? 0 : 2)); - } - // shift current back to previous, and then reuse previous' array - const tmp = previous; - previous = current; - current = tmp; - } - return previous[previous.length - 1]; - } - export function skipAlias(symbol: Symbol, checker: TypeChecker) { return symbol.flags & SymbolFlags.Alias ? checker.getAliasedSymbol(symbol) : symbol; } diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 2ca7d4e21dd..ff2db0f9ee6 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -232,7 +232,7 @@ namespace ts.projectSystem { return this.executeCommand(request); } - public event(body: T, eventName: string) { + public event(body: T, eventName: string) { this.events.push(server.toEvent(eventName, body)); super.event(body, eventName); } @@ -1561,7 +1561,11 @@ namespace ts.projectSystem { path: "/a/b/foo.js", content: "" }; - const host = createServerHost([file1, file2, customTypesMap]); + const file3 = { + path: "/a/b/Bacon.js", + content: "let y = 5" + }; + const host = createServerHost([file1, file2, file3, customTypesMap]); const projectService = createProjectService(host); try { projectService.openExternalProject({ projectFileName: "project", options: {}, rootFiles: toExternalFiles([file1.path, file2.path]), typeAcquisition: { enable: true } }); diff --git a/src/harness/unittests/typingsInstaller.ts b/src/harness/unittests/typingsInstaller.ts index 393d55a5ea4..d0038902ae7 100644 --- a/src/harness/unittests/typingsInstaller.ts +++ b/src/harness/unittests/typingsInstaller.ts @@ -1018,7 +1018,7 @@ namespace ts.projectSystem { } }; session.executeCommand(changeRequest); - host.checkTimeoutQueueLengthAndRun(0); // This enqueues the updategraph and refresh inferred projects + host.checkTimeoutQueueLengthAndRun(2); // This enqueues the updategraph and refresh inferred projects const version2 = proj.getCachedUnresolvedImportsPerFile_TestOnly().getVersion(); assert.equal(version1, version2, "set of unresolved imports should not change"); }); diff --git a/src/lib/dom.generated.d.ts b/src/lib/dom.generated.d.ts index c5e5e713ad2..001c63b44a1 100644 --- a/src/lib/dom.generated.d.ts +++ b/src/lib/dom.generated.d.ts @@ -15029,6 +15029,8 @@ interface SVGElementTagNameMap { "view": SVGViewElement; } +interface ElementTagNameMap extends HTMLElementTagNameMap, SVGElementTagNameMap { } + declare var Audio: { new(src?: string): HTMLAudioElement; }; declare var Image: { new(width?: number, height?: number): HTMLImageElement; }; declare var Option: { new(text?: string, value?: string, defaultSelected?: boolean, selected?: boolean): HTMLOptionElement; }; diff --git a/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl index 03965fb2b07..83479d879c5 100644 --- a/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/chs/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -144,30 +144,45 @@ + + + + + + + + + + + + + + + @@ -291,6 +306,15 @@ + + + + + + + + + @@ -507,12 +531,18 @@ + + + + + + @@ -765,6 +795,9 @@ + + + @@ -2583,6 +2616,9 @@ + + + @@ -2796,6 +2832,15 @@ + + + + + + + + + @@ -2937,6 +2982,9 @@ + + + @@ -2970,6 +3018,9 @@ + + + @@ -3717,32 +3768,11 @@ - + - + - - - - - - - - - - - - - - - - - - - - - - + @@ -4506,12 +4536,18 @@ + + + + + + @@ -5439,6 +5475,15 @@ + + + + + + + + + @@ -5559,6 +5604,15 @@ + + + + + + + + + @@ -5661,18 +5715,27 @@ + + + + + + + + + @@ -5706,18 +5769,27 @@ + + + + + + + + + @@ -6510,6 +6582,9 @@ + + + @@ -6738,6 +6813,9 @@ + + + @@ -8790,18 +8868,27 @@ + + + + + + + + + diff --git a/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl index 425b451c38c..fb4dfda449c 100644 --- a/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/cht/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -144,30 +144,45 @@ + + + + + + + + + + + + + + + @@ -291,6 +306,15 @@ + + + + + + + + + @@ -507,12 +531,18 @@ + + + + + + @@ -765,6 +795,9 @@ + + + @@ -2583,6 +2616,9 @@ + + + @@ -2796,6 +2832,15 @@ + + + + + + + + + @@ -2937,6 +2982,9 @@ + + + @@ -2970,6 +3018,9 @@ + + + @@ -3717,32 +3768,11 @@ - + - + - - - - - - - - - - - - - - - - - - - - - - + @@ -4506,12 +4536,18 @@ + + + + + + @@ -5439,6 +5475,15 @@ + + + + + + + + + @@ -5559,6 +5604,15 @@ + + + + + + + + + @@ -5661,18 +5715,27 @@ + + + + + + + + + @@ -5706,18 +5769,27 @@ + + + + + + + + + @@ -6510,6 +6582,9 @@ + + + @@ -6738,6 +6813,9 @@ + + + @@ -8790,18 +8868,27 @@ + + + + + + + + + diff --git a/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl index 20ef6bead25..de3f3987097 100644 --- a/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/csy/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -150,47 +150,47 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -315,6 +315,12 @@ + + + + + + @@ -528,6 +534,24 @@ + + + + + + + + + + + + + + + + + + @@ -774,6 +798,15 @@ + + + + + + + + + @@ -2586,6 +2619,15 @@ + + + + + + + + + @@ -2796,6 +2838,15 @@ + + + + + + + + + @@ -2934,11 +2985,11 @@ - + - + - + @@ -2970,11 +3021,11 @@ - + - + - + @@ -4131,6 +4182,15 @@ + + + + + + + + + @@ -4500,6 +4560,24 @@ + + + + + + + + + + + + + + + + + + @@ -5424,6 +5502,15 @@ + + + + + + + + + @@ -5544,6 +5631,15 @@ + + + + + + + + + @@ -5643,6 +5739,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -5670,6 +5793,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -6456,6 +6606,15 @@ + + + + + + + + + @@ -6678,11 +6837,11 @@ - + - + - + @@ -8733,6 +8892,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl index dfba55014e0..958d9774e8e 100644 --- a/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/deu/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -144,30 +144,45 @@ + + + + + + + + + + + + + + + @@ -291,6 +306,12 @@ + + + + + + @@ -507,12 +528,18 @@ + + + + + + @@ -762,6 +789,9 @@ + + + @@ -2574,6 +2604,9 @@ + + + @@ -2787,6 +2820,15 @@ + + + + + + + + + @@ -2928,6 +2970,9 @@ + + + @@ -2961,6 +3006,9 @@ + + + @@ -4494,12 +4542,18 @@ + + + + + + @@ -5424,6 +5478,15 @@ + + + + + + + + + @@ -5544,6 +5607,15 @@ + + + + + + + + + @@ -5646,18 +5718,27 @@ + + + + + + + + + @@ -5691,18 +5772,27 @@ + + + + + + + + + @@ -6489,6 +6579,9 @@ + + + @@ -6717,6 +6810,9 @@ + + + @@ -8769,18 +8865,27 @@ + + + + + + + + + diff --git a/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl index d22a3ecd34c..e2a933198cf 100644 --- a/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/esn/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -150,47 +150,47 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -315,6 +315,15 @@ + + + + + + + + + @@ -528,6 +537,24 @@ + + + + + + + + + + + + + + + + + + @@ -774,6 +801,15 @@ + + + + + + + + + @@ -2586,6 +2622,15 @@ + + + + + + + + + @@ -2796,6 +2841,15 @@ + + + + + + + + + @@ -2934,11 +2988,11 @@ - + - + - + @@ -2970,11 +3024,11 @@ - + - + - + @@ -3723,32 +3777,11 @@ - + - + - - - - - - - - - - - - - - - - - - - - - - + @@ -4509,6 +4542,24 @@ + + + + + + + + + + + + + + + + + + @@ -5433,6 +5484,15 @@ + + + + + + + + + @@ -5553,6 +5613,15 @@ + + + + + + + + + @@ -5652,6 +5721,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -5679,6 +5775,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -6465,6 +6588,15 @@ + + + + + + + + + @@ -6687,11 +6819,11 @@ - + - + - + @@ -8742,6 +8874,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl index 67025087ec8..b77e815dfd5 100644 --- a/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/fra/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -150,47 +150,47 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -315,6 +315,12 @@ + + + + + + @@ -528,6 +534,24 @@ + + + + + + + + + + + + + + + + + + @@ -774,6 +798,15 @@ + + + + + + + + + @@ -2586,6 +2619,15 @@ + + + + + + + + + @@ -2796,6 +2838,15 @@ + + + + + + + + + @@ -2934,11 +2985,11 @@ - + - + - + @@ -2970,11 +3021,11 @@ - + - + - + @@ -4509,6 +4560,24 @@ + + + + + + + + + + + + + + + + + + @@ -5433,6 +5502,15 @@ + + + + + + + + + @@ -5553,6 +5631,15 @@ + + + + + + + + + @@ -5652,6 +5739,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -5679,6 +5793,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -6465,6 +6606,15 @@ + + + + + + + + + @@ -6687,11 +6837,11 @@ - + - + - + @@ -8742,6 +8892,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl index 3a589da079d..e204b688ed7 100644 --- a/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -144,30 +144,45 @@ + + + + + + + + + + + + + + + @@ -291,6 +306,15 @@ + + + + + + + + + @@ -507,12 +531,18 @@ + + + + + + @@ -765,6 +795,9 @@ + + + @@ -2583,6 +2616,9 @@ + + + @@ -2796,6 +2832,15 @@ + + + + + + + + + @@ -2937,6 +2982,9 @@ + + + @@ -2970,6 +3018,9 @@ + + + @@ -3717,32 +3768,11 @@ - + - + - - - - - - - - - - - - - - - - - - - - - - + @@ -4506,12 +4536,18 @@ + + + + + + @@ -5439,6 +5475,15 @@ + + + + + + + + + @@ -5559,6 +5604,15 @@ + + + + + + + + + @@ -5661,18 +5715,27 @@ + + + + + + + + + @@ -5706,18 +5769,27 @@ + + + + + + + + + @@ -6510,6 +6582,9 @@ + + + @@ -6738,6 +6813,9 @@ + + + @@ -8790,18 +8868,27 @@ + + + + + + + + + diff --git a/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl index 1034ed53292..861d10e5028 100644 --- a/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/jpn/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -144,30 +144,45 @@ + + + + + + + + + + + + + + + @@ -291,6 +306,15 @@ + + + + + + + + + @@ -507,12 +531,18 @@ + + + + + + @@ -765,6 +795,9 @@ + + + @@ -2583,6 +2616,9 @@ + + + @@ -2796,6 +2832,15 @@ + + + + + + + + + @@ -2937,6 +2982,9 @@ + + + @@ -2970,6 +3018,9 @@ + + + @@ -3717,32 +3768,11 @@ - + - + - - - - - - - - - - - - - - - - - - - - - - + @@ -4506,12 +4536,18 @@ + + + + + + @@ -5439,6 +5475,15 @@ + + + + + + + + + @@ -5559,6 +5604,15 @@ + + + + + + + + + @@ -5661,18 +5715,27 @@ + + + + + + + + + @@ -5706,18 +5769,27 @@ + + + + + + + + + @@ -6510,6 +6582,9 @@ + + + @@ -6738,6 +6813,9 @@ + + + @@ -8790,18 +8868,27 @@ + + + + + + + + + diff --git a/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl index e1edb303ec2..9c099aeb990 100644 --- a/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/kor/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -144,30 +144,45 @@ + + + + + + + + + + + + + + + @@ -291,6 +306,15 @@ + + + + + + + + + @@ -507,12 +531,18 @@ + + + + + + @@ -765,6 +795,9 @@ + + + @@ -2583,6 +2616,9 @@ + + + @@ -2796,6 +2832,15 @@ + + + + + + + + + @@ -2937,6 +2982,9 @@ + + + @@ -2970,6 +3018,9 @@ + + + @@ -3717,32 +3768,11 @@ - + - + - - - - - - - - - - - - - - - - - - - - - - + @@ -4506,12 +4536,18 @@ + + + + + + @@ -5439,6 +5475,15 @@ + + + + + + + + + @@ -5473,7 +5518,7 @@ - + @@ -5559,6 +5604,15 @@ + + + + + + + + + @@ -5661,18 +5715,27 @@ + + + + + + + + + @@ -5706,18 +5769,27 @@ + + + + + + + + + @@ -6510,6 +6582,9 @@ + + + @@ -6738,6 +6813,9 @@ + + + @@ -8017,7 +8095,7 @@ - + @@ -8790,18 +8868,27 @@ + + + + + + + + + diff --git a/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl index 2524f29e99e..be3889c2dd4 100644 --- a/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/plk/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -111,7 +111,7 @@ - + @@ -137,30 +137,45 @@ + + + + + + + + + + + + + + + @@ -186,7 +201,7 @@ - + @@ -284,6 +299,12 @@ + + + + + + @@ -387,7 +408,7 @@ - + @@ -500,12 +521,18 @@ + + + + + + @@ -675,7 +702,7 @@ - + @@ -755,6 +782,9 @@ + + + @@ -1053,7 +1083,7 @@ - + @@ -1305,7 +1335,7 @@ - + @@ -1425,7 +1455,7 @@ - + @@ -1434,7 +1464,7 @@ - + @@ -1698,7 +1728,7 @@ - + @@ -1707,7 +1737,7 @@ - + @@ -1968,7 +1998,7 @@ - + @@ -1977,7 +2007,7 @@ - + @@ -1986,7 +2016,7 @@ - + @@ -1995,7 +2025,7 @@ - + @@ -2004,7 +2034,7 @@ - + @@ -2052,7 +2082,7 @@ - + @@ -2133,7 +2163,7 @@ - + @@ -2567,6 +2597,9 @@ + + + @@ -2637,7 +2670,7 @@ - + @@ -2780,6 +2813,15 @@ + + + + + + + + + @@ -2847,7 +2889,7 @@ - + @@ -2856,7 +2898,7 @@ - + @@ -2877,7 +2919,7 @@ - + @@ -2921,6 +2963,9 @@ + + + @@ -2954,6 +2999,9 @@ + + + @@ -3135,7 +3183,7 @@ - + @@ -3810,7 +3858,7 @@ - + @@ -3828,7 +3876,7 @@ - + @@ -3909,7 +3957,7 @@ - + @@ -4128,7 +4176,7 @@ - + @@ -4443,7 +4491,7 @@ - + @@ -4487,12 +4535,18 @@ + + + + + + @@ -4509,7 +4563,7 @@ - + @@ -4527,7 +4581,7 @@ - + @@ -4677,7 +4731,7 @@ - + @@ -4704,7 +4758,7 @@ - + @@ -4713,7 +4767,7 @@ - + @@ -4812,7 +4866,7 @@ - + @@ -4896,7 +4950,7 @@ - + @@ -5417,6 +5471,15 @@ + + + + + + + + + @@ -5537,6 +5600,15 @@ + + + + + + + + + @@ -5639,18 +5711,27 @@ + + + + + + + + + @@ -5684,18 +5765,27 @@ + + + + + + + + + @@ -6426,7 +6516,7 @@ - + @@ -6482,6 +6572,9 @@ + + + @@ -6710,6 +6803,9 @@ + + + @@ -6882,7 +6978,7 @@ - + @@ -7050,7 +7146,7 @@ - + @@ -7401,7 +7497,7 @@ - + @@ -7410,7 +7506,7 @@ - + @@ -7419,7 +7515,7 @@ - + @@ -8088,7 +8184,7 @@ - + @@ -8292,7 +8388,7 @@ - + @@ -8301,7 +8397,7 @@ - + @@ -8592,7 +8688,7 @@ - + @@ -8619,7 +8715,7 @@ - + @@ -8646,7 +8742,7 @@ - + @@ -8655,7 +8751,7 @@ - + @@ -8762,18 +8858,27 @@ + + + + + + + + + diff --git a/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl index c8ff92b6a88..38902fa6734 100644 --- a/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/ptb/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -134,47 +134,47 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -299,6 +299,15 @@ + + + + + + + + + @@ -512,6 +521,24 @@ + + + + + + + + + + + + + + + + + + @@ -755,6 +782,15 @@ + + + + + + + + + @@ -2561,6 +2597,15 @@ + + + + + + + + + @@ -2771,6 +2816,15 @@ + + + + + + + + + @@ -2909,11 +2963,11 @@ - + - + - + @@ -2945,11 +2999,11 @@ - + - + - + @@ -3695,32 +3749,11 @@ - + - + - - - - - - - - - - - - - - - - - - - - - - + @@ -4481,6 +4514,24 @@ + + + + + + + + + + + + + + + + + + @@ -5402,6 +5453,15 @@ + + + + + + + + + @@ -5522,6 +5582,15 @@ + + + + + + + + + @@ -5621,6 +5690,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -5648,6 +5744,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -6428,6 +6551,15 @@ + + + + + + + + + @@ -6650,11 +6782,11 @@ - + - + - + @@ -8705,6 +8837,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl index ff50a731206..543639d56e9 100644 --- a/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/rus/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -143,30 +143,45 @@ + + + + + + + + + + + + + + + @@ -290,6 +305,12 @@ + + + + + + @@ -506,12 +527,18 @@ + + + + + + @@ -764,6 +791,9 @@ + + + @@ -2582,6 +2612,9 @@ + + + @@ -2795,6 +2828,15 @@ + + + + + + + + + @@ -2936,6 +2978,9 @@ + + + @@ -2969,6 +3014,9 @@ + + + @@ -4505,12 +4553,18 @@ + + + + + + @@ -5438,6 +5492,15 @@ + + + + + + + + + @@ -5558,6 +5621,15 @@ + + + + + + + + + @@ -5660,18 +5732,27 @@ + + + + + + + + + @@ -5705,18 +5786,27 @@ + + + + + + + + + @@ -6509,6 +6599,9 @@ + + + @@ -6737,6 +6830,9 @@ + + + @@ -8789,18 +8885,27 @@ + + + + + + + + + diff --git a/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl index 44970d1fc65..5bf19ff41b3 100644 --- a/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/trk/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -137,30 +137,45 @@ + + + + + + + + + + + + + + + @@ -284,6 +299,12 @@ + + + + + + @@ -500,12 +521,18 @@ + + + + + + @@ -758,6 +785,9 @@ + + + @@ -2576,6 +2606,9 @@ + + + @@ -2789,6 +2822,15 @@ + + + + + + + + + @@ -2930,6 +2972,9 @@ + + + @@ -2963,6 +3008,9 @@ + + + @@ -4499,12 +4547,18 @@ + + + + + + @@ -5432,6 +5486,15 @@ + + + + + + + + + @@ -5552,6 +5615,15 @@ + + + + + + + + + @@ -5654,18 +5726,27 @@ + + + + + + + + + @@ -5699,18 +5780,27 @@ + + + + + + + + + @@ -6503,6 +6593,9 @@ + + + @@ -6731,6 +6824,9 @@ + + + @@ -8783,18 +8879,27 @@ + + + + + + + + + diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index bda540d6b39..a5b09c6a63f 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -527,7 +527,11 @@ namespace ts.server { } // raw is now fixed and ready this.safelist = raw.typesMap; - this.legacySafelist = raw.simpleMap; + for (const key in raw.simpleMap) { + if (raw.simpleMap.hasOwnProperty(key)) { + this.legacySafelist[key] = raw.simpleMap[key].toLowerCase(); + } + } } catch (e) { this.logger.info(`Error loading types map: ${e}`); @@ -536,7 +540,7 @@ namespace ts.server { } } - updateTypingsForProject(response: SetTypings | InvalidateCachedTypings): void { + updateTypingsForProject(response: SetTypings | InvalidateCachedTypings | PackageInstalledResponse): void { const project = this.findProject(response.projectName); if (!project) { return; diff --git a/src/server/project.ts b/src/server/project.ts index 8988e8b1bec..ce750c78e23 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -249,7 +249,7 @@ namespace ts.server { return this.typingsCache.isKnownTypesPackageName(name); } installPackage(options: InstallPackageOptions): Promise { - return this.typingsCache.installPackage({ ...options, projectRootPath: this.toPath(this.currentDirectory) }); + return this.typingsCache.installPackage({ ...options, projectName: this.projectName, projectRootPath: this.toPath(this.currentDirectory) }); } private get typingsCache(): TypingsCache { return this.projectService.typingsCache; diff --git a/src/server/server.ts b/src/server/server.ts index fb0b3b781af..86349fa2be5 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -290,7 +290,7 @@ namespace ts.server { return false; } - installPackage(options: InstallPackageOptionsWithProjectRootPath): Promise { + installPackage(options: InstallPackageOptionsWithProject): Promise { const rq: InstallPackageRequest = { kind: "installPackage", ...options }; this.send(rq); Debug.assert(this.packageInstalledPromise === undefined); @@ -392,7 +392,7 @@ namespace ts.server { case EventTypesRegistry: this.typesRegistryCache = ts.createMapFromTemplate(response.typesRegistry); break; - case EventPackageInstalled: { + case ActionPackageInstalled: { const { success, message } = response; if (success) { this.packageInstalledPromise.resolve({ successMessage: message }); @@ -401,6 +401,11 @@ namespace ts.server { this.packageInstalledPromise.reject(message); } this.packageInstalledPromise = undefined; + + this.projectService.updateTypingsForProject(response); + + // The behavior is the same as for setTypings, so send the same event. + this.event(response, "setTypings"); break; } case EventInitializationFailed: @@ -502,7 +507,7 @@ namespace ts.server { constructor(options: IoSessionOptions) { const { host, eventPort, globalTypingsCacheLocation, typingSafeListLocation, typesMapLocation, npmLocation, canUseEvents } = options; - const event: Event | undefined = (body: {}, eventName: string) => { + const event: Event | undefined = (body: object, eventName: string) => { if (this.constructed) { this.event(body, eventName); } @@ -551,7 +556,7 @@ namespace ts.server { this.constructed = true; } - event(body: T, eventName: string): void { + event(body: T, eventName: string): void { Debug.assert(this.constructed, "Should only call `IOSession.prototype.event` on an initialized IOSession"); if (this.canUseEvents && this.eventPort) { @@ -572,8 +577,8 @@ namespace ts.server { } } - private writeToEventSocket(body: any, eventName: string): void { - this.eventSocket.write(formatMessage(toEvent(body, eventName), this.logger, this.byteLength, this.host.newLine), "utf8"); + private writeToEventSocket(body: object, eventName: string): void { + this.eventSocket.write(formatMessage(toEvent(eventName, body), this.logger, this.byteLength, this.host.newLine), "utf8"); } exit() { diff --git a/src/server/session.ts b/src/server/session.ts index 9e6378ebebf..309a6aef0ca 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -239,14 +239,14 @@ namespace ts.server { } } - export type Event = (body: T, eventName: string) => void; + export type Event = (body: T, eventName: string) => void; export interface EventSender { event: Event; } /** @internal */ - export function toEvent(eventName: string, body: {}): protocol.Event { + export function toEvent(eventName: string, body: object): protocol.Event { return { seq: 0, type: "event", @@ -409,7 +409,7 @@ namespace ts.server { this.host.write(formatMessage(msg, this.logger, this.byteLength, this.host.newLine)); } - public event(body: T, eventName: string): void { + public event(body: T, eventName: string): void { this.send(toEvent(eventName, body)); } diff --git a/src/server/shared.ts b/src/server/shared.ts index 99a38eba389..e8b64ce06ec 100644 --- a/src/server/shared.ts +++ b/src/server/shared.ts @@ -4,8 +4,8 @@ namespace ts.server { // tslint:disable variable-name export const ActionSet: ActionSet = "action::set"; export const ActionInvalidate: ActionInvalidate = "action::invalidate"; + export const ActionPackageInstalled: ActionPackageInstalled = "action::packageInstalled"; export const EventTypesRegistry: EventTypesRegistry = "event::typesRegistry"; - export const EventPackageInstalled: EventPackageInstalled = "event::packageInstalled"; export const EventBeginInstallTypes: EventBeginInstallTypes = "event::beginInstallTypes"; export const EventEndInstallTypes: EventEndInstallTypes = "event::endInstallTypes"; export const EventInitializationFailed: EventInitializationFailed = "event::initializationFailed"; diff --git a/src/server/types.ts b/src/server/types.ts index af5e121278e..32132ed278b 100644 --- a/src/server/types.ts +++ b/src/server/types.ts @@ -53,7 +53,7 @@ declare namespace ts.server { readonly kind: "typesRegistry"; } - export interface InstallPackageRequest { + export interface InstallPackageRequest extends TypingInstallerRequestWithProjectName { readonly kind: "installPackage"; readonly fileName: Path; readonly packageName: string; @@ -62,14 +62,14 @@ declare namespace ts.server { export type ActionSet = "action::set"; export type ActionInvalidate = "action::invalidate"; + export type ActionPackageInstalled = "action::packageInstalled"; export type EventTypesRegistry = "event::typesRegistry"; - export type EventPackageInstalled = "event::packageInstalled"; export type EventBeginInstallTypes = "event::beginInstallTypes"; export type EventEndInstallTypes = "event::endInstallTypes"; export type EventInitializationFailed = "event::initializationFailed"; export interface TypingInstallerResponse { - readonly kind: ActionSet | ActionInvalidate | EventTypesRegistry | EventPackageInstalled | EventBeginInstallTypes | EventEndInstallTypes | EventInitializationFailed; + readonly kind: ActionSet | ActionInvalidate | EventTypesRegistry | ActionPackageInstalled | EventBeginInstallTypes | EventEndInstallTypes | EventInitializationFailed; } /* @internal */ export type TypingInstallerResponseUnion = SetTypings | InvalidateCachedTypings | TypesRegistryResponse | PackageInstalledResponse | InstallTypes | InitializationFailedResponse; @@ -80,9 +80,8 @@ declare namespace ts.server { readonly typesRegistry: MapLike; } - /* @internal */ - export interface PackageInstalledResponse extends TypingInstallerResponse { - readonly kind: EventPackageInstalled; + export interface PackageInstalledResponse extends ProjectResponse { + readonly kind: ActionPackageInstalled; readonly success: boolean; readonly message: string; } diff --git a/src/server/typingsCache.ts b/src/server/typingsCache.ts index cde303bfd39..a1d8f65f6e0 100644 --- a/src/server/typingsCache.ts +++ b/src/server/typingsCache.ts @@ -1,14 +1,15 @@ /// namespace ts.server { - export interface InstallPackageOptionsWithProjectRootPath extends InstallPackageOptions { + export interface InstallPackageOptionsWithProject extends InstallPackageOptions { + projectName: string; projectRootPath: Path; } // tslint:disable-next-line interface-name (for backwards-compatibility) export interface ITypingsInstaller { isKnownTypesPackageName(name: string): boolean; - installPackage(options: InstallPackageOptionsWithProjectRootPath): Promise; + installPackage(options: InstallPackageOptionsWithProject): Promise; enqueueInstallTypingsRequest(p: Project, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray): void; attach(projectService: ProjectService): void; onProjectClosed(p: Project): void; @@ -91,7 +92,7 @@ namespace ts.server { return this.installer.isKnownTypesPackageName(name); } - installPackage(options: InstallPackageOptionsWithProjectRootPath): Promise { + installPackage(options: InstallPackageOptionsWithProject): Promise { return this.installer.installPackage(options); } diff --git a/src/server/typingsInstaller/nodeTypingsInstaller.ts b/src/server/typingsInstaller/nodeTypingsInstaller.ts index da16d5dde82..36f5adab400 100644 --- a/src/server/typingsInstaller/nodeTypingsInstaller.ts +++ b/src/server/typingsInstaller/nodeTypingsInstaller.ts @@ -150,17 +150,17 @@ namespace ts.server.typingsInstaller { break; } case "installPackage": { - const { fileName, packageName, projectRootPath } = req; + const { fileName, packageName, projectName, projectRootPath } = req; const cwd = getDirectoryOfPackageJson(fileName, this.installTypingHost) || projectRootPath; if (cwd) { this.installWorker(-1, [packageName], cwd, success => { const message = success ? `Package ${packageName} installed.` : `There was an error installing ${packageName}.`; - const response: PackageInstalledResponse = { kind: EventPackageInstalled, success, message }; + const response: PackageInstalledResponse = { kind: ActionPackageInstalled, projectName, success, message }; this.sendResponse(response); }); } else { - const response: PackageInstalledResponse = { kind: EventPackageInstalled, success: false, message: "Could not determine a project root path." }; + const response: PackageInstalledResponse = { kind: ActionPackageInstalled, projectName, success: false, message: "Could not determine a project root path." }; this.sendResponse(response); } break; diff --git a/src/server/typingsInstaller/typingsInstaller.ts b/src/server/typingsInstaller/typingsInstaller.ts index 63bbc219789..3e8f79d0f1d 100644 --- a/src/server/typingsInstaller/typingsInstaller.ts +++ b/src/server/typingsInstaller/typingsInstaller.ts @@ -257,8 +257,9 @@ namespace ts.server.typingsInstaller { const filteredTypings = this.filterTypings(typingsToInstall); if (filteredTypings.length === 0) { if (this.log.isEnabled()) { - this.log.writeLine(`All typings are known to be missing or invalid - no need to go any further`); + this.log.writeLine(`All typings are known to be missing or invalid - no need to install more typings`); } + this.sendResponse(this.createSetTypings(req, currentlyCachedTypings)); return; } diff --git a/src/server/utilities.ts b/src/server/utilities.ts index c57d3b40dee..d76ff1bf6d0 100644 --- a/src/server/utilities.ts +++ b/src/server/utilities.ts @@ -43,7 +43,7 @@ namespace ts.server { return ""; case ProjectKind.External: const projectName = normalizeSlashes(project.getProjectName()); - return project.projectService.host.fileExists(projectName) ? getDirectoryPath(projectName) : projectName; + return getDirectoryPath(projectName); } } diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index ec56a08656c..41515265862 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -209,8 +209,7 @@ namespace ts.codefix { } } } - actions.push(getCodeActionForAddImport(moduleSymbols, context, declarations)); - return actions; + return [...actions, ...getCodeActionsForAddImport(moduleSymbols, context, declarations)]; } function getNamespaceImportName(declaration: AnyImportSyntax): Identifier { @@ -276,17 +275,11 @@ namespace ts.codefix { } }); - const actionFormat = kind === ImportKind.Equals - ? Diagnostics.Import_0_require_1 - : kind === ImportKind.Namespace - ? Diagnostics.Import_Asterisk_as_0_from_1 - : Diagnostics.Import_0_from_1; - // if this file doesn't have any import statements, insert an import statement and then insert a new line // between the only import statement and user code. Otherwise just insert the statement because chances // are there are already a new line seperating code and import statements. return createCodeAction( - actionFormat, + Diagnostics.Import_0_from_module_1, [symbolName, moduleSpecifierWithoutQuotes], changes, "NewImport", @@ -315,19 +308,84 @@ namespace ts.codefix { } } - export function getModuleSpecifierForNewImport(sourceFile: SourceFile, moduleSymbols: ReadonlyArray, options: CompilerOptions, getCanonicalFileName: (file: string) => string, host: LanguageServiceHost): string | undefined { - const choices = mapIterator(arrayIterator(moduleSymbols), moduleSymbol => { + export function getModuleSpecifiersForNewImport( + sourceFile: SourceFile, + moduleSymbols: ReadonlyArray, + options: CompilerOptions, + getCanonicalFileName: (file: string) => string, + host: LanguageServiceHost, + ): string[] { + const { baseUrl, paths, rootDirs } = options; + const choicesForEachExportingModule = mapIterator(arrayIterator(moduleSymbols), moduleSymbol => { const moduleFileName = moduleSymbol.valueDeclaration.getSourceFile().fileName; const sourceDirectory = getDirectoryPath(sourceFile.fileName); + const global = tryGetModuleNameFromAmbientModule(moduleSymbol) + || tryGetModuleNameFromTypeRoots(options, host, getCanonicalFileName, moduleFileName) + || tryGetModuleNameAsNodeModule(options, moduleFileName, host, getCanonicalFileName, sourceDirectory) + || rootDirs && tryGetModuleNameFromRootDirs(rootDirs, moduleFileName, sourceDirectory, getCanonicalFileName); + if (global) { + return [global]; + } - return tryGetModuleNameFromAmbientModule(moduleSymbol) || - tryGetModuleNameFromTypeRoots(options, host, getCanonicalFileName, moduleFileName) || - tryGetModuleNameAsNodeModule(options, moduleFileName, host, getCanonicalFileName, sourceDirectory) || - tryGetModuleNameFromBaseUrl(options, moduleFileName, getCanonicalFileName) || - options.rootDirs && tryGetModuleNameFromRootDirs(options.rootDirs, moduleFileName, sourceDirectory, getCanonicalFileName) || - removeExtensionAndIndexPostFix(getRelativePath(moduleFileName, sourceDirectory, getCanonicalFileName), options); + const relativePath = removeExtensionAndIndexPostFix(getRelativePath(moduleFileName, sourceDirectory, getCanonicalFileName), options); + if (!baseUrl) { + return [relativePath]; + } + + const relativeToBaseUrl = getRelativePathIfInDirectory(moduleFileName, baseUrl, getCanonicalFileName); + if (!relativeToBaseUrl) { + return [relativePath]; + } + + const importRelativeToBaseUrl = removeExtensionAndIndexPostFix(relativeToBaseUrl, options); + if (paths) { + const fromPaths = tryGetModuleNameFromPaths(removeFileExtension(relativeToBaseUrl), importRelativeToBaseUrl, paths); + if (fromPaths) { + return [fromPaths]; + } + } + + /* + Prefer a relative import over a baseUrl import if it doesn't traverse up to baseUrl. + + Suppose we have: + baseUrl = /base + sourceDirectory = /base/a/b + moduleFileName = /base/foo/bar + Then: + relativePath = ../../foo/bar + getRelativePathNParents(relativePath) = 2 + pathFromSourceToBaseUrl = ../../ + getRelativePathNParents(pathFromSourceToBaseUrl) = 2 + 2 < 2 = false + In this case we should prefer using the baseUrl path "/a/b" instead of the relative path "../../foo/bar". + + Suppose we have: + baseUrl = /base + sourceDirectory = /base/foo/a + moduleFileName = /base/foo/bar + Then: + relativePath = ../a + getRelativePathNParents(relativePath) = 1 + pathFromSourceToBaseUrl = ../../ + getRelativePathNParents(pathFromSourceToBaseUrl) = 2 + 1 < 2 = true + In this case we should prefer using the relative path "../a" instead of the baseUrl path "foo/a". + */ + const pathFromSourceToBaseUrl = getRelativePath(baseUrl, sourceDirectory, getCanonicalFileName); + const relativeFirst = getRelativePathNParents(pathFromSourceToBaseUrl) < getRelativePathNParents(relativePath); + return relativeFirst ? [relativePath, importRelativeToBaseUrl] : [importRelativeToBaseUrl, relativePath]; }); - return best(choices, (a, b) => a.length < b.length); + // Only return results for the re-export with the shortest possible path (and also give the other path even if that's long.) + return best(choicesForEachExportingModule, (a, b) => a[0].length < b[0].length); + } + + function getRelativePathNParents(relativePath: string): number { + let count = 0; + for (let i = 0; i + 3 <= relativePath.length && relativePath.slice(i, i + 3) === "../"; i += 3) { + count++; + } + return count; } function tryGetModuleNameFromAmbientModule(moduleSymbol: Symbol): string | undefined { @@ -337,44 +395,28 @@ namespace ts.codefix { } } - function tryGetModuleNameFromBaseUrl(options: CompilerOptions, moduleFileName: string, getCanonicalFileName: (file: string) => string): string | undefined { - if (!options.baseUrl) { - return undefined; - } - - let relativeName = getRelativePathIfInDirectory(moduleFileName, options.baseUrl, getCanonicalFileName); - if (!relativeName) { - return undefined; - } - - const relativeNameWithIndex = removeFileExtension(relativeName); - relativeName = removeExtensionAndIndexPostFix(relativeName, options); - - if (options.paths) { - for (const key in options.paths) { - for (const pattern of options.paths[key]) { - const indexOfStar = pattern.indexOf("*"); - if (indexOfStar === 0 && pattern.length === 1) { - continue; - } - else if (indexOfStar !== -1) { - const prefix = pattern.substr(0, indexOfStar); - const suffix = pattern.substr(indexOfStar + 1); - if (relativeName.length >= prefix.length + suffix.length && - startsWith(relativeName, prefix) && - endsWith(relativeName, suffix)) { - const matchedStar = relativeName.substr(prefix.length, relativeName.length - suffix.length); - return key.replace("\*", matchedStar); - } - } - else if (pattern === relativeName || pattern === relativeNameWithIndex) { - return key; + function tryGetModuleNameFromPaths(relativeNameWithIndex: string, relativeName: string, paths: MapLike>): string | undefined { + for (const key in paths) { + for (const pattern of paths[key]) { + const indexOfStar = pattern.indexOf("*"); + if (indexOfStar === 0 && pattern.length === 1) { + continue; + } + else if (indexOfStar !== -1) { + const prefix = pattern.substr(0, indexOfStar); + const suffix = pattern.substr(indexOfStar + 1); + if (relativeName.length >= prefix.length + suffix.length && + startsWith(relativeName, prefix) && + endsWith(relativeName, suffix)) { + const matchedStar = relativeName.substr(prefix.length, relativeName.length - suffix.length); + return key.replace("\*", matchedStar); } } + else if (pattern === relativeName || pattern === relativeNameWithIndex) { + return key; + } } } - - return relativeName; } function tryGetModuleNameFromRootDirs(rootDirs: ReadonlyArray, moduleFileName: string, sourceDirectory: string, getCanonicalFileName: (file: string) => string): string | undefined { @@ -547,10 +589,11 @@ namespace ts.codefix { return !pathIsRelative(relativePath) ? "./" + relativePath : relativePath; } - function getCodeActionForAddImport( + function getCodeActionsForAddImport( moduleSymbols: ReadonlyArray, ctx: ImportCodeFixOptions, - declarations: ReadonlyArray): ImportCodeAction { + declarations: ReadonlyArray + ): ImportCodeAction[] { const fromExistingImport = firstDefined(declarations, declaration => { if (declaration.kind === SyntaxKind.ImportDeclaration && declaration.importClause) { const changes = tryUpdateExistingImport(ctx, isImportClause(declaration.importClause) && declaration.importClause || undefined); @@ -566,12 +609,12 @@ namespace ts.codefix { } }); if (fromExistingImport) { - return fromExistingImport; + return [fromExistingImport]; } - const moduleSpecifier = firstDefined(declarations, moduleSpecifierFromAnyImport) - || getModuleSpecifierForNewImport(ctx.sourceFile, moduleSymbols, ctx.compilerOptions, ctx.getCanonicalFileName, ctx.host); - return getCodeActionForNewImport(ctx, moduleSpecifier); + const existingDeclaration = firstDefined(declarations, moduleSpecifierFromAnyImport); + const moduleSpecifiers = existingDeclaration ? [existingDeclaration] : getModuleSpecifiersForNewImport(ctx.sourceFile, moduleSymbols, ctx.compilerOptions, ctx.getCanonicalFileName, ctx.host); + return moduleSpecifiers.map(spec => getCodeActionForNewImport(ctx, spec)); } function moduleSpecifierFromAnyImport(node: AnyImportSyntax): string | undefined { diff --git a/src/services/completions.ts b/src/services/completions.ts index 6bbdfacac4c..a3b94acd4c0 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -488,7 +488,7 @@ namespace ts.Completions { const moduleSymbols = getAllReExportingModules(exportedSymbol, checker, allSourceFiles); Debug.assert(contains(moduleSymbols, moduleSymbol)); - const sourceDisplay = [textPart(codefix.getModuleSpecifierForNewImport(sourceFile, moduleSymbols, compilerOptions, getCanonicalFileName, host))]; + const sourceDisplay = [textPart(first(codefix.getModuleSpecifiersForNewImport(sourceFile, moduleSymbols, compilerOptions, getCanonicalFileName, host)))]; const codeActions = codefix.getCodeActionForImport(moduleSymbols, { host, checker, @@ -942,6 +942,7 @@ namespace ts.Completions { scopeNode.kind === SyntaxKind.SourceFile || scopeNode.kind === SyntaxKind.TemplateExpression || scopeNode.kind === SyntaxKind.JsxExpression || + scopeNode.kind === SyntaxKind.Block || // Some blocks aren't statements, but all get global completions isStatement(scopeNode); } diff --git a/src/services/documentRegistry.ts b/src/services/documentRegistry.ts index 0c3d4d1cb48..81742018fb7 100644 --- a/src/services/documentRegistry.ts +++ b/src/services/documentRegistry.ts @@ -24,9 +24,9 @@ namespace ts { * @param compilationSettings Some compilation settings like target affects the * shape of a the resulting SourceFile. This allows the DocumentRegistry to store * multiple copies of the same file for different compilation settings. - * @parm scriptSnapshot Text of the file. Only used if the file was not found + * @param scriptSnapshot Text of the file. Only used if the file was not found * in the registry and a new one was created. - * @parm version Current version of the file. Only used if the file was not found + * @param version Current version of the file. Only used if the file was not found * in the registry and a new one was created. */ acquireDocument( diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index 0f64321f1be..86db21e3225 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -1427,10 +1427,7 @@ namespace ts.FindAllReferences.Core { // we should include both parameter declaration symbol and property declaration symbol // Parameter Declaration symbol is only visible within function scope, so the symbol is stored in constructor.locals. // Property Declaration symbol is a member of the class, so the symbol is stored in its class Declaration.symbol.members - if (symbol.valueDeclaration && symbol.valueDeclaration.kind === SyntaxKind.Parameter && - isParameterPropertyDeclaration(symbol.valueDeclaration)) { - addRange(result, checker.getSymbolsOfParameterPropertyDeclaration(symbol.valueDeclaration, symbol.name)); - } + addRange(result, getParameterPropertySymbols(symbol, checker)); // If this is symbol of binding element without propertyName declaration in Object binding pattern // Include the property in the search @@ -1460,6 +1457,12 @@ namespace ts.FindAllReferences.Core { } } + function getParameterPropertySymbols(symbol: Symbol, checker: TypeChecker): Symbol[] { + return symbol.valueDeclaration && isParameter(symbol.valueDeclaration) && isParameterPropertyDeclaration(symbol.valueDeclaration) + ? checker.getSymbolsOfParameterPropertyDeclaration(symbol.valueDeclaration, symbol.name) + : undefined; + } + /** * Find symbol of the given property-name and add the symbol to the given result array * @param symbol a symbol to start searching for the given propertyName @@ -1519,17 +1522,26 @@ namespace ts.FindAllReferences.Core { } function getRelatedSymbol(search: Search, referenceSymbol: Symbol, referenceLocation: Node, state: State): Symbol | undefined { + const { checker } = state; if (search.includes(referenceSymbol)) { return referenceSymbol; } + if (referenceSymbol.flags & SymbolFlags.FunctionScopedVariable) { + Debug.assert(!(referenceSymbol.flags & SymbolFlags.Property)); + const paramProps = getParameterPropertySymbols(referenceSymbol, checker); + if (paramProps) { + return getRelatedSymbol(search, find(paramProps, x => !!(x.flags & SymbolFlags.Property))!, referenceLocation, state); + } + } + // If the reference location is in an object literal, try to get the contextual type for the // object literal, lookup the property symbol in the contextual type, and use this symbol to // compare to our searchSymbol const containingObjectLiteralElement = getContainingObjectLiteralElement(referenceLocation); if (containingObjectLiteralElement) { - const contextualSymbol = forEach(getPropertySymbolsFromContextualType(containingObjectLiteralElement, state.checker), contextualSymbol => - find(state.checker.getRootSymbols(contextualSymbol), search.includes)); + const contextualSymbol = forEach(getPropertySymbolsFromContextualType(containingObjectLiteralElement, checker), contextualSymbol => + find(checker.getRootSymbols(contextualSymbol), search.includes)); if (contextualSymbol) { return contextualSymbol; @@ -1539,7 +1551,7 @@ namespace ts.FindAllReferences.Core { // Get the property symbol from the object literal's type and look if thats the search symbol // In below eg. get 'property' from type of elems iterating type // for ( { property: p2 } of elems) { } - const propertySymbol = getPropertySymbolOfDestructuringAssignment(referenceLocation, state.checker); + const propertySymbol = getPropertySymbolOfDestructuringAssignment(referenceLocation, checker); if (propertySymbol && search.includes(propertySymbol)) { return propertySymbol; } @@ -1548,7 +1560,7 @@ namespace ts.FindAllReferences.Core { // If the reference location is the binding element and doesn't have property name // then include the binding element in the related symbols // let { a } : { a }; - const bindingElementPropertySymbol = getPropertySymbolOfObjectBindingPatternWithoutPropertyName(referenceSymbol, state.checker); + const bindingElementPropertySymbol = getPropertySymbolOfObjectBindingPatternWithoutPropertyName(referenceSymbol, checker); if (bindingElementPropertySymbol) { const fromBindingElement = findRootSymbol(bindingElementPropertySymbol); if (fromBindingElement) return fromBindingElement; diff --git a/src/services/outliningElementsCollector.ts b/src/services/outliningElementsCollector.ts index bd294209088..f3f91724a9c 100644 --- a/src/services/outliningElementsCollector.ts +++ b/src/services/outliningElementsCollector.ts @@ -1,227 +1,166 @@ /* @internal */ namespace ts.OutliningElementsCollector { - const collapseText = "..."; - const maxDepth = 40; - const defaultLabel = "#region"; - const regionMatch = new RegExp("^\\s*//\\s*#(end)?region(?:\\s+(.*))?$"); - export function collectElements(sourceFile: SourceFile, cancellationToken: CancellationToken): OutliningSpan[] { - const elements: OutliningSpan[] = []; - let depth = 0; - const regions: OutliningSpan[] = []; + const res: OutliningSpan[] = []; + addNodeOutliningSpans(sourceFile, cancellationToken, res); + addRegionOutliningSpans(sourceFile, res); + return res.sort((span1, span2) => span1.textSpan.start - span2.textSpan.start); + } - walk(sourceFile); - gatherRegions(); - return elements.sort((span1, span2) => span1.textSpan.start - span2.textSpan.start); - - /** If useFullStart is true, then the collapsing span includes leading whitespace, including linebreaks. */ - function addOutliningSpan(hintSpanNode: Node, startElement: Node, endElement: Node, autoCollapse: boolean, useFullStart: boolean) { - if (hintSpanNode && startElement && endElement) { - const span: OutliningSpan = { - textSpan: createTextSpanFromBounds(useFullStart ? startElement.getFullStart() : startElement.getStart(), endElement.getEnd()), - hintSpan: createTextSpanFromNode(hintSpanNode, sourceFile), - bannerText: collapseText, - autoCollapse, - }; - elements.push(span); - } - } - - function addOutliningSpanComments(commentSpan: CommentRange, autoCollapse: boolean) { - if (commentSpan) { - const span: OutliningSpan = { - textSpan: createTextSpanFromBounds(commentSpan.pos, commentSpan.end), - hintSpan: createTextSpanFromBounds(commentSpan.pos, commentSpan.end), - bannerText: collapseText, - autoCollapse, - }; - elements.push(span); - } - } - - function addOutliningForLeadingCommentsForNode(n: Node) { - const comments = ts.getLeadingCommentRangesOfNode(n, sourceFile); - - if (comments) { - let firstSingleLineCommentStart = -1; - let lastSingleLineCommentEnd = -1; - let isFirstSingleLineComment = true; - let singleLineCommentCount = 0; - - for (const currentComment of comments) { - cancellationToken.throwIfCancellationRequested(); - - // For single line comments, combine consecutive ones (2 or more) into - // a single span from the start of the first till the end of the last - if (currentComment.kind === SyntaxKind.SingleLineCommentTrivia) { - if (isFirstSingleLineComment) { - firstSingleLineCommentStart = currentComment.pos; - } - isFirstSingleLineComment = false; - lastSingleLineCommentEnd = currentComment.end; - singleLineCommentCount++; - } - else if (currentComment.kind === SyntaxKind.MultiLineCommentTrivia) { - combineAndAddMultipleSingleLineComments(singleLineCommentCount, firstSingleLineCommentStart, lastSingleLineCommentEnd); - addOutliningSpanComments(currentComment, /*autoCollapse*/ false); - - singleLineCommentCount = 0; - lastSingleLineCommentEnd = -1; - isFirstSingleLineComment = true; - } - } - - combineAndAddMultipleSingleLineComments(singleLineCommentCount, firstSingleLineCommentStart, lastSingleLineCommentEnd); - } - } - - function combineAndAddMultipleSingleLineComments(count: number, start: number, end: number) { - - // Only outline spans of two or more consecutive single line comments - if (count > 1) { - const multipleSingleLineComments: CommentRange = { - kind: SyntaxKind.SingleLineCommentTrivia, - pos: start, - end, - }; - - addOutliningSpanComments(multipleSingleLineComments, /*autoCollapse*/ false); - } - } - - function autoCollapse(node: Node) { - return isFunctionBlock(node) && node.parent.kind !== SyntaxKind.ArrowFunction; - } - - function gatherRegions(): void { - const lineStarts = sourceFile.getLineStarts(); - - for (let i = 0; i < lineStarts.length; i++) { - const currentLineStart = lineStarts[i]; - const lineEnd = lineStarts[i + 1] - 1 || sourceFile.getEnd(); - const comment = sourceFile.text.substring(currentLineStart, lineEnd); - const result = comment.match(regionMatch); - - if (result && !isInComment(sourceFile, currentLineStart)) { - if (!result[1]) { - const start = sourceFile.getFullText().indexOf("//", currentLineStart); - const textSpan = createTextSpanFromBounds(start, lineEnd); - const region: OutliningSpan = { - textSpan, - hintSpan: textSpan, - bannerText: result[2] || defaultLabel, - autoCollapse: false - }; - regions.push(region); - } - else { - const region = regions.pop(); - if (region) { - region.textSpan.length = lineEnd - region.textSpan.start; - region.hintSpan.length = lineEnd - region.textSpan.start; - elements.push(region); - } - } - } - } - } - - function walk(n: Node): void { + function addNodeOutliningSpans(sourceFile: SourceFile, cancellationToken: CancellationToken, out: Push): void { + let depthRemaining = 40; + sourceFile.forEachChild(function walk(n) { + if (depthRemaining === 0) return; cancellationToken.throwIfCancellationRequested(); - if (depth > maxDepth) { - return; - } if (isDeclaration(n)) { - addOutliningForLeadingCommentsForNode(n); + addOutliningForLeadingCommentsForNode(n, sourceFile, cancellationToken, out); } - switch (n.kind) { - case SyntaxKind.Block: - if (!isFunctionBlock(n)) { - const parent = n.parent; - const openBrace = findChildOfKind(n, SyntaxKind.OpenBraceToken, sourceFile); - const closeBrace = findChildOfKind(n, SyntaxKind.CloseBraceToken, sourceFile); + const span = getOutliningSpanForNode(n, sourceFile); + if (span) out.push(span); - // Check if the block is standalone, or 'attached' to some parent statement. - // If the latter, we want to collapse the block, but consider its hint span - // to be the entire span of the parent. - if (parent.kind === SyntaxKind.DoStatement || - parent.kind === SyntaxKind.ForInStatement || - parent.kind === SyntaxKind.ForOfStatement || - parent.kind === SyntaxKind.ForStatement || - parent.kind === SyntaxKind.IfStatement || - parent.kind === SyntaxKind.WhileStatement || - parent.kind === SyntaxKind.WithStatement || - parent.kind === SyntaxKind.CatchClause) { + depthRemaining--; + n.forEachChild(walk); + depthRemaining++; + }); + } - addOutliningSpan(parent, openBrace, closeBrace, autoCollapse(n), /*useFullStart*/ true); - break; - } + function addRegionOutliningSpans(sourceFile: SourceFile, out: Push): void { + const regions: OutliningSpan[] = []; + const lineStarts = sourceFile.getLineStarts(); + for (let i = 0; i < lineStarts.length; i++) { + const currentLineStart = lineStarts[i]; + const lineEnd = i + 1 === lineStarts.length ? sourceFile.getEnd() : lineStarts[i + 1] - 1; + const lineText = sourceFile.text.substring(currentLineStart, lineEnd); + const result = lineText.match(/^\s*\/\/\s*#(end)?region(?:\s+(.*))?$/); + if (!result || isInComment(sourceFile, currentLineStart)) { + continue; + } - if (parent.kind === SyntaxKind.TryStatement) { - // Could be the try-block, or the finally-block. - const tryStatement = parent; - if (tryStatement.tryBlock === n) { - addOutliningSpan(parent, openBrace, closeBrace, autoCollapse(n), /*useFullStart*/ true); - break; - } - else if (tryStatement.finallyBlock === n) { - const finallyKeyword = findChildOfKind(tryStatement, SyntaxKind.FinallyKeyword, sourceFile); - if (finallyKeyword) { - addOutliningSpan(finallyKeyword, openBrace, closeBrace, autoCollapse(n), /*useFullStart*/ true); - break; - } - } - - // fall through. - } - - // Block was a standalone block. In this case we want to only collapse - // the span of the block, independent of any parent span. - const span = createTextSpanFromNode(n); - elements.push({ - textSpan: span, - hintSpan: span, - bannerText: collapseText, - autoCollapse: autoCollapse(n) - }); - break; - } - // falls through - - case SyntaxKind.ModuleBlock: { - const openBrace = findChildOfKind(n, SyntaxKind.OpenBraceToken, sourceFile); - const closeBrace = findChildOfKind(n, SyntaxKind.CloseBraceToken, sourceFile); - addOutliningSpan(n.parent, openBrace, closeBrace, autoCollapse(n), /*useFullStart*/ true); - break; - } - case SyntaxKind.ClassDeclaration: - case SyntaxKind.InterfaceDeclaration: - case SyntaxKind.EnumDeclaration: - case SyntaxKind.CaseBlock: { - const openBrace = findChildOfKind(n, SyntaxKind.OpenBraceToken, sourceFile); - const closeBrace = findChildOfKind(n, SyntaxKind.CloseBraceToken, sourceFile); - addOutliningSpan(n, openBrace, closeBrace, autoCollapse(n), /*useFullStart*/ true); - break; + if (!result[1]) { + const span = createTextSpanFromBounds(sourceFile.text.indexOf("//", currentLineStart), lineEnd); + regions.push(createOutliningSpan(span, span, /*autoCollapse*/ false, result[2] || "#region")); + } + else { + const region = regions.pop(); + if (region) { + region.textSpan.length = lineEnd - region.textSpan.start; + region.hintSpan.length = lineEnd - region.textSpan.start; + out.push(region); } - // If the block has no leading keywords and is inside an array literal, - // we only want to collapse the span of the block. - // Otherwise, the collapsed section will include the end of the previous line. - case SyntaxKind.ObjectLiteralExpression: - const openBrace = findChildOfKind(n, SyntaxKind.OpenBraceToken, sourceFile); - const closeBrace = findChildOfKind(n, SyntaxKind.CloseBraceToken, sourceFile); - addOutliningSpan(n, openBrace, closeBrace, autoCollapse(n), /*useFullStart*/ !isArrayLiteralExpression(n.parent)); - break; - case SyntaxKind.ArrayLiteralExpression: - const openBracket = findChildOfKind(n, SyntaxKind.OpenBracketToken, sourceFile); - const closeBracket = findChildOfKind(n, SyntaxKind.CloseBracketToken, sourceFile); - addOutliningSpan(n, openBracket, closeBracket, autoCollapse(n), /*useFullStart*/ !isArrayLiteralExpression(n.parent)); - break; } - depth++; - forEachChild(n, walk); - depth--; } } + + function addOutliningForLeadingCommentsForNode(n: Node, sourceFile: SourceFile, cancellationToken: CancellationToken, out: Push): void { + const comments = getLeadingCommentRangesOfNode(n, sourceFile); + if (!comments) return; + let firstSingleLineCommentStart = -1; + let lastSingleLineCommentEnd = -1; + let singleLineCommentCount = 0; + for (const { kind, pos, end } of comments) { + cancellationToken.throwIfCancellationRequested(); + switch (kind) { + case SyntaxKind.SingleLineCommentTrivia: + // For single line comments, combine consecutive ones (2 or more) into + // a single span from the start of the first till the end of the last + if (singleLineCommentCount === 0) { + firstSingleLineCommentStart = pos; + } + lastSingleLineCommentEnd = end; + singleLineCommentCount++; + break; + case SyntaxKind.MultiLineCommentTrivia: + combineAndAddMultipleSingleLineComments(); + out.push(createOutliningSpanFromBounds(pos, end)); + singleLineCommentCount = 0; + break; + default: + Debug.assertNever(kind); + } + } + combineAndAddMultipleSingleLineComments(); + + function combineAndAddMultipleSingleLineComments(): void { + // Only outline spans of two or more consecutive single line comments + if (singleLineCommentCount > 1) { + out.push(createOutliningSpanFromBounds(firstSingleLineCommentStart, lastSingleLineCommentEnd)); + } + } + } + + function createOutliningSpanFromBounds(pos: number, end: number): OutliningSpan { + return createOutliningSpan(createTextSpanFromBounds(pos, end)); + } + + function getOutliningSpanForNode(n: Node, sourceFile: SourceFile): OutliningSpan | undefined { + switch (n.kind) { + case SyntaxKind.Block: + if (isFunctionBlock(n)) { + return spanForNode(n.parent, /*autoCollapse*/ n.parent.kind !== SyntaxKind.ArrowFunction); + } + // Check if the block is standalone, or 'attached' to some parent statement. + // If the latter, we want to collapse the block, but consider its hint span + // to be the entire span of the parent. + switch (n.parent.kind) { + case SyntaxKind.DoStatement: + case SyntaxKind.ForInStatement: + case SyntaxKind.ForOfStatement: + case SyntaxKind.ForStatement: + case SyntaxKind.IfStatement: + case SyntaxKind.WhileStatement: + case SyntaxKind.WithStatement: + case SyntaxKind.CatchClause: + return spanForNode(n.parent); + case SyntaxKind.TryStatement: + // Could be the try-block, or the finally-block. + const tryStatement = n.parent; + if (tryStatement.tryBlock === n) { + return spanForNode(n.parent); + } + else if (tryStatement.finallyBlock === n) { + return spanForNode(findChildOfKind(tryStatement, SyntaxKind.FinallyKeyword, sourceFile)!); + } + // falls through + default: + // Block was a standalone block. In this case we want to only collapse + // the span of the block, independent of any parent span. + return createOutliningSpan(createTextSpanFromNode(n, sourceFile)); + } + case SyntaxKind.ModuleBlock: + return spanForNode(n.parent); + case SyntaxKind.ClassDeclaration: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.CaseBlock: + return spanForNode(n); + case SyntaxKind.ObjectLiteralExpression: + return spanForObjectOrArrayLiteral(n); + case SyntaxKind.ArrayLiteralExpression: + return spanForObjectOrArrayLiteral(n, SyntaxKind.OpenBracketToken); + } + + function spanForObjectOrArrayLiteral(node: Node, open: SyntaxKind.OpenBraceToken | SyntaxKind.OpenBracketToken = SyntaxKind.OpenBraceToken): OutliningSpan | undefined { + // If the block has no leading keywords and is inside an array literal, + // we only want to collapse the span of the block. + // Otherwise, the collapsed section will include the end of the previous line. + return spanForNode(node, /*autoCollapse*/ false, /*useFullStart*/ !isArrayLiteralExpression(node.parent), open); + } + + function spanForNode(hintSpanNode: Node, autoCollapse = false, useFullStart = true, open: SyntaxKind.OpenBraceToken | SyntaxKind.OpenBracketToken = SyntaxKind.OpenBraceToken): OutliningSpan | undefined { + const openToken = findChildOfKind(n, open, sourceFile); + const close = open === SyntaxKind.OpenBraceToken ? SyntaxKind.CloseBraceToken : SyntaxKind.CloseBracketToken; + const closeToken = findChildOfKind(n, close, sourceFile); + if (!openToken || !closeToken) { + return undefined; + } + const textSpan = createTextSpanFromBounds(useFullStart ? openToken.getFullStart() : openToken.getStart(sourceFile), closeToken.getEnd()); + return createOutliningSpan(textSpan, createTextSpanFromNode(hintSpanNode, sourceFile), autoCollapse); + } + } + + function createOutliningSpan(textSpan: TextSpan, hintSpan: TextSpan = textSpan, autoCollapse = false, bannerText = "..."): OutliningSpan { + return { textSpan, hintSpan, bannerText, autoCollapse }; + } } \ No newline at end of file diff --git a/src/services/services.ts b/src/services/services.ts index f479a47f398..24679e6a167 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -473,6 +473,12 @@ namespace ts { getNonNullableType(): Type { return this.checker.getNonNullableType(this); } + getConstraint(): Type | undefined { + return this.checker.getBaseConstraintOfType(this); + } + getDefault(): Type | undefined { + return this.checker.getDefaultFromTypeParameter(this); + } } class SignatureObject implements Signature { diff --git a/src/services/types.ts b/src/services/types.ts index 28de0566a50..e74b830cc45 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -50,6 +50,8 @@ namespace ts { getNumberIndexType(): Type | undefined; getBaseTypes(): BaseType[] | undefined; getNonNullableType(): Type; + getConstraint(): Type | undefined; + getDefault(): Type | undefined; } export interface Signature { diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 3837763cee5..e76fcd93492 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1329,13 +1329,17 @@ namespace ts { return getTokenAtPosition(sourceFile, declaration.members.pos - 1, /*includeJsDocComment*/ false); } - export function getSourceFileImportLocation(node: SourceFile) { - // For a source file, it is possible there are detached comments we should not skip - const text = node.text; - const textLength = text.length; - let ranges = getLeadingCommentRanges(text, 0); - if (!ranges) return 0; + export function getSourceFileImportLocation({ text }: SourceFile) { + const shebang = getShebang(text); let position = 0; + if (shebang !== undefined) { + position = shebang.length; + advancePastLineBreak(); + } + + // For a source file, it is possible there are detached comments we should not skip + let ranges = getLeadingCommentRanges(text, position); + if (!ranges) return position; // However we should still skip a pinned comment at the top if (ranges.length && ranges[0].kind === SyntaxKind.MultiLineCommentTrivia && isPinnedComment(text, ranges[0])) { position = ranges[0].end; @@ -1344,7 +1348,7 @@ namespace ts { } // As well as any triple slash references for (const range of ranges) { - if (range.kind === SyntaxKind.SingleLineCommentTrivia && isRecognizedTripleSlashComment(node.text, range.pos, range.end)) { + if (range.kind === SyntaxKind.SingleLineCommentTrivia && isRecognizedTripleSlashComment(text, range.pos, range.end)) { position = range.end; advancePastLineBreak(); continue; @@ -1354,12 +1358,12 @@ namespace ts { return position; function advancePastLineBreak() { - if (position < textLength) { + if (position < text.length) { const charCode = text.charCodeAt(position); if (isLineBreak(charCode)) { position++; - if (position < textLength && charCode === CharacterCodes.carriageReturn && text.charCodeAt(position) === CharacterCodes.lineFeed) { + if (position < text.length && charCode === CharacterCodes.carriageReturn && text.charCodeAt(position) === CharacterCodes.lineFeed) { position++; } } diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index f3feec89acc..bd8bab1e3b8 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -1783,6 +1783,8 @@ declare namespace ts { getApparentType(type: Type): Type; getSuggestionForNonexistentProperty(node: Identifier, containingType: Type): string | undefined; getSuggestionForNonexistentSymbol(location: Node, name: string, meaning: SymbolFlags): string | undefined; + getBaseConstraintOfType(type: Type): Type | undefined; + getDefaultFromTypeParameter(type: Type): Type | undefined; } enum NodeBuilderFlags { None = 0, @@ -2119,9 +2121,6 @@ declare namespace ts { interface TypeVariable extends Type { } interface TypeParameter extends TypeVariable { - /** Retrieve using getConstraintFromTypeParameter */ - constraint: Type; - default?: Type; } interface IndexedAccessType extends TypeVariable { objectType: Type; @@ -3843,6 +3842,8 @@ declare namespace ts { getNumberIndexType(): Type | undefined; getBaseTypes(): BaseType[] | undefined; getNonNullableType(): Type; + getConstraint(): Type | undefined; + getDefault(): Type | undefined; } interface Signature { getDeclaration(): SignatureDeclaration; @@ -4586,9 +4587,9 @@ declare namespace ts { * @param compilationSettings Some compilation settings like target affects the * shape of a the resulting SourceFile. This allows the DocumentRegistry to store * multiple copies of the same file for different compilation settings. - * @parm scriptSnapshot Text of the file. Only used if the file was not found + * @param scriptSnapshot Text of the file. Only used if the file was not found * in the registry and a new one was created. - * @parm version Current version of the file. Only used if the file was not found + * @param version Current version of the file. Only used if the file was not found * in the registry and a new one was created. */ acquireDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile; @@ -4716,7 +4717,7 @@ declare namespace ts.server { interface TypesRegistryRequest { readonly kind: "typesRegistry"; } - interface InstallPackageRequest { + interface InstallPackageRequest extends TypingInstallerRequestWithProjectName { readonly kind: "installPackage"; readonly fileName: Path; readonly packageName: string; @@ -4724,13 +4725,18 @@ declare namespace ts.server { } type ActionSet = "action::set"; type ActionInvalidate = "action::invalidate"; + type ActionPackageInstalled = "action::packageInstalled"; type EventTypesRegistry = "event::typesRegistry"; - type EventPackageInstalled = "event::packageInstalled"; type EventBeginInstallTypes = "event::beginInstallTypes"; type EventEndInstallTypes = "event::endInstallTypes"; type EventInitializationFailed = "event::initializationFailed"; interface TypingInstallerResponse { - readonly kind: ActionSet | ActionInvalidate | EventTypesRegistry | EventPackageInstalled | EventBeginInstallTypes | EventEndInstallTypes | EventInitializationFailed; + readonly kind: ActionSet | ActionInvalidate | EventTypesRegistry | ActionPackageInstalled | EventBeginInstallTypes | EventEndInstallTypes | EventInitializationFailed; + } + interface PackageInstalledResponse extends ProjectResponse { + readonly kind: ActionPackageInstalled; + readonly success: boolean; + readonly message: string; } interface InitializationFailedResponse extends TypingInstallerResponse { readonly kind: EventInitializationFailed; @@ -4766,8 +4772,8 @@ declare namespace ts.server { declare namespace ts.server { const ActionSet: ActionSet; const ActionInvalidate: ActionInvalidate; + const ActionPackageInstalled: ActionPackageInstalled; const EventTypesRegistry: EventTypesRegistry; - const EventPackageInstalled: EventPackageInstalled; const EventBeginInstallTypes: EventBeginInstallTypes; const EventEndInstallTypes: EventEndInstallTypes; const EventInitializationFailed: EventInitializationFailed; @@ -6930,7 +6936,7 @@ declare namespace ts.server { type CommandNames = protocol.CommandTypes; const CommandNames: any; function formatMessage(msg: T, logger: server.Logger, byteLength: (s: string, encoding: string) => number, newLine: string): string; - type Event = (body: T, eventName: string) => void; + type Event = (body: T, eventName: string) => void; interface EventSender { event: Event; } @@ -6973,7 +6979,7 @@ declare namespace ts.server { private projectsUpdatedInBackgroundEvent(openFiles); logError(err: Error, cmd: string): void; send(msg: protocol.Message): void; - event(body: T, eventName: string): void; + event(body: T, eventName: string): void; /** @deprecated */ output(info: any, cmdName: string, reqSeq?: number, errorMsg?: string): void; private doOutput(info, cmdName, reqSeq, success, message?); @@ -7125,12 +7131,13 @@ declare namespace ts.server { } } declare namespace ts.server { - interface InstallPackageOptionsWithProjectRootPath extends InstallPackageOptions { + interface InstallPackageOptionsWithProject extends InstallPackageOptions { + projectName: string; projectRootPath: Path; } interface ITypingsInstaller { isKnownTypesPackageName(name: string): boolean; - installPackage(options: InstallPackageOptionsWithProjectRootPath): Promise; + installPackage(options: InstallPackageOptionsWithProject): Promise; enqueueInstallTypingsRequest(p: Project, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray): void; attach(projectService: ProjectService): void; onProjectClosed(p: Project): void; @@ -7142,7 +7149,7 @@ declare namespace ts.server { private readonly perProjectCache; constructor(installer: ITypingsInstaller); isKnownTypesPackageName(name: string): boolean; - installPackage(options: InstallPackageOptionsWithProjectRootPath): Promise; + installPackage(options: InstallPackageOptionsWithProject): Promise; getTypingsForProject(project: Project, unresolvedImports: SortedReadonlyArray, forceRefresh: boolean): SortedReadonlyArray; updateTypingsForProject(projectName: string, compilerOptions: CompilerOptions, typeAcquisition: TypeAcquisition, unresolvedImports: SortedReadonlyArray, newTypings: string[]): void; deleteTypingsForProject(projectName: string): void; @@ -7566,7 +7573,7 @@ declare namespace ts.server { private createWatcherLog(watchType, project); toPath(fileName: string): Path; private loadTypesMap(); - updateTypingsForProject(response: SetTypings | InvalidateCachedTypings): void; + updateTypingsForProject(response: SetTypings | InvalidateCachedTypings | PackageInstalledResponse): void; private delayInferredProjectsRefresh(); private delayUpdateProjectGraph(project); private sendProjectsUpdatedInBackgroundEvent(); diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 1cd6fc30ef4..147b62e63c1 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -1783,6 +1783,8 @@ declare namespace ts { getApparentType(type: Type): Type; getSuggestionForNonexistentProperty(node: Identifier, containingType: Type): string | undefined; getSuggestionForNonexistentSymbol(location: Node, name: string, meaning: SymbolFlags): string | undefined; + getBaseConstraintOfType(type: Type): Type | undefined; + getDefaultFromTypeParameter(type: Type): Type | undefined; } enum NodeBuilderFlags { None = 0, @@ -2119,9 +2121,6 @@ declare namespace ts { interface TypeVariable extends Type { } interface TypeParameter extends TypeVariable { - /** Retrieve using getConstraintFromTypeParameter */ - constraint: Type; - default?: Type; } interface IndexedAccessType extends TypeVariable { objectType: Type; @@ -3843,6 +3842,8 @@ declare namespace ts { getNumberIndexType(): Type | undefined; getBaseTypes(): BaseType[] | undefined; getNonNullableType(): Type; + getConstraint(): Type | undefined; + getDefault(): Type | undefined; } interface Signature { getDeclaration(): SignatureDeclaration; @@ -4586,9 +4587,9 @@ declare namespace ts { * @param compilationSettings Some compilation settings like target affects the * shape of a the resulting SourceFile. This allows the DocumentRegistry to store * multiple copies of the same file for different compilation settings. - * @parm scriptSnapshot Text of the file. Only used if the file was not found + * @param scriptSnapshot Text of the file. Only used if the file was not found * in the registry and a new one was created. - * @parm version Current version of the file. Only used if the file was not found + * @param version Current version of the file. Only used if the file was not found * in the registry and a new one was created. */ acquireDocument(fileName: string, compilationSettings: CompilerOptions, scriptSnapshot: IScriptSnapshot, version: string, scriptKind?: ScriptKind): SourceFile; diff --git a/tests/baselines/reference/destructuredDeclarationEmit.js b/tests/baselines/reference/destructuredDeclarationEmit.js new file mode 100644 index 00000000000..d4197652581 --- /dev/null +++ b/tests/baselines/reference/destructuredDeclarationEmit.js @@ -0,0 +1,77 @@ +//// [tests/cases/compiler/destructuredDeclarationEmit.ts] //// + +//// [foo.ts] +const foo = { bar: 'hello', bat: 'world', bam: { bork: { bar: 'a', baz: 'b' } } }; +const arr: [0, 1, 2, ['a', 'b', 'c', [{def: 'def'}, {sec: 'sec'}]]] = [0, 1, 2, ['a', 'b', 'c', [{def: 'def'}, {sec: 'sec'}]]]; +export { foo, arr }; +//// [index.ts] +import { foo, arr } from './foo'; +export { foo, arr }; + +const { bar: baz, bat, bam: { bork: { bar: ibar, baz: ibaz } } } = foo; +export { baz, ibaz }; + +const [ , one, , [, bee, , [, {sec} ]]] = arr; +export { one, bee, sec }; + +const getFoo = () => ({ + foo: 'foo' +}); + +const { foo: foo2 } = getFoo(); +export { foo2 }; + + +//// [foo.js] +"use strict"; +exports.__esModule = true; +var foo = { bar: 'hello', bat: 'world', bam: { bork: { bar: 'a', baz: 'b' } } }; +exports.foo = foo; +var arr = [0, 1, 2, ['a', 'b', 'c', [{ def: 'def' }, { sec: 'sec' }]]]; +exports.arr = arr; +//// [index.js] +"use strict"; +exports.__esModule = true; +var foo_1 = require("./foo"); +exports.foo = foo_1.foo; +exports.arr = foo_1.arr; +var baz = foo_1.foo.bar, bat = foo_1.foo.bat, _a = foo_1.foo.bam.bork, ibar = _a.bar, ibaz = _a.baz; +exports.baz = baz; +exports.ibaz = ibaz; +var one = foo_1.arr[1], _b = foo_1.arr[3], bee = _b[1], _c = _b[3], sec = _c[1].sec; +exports.one = one; +exports.bee = bee; +exports.sec = sec; +var getFoo = function () { return ({ + foo: 'foo' +}); }; +var foo2 = getFoo().foo; +exports.foo2 = foo2; + + +//// [foo.d.ts] +declare const foo: { + bar: string; + bat: string; + bam: { + bork: { + bar: string; + baz: string; + }; + }; +}; +declare const arr: [0, 1, 2, ['a', 'b', 'c', [{ + def: 'def'; +}, { + sec: 'sec'; +}]]]; +export { foo, arr }; +//// [index.d.ts] +import { foo, arr } from './foo'; +export { foo, arr }; +declare const baz: string, ibaz: string; +export { baz, ibaz }; +declare const one: 1, bee: "b", sec: "sec"; +export { one, bee, sec }; +declare const foo2: string; +export { foo2 }; diff --git a/tests/baselines/reference/destructuredDeclarationEmit.symbols b/tests/baselines/reference/destructuredDeclarationEmit.symbols new file mode 100644 index 00000000000..daeed5befd7 --- /dev/null +++ b/tests/baselines/reference/destructuredDeclarationEmit.symbols @@ -0,0 +1,73 @@ +=== tests/cases/compiler/foo.ts === +const foo = { bar: 'hello', bat: 'world', bam: { bork: { bar: 'a', baz: 'b' } } }; +>foo : Symbol(foo, Decl(foo.ts, 0, 5)) +>bar : Symbol(bar, Decl(foo.ts, 0, 13)) +>bat : Symbol(bat, Decl(foo.ts, 0, 27)) +>bam : Symbol(bam, Decl(foo.ts, 0, 41)) +>bork : Symbol(bork, Decl(foo.ts, 0, 48)) +>bar : Symbol(bar, Decl(foo.ts, 0, 56)) +>baz : Symbol(baz, Decl(foo.ts, 0, 66)) + +const arr: [0, 1, 2, ['a', 'b', 'c', [{def: 'def'}, {sec: 'sec'}]]] = [0, 1, 2, ['a', 'b', 'c', [{def: 'def'}, {sec: 'sec'}]]]; +>arr : Symbol(arr, Decl(foo.ts, 1, 5)) +>def : Symbol(def, Decl(foo.ts, 1, 39)) +>sec : Symbol(sec, Decl(foo.ts, 1, 53)) +>def : Symbol(def, Decl(foo.ts, 1, 98)) +>sec : Symbol(sec, Decl(foo.ts, 1, 112)) + +export { foo, arr }; +>foo : Symbol(foo, Decl(foo.ts, 2, 8)) +>arr : Symbol(arr, Decl(foo.ts, 2, 13)) + +=== tests/cases/compiler/index.ts === +import { foo, arr } from './foo'; +>foo : Symbol(foo, Decl(index.ts, 0, 8)) +>arr : Symbol(arr, Decl(index.ts, 0, 13)) + +export { foo, arr }; +>foo : Symbol(foo, Decl(index.ts, 1, 8)) +>arr : Symbol(arr, Decl(index.ts, 1, 13)) + +const { bar: baz, bat, bam: { bork: { bar: ibar, baz: ibaz } } } = foo; +>bar : Symbol(bar, Decl(foo.ts, 0, 13)) +>baz : Symbol(baz, Decl(index.ts, 3, 7)) +>bat : Symbol(bat, Decl(index.ts, 3, 17)) +>bam : Symbol(bam, Decl(foo.ts, 0, 41)) +>bork : Symbol(bork, Decl(foo.ts, 0, 48)) +>bar : Symbol(bar, Decl(foo.ts, 0, 56)) +>ibar : Symbol(ibar, Decl(index.ts, 3, 37)) +>baz : Symbol(baz, Decl(foo.ts, 0, 66)) +>ibaz : Symbol(ibaz, Decl(index.ts, 3, 48)) +>foo : Symbol(foo, Decl(index.ts, 0, 8)) + +export { baz, ibaz }; +>baz : Symbol(baz, Decl(index.ts, 4, 8)) +>ibaz : Symbol(ibaz, Decl(index.ts, 4, 13)) + +const [ , one, , [, bee, , [, {sec} ]]] = arr; +>one : Symbol(one, Decl(index.ts, 6, 9)) +>bee : Symbol(bee, Decl(index.ts, 6, 19)) +>sec : Symbol(sec, Decl(index.ts, 6, 31)) +>arr : Symbol(arr, Decl(index.ts, 0, 13)) + +export { one, bee, sec }; +>one : Symbol(one, Decl(index.ts, 7, 8)) +>bee : Symbol(bee, Decl(index.ts, 7, 13)) +>sec : Symbol(sec, Decl(index.ts, 7, 18)) + +const getFoo = () => ({ +>getFoo : Symbol(getFoo, Decl(index.ts, 9, 5)) + + foo: 'foo' +>foo : Symbol(foo, Decl(index.ts, 9, 23)) + +}); + +const { foo: foo2 } = getFoo(); +>foo : Symbol(foo, Decl(index.ts, 9, 23)) +>foo2 : Symbol(foo2, Decl(index.ts, 13, 7)) +>getFoo : Symbol(getFoo, Decl(index.ts, 9, 5)) + +export { foo2 }; +>foo2 : Symbol(foo2, Decl(index.ts, 14, 8)) + diff --git a/tests/baselines/reference/destructuredDeclarationEmit.types b/tests/baselines/reference/destructuredDeclarationEmit.types new file mode 100644 index 00000000000..94845f94885 --- /dev/null +++ b/tests/baselines/reference/destructuredDeclarationEmit.types @@ -0,0 +1,103 @@ +=== tests/cases/compiler/foo.ts === +const foo = { bar: 'hello', bat: 'world', bam: { bork: { bar: 'a', baz: 'b' } } }; +>foo : { bar: string; bat: string; bam: { bork: { bar: string; baz: string; }; }; } +>{ bar: 'hello', bat: 'world', bam: { bork: { bar: 'a', baz: 'b' } } } : { bar: string; bat: string; bam: { bork: { bar: string; baz: string; }; }; } +>bar : string +>'hello' : "hello" +>bat : string +>'world' : "world" +>bam : { bork: { bar: string; baz: string; }; } +>{ bork: { bar: 'a', baz: 'b' } } : { bork: { bar: string; baz: string; }; } +>bork : { bar: string; baz: string; } +>{ bar: 'a', baz: 'b' } : { bar: string; baz: string; } +>bar : string +>'a' : "a" +>baz : string +>'b' : "b" + +const arr: [0, 1, 2, ['a', 'b', 'c', [{def: 'def'}, {sec: 'sec'}]]] = [0, 1, 2, ['a', 'b', 'c', [{def: 'def'}, {sec: 'sec'}]]]; +>arr : [0, 1, 2, ["a", "b", "c", [{ def: "def"; }, { sec: "sec"; }]]] +>def : "def" +>sec : "sec" +>[0, 1, 2, ['a', 'b', 'c', [{def: 'def'}, {sec: 'sec'}]]] : [0, 1, 2, ["a", "b", "c", [{ def: "def"; }, { sec: "sec"; }]]] +>0 : 0 +>1 : 1 +>2 : 2 +>['a', 'b', 'c', [{def: 'def'}, {sec: 'sec'}]] : ["a", "b", "c", [{ def: "def"; }, { sec: "sec"; }]] +>'a' : "a" +>'b' : "b" +>'c' : "c" +>[{def: 'def'}, {sec: 'sec'}] : [{ def: "def"; }, { sec: "sec"; }] +>{def: 'def'} : { def: "def"; } +>def : string +>'def' : "def" +>{sec: 'sec'} : { sec: "sec"; } +>sec : string +>'sec' : "sec" + +export { foo, arr }; +>foo : { bar: string; bat: string; bam: { bork: { bar: string; baz: string; }; }; } +>arr : [0, 1, 2, ["a", "b", "c", [{ def: "def"; }, { sec: "sec"; }]]] + +=== tests/cases/compiler/index.ts === +import { foo, arr } from './foo'; +>foo : { bar: string; bat: string; bam: { bork: { bar: string; baz: string; }; }; } +>arr : [0, 1, 2, ["a", "b", "c", [{ def: "def"; }, { sec: "sec"; }]]] + +export { foo, arr }; +>foo : { bar: string; bat: string; bam: { bork: { bar: string; baz: string; }; }; } +>arr : [0, 1, 2, ["a", "b", "c", [{ def: "def"; }, { sec: "sec"; }]]] + +const { bar: baz, bat, bam: { bork: { bar: ibar, baz: ibaz } } } = foo; +>bar : any +>baz : string +>bat : string +>bam : any +>bork : any +>bar : any +>ibar : string +>baz : any +>ibaz : string +>foo : { bar: string; bat: string; bam: { bork: { bar: string; baz: string; }; }; } + +export { baz, ibaz }; +>baz : string +>ibaz : string + +const [ , one, , [, bee, , [, {sec} ]]] = arr; +> : undefined +>one : 1 +> : undefined +> : undefined +>bee : "b" +> : undefined +> : undefined +>sec : "sec" +>arr : [0, 1, 2, ["a", "b", "c", [{ def: "def"; }, { sec: "sec"; }]]] + +export { one, bee, sec }; +>one : 1 +>bee : "b" +>sec : "sec" + +const getFoo = () => ({ +>getFoo : () => { foo: string; } +>() => ({ foo: 'foo'}) : () => { foo: string; } +>({ foo: 'foo'}) : { foo: string; } +>{ foo: 'foo'} : { foo: string; } + + foo: 'foo' +>foo : string +>'foo' : "foo" + +}); + +const { foo: foo2 } = getFoo(); +>foo : any +>foo2 : string +>getFoo() : { foo: string; } +>getFoo : () => { foo: string; } + +export { foo2 }; +>foo2 : string + diff --git a/tests/baselines/reference/initializedParameterBeforeNonoptionalNotOptional.js b/tests/baselines/reference/initializedParameterBeforeNonoptionalNotOptional.js new file mode 100644 index 00000000000..8a6a602d6d7 --- /dev/null +++ b/tests/baselines/reference/initializedParameterBeforeNonoptionalNotOptional.js @@ -0,0 +1,11 @@ +//// [initializedParameterBeforeNonoptionalNotOptional.ts] +export declare function foo({a}?: { + a?: string; +}): void; +export declare function foo2({a}: { + a?: string | undefined; +} | undefined, b: string): void; + +//// [initializedParameterBeforeNonoptionalNotOptional.js] +"use strict"; +exports.__esModule = true; diff --git a/tests/baselines/reference/initializedParameterBeforeNonoptionalNotOptional.symbols b/tests/baselines/reference/initializedParameterBeforeNonoptionalNotOptional.symbols new file mode 100644 index 00000000000..9e91e2bd3aa --- /dev/null +++ b/tests/baselines/reference/initializedParameterBeforeNonoptionalNotOptional.symbols @@ -0,0 +1,34 @@ +=== tests/cases/compiler/index.d.ts === +export declare function foo({a}?: { +>foo : Symbol(foo, Decl(index.d.ts, 0, 0)) +>a : Symbol(a, Decl(index.d.ts, 0, 29)) + + a?: string; +>a : Symbol(a, Decl(index.d.ts, 0, 35)) + +}): void; +export declare function foo2({a}: { +>foo2 : Symbol(foo2, Decl(index.d.ts, 2, 9)) +>a : Symbol(a, Decl(index.d.ts, 3, 30)) + + a?: string | undefined; +>a : Symbol(a, Decl(index.d.ts, 3, 35)) + +} | undefined, b: string): void; +>b : Symbol(b, Decl(index.d.ts, 5, 14)) + +export declare function foo3({a, b: {c}}: { +>foo3 : Symbol(foo3, Decl(index.d.ts, 5, 32)) +>a : Symbol(a, Decl(index.d.ts, 6, 30)) +>c : Symbol(c, Decl(index.d.ts, 6, 37)) + + a?: string | undefined; +>a : Symbol(a, Decl(index.d.ts, 6, 43)) + + b?: {c?: string | undefined;} | undefined; +>b : Symbol(b, Decl(index.d.ts, 7, 27)) +>c : Symbol(c, Decl(index.d.ts, 8, 9)) + +} | undefined, b: string): void; +>b : Symbol(b, Decl(index.d.ts, 9, 14)) + diff --git a/tests/baselines/reference/initializedParameterBeforeNonoptionalNotOptional.types b/tests/baselines/reference/initializedParameterBeforeNonoptionalNotOptional.types new file mode 100644 index 00000000000..798b5268337 --- /dev/null +++ b/tests/baselines/reference/initializedParameterBeforeNonoptionalNotOptional.types @@ -0,0 +1,35 @@ +=== tests/cases/compiler/index.d.ts === +export declare function foo({a}?: { +>foo : ({ a }?: { a?: string | undefined; } | undefined) => void +>a : string | undefined + + a?: string; +>a : string | undefined + +}): void; +export declare function foo2({a}: { +>foo2 : ({ a }: { a?: string | undefined; } | undefined, b: string) => void +>a : string | undefined + + a?: string | undefined; +>a : string | undefined + +} | undefined, b: string): void; +>b : string + +export declare function foo3({a, b: {c}}: { +>foo3 : ({ a, b: { c } }: { a?: string | undefined; b?: { c?: string | undefined; } | undefined; } | undefined, b: string) => void +>a : string | undefined +>b : any +>c : string | undefined + + a?: string | undefined; +>a : string | undefined + + b?: {c?: string | undefined;} | undefined; +>b : { c?: string | undefined; } | undefined +>c : string | undefined + +} | undefined, b: string): void; +>b : string + diff --git a/tests/baselines/reference/jsdocIllegalTags.errors.txt b/tests/baselines/reference/jsdocIllegalTags.errors.txt new file mode 100644 index 00000000000..485d01b12d9 --- /dev/null +++ b/tests/baselines/reference/jsdocIllegalTags.errors.txt @@ -0,0 +1,18 @@ +/a.js(2,19): error TS1092: Type parameters cannot appear on a constructor declaration. +/a.js(6,18): error TS1093: Type annotation cannot appear on a constructor declaration. + + +==== /a.js (2 errors) ==== + class C { + /** @template T */ + ~ +!!! error TS1092: Type parameters cannot appear on a constructor declaration. + constructor() { } + } + class D { + /** @return {number} */ + ~~~~~~ +!!! error TS1093: Type annotation cannot appear on a constructor declaration. + constructor() {} + } + \ No newline at end of file diff --git a/tests/baselines/reference/jsdocIllegalTags.symbols b/tests/baselines/reference/jsdocIllegalTags.symbols new file mode 100644 index 00000000000..615bdc2facd --- /dev/null +++ b/tests/baselines/reference/jsdocIllegalTags.symbols @@ -0,0 +1,14 @@ +=== /a.js === +class C { +>C : Symbol(C, Decl(a.js, 0, 0)) + + /** @template T */ + constructor() { } +} +class D { +>D : Symbol(D, Decl(a.js, 3, 1)) + + /** @return {number} */ + constructor() {} +} + diff --git a/tests/baselines/reference/jsdocIllegalTags.types b/tests/baselines/reference/jsdocIllegalTags.types new file mode 100644 index 00000000000..c40302f11d3 --- /dev/null +++ b/tests/baselines/reference/jsdocIllegalTags.types @@ -0,0 +1,14 @@ +=== /a.js === +class C { +>C : C + + /** @template T */ + constructor() { } +} +class D { +>D : D + + /** @return {number} */ + constructor() {} +} + diff --git a/tests/baselines/reference/mutuallyRecursiveInterfaceDeclaration.js b/tests/baselines/reference/mutuallyRecursiveInterfaceDeclaration.js new file mode 100644 index 00000000000..567cb71cafb --- /dev/null +++ b/tests/baselines/reference/mutuallyRecursiveInterfaceDeclaration.js @@ -0,0 +1,23 @@ +//// [mutuallyRecursiveInterfaceDeclaration.ts] +interface A { + b: B +} + +interface B { + a: A +} +export {A, B} + +//// [mutuallyRecursiveInterfaceDeclaration.js] +"use strict"; +exports.__esModule = true; + + +//// [mutuallyRecursiveInterfaceDeclaration.d.ts] +interface A { + b: B; +} +interface B { + a: A; +} +export { A, B }; diff --git a/tests/baselines/reference/mutuallyRecursiveInterfaceDeclaration.symbols b/tests/baselines/reference/mutuallyRecursiveInterfaceDeclaration.symbols new file mode 100644 index 00000000000..b0ac456859c --- /dev/null +++ b/tests/baselines/reference/mutuallyRecursiveInterfaceDeclaration.symbols @@ -0,0 +1,20 @@ +=== tests/cases/compiler/mutuallyRecursiveInterfaceDeclaration.ts === +interface A { +>A : Symbol(A, Decl(mutuallyRecursiveInterfaceDeclaration.ts, 0, 0)) + + b: B +>b : Symbol(A.b, Decl(mutuallyRecursiveInterfaceDeclaration.ts, 0, 13)) +>B : Symbol(B, Decl(mutuallyRecursiveInterfaceDeclaration.ts, 2, 1)) +} + +interface B { +>B : Symbol(B, Decl(mutuallyRecursiveInterfaceDeclaration.ts, 2, 1)) + + a: A +>a : Symbol(B.a, Decl(mutuallyRecursiveInterfaceDeclaration.ts, 4, 13)) +>A : Symbol(A, Decl(mutuallyRecursiveInterfaceDeclaration.ts, 0, 0)) +} +export {A, B} +>A : Symbol(A, Decl(mutuallyRecursiveInterfaceDeclaration.ts, 7, 8)) +>B : Symbol(B, Decl(mutuallyRecursiveInterfaceDeclaration.ts, 7, 10)) + diff --git a/tests/baselines/reference/mutuallyRecursiveInterfaceDeclaration.types b/tests/baselines/reference/mutuallyRecursiveInterfaceDeclaration.types new file mode 100644 index 00000000000..807687160b2 --- /dev/null +++ b/tests/baselines/reference/mutuallyRecursiveInterfaceDeclaration.types @@ -0,0 +1,20 @@ +=== tests/cases/compiler/mutuallyRecursiveInterfaceDeclaration.ts === +interface A { +>A : A + + b: B +>b : B +>B : B +} + +interface B { +>B : B + + a: A +>a : A +>A : A +} +export {A, B} +>A : any +>B : any + diff --git a/tests/baselines/reference/parenthesizedAsyncArrowFunction.js b/tests/baselines/reference/parenthesizedAsyncArrowFunction.js new file mode 100644 index 00000000000..1f2cbc722e0 --- /dev/null +++ b/tests/baselines/reference/parenthesizedAsyncArrowFunction.js @@ -0,0 +1,47 @@ +//// [parenthesizedAsyncArrowFunction.ts] +// Repro from #20096 + +let foo = (async bar => bar); + + +//// [parenthesizedAsyncArrowFunction.js] +// Repro from #20096 +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [0, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +var _this = this; +var foo = (function (bar) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { + return [2 /*return*/, bar]; +}); }); }); diff --git a/tests/baselines/reference/parenthesizedAsyncArrowFunction.symbols b/tests/baselines/reference/parenthesizedAsyncArrowFunction.symbols new file mode 100644 index 00000000000..a6428c3e998 --- /dev/null +++ b/tests/baselines/reference/parenthesizedAsyncArrowFunction.symbols @@ -0,0 +1,8 @@ +=== tests/cases/compiler/parenthesizedAsyncArrowFunction.ts === +// Repro from #20096 + +let foo = (async bar => bar); +>foo : Symbol(foo, Decl(parenthesizedAsyncArrowFunction.ts, 2, 3)) +>bar : Symbol(bar, Decl(parenthesizedAsyncArrowFunction.ts, 2, 16)) +>bar : Symbol(bar, Decl(parenthesizedAsyncArrowFunction.ts, 2, 16)) + diff --git a/tests/baselines/reference/parenthesizedAsyncArrowFunction.types b/tests/baselines/reference/parenthesizedAsyncArrowFunction.types new file mode 100644 index 00000000000..cb1461764cb --- /dev/null +++ b/tests/baselines/reference/parenthesizedAsyncArrowFunction.types @@ -0,0 +1,10 @@ +=== tests/cases/compiler/parenthesizedAsyncArrowFunction.ts === +// Repro from #20096 + +let foo = (async bar => bar); +>foo : (bar: any) => Promise +>(async bar => bar) : (bar: any) => Promise +>async bar => bar : (bar: any) => Promise +>bar : any +>bar : any + diff --git a/tests/cases/compiler/destructuredDeclarationEmit.ts b/tests/cases/compiler/destructuredDeclarationEmit.ts new file mode 100644 index 00000000000..99435aff5b1 --- /dev/null +++ b/tests/cases/compiler/destructuredDeclarationEmit.ts @@ -0,0 +1,21 @@ +// @declaration: true +// @filename: foo.ts +const foo = { bar: 'hello', bat: 'world', bam: { bork: { bar: 'a', baz: 'b' } } }; +const arr: [0, 1, 2, ['a', 'b', 'c', [{def: 'def'}, {sec: 'sec'}]]] = [0, 1, 2, ['a', 'b', 'c', [{def: 'def'}, {sec: 'sec'}]]]; +export { foo, arr }; +// @filename: index.ts +import { foo, arr } from './foo'; +export { foo, arr }; + +const { bar: baz, bat, bam: { bork: { bar: ibar, baz: ibaz } } } = foo; +export { baz, ibaz }; + +const [ , one, , [, bee, , [, {sec} ]]] = arr; +export { one, bee, sec }; + +const getFoo = () => ({ + foo: 'foo' +}); + +const { foo: foo2 } = getFoo(); +export { foo2 }; diff --git a/tests/cases/compiler/initializedParameterBeforeNonoptionalNotOptional.ts b/tests/cases/compiler/initializedParameterBeforeNonoptionalNotOptional.ts new file mode 100644 index 00000000000..327849ae80e --- /dev/null +++ b/tests/cases/compiler/initializedParameterBeforeNonoptionalNotOptional.ts @@ -0,0 +1,12 @@ +// @strict: true +// @filename: index.d.ts +export declare function foo({a}?: { + a?: string; +}): void; +export declare function foo2({a}: { + a?: string | undefined; +} | undefined, b: string): void; +export declare function foo3({a, b: {c}}: { + a?: string | undefined; + b?: {c?: string | undefined;} | undefined; +} | undefined, b: string): void; \ No newline at end of file diff --git a/tests/cases/compiler/jsdocIllegalTags.ts b/tests/cases/compiler/jsdocIllegalTags.ts new file mode 100644 index 00000000000..a59a70dda87 --- /dev/null +++ b/tests/cases/compiler/jsdocIllegalTags.ts @@ -0,0 +1,13 @@ +// @allowJs: true +// @checkJs: true +// @noEmit: true +// @Filename: /a.js + +class C { + /** @template T */ + constructor() { } +} +class D { + /** @return {number} */ + constructor() {} +} diff --git a/tests/cases/compiler/mutuallyRecursiveInterfaceDeclaration.ts b/tests/cases/compiler/mutuallyRecursiveInterfaceDeclaration.ts new file mode 100644 index 00000000000..e9609605c69 --- /dev/null +++ b/tests/cases/compiler/mutuallyRecursiveInterfaceDeclaration.ts @@ -0,0 +1,9 @@ +// @declaration: true +interface A { + b: B +} + +interface B { + a: A +} +export {A, B} \ No newline at end of file diff --git a/tests/cases/compiler/parenthesizedAsyncArrowFunction.ts b/tests/cases/compiler/parenthesizedAsyncArrowFunction.ts new file mode 100644 index 00000000000..00c1aca6533 --- /dev/null +++ b/tests/cases/compiler/parenthesizedAsyncArrowFunction.ts @@ -0,0 +1,3 @@ +// Repro from #20096 + +let foo = (async bar => bar); diff --git a/tests/cases/fourslash/completionListIsGlobalCompletion.ts b/tests/cases/fourslash/completionListIsGlobalCompletion.ts index 49196bdabd4..121ab940d65 100644 --- a/tests/cases/fourslash/completionListIsGlobalCompletion.ts +++ b/tests/cases/fourslash/completionListIsGlobalCompletion.ts @@ -47,7 +47,7 @@ verify.completionListIsGlobal(true); goTo.marker("6"); verify.completionListIsGlobal(false); goTo.marker("7"); -verify.completionListIsGlobal(false); +verify.completionListIsGlobal(true); goTo.marker("8"); verify.completionListIsGlobal(false); goTo.marker("9"); diff --git a/tests/cases/fourslash/completionsImport_default_alreadyExistedWithRename.ts b/tests/cases/fourslash/completionsImport_default_alreadyExistedWithRename.ts index d8cb53167f5..c8908ab2ebd 100644 --- a/tests/cases/fourslash/completionsImport_default_alreadyExistedWithRename.ts +++ b/tests/cases/fourslash/completionsImport_default_alreadyExistedWithRename.ts @@ -16,7 +16,7 @@ verify.completionListContains({ name: "foo", source: "/a" }, "function foo(): vo verify.applyCodeActionFromCompletion("", { name: "foo", source: "/a", - description: `Import 'foo' from "./a".`, + description: `Import 'foo' from module "./a".`, // TODO: GH#18445 newFileContent: `import f_o_o from "./a"; import foo from "./a";\r diff --git a/tests/cases/fourslash/completionsImport_default_anonymous.ts b/tests/cases/fourslash/completionsImport_default_anonymous.ts index 4be0184d9fa..297567d1c19 100644 --- a/tests/cases/fourslash/completionsImport_default_anonymous.ts +++ b/tests/cases/fourslash/completionsImport_default_anonymous.ts @@ -21,7 +21,7 @@ verify.completionListContains({ name: "fooBar", source: "/src/foo-bar" }, "(prop verify.applyCodeActionFromCompletion("1", { name: "fooBar", source: "/src/foo-bar", - description: `Import 'fooBar' from "./foo-bar".`, + description: `Import 'fooBar' from module "./foo-bar".`, // TODO: GH#18445 newFileContent: `import fooBar from "./foo-bar";\r \r diff --git a/tests/cases/fourslash/completionsImport_default_didNotExistBefore.ts b/tests/cases/fourslash/completionsImport_default_didNotExistBefore.ts index a4f943f68ee..dcdffc10907 100644 --- a/tests/cases/fourslash/completionsImport_default_didNotExistBefore.ts +++ b/tests/cases/fourslash/completionsImport_default_didNotExistBefore.ts @@ -17,7 +17,7 @@ verify.completionListContains({ name: "foo", source: "/a" }, "function foo(): vo verify.applyCodeActionFromCompletion("", { name: "foo", source: "/a", - description: `Import 'foo' from "./a".`, + description: `Import 'foo' from module "./a".`, // TODO: GH#18445 newFileContent: `import foo from "./a";\r \r diff --git a/tests/cases/fourslash/completionsImport_fromAmbientModule.ts b/tests/cases/fourslash/completionsImport_fromAmbientModule.ts index 05e7601c690..3b202ee33d6 100644 --- a/tests/cases/fourslash/completionsImport_fromAmbientModule.ts +++ b/tests/cases/fourslash/completionsImport_fromAmbientModule.ts @@ -11,7 +11,7 @@ verify.applyCodeActionFromCompletion("", { name: "x", source: "m", - description: `Import 'x' from "m".`, + description: `Import 'x' from module "m".`, // TODO: GH#18445 newFileContent: `import { x } from "m";\r \r diff --git a/tests/cases/fourslash/completionsImport_multipleWithSameName.ts b/tests/cases/fourslash/completionsImport_multipleWithSameName.ts index 81a054e3d23..50f20d60bf2 100644 --- a/tests/cases/fourslash/completionsImport_multipleWithSameName.ts +++ b/tests/cases/fourslash/completionsImport_multipleWithSameName.ts @@ -22,7 +22,7 @@ verify.completionListContains({ name: "foo", source: "/b" }, "const foo: 1", "", verify.applyCodeActionFromCompletion("", { name: "foo", source: "/b", - description: `Import 'foo' from "./b".`, + description: `Import 'foo' from module "./b".`, // TODO: GH#18445 newFileContent: `import { foo } from "./b";\r \r diff --git a/tests/cases/fourslash/completionsImport_named_namespaceImportExists.ts b/tests/cases/fourslash/completionsImport_named_namespaceImportExists.ts index 17b909b48ed..4f547259ee8 100644 --- a/tests/cases/fourslash/completionsImport_named_namespaceImportExists.ts +++ b/tests/cases/fourslash/completionsImport_named_namespaceImportExists.ts @@ -16,7 +16,7 @@ verify.completionListContains({ name: "foo", source: "/a" }, "function foo(): vo verify.applyCodeActionFromCompletion("", { name: "foo", source: "/a", - description: `Import 'foo' from "./a".`, + description: `Import 'foo' from module "./a".`, // TODO: GH#18445 newFileContent: `import * as a from "./a"; import { foo } from "./a";\r diff --git a/tests/cases/fourslash/completionsImport_ofAlias.ts b/tests/cases/fourslash/completionsImport_ofAlias.ts index cb4f1255a3e..1eb730df84f 100644 --- a/tests/cases/fourslash/completionsImport_ofAlias.ts +++ b/tests/cases/fourslash/completionsImport_ofAlias.ts @@ -28,7 +28,7 @@ verify.not.completionListContains({ name: "foo", source: "/a_reexport_2" }, unde verify.applyCodeActionFromCompletion("", { name: "foo", source: "/a", - description: `Import 'foo' from "./a".`, + description: `Import 'foo' from module "./a".`, // TODO: GH#18445 newFileContent: `import { foo } from "./a";\r \r diff --git a/tests/cases/fourslash/completionsImport_ofAlias_preferShortPath.ts b/tests/cases/fourslash/completionsImport_ofAlias_preferShortPath.ts index a1eba5981db..fae8a4abf52 100644 --- a/tests/cases/fourslash/completionsImport_ofAlias_preferShortPath.ts +++ b/tests/cases/fourslash/completionsImport_ofAlias_preferShortPath.ts @@ -23,7 +23,7 @@ verify.not.completionListContains({ name: "foo", source: "/foo/index" }, undefin verify.applyCodeActionFromCompletion("", { name: "foo", source: "/foo/lib/foo", - description: `Import 'foo' from "./foo".`, + description: `Import 'foo' from module "./foo".`, // TODO: GH#18445 newFileContent: `import { foo } from "./foo";\r \r diff --git a/tests/cases/fourslash/completionsImport_require.ts b/tests/cases/fourslash/completionsImport_require.ts index 8ec750d2c48..2913bac27b0 100644 --- a/tests/cases/fourslash/completionsImport_require.ts +++ b/tests/cases/fourslash/completionsImport_require.ts @@ -22,7 +22,7 @@ verify.completionListContains({ name: "foo", source: "/a" }, "const foo: 0", "", verify.applyCodeActionFromCompletion("b", { name: "foo", source: "/a", - description: `Import 'foo' from "./a".`, + description: `Import 'foo' from module "./a".`, // TODO: GH#18445 newFileContent: `import { foo } from "./a";\r \r @@ -39,7 +39,7 @@ verify.completionListContains({ name: "foo", source: "/a" }, "const foo: 0", "", verify.applyCodeActionFromCompletion("c", { name: "foo", source: "/a", - description: `Import 'foo' from "./a".`, + description: `Import 'foo' from module "./a".`, // TODO: GH#18445 newFileContent: `import { foo } from "./a";\r \r diff --git a/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration_inheritance.ts b/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration_inheritance.ts new file mode 100644 index 00000000000..3002cd4d3e7 --- /dev/null +++ b/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration_inheritance.ts @@ -0,0 +1,31 @@ +/// + +////class C { +//// constructor(public [|{| "isWriteAccess": true, "isDefinition": true |}x|]: string) { +//// [|x|]; +//// } +////} +////class D extends C { +//// constructor(public [|{| "isWriteAccess": true, "isDefinition": true |}x|]: string) { +//// super([|x|]); +//// } +////} + +const [r0, r1, r2, r3] = test.ranges(); +verify.referenceGroups(r0, [ + { definition: "(property) C.x: string", ranges: [r0, r2, r3] }, + { definition: "(parameter) x: string", ranges: [r1] }, +]); +verify.referenceGroups(r1, [ + { definition: "(property) C.x: string", ranges: [r0] }, + { definition: "(parameter) x: string", ranges: [r1] }, +]); +verify.referenceGroups(r2, [ + { definition: "(property) C.x: string", ranges: [r0, r1] }, + { definition: "(property) D.x: string", ranges: [r2] }, + { definition: "(parameter) x: string", ranges: [r3] }, +]); +verify.referenceGroups(r3, [ + { definition: "(property) D.x: string", ranges: [r2] }, + { definition: "(parameter) x: string", ranges: [r3] }, +]); diff --git a/tests/cases/fourslash/getOutliningSpans.ts b/tests/cases/fourslash/getOutliningSpans.ts index 4e2a58c9acb..63e8becfc4f 100644 --- a/tests/cases/fourslash/getOutliningSpans.ts +++ b/tests/cases/fourslash/getOutliningSpans.ts @@ -1,6 +1,6 @@ /// -////// interface +////// interface ////interface IFoo[| { //// getDist(): number; ////}|] @@ -63,9 +63,9 @@ ////}|]) //// ////// trivia handeling -////class ClassFooWithTrivia[| /* some comments */ +////class ClassFooWithTrivia[| /* some comments */ //// /* more trivia */ { -//// +//// //// //// /*some trailing trivia */ ////}|] /* even more */ @@ -85,8 +85,8 @@ //// [ //// [ //// [ -//// 1,2,3 -//// ] +//// 1,2,3 +//// ] //// ] //// ] //// ] diff --git a/tests/cases/fourslash/importNameCodeFixNewImportBaseUrl0.ts b/tests/cases/fourslash/importNameCodeFixNewImportBaseUrl0.ts index a48b381df68..bc852b5c47c 100644 --- a/tests/cases/fourslash/importNameCodeFixNewImportBaseUrl0.ts +++ b/tests/cases/fourslash/importNameCodeFixNewImportBaseUrl0.ts @@ -13,6 +13,9 @@ //// export function f1() { }; verify.importFixAtPosition([ +`import { f1 } from "./a/b"; + +f1();`, `import { f1 } from "b"; f1();` diff --git a/tests/cases/fourslash/importNameCodeFixNewImportBaseUrl1.ts b/tests/cases/fourslash/importNameCodeFixNewImportBaseUrl1.ts new file mode 100644 index 00000000000..e690cfd3dbb --- /dev/null +++ b/tests/cases/fourslash/importNameCodeFixNewImportBaseUrl1.ts @@ -0,0 +1,25 @@ +/// + +// @Filename: /tsconfig.json +////{ +//// "compilerOptions": { +//// "baseUrl": "./a" +//// } +////} + +// @Filename: /a/b/x.ts +////export function f1() { }; + +// @Filename: /a/b/y.ts +////[|f1/*0*/();|] + +goTo.file("/a/b/y.ts"); +// Order the local import first because it's simpler. +verify.importFixAtPosition([ +`import { f1 } from "./x"; + +f1();`, +`import { f1 } from "b/x"; + +f1();` +]); diff --git a/tests/cases/fourslash/importNameCodeFixNewImportBaseUrl2.ts b/tests/cases/fourslash/importNameCodeFixNewImportBaseUrl2.ts new file mode 100644 index 00000000000..658bd25823f --- /dev/null +++ b/tests/cases/fourslash/importNameCodeFixNewImportBaseUrl2.ts @@ -0,0 +1,25 @@ +/// + +// @Filename: /tsconfig.json +////{ +//// "compilerOptions": { +//// "baseUrl": "./a" +//// } +////} + +// @Filename: /a/b/x.ts +////export function f1() { }; + +// @Filename: /a/c/y.ts +////[|f1/*0*/();|] + +goTo.file("/a/c/y.ts"); +// Order the baseUrl import first, because the relative import climbs up to the base url. +verify.importFixAtPosition([ +`import { f1 } from "b/x"; + +f1();`, +`import { f1 } from "../b/x"; + +f1();` +]); diff --git a/tests/cases/fourslash/importNameCodeFixShebang.ts b/tests/cases/fourslash/importNameCodeFixShebang.ts new file mode 100644 index 00000000000..1ef7be11625 --- /dev/null +++ b/tests/cases/fourslash/importNameCodeFixShebang.ts @@ -0,0 +1,18 @@ +/// + +// @Filename: /a.ts +////export const foo = 0; + +// @Filename: /b.ts +////[|#!/usr/bin/env node +////foo/**/|] + +goTo.file("/a.ts"); +goTo.file("/b.ts"); + +verify.importFixAtPosition([ +`#!/usr/bin/env node +import { foo } from "./a"; + +foo`, +]); diff --git a/tests/cases/fourslash/quickInfoSpecialPropertyAssignment.ts b/tests/cases/fourslash/quickInfoSpecialPropertyAssignment.ts new file mode 100644 index 00000000000..817e68f6782 --- /dev/null +++ b/tests/cases/fourslash/quickInfoSpecialPropertyAssignment.ts @@ -0,0 +1,10 @@ +// @allowJs: true +// @Filename: /a.js +////class C { +//// constructor() { +//// /** Doc */ +//// this./**/x = 0; +//// } +////} + +verify.quickInfoAt("", "(property) C.x: number", "Doc "); diff --git a/tests/cases/fourslash/shims-pp/getOutliningSpans.ts b/tests/cases/fourslash/shims-pp/getOutliningSpans.ts index 4e2a58c9acb..63e8becfc4f 100644 --- a/tests/cases/fourslash/shims-pp/getOutliningSpans.ts +++ b/tests/cases/fourslash/shims-pp/getOutliningSpans.ts @@ -1,6 +1,6 @@ /// -////// interface +////// interface ////interface IFoo[| { //// getDist(): number; ////}|] @@ -63,9 +63,9 @@ ////}|]) //// ////// trivia handeling -////class ClassFooWithTrivia[| /* some comments */ +////class ClassFooWithTrivia[| /* some comments */ //// /* more trivia */ { -//// +//// //// //// /*some trailing trivia */ ////}|] /* even more */ @@ -85,8 +85,8 @@ //// [ //// [ //// [ -//// 1,2,3 -//// ] +//// 1,2,3 +//// ] //// ] //// ] //// ] diff --git a/tests/cases/fourslash/shims/getOutliningSpans.ts b/tests/cases/fourslash/shims/getOutliningSpans.ts index 4e2a58c9acb..63e8becfc4f 100644 --- a/tests/cases/fourslash/shims/getOutliningSpans.ts +++ b/tests/cases/fourslash/shims/getOutliningSpans.ts @@ -1,6 +1,6 @@ /// -////// interface +////// interface ////interface IFoo[| { //// getDist(): number; ////}|] @@ -63,9 +63,9 @@ ////}|]) //// ////// trivia handeling -////class ClassFooWithTrivia[| /* some comments */ +////class ClassFooWithTrivia[| /* some comments */ //// /* more trivia */ { -//// +//// //// //// /*some trailing trivia */ ////}|] /* even more */ @@ -85,8 +85,8 @@ //// [ //// [ //// [ -//// 1,2,3 -//// ] +//// 1,2,3 +//// ] //// ] //// ] //// ]