Repository: Matejkob/swift-spyable (swift)

Issue:
Variable declaration of forced unwrapped optional fails 
```swift
@Spyable protocol Name {
  var name: String!
}
```

**Error Message**
```
macro expansion @Spyable:30:29: error: using '!' is not allowed here; perhaps '?' was intended?
`- /Users/matejko/Developer/swift-spyable/Examples/Sources/ViewModel.swift:19:2: note: expanded code originates here
17 |   func append(name: (any Codable) -> (any Codable)?)
18 | //  func get() -> any Codable
19 | }
   +--- macro expansion @Spyable ---------------------------------------
   | 28 |         }
   | 29 |     }
   | 30 |     var underlyingAddress: (String!)!
   |    |                             `- error: using '!' is not allowed here; perhaps '?' was intended?
   | 31 |     var added: () -> Void {
   | 32 |         get {
   +--------------------------------------------------------------------
20 |
21 | final class ViewModel {
```

Pull request description:
Resolve #95 

Add support for such a declaration:
```swift
@Spyable protocol Foo {
  var name: String!
}
```

Patch:
diff --git a/Examples/Sources/ViewModel.swift b/Examples/Sources/ViewModel.swift
index c6b2141..0797ebf 100644
--- a/Examples/Sources/ViewModel.swift
+++ b/Examples/Sources/ViewModel.swift
@@ -5,6 +5,7 @@ protocol ServiceProtocol {
   var name: String { get }
   var anyProtocol: any Codable { get set }
   var secondName: String? { get }
+  var address: String! { get }
   var added: () -> Void { get set }
   var removed: (() -> Void)? { get set }
 
diff --git a/Sources/SpyableMacro/Factories/VariablesImplementationFactory.swift b/Sources/SpyableMacro/Factories/VariablesImplementationFactory.swift
index fdeff47..402ec73 100644
--- a/Sources/SpyableMacro/Factories/VariablesImplementationFactory.swift
+++ b/Sources/SpyableMacro/Factories/VariablesImplementationFactory.swift
@@ -53,8 +53,16 @@ struct VariablesImplementationFactory {
       // Since the count of `bindings` is exactly 1, it is safe to force unwrap it.
       let binding = protocolVariableDeclaration.bindings.first!
 
-      if binding.typeAnnotation?.type.is(OptionalTypeSyntax.self) == true {
+      /*
+       var name: String?
+       var name: String!
+       */
+      if binding.typeAnnotation?.type.is(OptionalTypeSyntax.self) == true ||
+          binding.typeAnnotation?.type.is(ImplicitlyUnwrappedOptionalTypeSyntax.self) == true {
         accessorRemovalVisitor.visit(protocolVariableDeclaration)
+      /*
+       var name: String
+       */
       } else {
         try protocolVariableDeclarationWithGetterAndSetter(binding: binding)
 


Test patch:
diff --git a/Tests/SpyableMacroTests/Factories/UT_SpyFactory.swift b/Tests/SpyableMacroTests/Factories/UT_SpyFactory.swift
index fe080e5..a63d730 100644
--- a/Tests/SpyableMacroTests/Factories/UT_SpyFactory.swift
+++ b/Tests/SpyableMacroTests/Factories/UT_SpyFactory.swift
@@ -413,6 +413,21 @@ final class UT_SpyFactory: XCTestCase {
     )
   }
 
+  func testDeclarationForcedUnwrappedVariable() throws {
+    try assertProtocol(
+      withDeclaration: """
+        protocol ServiceProtocol {
+            var data: String! { get set }
+        }
+        """,
+      expectingClassDeclaration: """
+        class ServiceProtocolSpy: ServiceProtocol {
+            var data: String!
+        }
+        """
+    )
+  }
+
   func testDeclarationExistentialVariable() throws {
     try assertProtocol(
       withDeclaration: """
diff --git a/Tests/SpyableMacroTests/Factories/UT_VariablesImplementationFactory.swift b/Tests/SpyableMacroTests/Factories/UT_VariablesImplementationFactory.swift
index ee49aa6..1a0304a 100644
--- a/Tests/SpyableMacroTests/Factories/UT_VariablesImplementationFactory.swift
+++ b/Tests/SpyableMacroTests/Factories/UT_VariablesImplementationFactory.swift
@@ -31,6 +31,13 @@ final class UT_VariablesImplementationFactory: XCTestCase {
     )
   }
 
+  func testVariablesDeclarationsForcedUnwrapped() throws {
+    try assertProtocolVariable(
+      withVariableDeclaration: "var foo: String! { get }",
+      expectingVariableDeclaration: "var foo: String!"
+    )
+  }
+
   func testVariablesDeclarationsClosure() throws {
     try assertProtocolVariable(
       withVariableDeclaration: "var completion: () -> Void { get }",