Skip to content

Commit

Permalink
Improve error position/range for arrow functions with expression body
Browse files Browse the repository at this point in the history
Fixes microsoft#57866
diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts
index 1ff3a2acad..2ea2c5ee56 100644
--- a/src/compiler/utilities.ts
+++ b/src/compiler/utilities.ts
@@ -2527,6 +2527,14 @@ export function getErrorSpanForNode(sourceFile: SourceFile, node: Node): TextSpa
         }
     }

+    if (node.parent !== undefined && node.parent.kind === SyntaxKind.ArrowFunction) {
+        const arrowFn = node.parent as ArrowFunction;
+        if (arrowFn.body === node && arrowFn.type !== undefined) {
+            const pos = skipTrivia(sourceFile.text, arrowFn.type.pos);
+            return getSpanOfTokenAtPosition(sourceFile, pos);
+        }
+    }
+
     if (errorNode === undefined) {
         // If we don't have a better node, then just set the error on the first token of
         // construct.
diff --git a/tests/baselines/reference/conditionalTypes1.errors.txt b/tests/baselines/reference/conditionalTypes1.errors.txt
index aa2ae24033..476345ed9f 100644
--- a/tests/baselines/reference/conditionalTypes1.errors.txt
+++ b/tests/baselines/reference/conditionalTypes1.errors.txt
@@ -73,7 +73,7 @@ conditionalTypes1.ts(160,5): error TS2322: Type 'T' is not assignable to type 'Z
   Type 'string | number' is not assignable to type 'ZeroOf<T>'.
     Type 'string' is not assignable to type 'ZeroOf<T>'.
 conditionalTypes1.ts(263,9): error TS2403: Subsequent variable declarations must have the same type.  Variable 'z' must be of type 'T1', but here has type 'Foo<T & U>'.
-conditionalTypes1.ts(288,43): error TS2322: Type 'T95<U>' is not assignable to type 'T94<U>'.
+conditionalTypes1.ts(288,33): error TS2322: Type 'T95<U>' is not assignable to type 'T94<U>'.
   Type 'number | boolean' is not assignable to type 'T94<U>'.
     Type 'number' is not assignable to type 'T94<U>'.
       Type 'boolean' is not assignable to type 'true'.
@@ -465,7 +465,7 @@ conditionalTypes1.ts(288,43): error TS2322: Type 'T95<U>' is not assignable to t
     type T95<T> = T extends string ? boolean : number;
     const f44 = <U>(value: T94<U>): T95<U> => value;
     const f45 = <U>(value: T95<U>): T94<U> => value;  // Error
-                                              ~~~~~
+                                    ~~~
 !!! error TS2322: Type 'T95<U>' is not assignable to type 'T94<U>'.
 !!! error TS2322:   Type 'number | boolean' is not assignable to type 'T94<U>'.
 !!! error TS2322:     Type 'number' is not assignable to type 'T94<U>'.
diff --git a/tests/baselines/reference/mappedTypeConstraints2.errors.txt b/tests/baselines/reference/mappedTypeConstraints2.errors.txt
index 0d3b3244c9..098bbd3f4b 100644
--- a/tests/baselines/reference/mappedTypeConstraints2.errors.txt
+++ b/tests/baselines/reference/mappedTypeConstraints2.errors.txt
@@ -6,7 +6,7 @@ mappedTypeConstraints2.ts(16,11): error TS2322: Type 'Mapped3<K>[Uppercase<K>]'
 mappedTypeConstraints2.ts(42,7): error TS2322: Type 'Mapped6<K>[keyof Mapped6<K>]' is not assignable to type '`_${string}`'.
   Type 'Mapped6<K>[string] | Mapped6<K>[number] | Mapped6<K>[symbol]' is not assignable to type '`_${string}`'.
     Type 'Mapped6<K>[string]' is not assignable to type '`_${string}`'.
-mappedTypeConstraints2.ts(51,57): error TS2322: Type 'Foo<T>[`get${T}`]' is not assignable to type 'T'.
+mappedTypeConstraints2.ts(51,52): error TS2322: Type 'Foo<T>[`get${T}`]' is not assignable to type 'T'.
   'T' could be instantiated with an arbitrary type which could be unrelated to 'Foo<T>[`get${T}`]'.
 mappedTypeConstraints2.ts(82,9): error TS2322: Type 'ObjectWithUnderscoredKeys<K>[`_${K}`]' is not assignable to type 'true'.
   Type 'ObjectWithUnderscoredKeys<K>[`_${string}`]' is not assignable to type 'true'.
@@ -75,7 +75,7 @@ mappedTypeConstraints2.ts(82,9): error TS2322: Type 'ObjectWithUnderscoredKeys<K
     };

     const get = <T extends string>(t: T, foo: Foo<T>): T => foo[`get${t}`];  // Type 'Foo<T>[`get${T}`]' is not assignable to type 'T'
