Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compilation Error: java.util.Map needs to be fully qualified when domain class is called Map #5135

Closed
NetzwergX opened this issue Aug 12, 2024 · 6 comments · Fixed by #5184
Closed
Assignees
Labels
Java type:bug A broken experience WIP
Milestone

Comments

@NetzwergX
Copy link

@jakarta.annotation.Generated("com.microsoft.kiota")
public class Map implements AdditionalDataHolder, Parsable {

    /**
     * Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well.
     */
    private Map<String, Object> additionalData;

    // ...

}

If the domain class for an endpoint is called Map (see above), the compilation fails due to the clash with the import java.util.Map. In those cases, the generated code is trivially fixed by removing the import and fully qualifying all instances where Map refers to java.util.Map:

Swagger config to try this out:

@baywet baywet transferred this issue from microsoft/kiota-java Aug 12, 2024
@baywet baywet added type:bug A broken experience Java labels Aug 12, 2024
@baywet baywet moved this from Needs Triage 🔍 to Todo 📃 in Kiota Aug 12, 2024
@baywet baywet added this to the Kiota v1.18 milestone Aug 12, 2024
@baywet
Copy link
Member

baywet commented Aug 12, 2024

Hi @NetzwergX
Thank you for using kiota and for reaching out.
This is typically handled in kiota by adding to the list of reserved names instead.
Is this something you'd like to submit a pull request for provided some guidance?

@baywet baywet added the status:waiting-for-author-feedback Issue that we've responded but needs author feedback to close label Aug 12, 2024
@NetzwergX
Copy link
Author

@baywet Thanks for pointing out the reserved names list. I am willing to provide a PR if I have a sufficient understand of what is going on.

What exactly is the effect of adding the class, e.g. Map, there? Would this lead to java.util.Map no longer being imported but always being referred to by FQN?

@baywet
Copy link
Member

baywet commented Aug 13, 2024

Not exactly, the result is that name cannot be used anymore for generated symbols (class names, enum names, enum members....).
Every time a symbol should be "Map", it'll instead be "Map_escaped" or something along those lines depending on language conventions.

@NetzwergX
Copy link
Author

I wonder if thats the desired solution when we look at where this converges. There are several dozens of imports declared in the generated code files.

  • I could provide a PR for just Map. This would solve this issue. It has two rather severe drawbacks, though. First of all, having the domain object called Map is quite desirable. Second, it would not solve all the other instances where a domain object is generated that has a name that clashes with some import.
  • I could provide a PR for all classes that are currently imported -- at least the ones I can find out about. This would take care of all possible domain names, but it would also severely restrict which domain names are valid. It also wouldn't really be future-proof, because when a new import is added in the future because the generated code is changed, that would need to be added as well.

The last point is also a problem for evolution overall and applies to the reserved classes list in general. Say today I generate a client that uses a name as domain object class name that ends up being on the reserved names list in some future version. This would make all code generated in the future, where that class name is escaped incompatible with the current code.

So overall, it seems a more robust solution would be highly desirable. And that is actually possible without too much effort. There are in general two approaches that can be used.

  • The easiest solution would be not to import anything at all and always use the FQN, which is guaranteed to be unique, to refer to any type in the generated source. This is a backwards compatible change and would be quite robust to changes in required types in the future. It has the disadvantage of making the generated source code files more verbose, though. Which only affects human-readability to some extend, but is irrelevant once compiled to bytecode.
  • The somewhat smarter solution would be to track all simple names and FQNs during generation and to disambiguate them while generating the code. I don't know how the Kiota generator works and how much effort this would be, but I have implemented this in the past to some extend. Suffice to say, this is a magnitude more complex to implement than the first offered solution.

From a robustness perspective, especially wrt. forwards- and backwards compatibility (of the generated api and model), it seems to me that dealing with this on the side of the source generator and by disambiguating the class names while generating is the preferable option. It also ensures that future evolution of the generated code does not require synced changes in the reserved words list, making changes less error-prone.

Personally, I'd go with just using FQNs everywhere when referring to types. Its the simplest to implement, offers all the advantages (robustness, forward- and backward compatibility both wrt. the generated source and evolution of the generated code) and has the only drawback of being more verbose on the source level.

Let me know what your thoughts are on this topic.

@microsoft-github-policy-service microsoft-github-policy-service bot added Needs: Attention 👋 and removed status:waiting-for-author-feedback Issue that we've responded but needs author feedback to close labels Aug 13, 2024
@baywet
Copy link
Member

baywet commented Aug 13, 2024

Thank you for the additional information.

We've been through this topic with dotnet #5020, #4796 and many more. The solution depends a lot on the internals of the compiler. FQNs often seems like a more favorable approach until you start having symbol names that match namespace segments...

The easiest to implement solution, with the least impact to existing clients that would potentially be refreshed, is the reserved names approach. We can always adjust later on based on people's feedback.

From looking at this list here are the types that would need to be added f not already present:

  • Map
  • HashMap
  • Collection
  • RequestAdapter
  • RequestInformation
  • RequestOption
  • HttpMethod
  • Parsable
  • AdditionalDataHolder
  • Objects
  • InputStream
  • SerializationWriter
  • ParseNode
  • Parsable
  • ParsableFactory
  • BackingStoreFactory
  • BackingStoreFactorySingleton
  • BackingStore
  • BackedModel
  • BigDecimal
  • QueryParameters
  • ParseNodeHelper
  • MultipartBody
  • UntypedNode

We're talking about ~30 reserved names, and we're not expecting this list to grow by much in the future.

Let us know if you have any additional comments or questions.

@baywet
Copy link
Member

baywet commented Aug 19, 2024

authored #5184

@baywet baywet removed Status: No Recent Activity status:waiting-for-author-feedback Issue that we've responded but needs author feedback to close labels Aug 19, 2024
@baywet baywet self-assigned this Aug 19, 2024
@github-project-automation github-project-automation bot moved this from Todo 📃 to Done ✔️ in Kiota Aug 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Java type:bug A broken experience WIP
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.

2 participants