From f4d76e5b934186717d0709daa91bd0ee97b4e581 Mon Sep 17 00:00:00 2001
From: Oleksandr T <oleksandr.tarasiuk@outlook.com>
Date: Sat, 26 Mar 2022 00:36:22 +0200
Subject: [PATCH] fix(48031): show circularity error for self referential get
 accessor annotations (#48050)

---
 src/compiler/checker.ts                            | 14 +++++++++-----
 ...ularGetAccessor(noimplicitany=false).errors.txt | 10 ++++++++++
 .../circularGetAccessor(noimplicitany=false).js    |  7 +++++++
 ...ircularGetAccessor(noimplicitany=false).symbols | 11 +++++++++++
 .../circularGetAccessor(noimplicitany=false).types | 11 +++++++++++
 ...cularGetAccessor(noimplicitany=true).errors.txt | 10 ++++++++++
 .../circularGetAccessor(noimplicitany=true).js     |  7 +++++++
 ...circularGetAccessor(noimplicitany=true).symbols | 11 +++++++++++
 .../circularGetAccessor(noimplicitany=true).types  | 11 +++++++++++
 tests/cases/compiler/circularGetAccessor.ts        |  5 +++++
 10 files changed, 92 insertions(+), 5 deletions(-)
 create mode 100644 tests/baselines/reference/circularGetAccessor(noimplicitany=false).errors.txt
 create mode 100644 tests/baselines/reference/circularGetAccessor(noimplicitany=false).js
 create mode 100644 tests/baselines/reference/circularGetAccessor(noimplicitany=false).symbols
 create mode 100644 tests/baselines/reference/circularGetAccessor(noimplicitany=false).types
 create mode 100644 tests/baselines/reference/circularGetAccessor(noimplicitany=true).errors.txt
 create mode 100644 tests/baselines/reference/circularGetAccessor(noimplicitany=true).js
 create mode 100644 tests/baselines/reference/circularGetAccessor(noimplicitany=true).symbols
 create mode 100644 tests/baselines/reference/circularGetAccessor(noimplicitany=true).types
 create mode 100644 tests/cases/compiler/circularGetAccessor.ts

diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index e7fe957e8635f..6c956a9037887 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -9628,13 +9628,17 @@ namespace ts {
             }
 
             let type = resolveTypeOfAccessors(symbol, writing);
-
             if (!popTypeResolution()) {
-                type = anyType;
-                if (noImplicitAny) {
-                    const getter = getDeclarationOfKind<AccessorDeclaration>(symbol, SyntaxKind.GetAccessor);
-                    error(getter, Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, symbolToString(symbol));
+                const getter = getDeclarationOfKind<AccessorDeclaration>(symbol, SyntaxKind.GetAccessor);
+                if (getter) {
+                    if (getEffectiveTypeAnnotationNode(getter)) {
+                        error(getter.name, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, symbolToString(symbol));
+                    }
+                    else if (noImplicitAny) {
+                        error(getter, Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, symbolToString(symbol));
+                    }
                 }
+                type = anyType;
             }
             return type;
         }
diff --git a/tests/baselines/reference/circularGetAccessor(noimplicitany=false).errors.txt b/tests/baselines/reference/circularGetAccessor(noimplicitany=false).errors.txt
new file mode 100644
index 0000000000000..b616c1ad8bfeb
--- /dev/null
+++ b/tests/baselines/reference/circularGetAccessor(noimplicitany=false).errors.txt
@@ -0,0 +1,10 @@
+tests/cases/compiler/circularGetAccessor.ts(2,9): error TS2502: 'foo' is referenced directly or indirectly in its own type annotation.
+
+
+==== tests/cases/compiler/circularGetAccessor.ts (1 errors) ====
+    declare class C {
+        get foo(): typeof this.foo;
+            ~~~
+!!! error TS2502: 'foo' is referenced directly or indirectly in its own type annotation.
+    }
+    
\ No newline at end of file
diff --git a/tests/baselines/reference/circularGetAccessor(noimplicitany=false).js b/tests/baselines/reference/circularGetAccessor(noimplicitany=false).js
new file mode 100644
index 0000000000000..ffe5c03a85d0b
--- /dev/null
+++ b/tests/baselines/reference/circularGetAccessor(noimplicitany=false).js
@@ -0,0 +1,7 @@
+//// [circularGetAccessor.ts]
+declare class C {
+    get foo(): typeof this.foo;
+}
+
+
+//// [circularGetAccessor.js]
diff --git a/tests/baselines/reference/circularGetAccessor(noimplicitany=false).symbols b/tests/baselines/reference/circularGetAccessor(noimplicitany=false).symbols
new file mode 100644
index 0000000000000..0afc5b19d1e5d
--- /dev/null
+++ b/tests/baselines/reference/circularGetAccessor(noimplicitany=false).symbols
@@ -0,0 +1,11 @@
+=== tests/cases/compiler/circularGetAccessor.ts ===
+declare class C {
+>C : Symbol(C, Decl(circularGetAccessor.ts, 0, 0))
+
+    get foo(): typeof this.foo;
+>foo : Symbol(C.foo, Decl(circularGetAccessor.ts, 0, 17))
+>this.foo : Symbol(C.foo, Decl(circularGetAccessor.ts, 0, 17))
+>this : Symbol(C, Decl(circularGetAccessor.ts, 0, 0))
+>foo : Symbol(C.foo, Decl(circularGetAccessor.ts, 0, 17))
+}
+
diff --git a/tests/baselines/reference/circularGetAccessor(noimplicitany=false).types b/tests/baselines/reference/circularGetAccessor(noimplicitany=false).types
new file mode 100644
index 0000000000000..bb7527742c71c
--- /dev/null
+++ b/tests/baselines/reference/circularGetAccessor(noimplicitany=false).types
@@ -0,0 +1,11 @@
+=== tests/cases/compiler/circularGetAccessor.ts ===
+declare class C {
+>C : C
+
+    get foo(): typeof this.foo;
+>foo : any
+>this.foo : any
+>this : this
+>foo : any
+}
+
diff --git a/tests/baselines/reference/circularGetAccessor(noimplicitany=true).errors.txt b/tests/baselines/reference/circularGetAccessor(noimplicitany=true).errors.txt
new file mode 100644
index 0000000000000..b616c1ad8bfeb
--- /dev/null
+++ b/tests/baselines/reference/circularGetAccessor(noimplicitany=true).errors.txt
@@ -0,0 +1,10 @@
+tests/cases/compiler/circularGetAccessor.ts(2,9): error TS2502: 'foo' is referenced directly or indirectly in its own type annotation.
+
+
+==== tests/cases/compiler/circularGetAccessor.ts (1 errors) ====
+    declare class C {
+        get foo(): typeof this.foo;
+            ~~~
+!!! error TS2502: 'foo' is referenced directly or indirectly in its own type annotation.
+    }
+    
\ No newline at end of file
diff --git a/tests/baselines/reference/circularGetAccessor(noimplicitany=true).js b/tests/baselines/reference/circularGetAccessor(noimplicitany=true).js
new file mode 100644
index 0000000000000..ffe5c03a85d0b
--- /dev/null
+++ b/tests/baselines/reference/circularGetAccessor(noimplicitany=true).js
@@ -0,0 +1,7 @@
+//// [circularGetAccessor.ts]
+declare class C {
+    get foo(): typeof this.foo;
+}
+
+
+//// [circularGetAccessor.js]
diff --git a/tests/baselines/reference/circularGetAccessor(noimplicitany=true).symbols b/tests/baselines/reference/circularGetAccessor(noimplicitany=true).symbols
new file mode 100644
index 0000000000000..0afc5b19d1e5d
--- /dev/null
+++ b/tests/baselines/reference/circularGetAccessor(noimplicitany=true).symbols
@@ -0,0 +1,11 @@
+=== tests/cases/compiler/circularGetAccessor.ts ===
+declare class C {
+>C : Symbol(C, Decl(circularGetAccessor.ts, 0, 0))
+
+    get foo(): typeof this.foo;
+>foo : Symbol(C.foo, Decl(circularGetAccessor.ts, 0, 17))
+>this.foo : Symbol(C.foo, Decl(circularGetAccessor.ts, 0, 17))
+>this : Symbol(C, Decl(circularGetAccessor.ts, 0, 0))
+>foo : Symbol(C.foo, Decl(circularGetAccessor.ts, 0, 17))
+}
+
diff --git a/tests/baselines/reference/circularGetAccessor(noimplicitany=true).types b/tests/baselines/reference/circularGetAccessor(noimplicitany=true).types
new file mode 100644
index 0000000000000..bb7527742c71c
--- /dev/null
+++ b/tests/baselines/reference/circularGetAccessor(noimplicitany=true).types
@@ -0,0 +1,11 @@
+=== tests/cases/compiler/circularGetAccessor.ts ===
+declare class C {
+>C : C
+
+    get foo(): typeof this.foo;
+>foo : any
+>this.foo : any
+>this : this
+>foo : any
+}
+
diff --git a/tests/cases/compiler/circularGetAccessor.ts b/tests/cases/compiler/circularGetAccessor.ts
new file mode 100644
index 0000000000000..b50bc7fc680c9
--- /dev/null
+++ b/tests/cases/compiler/circularGetAccessor.ts
@@ -0,0 +1,5 @@
+// @noImplicitAny: true, false
+
+declare class C {
+    get foo(): typeof this.foo;
+}