-                                                            ~~~~~~~~~~~~~~
+                                                       ~
 !!! error TS2322: Type 'Foo<T>[`get${T}`]' is not assignable to type 'T'.
 !!! error TS2322:   'T' could be instantiated with an arbitrary type which could be unrelated to 'Foo<T>[`get${T}`]'.

diff --git a/tests/baselines/reference/parserArrowFunctionExpression17.errors.txt b/tests/baselines/reference/parserArrowFunctionExpression17.errors.txt
index 28091b1745..73c2b637f0 100644
--- a/tests/baselines/reference/parserArrowFunctionExpression17.errors.txt
+++ b/tests/baselines/reference/parserArrowFunctionExpression17.errors.txt
@@ -1,12 +1,12 @@
 fileJs.js(1,1): error TS2304: Cannot find name 'a'.
 fileJs.js(1,5): error TS2304: Cannot find name 'b'.
 fileJs.js(1,15): error TS2304: Cannot find name 'd'.
+fileJs.js(1,15): error TS2304: Cannot find name 'e'.
 fileJs.js(1,15): error TS8010: Type annotations can only be used in TypeScript files.
-fileJs.js(1,20): error TS2304: Cannot find name 'e'.
 fileTs.ts(1,1): error TS2304: Cannot find name 'a'.
 fileTs.ts(1,5): error TS2304: Cannot find name 'b'.
 fileTs.ts(1,15): error TS2304: Cannot find name 'd'.
-fileTs.ts(1,20): error TS2304: Cannot find name 'e'.
+fileTs.ts(1,15): error TS2304: Cannot find name 'e'.

 ==== fileJs.js (5 errors) ====
@@ -18,9 +18,9 @@ fileTs.ts(1,20): error TS2304: Cannot find name 'e'.
                   ~
 !!! error TS2304: Cannot find name 'd'.
                   ~
-!!! error TS8010: Type annotations can only be used in TypeScript files.
-                       ~
 !!! error TS2304: Cannot find name 'e'.
+                  ~
+!!! error TS8010: Type annotations can only be used in TypeScript files.

 ==== fileTs.ts (4 errors) ====
     a ? b : (c) : d => e
@@ -30,6 +30,6 @@ fileTs.ts(1,20): error TS2304: Cannot find name 'e'.
 !!! error TS2304: Cannot find name 'b'.
                   ~
 !!! error TS2304: Cannot find name 'd'.
-                       ~
+                  ~
 !!! error TS2304: Cannot find name 'e'.

\ No newline at end of file
  • Loading branch information
OliverJAsh committed Dec 17, 2024
1 parent 1fc223a commit 796450a
Show file tree
Hide file tree
Showing 4 changed files with 16 additions and 8 deletions.
8 changes: 8 additions & 0 deletions src/compiler/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2527,6 +2527,14 @@ export function getErrorSpanForNode(sourceFile: SourceFile, node: Node): TextSpa
}
}

if (node.parent !== undefined && node.parent.kind === SyntaxKind.ArrowFunction) {
const arrowFn = node.parent as ArrowFunction;
if (arrowFn.body === node && arrowFn.type !== undefined) {
const pos = skipTrivia(sourceFile.text, arrowFn.type.pos);
return getSpanOfTokenAtPosition(sourceFile, pos);
}
}

