outfoxx / swiftpoet

Kotlin and Java API for generating .swift source files.
Apache License 2.0
277 stars 26 forks source link

SwiftPoet 1.6.1 Update: Scope Issue in Nested Struct Generation #109

Open PaulWoitaschek opened 6 months ago

PaulWoitaschek commented 6 months ago

With SwiftPoet 1.6.1, there seems to be an issue with nested scope resolution.

Generating Code

FileSpec.builder("file")
  .addType(
    TypeSpec.structBuilder("A")
      .addFunction(
        FunctionSpec.constructorBuilder()
          .addParameter(
            ParameterSpec.builder(
              parameterName = "c",
              type = DeclaredTypeName.typeName("A.B.C"),
            ).build(),
          )
          .build(),
      )
      .addType(
        TypeSpec.structBuilder("B")
          .addType(
            TypeSpec.structBuilder("C")
              .build(),
          )
          .build(),
      )
      .build(),
  )
  .build()

Output of 1.6.1

This does not compile, as the c: C is not in the scope of A.

import A

struct A {

  init(c: C) {
  }

  struct B {

    struct C {
    }

  }

}

Output of 1.6.0

This successfully compiles

struct A {

  init(c: B.C) {
  }

  struct B {

    struct C {
    }

  }

}

Diff

0a1,2
> import A
>
3c5
<   init(c: B.C) {
---
>   init(c: C) {
PaulWoitaschek commented 6 months ago

This can be worked around by qualifying:

DeclaredTypeName.typeName("A.B.C", alwaysQualify = true)

I would recommend to remove the alwaysQualify parameter and make it true by default. Generated code should mostly be correct. Also see the discussion in https://github.com/outfoxx/swiftpoet/issues/52

kdubb commented 6 months ago

@PaulWoitaschek Thanks for the filing the issue. WRT alwaysQualify as stated in the discussion referenced we are not removing it; we will fix the issues and add test coverage for them.

PaulWoitaschek commented 6 months ago

From my understanding it's not possible to fix it. (This specific bug is fixable ofc). With swifts ambiguous importing system you will always have a clash if something already exists with the same name in a project.

The only way to generate truly correct code is to overcome that umbiguity of swift by generating very explicit code.

Just like in kotlinpoet you don't generate a wildcard import but instead are very specific about your imports.