Skip to content

Commit d920efe

Browse files
committed
Merge branch 'master' into resolveJsonModuleError
2 parents dfb5cbd + f12e9a8 commit d920efe

31 files changed

+139
-148
lines changed

src/compiler/checker.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -20047,7 +20047,8 @@ namespace ts {
2004720047
if (produceDiagnostics && targetType !== errorType) {
2004820048
const widenedType = getWidenedType(exprType);
2004920049
if (!isTypeComparableTo(targetType, widenedType)) {
20050-
checkTypeComparableTo(exprType, targetType, errNode, Diagnostics.Type_0_cannot_be_converted_to_type_1);
20050+
checkTypeComparableTo(exprType, targetType, errNode,
20051+
Diagnostics.Conversion_of_type_0_to_type_1_may_be_a_mistake_because_neither_type_sufficiently_overlaps_with_the_other_If_this_was_intentional_convert_the_expression_to_unknown_first);
2005120052
}
2005220053
}
2005320054
return targetType;
@@ -21521,7 +21522,7 @@ namespace ts {
2152121522
// in tagged templates.
2152221523
forEach(node.templateSpans, templateSpan => {
2152321524
if (maybeTypeOfKind(checkExpression(templateSpan.expression), TypeFlags.ESSymbolLike)) {
21524-
error(templateSpan.expression, Diagnostics.Type_0_cannot_be_converted_to_type_1, typeToString(esSymbolType), typeToString(stringType));
21525+
error(templateSpan.expression, Diagnostics.Implicit_conversion_of_a_symbol_to_a_string_will_fail_at_runtime_Consider_wrapping_this_expression_in_String);
2152521526
}
2152621527
});
2152721528

src/compiler/diagnosticMessages.json

+6-2
Original file line numberDiff line numberDiff line change
@@ -1196,7 +1196,7 @@
11961196
"category": "Error",
11971197
"code": 2351
11981198
},
1199-
"Type '{0}' cannot be converted to type '{1}'.": {
1199+
"Conversion of type '{0}' to type '{1}' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.": {
12001200
"category": "Error",
12011201
"code": 2352
12021202
},
@@ -2421,10 +2421,14 @@
24212421
"category": "Error",
24222422
"code": 2730
24232423
},
2424-
"Cannot find module '{0}'. Consider using '--resolveJsonModule' to import module with '.json' extension": {
2424+
"Implicit conversion of a 'symbol' to a 'string' will fail at runtime. Consider wrapping this expression in 'String(...)'.": {
24252425
"category": "Error",
24262426
"code": 2731
24272427
},
2428+
"Cannot find module '{0}'. Consider using '--resolveJsonModule' to import module with '.json' extension": {
2429+
"category": "Error",
2430+
"code": 2732
2431+
},
24282432

24292433
"Import declaration '{0}' is using private name '{1}'.": {
24302434
"category": "Error",

src/services/goToDefinition.ts

+3-10
Original file line numberDiff line numberDiff line change
@@ -136,15 +136,8 @@ namespace ts.GoToDefinition {
136136

137137
const symbol = typeChecker.getSymbolAtLocation(node);
138138
const type = symbol && typeChecker.getTypeOfSymbolAtLocation(symbol, node);
139-
if (!type) {
140-
return undefined;
141-
}
142-
143-
if (type.isUnion() && !(type.flags & TypeFlags.Enum)) {
144-
return flatMap(type.types, t => t.symbol && getDefinitionFromSymbol(typeChecker, t.symbol, node));
145-
}
146-
147-
return type.symbol && getDefinitionFromSymbol(typeChecker, type.symbol, node);
139+
return type && flatMap(type.isUnion() && !(type.flags & TypeFlags.Enum) ? type.types : [type], t =>
140+
t.symbol && getDefinitionFromSymbol(typeChecker, t.symbol, node));
148141
}
149142

150143
export function getDefinitionAndBoundSpan(program: Program, sourceFile: SourceFile, position: number): DefinitionInfoAndBoundSpan | undefined {
@@ -230,7 +223,7 @@ namespace ts.GoToDefinition {
230223
}
231224

232225
function getCallSignatureDefinition(): DefinitionInfo[] | undefined {
233-
return isCallExpressionTarget(node) || isNewExpressionTarget(node) || isNameOfFunctionDeclaration(node)
226+
return isCallOrNewExpressionTarget(node) || isNameOfFunctionDeclaration(node)
234227
? getSignatureDefinition(symbol.declarations, /*selectConstructors*/ false)
235228
: undefined;
236229
}

src/services/signatureHelp.ts

+23-34
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,11 @@ namespace ts.SignatureHelp {
3030
}
3131

3232
// Only need to be careful if the user typed a character and signature help wasn't showing.
33-
const shouldCarefullyCheckContext = !!triggerReason && triggerReason.kind === "characterTyped";
33+
const onlyUseSyntacticOwners = !!triggerReason && triggerReason.kind === "characterTyped";
3434

3535
// Bail out quickly in the middle of a string or comment, don't provide signature help unless the user explicitly requested it.
36-
if (shouldCarefullyCheckContext) {
37-
if (isInString(sourceFile, position, startingToken) || isInComment(sourceFile, position)) {
38-
return undefined;
39-
}
36+
if (onlyUseSyntacticOwners && (isInString(sourceFile, position, startingToken) || isInComment(sourceFile, position))) {
37+
return undefined;
4038
}
4139

4240
const argumentInfo = getContainingArgumentInfo(startingToken, position, sourceFile);
@@ -45,7 +43,7 @@ namespace ts.SignatureHelp {
4543
cancellationToken.throwIfCancellationRequested();
4644

4745
// Extra syntactic and semantic filtering of signature help
48-
const candidateInfo = getCandidateInfo(argumentInfo, typeChecker, sourceFile, startingToken, shouldCarefullyCheckContext);
46+
const candidateInfo = getCandidateInfo(argumentInfo, typeChecker, sourceFile, startingToken, onlyUseSyntacticOwners);
4947
cancellationToken.throwIfCancellationRequested();
5048

5149
if (!candidateInfo) {
@@ -66,35 +64,9 @@ namespace ts.SignatureHelp {
6664

6765
const { invocation } = argumentInfo;
6866
if (invocation.kind === InvocationKind.Call) {
69-
if (onlyUseSyntacticOwners) {
70-
if (isCallOrNewExpression(invocation.node)) {
71-
const invocationChildren = invocation.node.getChildren(sourceFile);
72-
switch (startingToken.kind) {
73-
case SyntaxKind.OpenParenToken:
74-
if (!contains(invocationChildren, startingToken)) {
75-
return undefined;
76-
}
77-
break;
78-
case SyntaxKind.CommaToken:
79-
const containingList = findContainingList(startingToken);
80-
if (!containingList || !contains(invocationChildren, findContainingList(startingToken))) {
81-
return undefined;
82-
}
83-
break;
84-
case SyntaxKind.LessThanToken:
85-
if (!lessThanFollowsCalledExpression(startingToken, sourceFile, invocation.node.expression)) {
86-
return undefined;
87-
}
88-
break;
89-
default:
90-
return undefined;
91-
}
92-
}
93-
else {
94-
return undefined;
95-
}
67+
if (onlyUseSyntacticOwners && !isSyntacticOwner(startingToken, invocation.node, sourceFile)) {
68+
return undefined;
9669
}
97-
9870
const candidates: Signature[] = [];
9971
const resolvedSignature = checker.getResolvedSignature(invocation.node, candidates, argumentInfo.argumentCount)!; // TODO: GH#18217
10072
return candidates.length === 0 ? undefined : { candidates, resolvedSignature };
@@ -111,6 +83,23 @@ namespace ts.SignatureHelp {
11183
}
11284
}
11385

86+
function isSyntacticOwner(startingToken: Node, node: CallLikeExpression, sourceFile: SourceFile): boolean {
87+
if (!isCallOrNewExpression(node)) return false;
88+
const invocationChildren = node.getChildren(sourceFile);
89+
switch (startingToken.kind) {
90+
case SyntaxKind.OpenParenToken:
91+
return contains(invocationChildren, startingToken);
92+
case SyntaxKind.CommaToken: {
93+
const containingList = findContainingList(startingToken);
94+
return !!containingList && contains(invocationChildren, containingList);
95+
}
96+
case SyntaxKind.LessThanToken:
97+
return lessThanFollowsCalledExpression(startingToken, sourceFile, node.expression);
98+
default:
99+
return false;
100+
}
101+
}
102+
114103
function createJavaScriptSignatureHelpItems(argumentInfo: ArgumentListInfo, program: Program, cancellationToken: CancellationToken): SignatureHelpItems | undefined {
115104
// See if we can find some symbol with the call expression name that has call signatures.
116105
const expression = getExpressionFromInvocation(argumentInfo.invocation);

src/services/utilities.ts

+8-4
Original file line numberDiff line numberDiff line change
@@ -194,16 +194,20 @@ namespace ts {
194194
}
195195

196196
export function isCallExpressionTarget(node: Node): boolean {
197-
return isCallOrNewExpressionTarget(node, SyntaxKind.CallExpression);
197+
return isCallOrNewExpressionTargetWorker(node, isCallExpression);
198198
}
199199

200200
export function isNewExpressionTarget(node: Node): boolean {
201-
return isCallOrNewExpressionTarget(node, SyntaxKind.NewExpression);
201+
return isCallOrNewExpressionTargetWorker(node, isNewExpression);
202202
}
203203

204-
function isCallOrNewExpressionTarget(node: Node, kind: SyntaxKind): boolean {
204+
export function isCallOrNewExpressionTarget(node: Node): boolean {
205+
return isCallOrNewExpressionTargetWorker(node, isCallOrNewExpression);
206+
}
207+
208+
function isCallOrNewExpressionTargetWorker<T extends CallExpression | NewExpression>(node: Node, pred: (node: Node) => node is T): boolean {
205209
const target = climbPastPropertyAccess(node);
206-
return !!target && !!target.parent && target.parent.kind === kind && (<CallExpression>target.parent).expression === target;
210+
return !!target && !!target.parent && pred(target.parent) && target.parent.expression === target;
207211
}
208212

209213
export function climbPastPropertyAccess(node: Node) {

tests/baselines/reference/arrayCast.errors.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
tests/cases/compiler/arrayCast.ts(3,23): error TS2352: Type '{ foo: string; }[]' cannot be converted to type '{ id: number; }[]'.
1+
tests/cases/compiler/arrayCast.ts(3,23): error TS2352: Conversion of type '{ foo: string; }[]' to type '{ id: number; }[]' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
22
Type '{ foo: string; }' is not comparable to type '{ id: number; }'.
33
Object literal may only specify known properties, and 'foo' does not exist in type '{ id: number; }'.
44

@@ -8,7 +8,7 @@ tests/cases/compiler/arrayCast.ts(3,23): error TS2352: Type '{ foo: string; }[]'
88
// has type { foo: string }[], which is not assignable to { id: number }[].
99
<{ id: number; }[]>[{ foo: "s" }];
1010
~~~~~~~~
11-
!!! error TS2352: Type '{ foo: string; }[]' cannot be converted to type '{ id: number; }[]'.
11+
!!! error TS2352: Conversion of type '{ foo: string; }[]' to type '{ id: number; }[]' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
1212
!!! error TS2352: Type '{ foo: string; }' is not comparable to type '{ id: number; }'.
1313
!!! error TS2352: Object literal may only specify known properties, and 'foo' does not exist in type '{ id: number; }'.
1414

Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
tests/cases/conformance/expressions/asOperator/asOperator2.ts(1,9): error TS2352: Type 'number' cannot be converted to type 'string'.
1+
tests/cases/conformance/expressions/asOperator/asOperator2.ts(1,9): error TS2352: Conversion of type 'number' to type 'string' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
22

33

44
==== tests/cases/conformance/expressions/asOperator/asOperator2.ts (1 errors) ====
55
var x = 23 as string;
66
~~~~~~~~~~~~
7-
!!! error TS2352: Type 'number' cannot be converted to type 'string'.
7+
!!! error TS2352: Conversion of type 'number' to type 'string' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
88

Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
tests/cases/conformance/expressions/asOperator/asOperatorContextualType.ts(2,9): error TS2352: Type '(v: number) => number' cannot be converted to type '(x: number) => string'.
1+
tests/cases/conformance/expressions/asOperator/asOperatorContextualType.ts(2,9): error TS2352: Conversion of type '(v: number) => number' to type '(x: number) => string' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
22
Type 'number' is not comparable to type 'string'.
33

44

55
==== tests/cases/conformance/expressions/asOperator/asOperatorContextualType.ts (1 errors) ====
66
// should error
77
var x = (v => v) as (x: number) => string;
88
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9-
!!! error TS2352: Type '(v: number) => number' cannot be converted to type '(x: number) => string'.
9+
!!! error TS2352: Conversion of type '(v: number) => number' to type '(x: number) => string' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
1010
!!! error TS2352: Type 'number' is not comparable to type 'string'.
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
tests/cases/conformance/expressions/asOperator/asOperatorNames.ts(2,9): error TS2352: Type 'number' cannot be converted to type 'string'.
1+
tests/cases/conformance/expressions/asOperator/asOperatorNames.ts(2,9): error TS2352: Conversion of type 'number' to type 'string' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
22

33

44
==== tests/cases/conformance/expressions/asOperator/asOperatorNames.ts (1 errors) ====
55
var a = 20;
66
var b = a as string;
77
~~~~~~~~~~~
8-
!!! error TS2352: Type 'number' cannot be converted to type 'string'.
8+
!!! error TS2352: Conversion of type 'number' to type 'string' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
99
var as = "hello";
1010
var as1 = as as string;
1111

0 commit comments

Comments
 (0)