Skip to content

Commit f619282

Browse files
committed
[Transforms] Update transforms with recent master (#8960)
* Remove check narrowing only certain types, add test showing issues with this * string literal case test * Reconcile fix with CFA work * Defaultable -> NotNarrowable to align with use * Missed a defaultable in comments * Add test for narrowing to unions of string literals * Actually merge from master * Run fixupParentReferences when parsing isolated jsDocComment * initial revision of unit test support for project system in tsserver * Add non-widening forms of null and undefined * Create separate control flows for property declarations with initializers * Add regression test * Add tests * Remove unused variable * Add null check and CR feedback * Revert "Merge pull request #7235 from weswigham/narrow-all-types" This reverts commit ef0f6c8, reversing changes made to 9f087cb. * reuse the fixupParentReferences function * Fix up error from merging with master
1 parent e9dadd7 commit f619282

29 files changed

+2051
-65
lines changed

Jakefile.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,8 @@ var harnessSources = harnessCoreSources.concat([
180180
"tsconfigParsing.ts",
181181
"commandLineParsing.ts",
182182
"convertCompilerOptionsFromJson.ts",
183-
"convertTypingOptionsFromJson.ts"
183+
"convertTypingOptionsFromJson.ts",
184+
"tsserverProjectSystem.ts"
184185
].map(function (f) {
185186
return path.join(unittestsDirectory, f);
186187
})).concat([

src/compiler/binder.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1163,6 +1163,8 @@ namespace ts {
11631163

11641164
case SyntaxKind.ModuleBlock:
11651165
return ContainerFlags.IsControlFlowContainer;
1166+
case SyntaxKind.PropertyDeclaration:
1167+
return (<PropertyDeclaration>node).initializer ? ContainerFlags.IsControlFlowContainer : 0;
11661168

11671169
case SyntaxKind.CatchClause:
11681170
case SyntaxKind.ForStatement:

src/compiler/checker.ts

+19-17
Original file line numberDiff line numberDiff line change
@@ -108,16 +108,16 @@ namespace ts {
108108
const unknownSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient, "unknown");
109109
const resolvingSymbol = createSymbol(SymbolFlags.Transient, "__resolving__");
110110

111-
const nullableWideningFlags = strictNullChecks ? 0 : TypeFlags.ContainsUndefinedOrNull;
112111
const anyType = createIntrinsicType(TypeFlags.Any, "any");
113112
const stringType = createIntrinsicType(TypeFlags.String, "string");
114113
const numberType = createIntrinsicType(TypeFlags.Number, "number");
115114
const booleanType = createIntrinsicType(TypeFlags.Boolean, "boolean");
116115
const esSymbolType = createIntrinsicType(TypeFlags.ESSymbol, "symbol");
117116
const voidType = createIntrinsicType(TypeFlags.Void, "void");
118-
const undefinedType = createIntrinsicType(TypeFlags.Undefined | nullableWideningFlags, "undefined");
119-
const nullType = createIntrinsicType(TypeFlags.Null | nullableWideningFlags, "null");
120-
const emptyArrayElementType = createIntrinsicType(TypeFlags.Undefined | TypeFlags.ContainsUndefinedOrNull, "undefined");
117+
const undefinedType = createIntrinsicType(TypeFlags.Undefined, "undefined");
118+
const undefinedWideningType = strictNullChecks ? undefinedType : createIntrinsicType(TypeFlags.Undefined | TypeFlags.ContainsWideningType, "undefined");
119+
const nullType = createIntrinsicType(TypeFlags.Null, "null");
120+
const nullWideningType = strictNullChecks ? nullType : createIntrinsicType(TypeFlags.Null | TypeFlags.ContainsWideningType, "null");
121121
const unknownType = createIntrinsicType(TypeFlags.Any, "unknown");
122122
const neverType = createIntrinsicType(TypeFlags.Never, "never");
123123

@@ -3403,7 +3403,7 @@ namespace ts {
34033403
error(type.symbol.valueDeclaration, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_base_expression, symbolToString(type.symbol));
34043404
return type.resolvedBaseConstructorType = unknownType;
34053405
}
3406-
if (baseConstructorType !== unknownType && baseConstructorType !== nullType && !isConstructorType(baseConstructorType)) {
3406+
if (baseConstructorType !== unknownType && baseConstructorType !== nullWideningType && !isConstructorType(baseConstructorType)) {
34073407
error(baseTypeNode.expression, Diagnostics.Type_0_is_not_a_constructor_function_type, typeToString(baseConstructorType));
34083408
return type.resolvedBaseConstructorType = unknownType;
34093409
}
@@ -5009,6 +5009,7 @@ namespace ts {
50095009
containsAny?: boolean;
50105010
containsUndefined?: boolean;
50115011
containsNull?: boolean;
5012+
containsNonWideningType?: boolean;
50125013
}
50135014

50145015
function addTypeToSet(typeSet: TypeSet, type: Type, typeSetKind: TypeFlags) {
@@ -5019,6 +5020,7 @@ namespace ts {
50195020
if (type.flags & TypeFlags.Any) typeSet.containsAny = true;
50205021
if (type.flags & TypeFlags.Undefined) typeSet.containsUndefined = true;
50215022
if (type.flags & TypeFlags.Null) typeSet.containsNull = true;
5023+
if (!(type.flags & TypeFlags.ContainsWideningType)) typeSet.containsNonWideningType = true;
50225024
}
50235025
else if (type !== neverType && !contains(typeSet, type)) {
50245026
typeSet.push(type);
@@ -5079,8 +5081,8 @@ namespace ts {
50795081
removeSubtypes(typeSet);
50805082
}
50815083
if (typeSet.length === 0) {
5082-
return typeSet.containsNull ? nullType :
5083-
typeSet.containsUndefined ? undefinedType :
5084+
return typeSet.containsNull ? typeSet.containsNonWideningType ? nullType : nullWideningType :
5085+
typeSet.containsUndefined ? typeSet.containsNonWideningType ? undefinedType : undefinedWideningType :
50845086
neverType;
50855087
}
50865088
else if (typeSet.length === 1) {
@@ -5880,7 +5882,7 @@ namespace ts {
58805882
if (!(target.flags & TypeFlags.Never)) {
58815883
if (target.flags & TypeFlags.Any || source.flags & TypeFlags.Never) return Ternary.True;
58825884
if (source.flags & TypeFlags.Undefined) {
5883-
if (!strictNullChecks || target.flags & (TypeFlags.Undefined | TypeFlags.Void) || source === emptyArrayElementType) return Ternary.True;
5885+
if (!strictNullChecks || target.flags & (TypeFlags.Undefined | TypeFlags.Void)) return Ternary.True;
58845886
}
58855887
if (source.flags & TypeFlags.Null) {
58865888
if (!strictNullChecks || target.flags & TypeFlags.Null) return Ternary.True;
@@ -6970,7 +6972,7 @@ namespace ts {
69706972
if (type.flags & TypeFlags.ObjectLiteral) {
69716973
for (const p of getPropertiesOfObjectType(type)) {
69726974
const t = getTypeOfSymbol(p);
6973-
if (t.flags & TypeFlags.ContainsUndefinedOrNull) {
6975+
if (t.flags & TypeFlags.ContainsWideningType) {
69746976
if (!reportWideningErrorsInType(t)) {
69756977
error(p.valueDeclaration, Diagnostics.Object_literal_s_property_0_implicitly_has_an_1_type, p.name, typeToString(getWidenedType(t)));
69766978
}
@@ -7017,7 +7019,7 @@ namespace ts {
70177019
}
70187020

70197021
function reportErrorsFromWidening(declaration: Declaration, type: Type) {
7020-
if (produceDiagnostics && compilerOptions.noImplicitAny && type.flags & TypeFlags.ContainsUndefinedOrNull) {
7022+
if (produceDiagnostics && compilerOptions.noImplicitAny && type.flags & TypeFlags.ContainsWideningType) {
70217023
// Report implicit any error within type if possible, otherwise report error on declaration
70227024
if (!reportWideningErrorsInType(type)) {
70237025
reportImplicitAnyError(declaration, type);
@@ -8309,7 +8311,7 @@ namespace ts {
83098311
const classInstanceType = <InterfaceType>getDeclaredTypeOfSymbol(classSymbol);
83108312
const baseConstructorType = getBaseConstructorTypeOfClass(classInstanceType);
83118313

8312-
return baseConstructorType === nullType;
8314+
return baseConstructorType === nullWideningType;
83138315
}
83148316

83158317
function checkThisExpression(node: Node): Type {
@@ -9200,7 +9202,7 @@ namespace ts {
92009202
}
92019203
}
92029204
}
9203-
return createArrayType(elementTypes.length ? getUnionType(elementTypes) : emptyArrayElementType);
9205+
return createArrayType(elementTypes.length ? getUnionType(elementTypes) : strictNullChecks ? neverType : undefinedWideningType);
92049206
}
92059207

92069208
function isNumericName(name: DeclarationName): boolean {
@@ -12004,7 +12006,7 @@ namespace ts {
1200412006

1200512007
function checkVoidExpression(node: VoidExpression): Type {
1200612008
checkExpression(node.expression);
12007-
return undefinedType;
12009+
return undefinedWideningType;
1200812010
}
1200912011

1201012012
function checkAwaitExpression(node: AwaitExpression): Type {
@@ -12411,7 +12413,7 @@ namespace ts {
1241112413
case SyntaxKind.InKeyword:
1241212414
return checkInExpression(left, right, leftType, rightType);
1241312415
case SyntaxKind.AmpersandAmpersandToken:
12414-
return addNullableKind(rightType, getNullableKind(leftType));
12416+
return strictNullChecks ? addNullableKind(rightType, getNullableKind(leftType)) : rightType;
1241512417
case SyntaxKind.BarBarToken:
1241612418
return getUnionType([getNonNullableType(leftType), rightType]);
1241712419
case SyntaxKind.EqualsToken:
@@ -12678,7 +12680,7 @@ namespace ts {
1267812680
case SyntaxKind.SuperKeyword:
1267912681
return checkSuperExpression(node);
1268012682
case SyntaxKind.NullKeyword:
12681-
return nullType;
12683+
return nullWideningType;
1268212684
case SyntaxKind.TrueKeyword:
1268312685
case SyntaxKind.FalseKeyword:
1268412686
return booleanType;
@@ -12736,7 +12738,7 @@ namespace ts {
1273612738
case SyntaxKind.SpreadElementExpression:
1273712739
return checkSpreadElementExpression(<SpreadElementExpression>node, contextualMapper);
1273812740
case SyntaxKind.OmittedExpression:
12739-
return undefinedType;
12741+
return undefinedWideningType;
1274012742
case SyntaxKind.YieldExpression:
1274112743
return checkYieldExpression(<YieldExpression>node);
1274212744
case SyntaxKind.JsxExpression:
@@ -17728,7 +17730,7 @@ namespace ts {
1772817730
// Setup global builtins
1772917731
addToSymbolTable(globals, builtinGlobals, Diagnostics.Declaration_name_conflicts_with_built_in_global_identifier_0);
1773017732

17731-
getSymbolLinks(undefinedSymbol).type = undefinedType;
17733+
getSymbolLinks(undefinedSymbol).type = undefinedWideningType;
1773217734
getSymbolLinks(argumentsSymbol).type = getGlobalType("IArguments");
1773317735
getSymbolLinks(unknownSymbol).type = unknownType;
1773417736

src/compiler/parser.ts

+11-4
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,14 @@ namespace ts {
443443

444444
/* @internal */
445445
export function parseIsolatedJSDocComment(content: string, start?: number, length?: number) {
446-
return Parser.JSDocParser.parseIsolatedJSDocComment(content, start, length);
446+
const result = Parser.JSDocParser.parseIsolatedJSDocComment(content, start, length);
447+
if (result && result.jsDocComment) {
448+
// because the jsDocComment was parsed out of the source file, it might
449+
// not be covered by the fixupParentReferences.
450+
Parser.fixupParentReferences(result.jsDocComment);
451+
}
452+
453+
return result;
447454
}
448455

449456
/* @internal */
@@ -655,14 +662,14 @@ namespace ts {
655662
return node;
656663
}
657664

658-
export function fixupParentReferences(sourceFile: Node) {
665+
export function fixupParentReferences(rootNode: Node) {
659666
// normally parent references are set during binding. However, for clients that only need
660667
// a syntax tree, and no semantic features, then the binding process is an unnecessary
661668
// overhead. This functions allows us to set all the parents, without all the expense of
662669
// binding.
663670

664-
let parent: Node = sourceFile;
665-
forEachChild(sourceFile, visitNode);
671+
let parent: Node = rootNode;
672+
forEachChild(rootNode, visitNode);
666673
return;
667674

668675
function visitNode(n: Node): void {

src/compiler/types.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -2264,7 +2264,7 @@ namespace ts {
22642264
/* @internal */
22652265
FreshObjectLiteral = 0x00100000, // Fresh object literal type
22662266
/* @internal */
2267-
ContainsUndefinedOrNull = 0x00200000, // Type is or contains undefined or null type
2267+
ContainsWideningType = 0x00200000, // Type is or contains undefined or null widening type
22682268
/* @internal */
22692269
ContainsObjectLiteral = 0x00400000, // Type is or contains object literal type
22702270
/* @internal */
@@ -2287,9 +2287,9 @@ namespace ts {
22872287
StructuredType = ObjectType | Union | Intersection,
22882288
Narrowable = Any | ObjectType | Union | TypeParameter,
22892289
/* @internal */
2290-
RequiresWidening = ContainsUndefinedOrNull | ContainsObjectLiteral,
2290+
RequiresWidening = ContainsWideningType | ContainsObjectLiteral,
22912291
/* @internal */
2292-
PropagatingFlags = ContainsUndefinedOrNull | ContainsObjectLiteral | ContainsAnyFunctionType
2292+
PropagatingFlags = ContainsWideningType | ContainsObjectLiteral | ContainsAnyFunctionType
22932293
}
22942294

22952295
export type DestructuringPattern = BindingPattern | ObjectLiteralExpression | ArrayLiteralExpression;

src/server/editorServices.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1138,7 +1138,7 @@ namespace ts.server {
11381138
else {
11391139
this.log("No config files found.");
11401140
}
1141-
return {};
1141+
return configFileName ? { configFileName } : {};
11421142
}
11431143

11441144
/**

tests/baselines/reference/arrayLiteralWidened.js

+15
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// array literals are widened upon assignment according to their element type
33

44
var a = []; // any[]
5+
var a = [,,];
56

67
var a = [null, null];
78
var a = [undefined, undefined];
@@ -12,15 +13,29 @@ var b = [[undefined, undefined]];
1213

1314
var c = [[[]]]; // any[][][]
1415
var c = [[[null]],[undefined]]
16+
17+
// no widening when one or more elements are non-widening
18+
19+
var x: undefined = undefined;
20+
21+
var d = [x];
22+
var d = [, x];
23+
var d = [undefined, x];
1524

1625

1726
//// [arrayLiteralWidened.js]
1827
// array literals are widened upon assignment according to their element type
1928
var a = []; // any[]
29+
var a = [, ,];
2030
var a = [null, null];
2131
var a = [undefined, undefined];
2232
var b = [[], [null, null]]; // any[][]
2333
var b = [[], []];
2434
var b = [[undefined, undefined]];
2535
var c = [[[]]]; // any[][][]
2636
var c = [[[null]], [undefined]];
37+
// no widening when one or more elements are non-widening
38+
var x = undefined;
39+
var d = [x];
40+
var d = [, x];
41+
var d = [undefined, x];

tests/baselines/reference/arrayLiteralWidened.symbols

+30-8
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,53 @@
22
// array literals are widened upon assignment according to their element type
33

44
var a = []; // any[]
5-
>a : Symbol(a, Decl(arrayLiteralWidened.ts, 2, 3), Decl(arrayLiteralWidened.ts, 4, 3), Decl(arrayLiteralWidened.ts, 5, 3))
5+
>a : Symbol(a, Decl(arrayLiteralWidened.ts, 2, 3), Decl(arrayLiteralWidened.ts, 3, 3), Decl(arrayLiteralWidened.ts, 5, 3), Decl(arrayLiteralWidened.ts, 6, 3))
6+
7+
var a = [,,];
8+
>a : Symbol(a, Decl(arrayLiteralWidened.ts, 2, 3), Decl(arrayLiteralWidened.ts, 3, 3), Decl(arrayLiteralWidened.ts, 5, 3), Decl(arrayLiteralWidened.ts, 6, 3))
69

710
var a = [null, null];
8-
>a : Symbol(a, Decl(arrayLiteralWidened.ts, 2, 3), Decl(arrayLiteralWidened.ts, 4, 3), Decl(arrayLiteralWidened.ts, 5, 3))
11+
>a : Symbol(a, Decl(arrayLiteralWidened.ts, 2, 3), Decl(arrayLiteralWidened.ts, 3, 3), Decl(arrayLiteralWidened.ts, 5, 3), Decl(arrayLiteralWidened.ts, 6, 3))
912

1013
var a = [undefined, undefined];
11-
>a : Symbol(a, Decl(arrayLiteralWidened.ts, 2, 3), Decl(arrayLiteralWidened.ts, 4, 3), Decl(arrayLiteralWidened.ts, 5, 3))
14+
>a : Symbol(a, Decl(arrayLiteralWidened.ts, 2, 3), Decl(arrayLiteralWidened.ts, 3, 3), Decl(arrayLiteralWidened.ts, 5, 3), Decl(arrayLiteralWidened.ts, 6, 3))
1215
>undefined : Symbol(undefined)
1316
>undefined : Symbol(undefined)
1417

1518
var b = [[], [null, null]]; // any[][]
16-
>b : Symbol(b, Decl(arrayLiteralWidened.ts, 7, 3), Decl(arrayLiteralWidened.ts, 8, 3), Decl(arrayLiteralWidened.ts, 9, 3))
19+
>b : Symbol(b, Decl(arrayLiteralWidened.ts, 8, 3), Decl(arrayLiteralWidened.ts, 9, 3), Decl(arrayLiteralWidened.ts, 10, 3))
1720

1821
var b = [[], []];
19-
>b : Symbol(b, Decl(arrayLiteralWidened.ts, 7, 3), Decl(arrayLiteralWidened.ts, 8, 3), Decl(arrayLiteralWidened.ts, 9, 3))
22+
>b : Symbol(b, Decl(arrayLiteralWidened.ts, 8, 3), Decl(arrayLiteralWidened.ts, 9, 3), Decl(arrayLiteralWidened.ts, 10, 3))
2023

2124
var b = [[undefined, undefined]];
22-
>b : Symbol(b, Decl(arrayLiteralWidened.ts, 7, 3), Decl(arrayLiteralWidened.ts, 8, 3), Decl(arrayLiteralWidened.ts, 9, 3))
25+
>b : Symbol(b, Decl(arrayLiteralWidened.ts, 8, 3), Decl(arrayLiteralWidened.ts, 9, 3), Decl(arrayLiteralWidened.ts, 10, 3))
2326
>undefined : Symbol(undefined)
2427
>undefined : Symbol(undefined)
2528

2629
var c = [[[]]]; // any[][][]
27-
>c : Symbol(c, Decl(arrayLiteralWidened.ts, 11, 3), Decl(arrayLiteralWidened.ts, 12, 3))
30+
>c : Symbol(c, Decl(arrayLiteralWidened.ts, 12, 3), Decl(arrayLiteralWidened.ts, 13, 3))
2831

2932
var c = [[[null]],[undefined]]
30-
>c : Symbol(c, Decl(arrayLiteralWidened.ts, 11, 3), Decl(arrayLiteralWidened.ts, 12, 3))
33+
>c : Symbol(c, Decl(arrayLiteralWidened.ts, 12, 3), Decl(arrayLiteralWidened.ts, 13, 3))
34+
>undefined : Symbol(undefined)
35+
36+
// no widening when one or more elements are non-widening
37+
38+
var x: undefined = undefined;
39+
>x : Symbol(x, Decl(arrayLiteralWidened.ts, 17, 3))
40+
>undefined : Symbol(undefined)
41+
42+
var d = [x];
43+
>d : Symbol(d, Decl(arrayLiteralWidened.ts, 19, 3), Decl(arrayLiteralWidened.ts, 20, 3), Decl(arrayLiteralWidened.ts, 21, 3))
44+
>x : Symbol(x, Decl(arrayLiteralWidened.ts, 17, 3))
45+
46+
var d = [, x];
47+
>d : Symbol(d, Decl(arrayLiteralWidened.ts, 19, 3), Decl(arrayLiteralWidened.ts, 20, 3), Decl(arrayLiteralWidened.ts, 21, 3))
48+
>x : Symbol(x, Decl(arrayLiteralWidened.ts, 17, 3))
49+
50+
var d = [undefined, x];
51+
>d : Symbol(d, Decl(arrayLiteralWidened.ts, 19, 3), Decl(arrayLiteralWidened.ts, 20, 3), Decl(arrayLiteralWidened.ts, 21, 3))
3152
>undefined : Symbol(undefined)
53+
>x : Symbol(x, Decl(arrayLiteralWidened.ts, 17, 3))
3254

tests/baselines/reference/arrayLiteralWidened.types

+29
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ var a = []; // any[]
55
>a : any[]
66
>[] : undefined[]
77

8+
var a = [,,];
9+
>a : any[]
10+
>[,,] : undefined[]
11+
> : undefined
12+
> : undefined
13+
814
var a = [null, null];
915
>a : any[]
1016
>[null, null] : null[]
@@ -53,3 +59,26 @@ var c = [[[null]],[undefined]]
5359
>[undefined] : undefined[]
5460
>undefined : undefined
5561

62+
// no widening when one or more elements are non-widening
63+
64+
var x: undefined = undefined;
65+
>x : undefined
66+
>undefined : undefined
67+
68+
var d = [x];
69+
>d : undefined[]
70+
>[x] : undefined[]
71+
>x : undefined
72+
73+
var d = [, x];
74+
>d : undefined[]
75+
>[, x] : undefined[]
76+
> : undefined
77+
>x : undefined
78+
79+
var d = [undefined, x];
80+
>d : undefined[]
81+
>[undefined, x] : undefined[]
82+
>undefined : undefined
83+
>x : undefined
84+

0 commit comments

Comments
 (0)