if (errorNode === undefined) {
// If we don't have a better node, then just set the error on the first token of
// construct.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
arrowFunctionReturnTypeErrorSpan.ts(3,3): error TS2322: Type 'string' is not assignable to type 'number'.
arrowFunctionReturnTypeErrorSpan.ts(7,25): error TS2322: Type 'string' is not assignable to type 'number'.
arrowFunctionReturnTypeErrorSpan.ts(10,28): error TS2322: Type 'string' is not assignable to type 'number'.
arrowFunctionReturnTypeErrorSpan.ts(12,25): error TS2304: Cannot find name 'missing'.
arrowFunctionReturnTypeErrorSpan.ts(7,15): error TS2322: Type 'string' is not assignable to type 'number'.
arrowFunctionReturnTypeErrorSpan.ts(10,15): error TS2322: Type 'string' is not assignable to type 'number'.


==== arrowFunctionReturnTypeErrorSpan.ts (4 errors) ====
Expand All @@ -14,12 +14,12 @@ arrowFunctionReturnTypeErrorSpan.ts(12,25): error TS2304: Cannot find name 'miss

// expression body
const b = (): number => "foo";
~~~~~
~~~~~~
!!! error TS2322: Type 'string' is not assignable to type 'number'.

type F<T> = T;
const c = (): F<number> => "foo";
~~~~~
~
!!! error TS2322: Type 'string' is not assignable to type 'number'.

const d = (): number => missing;
Expand Down
4 changes: 2 additions & 2 deletions tests/baselines/reference/conditionalTypes1.errors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ conditionalTypes1.ts(160,5): error TS2322: Type 'T' is not assignable to type 'Z
Type 'string | number' is not assignable to type 'ZeroOf<T>'.
Type 'string' is not assignable to type 'ZeroOf<T>'.
conditionalTypes1.ts(263,9): error TS2403: Subsequent variable declarations must have the same type. Variable 'z' must be of type 'T1', but here has type 'Foo<T & U>'.
conditionalTypes1.ts(288,43): error TS2322: Type 'T95<U>' is not assignable to type 'T94<U>'.
conditionalTypes1.ts(288,33): error TS2322: Type 'T95<U>' is not assignable to type 'T94<U>'.
Type 'number | boolean' is not assignable to type 'T94<U>'.
Type 'number' is not assignable to type 'T94<U>'.
Type 'boolean' is not assignable to type 'true'.
Expand Down Expand Up @@ -465,7 +465,7 @@ conditionalTypes1.ts(288,43): error TS2322: Type 'T95<U>' is not assignable to t
type T95<T> = T extends string ? boolean : number;
const f44 = <U>(value: T94<U>): T95<U> => value;
const f45 = <U>(value: T95<U>): T94<U> => value; // Error
~~~~~
~~~
!!! error TS2322: Type 'T95<U>' is not assignable to type 'T94<U>'.
!!! error TS2322: Type 'number | boolean' is not assignable to type 'T94<U>'.
!!! error TS2322: Type 'number' is not assignable to type 'T94<U>'.
Expand Down
4 changes: 2 additions & 2 deletions tests/baselines/reference/mappedTypeConstraints2.errors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ mappedTypeConstraints2.ts(16,11): error TS2322: Type 'Mapped3<K>[Uppercase<K>]'
mappedTypeConstraints2.ts(42,7): error TS2322: Type 'Mapped6<K>[keyof Mapped6<K>]' is not assignable to type '`_${string}`'.
Type 'Mapped6<K>[string] | Mapped6<K>[number] | Mapped6<K>[symbol]' is not assignable to type '`_${string}`'.
Type 'Mapped6<K>[string]' is not assignable to type '`_${string}`'.
mappedTypeConstraints2.ts(51,57): error TS2322: Type 'Foo<T>[`get${T}`]' is not assignable to type 'T'.
mappedTypeConstraints2.ts(51,52): error TS2322: Type 'Foo<T>[`get${T}`]' is not assignable to type 'T'.
'T' could be instantiated with an arbitrary type which could be unrelated to 'Foo<T>[`get${T}`]'.
mappedTypeConstraints2.ts(82,9): error TS2322: Type 'ObjectWithUnderscoredKeys<K>[`_${K}`]' is not assignable to type 'true'.
Type 'ObjectWithUnderscoredKeys<K>[`_${string}`]' is not assignable to type 'true'.
Expand Down Expand Up @@ -75,7 +75,7 @@ mappedTypeConstraints2.ts(82,9): error TS2322: Type 'ObjectWithUnderscoredKeys<K
};

const get = <T extends string>(t: T, foo: Foo<T>): T => foo[`get${t}`]; // Type 'Foo<T>[`get${T}`]' is not assignable to type 'T'
~~~~~~~~~~~~~~
~
!!! error TS2322: Type 'Foo<T>[`get${T}`]' is not assignable to type 'T'.
!!! error TS2322: 'T' could be instantiated with an arbitrary type which could be unrelated to 'Foo<T>[`get${T}`]'.

Expand Down

0 comments on commit 796450a

Please sign in to comment.