Skip to content

Commit f32ec4e

Browse files
committed
Merge branch 'master' into alias-for-require
2 parents 122babd + 294fcb5 commit f32ec4e

27 files changed

+366
-38
lines changed

Diff for: .github/workflows/ci.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
node-version: [10.x, 12.x, 13.x]
2020

2121
steps:
22-
- uses: actions/checkout@v1
22+
- uses: actions/checkout@v2
2323
with:
2424
fetch-depth: 5
2525
- name: Use node version ${{ matrix.node-version }}
@@ -45,4 +45,4 @@ jobs:
4545

4646
- name: Validate the browser can import TypeScript
4747
run: gulp test-browser-integration
48-
48+

Diff for: src/compiler/checker.ts

+18-13
Original file line numberDiff line numberDiff line change
@@ -5121,6 +5121,9 @@ namespace ts {
51215121
if (parameterDeclaration && isRequiredInitializedParameter(parameterDeclaration)) {
51225122
parameterType = getOptionalType(parameterType);
51235123
}
5124+
if ((context.flags & NodeBuilderFlags.NoUndefinedOptionalParameterType) && parameterDeclaration && !isJSDocParameterTag(parameterDeclaration) && isOptionalUninitializedParameter(parameterDeclaration)) {
5125+
parameterType = getTypeWithFacts(parameterType, TypeFacts.NEUndefined);
5126+
}
51245127
const parameterTypeNode = serializeTypeForDeclaration(context, parameterType, parameterSymbol, context.enclosingDeclaration, privateSymbolVisitor, bundledImports);
51255128

51265129
const modifiers = !(context.flags & NodeBuilderFlags.OmitParameterModifiers) && preserveModifierFlags && parameterDeclaration && parameterDeclaration.modifiers ? parameterDeclaration.modifiers.map(factory.cloneNode) : undefined;
@@ -8782,6 +8785,12 @@ namespace ts {
87828785
(node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.ClassExpression || node.kind === SyntaxKind.InterfaceDeclaration || isJSConstructor(node)) &&
87838786
getDeclaredTypeOfClassOrInterface(getSymbolOfNode(node as ClassLikeDeclaration | InterfaceDeclaration)).thisType;
87848787
return thisType ? append(outerAndOwnTypeParameters, thisType) : outerAndOwnTypeParameters;
8788+
case SyntaxKind.JSDocParameterTag:
8789+
const paramSymbol = getParameterSymbolFromJSDoc(node as JSDocParameterTag);
8790+
if (paramSymbol) {
8791+
node = paramSymbol.valueDeclaration;
8792+
}
8793+
break;
87858794
}
87868795
}
87878796
}
@@ -14599,24 +14608,14 @@ namespace ts {
1459914608

1460014609
function getObjectTypeInstantiation(type: AnonymousType | DeferredTypeReference, mapper: TypeMapper) {
1460114610
const target = type.objectFlags & ObjectFlags.Instantiated ? type.target! : type;
14602-
const node = type.objectFlags & ObjectFlags.Reference ? (<TypeReference>type).node! : type.symbol.declarations[0];
14603-
const links = getNodeLinks(node);
14611+
const declaration = type.objectFlags & ObjectFlags.Reference ? (<TypeReference>type).node! : type.symbol.declarations[0];
14612+
const links = getNodeLinks(declaration);
1460414613
let typeParameters = links.outerTypeParameters;
1460514614
if (!typeParameters) {
1460614615
// The first time an anonymous type is instantiated we compute and store a list of the type
1460714616
// parameters that are in scope (and therefore potentially referenced). For type literals that
1460814617
// aren't the right hand side of a generic type alias declaration we optimize by reducing the
1460914618
// set of type parameters to those that are possibly referenced in the literal.
14610-
let declaration = node;
14611-
if (isInJSFile(declaration)) {
14612-
const paramTag = findAncestor(declaration, isJSDocParameterTag);
14613-
if (paramTag) {
14614-
const paramSymbol = getParameterSymbolFromJSDoc(paramTag);
14615-
if (paramSymbol) {
14616-
declaration = paramSymbol.valueDeclaration;
14617-
}
14618-
}
14619-
}
1462014619
let outerTypeParameters = getOuterTypeParameters(declaration, /*includeThisTypes*/ true);
1462114620
if (isJSConstructor(declaration)) {
1462214621
const templateTagParameters = getTypeParametersFromDeclaration(declaration as DeclarationWithTypeParameters);
@@ -20652,7 +20651,7 @@ namespace ts {
2065220651
// we defer subtype reduction until the evolving array type is finalized into a manifest
2065320652
// array type.
2065420653
function addEvolvingArrayElementType(evolvingArrayType: EvolvingArrayType, node: Expression): EvolvingArrayType {
20655-
const elementType = getBaseTypeOfLiteralType(getContextFreeTypeOfExpression(node));
20654+
const elementType = getRegularTypeOfObjectLiteral(getBaseTypeOfLiteralType(getContextFreeTypeOfExpression(node)));
2065620655
return isTypeSubsetOf(elementType, evolvingArrayType.elementType) ? evolvingArrayType : getEvolvingArrayType(getUnionType([evolvingArrayType.elementType, elementType]));
2065720656
}
2065820657

@@ -36989,6 +36988,12 @@ namespace ts {
3698936988
hasSyntacticModifier(parameter, ModifierFlags.ParameterPropertyModifier);
3699036989
}
3699136990

36991+
function isOptionalUninitializedParameter(parameter: ParameterDeclaration) {
36992+
return !!strictNullChecks &&
36993+
isOptionalParameter(parameter) &&
36994+
!parameter.initializer;
36995+
}
36996+
3699236997
function isExpandoFunctionDeclaration(node: Declaration): boolean {
3699336998
const declaration = getParseTreeNode(node, isFunctionDeclaration);
3699436999
if (!declaration) {

Diff for: src/compiler/types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -4161,6 +4161,7 @@ namespace ts {
41614161
UseAliasDefinedOutsideCurrentScope = 1 << 14, // Allow non-visible aliases
41624162
UseSingleQuotesForStringLiteralType = 1 << 28, // Use single quotes for string literal type
41634163
NoTypeReduction = 1 << 29, // Don't call getReducedType
4164+
NoUndefinedOptionalParameterType = 1 << 30, // Do not add undefined to optional parameter type
41644165

41654166
// Error handling
41664167
AllowThisInObjectLiteral = 1 << 15,

Diff for: src/compiler/utilities.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -4766,7 +4766,7 @@ namespace ts {
47664766
if (isPropertyAccessExpression(expr)) {
47674767
const baseStr = tryGetPropertyAccessOrIdentifierToString(expr.expression);
47684768
if (baseStr !== undefined) {
4769-
return baseStr + "." + expr.name;
4769+
return baseStr + "." + entityNameToString(expr.name);
47704770
}
47714771
}
47724772
else if (isIdentifier(expr)) {

Diff for: src/server/project.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -1948,7 +1948,7 @@ namespace ts.server {
19481948
* Otherwise it will create an InferredProject.
19491949
*/
19501950
export class ConfiguredProject extends Project {
1951-
private typeAcquisition!: TypeAcquisition; // TODO: GH#18217
1951+
private typeAcquisition: TypeAcquisition | undefined;
19521952
/* @internal */
19531953
configFileWatcher: FileWatcher | undefined;
19541954
private directoriesWatchedForWildcards: ESMap<string, WildcardDirectoryWatcher> | undefined;
@@ -2164,7 +2164,7 @@ namespace ts.server {
21642164
}
21652165

21662166
getTypeAcquisition() {
2167-
return this.typeAcquisition;
2167+
return this.typeAcquisition || {};
21682168
}
21692169

21702170
/*@internal*/
@@ -2282,7 +2282,7 @@ namespace ts.server {
22822282
*/
22832283
export class ExternalProject extends Project {
22842284
excludedFiles: readonly NormalizedPath[] = [];
2285-
private typeAcquisition!: TypeAcquisition; // TODO: GH#18217
2285+
private typeAcquisition: TypeAcquisition | undefined;
22862286
/*@internal*/
22872287
constructor(public externalProjectName: string,
22882288
projectService: ProjectService,
@@ -2318,7 +2318,7 @@ namespace ts.server {
23182318
}
23192319

23202320
getTypeAcquisition() {
2321-
return this.typeAcquisition;
2321+
return this.typeAcquisition || {};
23222322
}
23232323

23242324
setTypeAcquisition(newTypeAcquisition: TypeAcquisition): void {

Diff for: src/services/codefixes/helpers.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ namespace ts.codefix {
164164
const program = context.program;
165165
const checker = program.getTypeChecker();
166166
const scriptTarget = getEmitScriptTarget(program.getCompilerOptions());
167-
const flags = NodeBuilderFlags.NoTruncation | NodeBuilderFlags.SuppressAnyReturnType | (quotePreference === QuotePreference.Single ? NodeBuilderFlags.UseSingleQuotesForStringLiteralType : 0);
167+
const flags = NodeBuilderFlags.NoTruncation | NodeBuilderFlags.NoUndefinedOptionalParameterType | NodeBuilderFlags.SuppressAnyReturnType | (quotePreference === QuotePreference.Single ? NodeBuilderFlags.UseSingleQuotesForStringLiteralType : 0);
168168
const signatureDeclaration = <MethodDeclaration>checker.signatureToSignatureDeclaration(signature, SyntaxKind.MethodDeclaration, enclosingDeclaration, flags, getNoopSymbolTrackerWithResolver(context));
169169
if (!signatureDeclaration) {
170170
return undefined;

Diff for: src/services/findAllReferences.ts

+40-7
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ namespace ts.FindAllReferences {
132132
return node.parent.parent;
133133

134134
case SyntaxKind.ImportClause:
135+
case SyntaxKind.NamespaceExport:
135136
return node.parent;
136137

137138
case SyntaxKind.BinaryExpression:
@@ -1906,13 +1907,28 @@ namespace ts.FindAllReferences {
19061907
function populateSearchSymbolSet(symbol: Symbol, location: Node, checker: TypeChecker, isForRename: boolean, providePrefixAndSuffixText: boolean, implementations: boolean): Symbol[] {
19071908
const result: Symbol[] = [];
19081909
forEachRelatedSymbol<void>(symbol, location, checker, isForRename, !(isForRename && providePrefixAndSuffixText),
1909-
(sym, root, base) => { result.push(base || root || sym); },
1910-
/*allowBaseTypes*/ () => !implementations);
1910+
(sym, root, base) => {
1911+
// static method/property and instance method/property might have the same name. Only include static or only include instance.
1912+
if (base) {
1913+
if (isStatic(symbol) !== isStatic(base)) {
1914+
base = undefined;
1915+
}
1916+
}
1917+
result.push(base || root || sym);
1918+
},
1919+
// when try to find implementation, implementations is true, and not allowed to find base class
1920+
/*allowBaseTypes*/() => !implementations);
19111921
return result;
19121922
}
19131923

1924+
/**
1925+
* @param allowBaseTypes return true means it would try to find in base class or interface.
1926+
*/
19141927
function forEachRelatedSymbol<T>(
19151928
symbol: Symbol, location: Node, checker: TypeChecker, isForRenamePopulateSearchSymbolSet: boolean, onlyIncludeBindingElementAtReferenceLocation: boolean,
1929+
/**
1930+
* @param baseSymbol This symbol means one property/mehtod from base class or interface when it is not null or undefined,
1931+
*/
19161932
cbSymbol: (symbol: Symbol, rootSymbol?: Symbol, baseSymbol?: Symbol, kind?: NodeEntryKind) => T | undefined,
19171933
allowBaseTypes: (rootSymbol: Symbol) => boolean,
19181934
): T | undefined {
@@ -2031,16 +2047,33 @@ namespace ts.FindAllReferences {
20312047
readonly symbol: Symbol;
20322048
readonly kind: NodeEntryKind | undefined;
20332049
}
2050+
2051+
function isStatic(symbol: Symbol): boolean {
2052+
if (!symbol.valueDeclaration) { return false; }
2053+
const modifierFlags = getEffectiveModifierFlags(symbol.valueDeclaration);
2054+
return !!(modifierFlags & ModifierFlags.Static);
2055+
}
2056+
20342057
function getRelatedSymbol(search: Search, referenceSymbol: Symbol, referenceLocation: Node, state: State): RelatedSymbol | undefined {
20352058
const { checker } = state;
20362059
return forEachRelatedSymbol(referenceSymbol, referenceLocation, checker, /*isForRenamePopulateSearchSymbolSet*/ false,
20372060
/*onlyIncludeBindingElementAtReferenceLocation*/ state.options.use !== FindReferencesUse.Rename || !!state.options.providePrefixAndSuffixTextForRename,
2038-
(sym, rootSymbol, baseSymbol, kind): RelatedSymbol | undefined => search.includes(baseSymbol || rootSymbol || sym)
2039-
// For a base type, use the symbol for the derived type. For a synthetic (e.g. union) property, use the union symbol.
2040-
? { symbol: rootSymbol && !(getCheckFlags(sym) & CheckFlags.Synthetic) ? rootSymbol : sym, kind }
2041-
: undefined,
2061+
(sym, rootSymbol, baseSymbol, kind): RelatedSymbol | undefined => {
2062+
// check whether the symbol used to search itself is just the searched one.
2063+
if (baseSymbol) {
2064+
// static method/property and instance method/property might have the same name. Only check static or only check instance.
2065+
if (isStatic(referenceSymbol) !== isStatic(baseSymbol)) {
2066+
baseSymbol = undefined;
2067+
}
2068+
}
2069+
return search.includes(baseSymbol || rootSymbol || sym)
2070+
// For a base type, use the symbol for the derived type. For a synthetic (e.g. union) property, use the union symbol.
2071+
? { symbol: rootSymbol && !(getCheckFlags(sym) & CheckFlags.Synthetic) ? rootSymbol : sym, kind }
2072+
: undefined;
2073+
},
20422074
/*allowBaseTypes*/ rootSymbol =>
2043-
!(search.parents && !search.parents.some(parent => explicitlyInheritsFrom(rootSymbol.parent!, parent, state.inheritsFromCache, checker))));
2075+
!(search.parents && !search.parents.some(parent => explicitlyInheritsFrom(rootSymbol.parent!, parent, state.inheritsFromCache, checker)))
2076+
);
20442077
}
20452078

20462079
/**

Diff for: src/services/importTracker.ts

+3
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,9 @@ namespace ts.FindAllReferences {
481481
return exportInfo(symbol, getExportKindForDeclaration(exportNode));
482482
}
483483
}
484+
else if (isNamespaceExport(parent)) {
485+
return exportInfo(symbol, ExportKind.Named);
486+
}
484487
// If we are in `export = a;` or `export default a;`, `parent` is the export assignment.
485488
else if (isExportAssignment(parent)) {
486489
return getExportAssignmentExport(parent);

Diff for: tests/baselines/reference/api/tsserverlibrary.d.ts

+1
Original file line numberDiff line numberDiff line change
@@ -2232,6 +2232,7 @@ declare namespace ts {
22322232
UseAliasDefinedOutsideCurrentScope = 16384,
22332233
UseSingleQuotesForStringLiteralType = 268435456,
22342234
NoTypeReduction = 536870912,
2235+
NoUndefinedOptionalParameterType = 1073741824,
22352236
AllowThisInObjectLiteral = 32768,
22362237
AllowQualifedNameInPlaceOfIdentifier = 65536,
22372238
AllowAnonymousIdentifier = 131072,

Diff for: tests/baselines/reference/api/typescript.d.ts

+1
Original file line numberDiff line numberDiff line change
@@ -2232,6 +2232,7 @@ declare namespace ts {
22322232
UseAliasDefinedOutsideCurrentScope = 16384,
22332233
UseSingleQuotesForStringLiteralType = 268435456,
22342234
NoTypeReduction = 536870912,
2235+
NoUndefinedOptionalParameterType = 1073741824,
22352236
AllowThisInObjectLiteral = 32768,
22362237
AllowQualifedNameInPlaceOfIdentifier = 65536,
22372238
AllowAnonymousIdentifier = 131072,

Diff for: tests/baselines/reference/controlFlowArrays.js

+13-1
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,16 @@ function f18() {
176176
x.unshift("hello");
177177
x[2] = true;
178178
return x; // (string | number | boolean)[]
179-
}
179+
}
180+
181+
// Repro from #39470
182+
183+
declare function foo(arg: { val: number }[]): void;
184+
185+
let arr = []
186+
arr.push({ val: 1, bar: 2 });
187+
foo(arr);
188+
180189

181190
//// [controlFlowArrays.js]
182191
function f1() {
@@ -340,3 +349,6 @@ function f18() {
340349
x[2] = true;
341350
return x; // (string | number | boolean)[]
342351
}
352+
var arr = [];
353+
arr.push({ val: 1, bar: 2 });
354+
foo(arr);

Diff for: tests/baselines/reference/controlFlowArrays.symbols

+22
Original file line numberDiff line numberDiff line change
@@ -467,3 +467,25 @@ function f18() {
467467
return x; // (string | number | boolean)[]
468468
>x : Symbol(x, Decl(controlFlowArrays.ts, 172, 7))
469469
}
470+
471+
// Repro from #39470
472+
473+
declare function foo(arg: { val: number }[]): void;
474+
>foo : Symbol(foo, Decl(controlFlowArrays.ts, 177, 1))
475+
>arg : Symbol(arg, Decl(controlFlowArrays.ts, 181, 21))
476+
>val : Symbol(val, Decl(controlFlowArrays.ts, 181, 27))
477+
478+
let arr = []
479+
>arr : Symbol(arr, Decl(controlFlowArrays.ts, 183, 3))
480+
481+
arr.push({ val: 1, bar: 2 });
482+
>arr.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --))
483+
>arr : Symbol(arr, Decl(controlFlowArrays.ts, 183, 3))
484+
>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --))
485+
>val : Symbol(val, Decl(controlFlowArrays.ts, 184, 10))
486+
>bar : Symbol(bar, Decl(controlFlowArrays.ts, 184, 18))
487+
488+
foo(arr);
489+
>foo : Symbol(foo, Decl(controlFlowArrays.ts, 177, 1))
490+
>arr : Symbol(arr, Decl(controlFlowArrays.ts, 183, 3))
491+

Diff for: tests/baselines/reference/controlFlowArrays.types

+28
Original file line numberDiff line numberDiff line change
@@ -612,3 +612,31 @@ function f18() {
612612
return x; // (string | number | boolean)[]
613613
>x : (string | number | boolean)[]
614614
}
615+
616+
// Repro from #39470
617+
618+
declare function foo(arg: { val: number }[]): void;
619+
>foo : (arg: { val: number;}[]) => void
620+
>arg : { val: number; }[]
621+
>val : number
622+
623+
let arr = []
624+
>arr : any[]
625+
>[] : never[]
626+
627+
arr.push({ val: 1, bar: 2 });
628+
>arr.push({ val: 1, bar: 2 }) : number
629+
>arr.push : (...items: any[]) => number
630+
>arr : any[]
631+
>push : (...items: any[]) => number
632+
>{ val: 1, bar: 2 } : { val: number; bar: number; }
633+
>val : number
634+
>1 : 1
635+
>bar : number
636+
>2 : 2
637+
638+
foo(arr);
639+
>foo(arr) : void
640+
>foo : (arg: { val: number; }[]) => void
641+
>arr : { val: number; bar: number; }[]
642+

Diff for: tests/baselines/reference/noImplicitAnyStringIndexerOnObject.errors.txt

+10-1
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,10 @@ tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(76,1): error TS7053:
3535
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(81,1): error TS7053: Element implicitly has an 'any' type because expression of type 'StrEnum' can't be used to index type '{ a: number; }'.
3636
Property '[StrEnum.b]' does not exist on type '{ a: number; }'.
3737
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(93,5): error TS2538: Type 'Dog' cannot be used as an index type.
38+
tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(99,1): error TS7052: Element implicitly has an 'any' type because type 'MyMap<string, string>' has no index signature. Did you mean to call 'm.prop.get'?
3839

3940

40-
==== tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts (30 errors) ====
41+
==== tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts (31 errors) ====
4142
var a = {}["hello"];
4243
~~~~~~~~~~~
4344
!!! error TS7053: Element implicitly has an 'any' type because expression of type '"hello"' can't be used to index type '{}'.
@@ -198,4 +199,12 @@ tests/cases/compiler/noImplicitAnyStringIndexerOnObject.ts(93,5): error TS2538:
198199
map[rover] = "Rover";
199200
~~~~~
200201
!!! error TS2538: Type 'Dog' cannot be used as an index type.
202+
203+
interface I {
204+
prop: MyMap<string, string>
205+
}
206+
declare const m: I;
207+
m.prop['a'];
208+
~~~~~~~~~~~
209+
!!! error TS7052: Element implicitly has an 'any' type because type 'MyMap<string, string>' has no index signature. Did you mean to call 'm.prop.get'?
201210

Diff for: tests/baselines/reference/noImplicitAnyStringIndexerOnObject.js

+7
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,12 @@ let rover: Dog = { bark() {} };
9292

9393
declare let map: MyMap<Dog, string>;
9494
map[rover] = "Rover";
95+
96+
interface I {
97+
prop: MyMap<string, string>
98+
}
99+
declare const m: I;
100+
m.prop['a'];
95101

96102

97103
//// [noImplicitAnyStringIndexerOnObject.js]
@@ -168,3 +174,4 @@ var strEnumKey;
168174
o[strEnumKey];
169175
var rover = { bark: function () { } };
170176
map[rover] = "Rover";
177+
m.prop['a'];

0 commit comments

Comments
 (0)