outfoxx/swiftpoet

SwiftPoet 1.6.1 Update: Scope Issue in Nested Struct Generation

Opened this issue · 3 comments

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) {

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 #52

@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.

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.