Skip to content

Commit de388ca

Browse files
author
Andy Hanson
committed
Merge branch 'master' into index
2 parents db8755a + 34a5589 commit de388ca

12 files changed

+112
-23
lines changed

src/compiler/checker.ts

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2156,6 +2156,11 @@ namespace ts {
21562156
return false;
21572157
}
21582158

2159+
function isTypeSymbolAccessible(typeSymbol: Symbol, enclosingDeclaration: Node): boolean {
2160+
const access = isSymbolAccessible(typeSymbol, enclosingDeclaration, SymbolFlags.Type, /*shouldComputeAliasesToMakeVisible*/ false);
2161+
return access.accessibility === SymbolAccessibility.Accessible;
2162+
}
2163+
21592164
/**
21602165
* Check if the given symbol in given enclosing declaration is accessible and mark all associated alias to be visible if requested
21612166
*
@@ -2486,8 +2491,7 @@ namespace ts {
24862491
// Ignore constraint/default when creating a usage (as opposed to declaration) of a type parameter.
24872492
return createTypeReferenceNode(name, /*typeArguments*/ undefined);
24882493
}
2489-
if (!inTypeAlias && type.aliasSymbol &&
2490-
isSymbolAccessible(type.aliasSymbol, context.enclosingDeclaration, SymbolFlags.Type, /*shouldComputeAliasesToMakeVisible*/ false).accessibility === SymbolAccessibility.Accessible) {
2494+
if (!inTypeAlias && type.aliasSymbol && isTypeSymbolAccessible(type.aliasSymbol, context.enclosingDeclaration)) {
24912495
const name = symbolToTypeReferenceName(type.aliasSymbol);
24922496
const typeArgumentNodes = mapToTypeNodes(type.aliasTypeArguments, context);
24932497
return createTypeReferenceNode(name, typeArgumentNodes);
@@ -3254,7 +3258,7 @@ namespace ts {
32543258
buildSymbolDisplay(type.symbol, writer, enclosingDeclaration, SymbolFlags.Type, SymbolFormatFlags.None, nextFlags);
32553259
}
32563260
else if (!(flags & TypeFormatFlags.InTypeAlias) && type.aliasSymbol &&
3257-
isSymbolAccessible(type.aliasSymbol, enclosingDeclaration, SymbolFlags.Type, /*shouldComputeAliasesToMakeVisible*/ false).accessibility === SymbolAccessibility.Accessible) {
3261+
((flags & TypeFormatFlags.UseAliasDefinedOutsideCurrentScope) || isTypeSymbolAccessible(type.aliasSymbol, enclosingDeclaration))) {
32583262
const typeArguments = type.aliasTypeArguments;
32593263
writeSymbolTypeReference(type.aliasSymbol, typeArguments, 0, length(typeArguments), nextFlags);
32603264
}
@@ -6578,6 +6582,10 @@ namespace ts {
65786582
return signature.resolvedReturnType;
65796583
}
65806584

6585+
function isResolvingReturnTypeOfSignature(signature: Signature) {
6586+
return !signature.resolvedReturnType && findResolutionCycleStartIndex(signature, TypeSystemPropertyName.ResolvedReturnType) >= 0;
6587+
}
6588+
65816589
function getRestTypeOfSignature(signature: Signature): Type {
65826590
if (signature.hasRestParameter) {
65836591
const type = getTypeOfSymbol(lastOrUndefined(signature.parameters));
@@ -12951,7 +12959,7 @@ namespace ts {
1295112959
// Otherwise, if the containing function is contextually typed by a function type with exactly one call signature
1295212960
// and that call signature is non-generic, return statements are contextually typed by the return type of the signature
1295312961
const signature = getContextualSignatureForFunctionLikeDeclaration(<FunctionExpression>functionDecl);
12954-
if (signature) {
12962+
if (signature && !isResolvingReturnTypeOfSignature(signature)) {
1295512963
return getReturnTypeOfSignature(signature);
1295612964
}
1295712965

@@ -22910,17 +22918,17 @@ namespace ts {
2291022918
// index access
2291122919
switch (node.parent.kind) {
2291222920
case SyntaxKind.ElementAccessExpression: {
22913-
if ((<ElementAccessExpression>node.parent).argumentExpression !== node) return undefined;
22921+
if ((<ElementAccessExpression>node.parent).argumentExpression !== node) {
22922+
return undefined;
22923+
}
2291422924
const objectType = getTypeOfExpression((<ElementAccessExpression>node.parent).expression);
22915-
if (objectType === unknownType) return undefined;
22916-
const apparentType = getApparentType(objectType);
22917-
if (apparentType === unknownType) return undefined;
22918-
return getPropertyOfType(apparentType, (<NumericLiteral>node).text as __String);
22925+
return getPropertyOfType(objectType, (<NumericLiteral>node).text as __String);
2291922926
}
2292022927
case SyntaxKind.LiteralType: {
22921-
if (!isIndexedAccessTypeNode(node.parent.parent)) return undefined;
22922-
const objectType = getApparentType(getTypeFromTypeNode(node.parent.parent.objectType));
22923-
if (objectType === unknownType) return undefined;
22928+
if (!isIndexedAccessTypeNode(node.parent.parent)) {
22929+
return undefined;
22930+
}
22931+
const objectType = getTypeFromTypeNode(node.parent.parent.objectType);
2292422932
return getPropertyOfType(objectType, escapeLeadingUnderscores((node as StringLiteral | NumericLiteral).text));
2292522933
}
2292622934
}

src/compiler/declarationEmitter.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,6 @@ namespace ts {
349349
errorNameNode = declaration.name;
350350
const format = TypeFormatFlags.UseTypeOfFunction |
351351
TypeFormatFlags.WriteClassExpressionAsTypeLiteral |
352-
TypeFormatFlags.UseTypeAliasValue |
353352
(shouldUseResolverType ? TypeFormatFlags.AddUndefined : 0);
354353
resolver.writeTypeOfDeclaration(declaration, enclosingDeclaration, format, writer);
355354
errorNameNode = undefined;
@@ -368,7 +367,7 @@ namespace ts {
368367
resolver.writeReturnTypeOfSignatureDeclaration(
369368
signature,
370369
enclosingDeclaration,
371-
TypeFormatFlags.UseTypeOfFunction | TypeFormatFlags.UseTypeAliasValue | TypeFormatFlags.WriteClassExpressionAsTypeLiteral,
370+
TypeFormatFlags.UseTypeOfFunction | TypeFormatFlags.WriteClassExpressionAsTypeLiteral,
372371
writer);
373372
errorNameNode = undefined;
374373
}
@@ -633,7 +632,7 @@ namespace ts {
633632
resolver.writeTypeOfExpression(
634633
expr,
635634
enclosingDeclaration,
636-
TypeFormatFlags.UseTypeOfFunction | TypeFormatFlags.UseTypeAliasValue | TypeFormatFlags.WriteClassExpressionAsTypeLiteral,
635+
TypeFormatFlags.UseTypeOfFunction | TypeFormatFlags.WriteClassExpressionAsTypeLiteral,
637636
writer);
638637
write(";");
639638
writeLine();

src/compiler/moduleNameResolver.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ namespace ts {
201201
let resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective | undefined;
202202
if (resolved) {
203203
if (!options.preserveSymlinks) {
204-
resolved = realpath(resolved, host, traceEnabled);
204+
resolved = realPath(resolved, host, traceEnabled);
205205
}
206206

207207
if (traceEnabled) {
@@ -741,7 +741,7 @@ namespace ts {
741741

742742
let resolvedValue = resolved.value;
743743
if (!compilerOptions.preserveSymlinks) {
744-
resolvedValue = resolvedValue && { ...resolved.value, path: realpath(resolved.value.path, host, traceEnabled), extension: resolved.value.extension };
744+
resolvedValue = resolvedValue && { ...resolved.value, path: realPath(resolved.value.path, host, traceEnabled), extension: resolved.value.extension };
745745
}
746746
// For node_modules lookups, get the real path so that multiple accesses to an `npm link`-ed module do not create duplicate files.
747747
return { value: resolvedValue && { resolved: resolvedValue, isExternalLibraryImport: true } };
@@ -754,7 +754,7 @@ namespace ts {
754754
}
755755
}
756756

757-
function realpath(path: string, host: ModuleResolutionHost, traceEnabled: boolean): string {
757+
function realPath(path: string, host: ModuleResolutionHost, traceEnabled: boolean): string {
758758
if (!host.realpath) {
759759
return path;
760760
}

src/compiler/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2717,11 +2717,12 @@ namespace ts {
27172717
UseFullyQualifiedType = 1 << 8, // Write out the fully qualified type name (eg. Module.Type, instead of Type)
27182718
InFirstTypeArgument = 1 << 9, // Writing first type argument of the instantiated type
27192719
InTypeAlias = 1 << 10, // Writing type in type alias declaration
2720-
UseTypeAliasValue = 1 << 11, // Serialize the type instead of using type-alias. This is needed when we emit declaration file.
27212720
SuppressAnyReturnType = 1 << 12, // If the return type is any-like, don't offer a return type.
27222721
AddUndefined = 1 << 13, // Add undefined to types of initialized, non-optional parameters
27232722
WriteClassExpressionAsTypeLiteral = 1 << 14, // Write a type literal instead of (Anonymous class)
27242723
InArrayType = 1 << 15, // Writing an array element type
2724+
UseAliasDefinedOutsideCurrentScope = 1 << 16, // For a `type T = ... ` defined in a different file, write `T` instead of its value,
2725+
// even though `T` can't be accessed in the current scope.
27252726
}
27262727

27272728
export const enum SymbolFormatFlags {

src/services/refactors/extractMethod.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -866,7 +866,7 @@ namespace ts.refactor.extractMethod {
866866
readonly node: Node;
867867
}
868868

869-
interface ScopeUsages {
869+
export interface ScopeUsages {
870870
usages: Map<UsageEntry>;
871871
substitutions: Map<Node>;
872872
}

src/services/textChanges.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ namespace ts.textChanges {
6464
*/
6565
export type ConfigurableStartEnd = ConfigurableStart & ConfigurableEnd;
6666

67-
interface InsertNodeOptions {
67+
export interface InsertNodeOptions {
6868
/**
6969
* Text to be inserted before the new node
7070
*/
@@ -96,7 +96,7 @@ namespace ts.textChanges {
9696
readonly range: TextRange;
9797
}
9898

99-
interface ChangeNodeOptions extends ConfigurableStartEnd, InsertNodeOptions {
99+
export interface ChangeNodeOptions extends ConfigurableStartEnd, InsertNodeOptions {
100100
readonly useIndentationFromFile?: boolean;
101101
}
102102
interface ReplaceWithSingleNode extends BaseChange {
@@ -111,7 +111,7 @@ namespace ts.textChanges {
111111
readonly options?: never;
112112
}
113113

114-
interface ChangeMultipleNodesOptions extends ChangeNodeOptions {
114+
export interface ChangeMultipleNodesOptions extends ChangeNodeOptions {
115115
nodeSeparator: string;
116116
}
117117
interface ReplaceWithMultipleNodes extends BaseChange {

src/services/utilities.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1259,6 +1259,7 @@ namespace ts {
12591259
}
12601260

12611261
export function signatureToDisplayParts(typechecker: TypeChecker, signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags): SymbolDisplayPart[] {
1262+
flags |= TypeFormatFlags.UseAliasDefinedOutsideCurrentScope;
12621263
return mapToDisplayParts(writer => {
12631264
typechecker.getSymbolDisplayBuilder().buildSignatureDisplay(signature, writer, enclosingDeclaration, flags);
12641265
});
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//// [circularContextualReturnType.ts]
2+
// Repro from #17711
3+
4+
Object.freeze({
5+
foo() {
6+
return Object.freeze('a');
7+
},
8+
});
9+
10+
11+
//// [circularContextualReturnType.js]
12+
"use strict";
13+
// Repro from #17711
14+
Object.freeze({
15+
foo: function () {
16+
return Object.freeze('a');
17+
}
18+
});
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
=== tests/cases/compiler/circularContextualReturnType.ts ===
2+
// Repro from #17711
3+
4+
Object.freeze({
5+
>Object.freeze : Symbol(ObjectConstructor.freeze, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
6+
>Object : Symbol(Object, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
7+
>freeze : Symbol(ObjectConstructor.freeze, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
8+
9+
foo() {
10+
>foo : Symbol(foo, Decl(circularContextualReturnType.ts, 2, 15))
11+
12+
return Object.freeze('a');
13+
>Object.freeze : Symbol(ObjectConstructor.freeze, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
14+
>Object : Symbol(Object, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
15+
>freeze : Symbol(ObjectConstructor.freeze, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
16+
17+
},
18+
});
19+
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
=== tests/cases/compiler/circularContextualReturnType.ts ===
2+
// Repro from #17711
3+
4+
Object.freeze({
5+
>Object.freeze({ foo() { return Object.freeze('a'); },}) : Readonly<{ foo(): string; }>
6+
>Object.freeze : { <T>(a: T[]): ReadonlyArray<T>; <T extends Function>(f: T): T; <T>(o: T): Readonly<T>; }
7+
>Object : ObjectConstructor
8+
>freeze : { <T>(a: T[]): ReadonlyArray<T>; <T extends Function>(f: T): T; <T>(o: T): Readonly<T>; }
9+
>{ foo() { return Object.freeze('a'); },} : { foo(): string; }
10+
11+
foo() {
12+
>foo : () => string
13+
14+
return Object.freeze('a');
15+
>Object.freeze('a') : string
16+
>Object.freeze : { <T>(a: T[]): ReadonlyArray<T>; <T extends Function>(f: T): T; <T>(o: T): Readonly<T>; }
17+
>Object : ObjectConstructor
18+
>freeze : { <T>(a: T[]): ReadonlyArray<T>; <T extends Function>(f: T): T; <T>(o: T): Readonly<T>; }
19+
>'a' : "a"
20+
21+
},
22+
});
23+
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// @strict: true
2+
3+
// Repro from #17711
4+
5+
Object.freeze({
6+
foo() {
7+
return Object.freeze('a');
8+
},
9+
});
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
// @Filename: /a.ts
4+
////export type X = { x: number };
5+
////export function f(x: X): void {}
6+
7+
// @Filename: /b.ts
8+
////import { f } from "./a";
9+
/////**/f({ x: 1 });
10+
11+
verify.quickInfoAt("", "(alias) f(x: X): void\nimport f");

0 commit comments

Comments
 (0)