[ODLPARENT-300] Revisit annotation artifact dependencies Created: 10/Mar/23  Updated: 04/Jun/23  Resolved: 30/May/23

Status: Resolved
Project: odlparent
Component/s: General
Affects Version/s: None
Fix Version/s: 13.0.0

Type: Improvement Priority: Medium
Reporter: mikael petterson Assignee: Robert Varga
Resolution: Done Votes: 0
Labels: pt
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Attachments: PNG File image-2023-03-15-14-02-18-101.png    
Issue Links:
Relates
relates to ODLPARENT-302 Unneeded artifacts included in features Resolved

 Description   

When we build in Eclipse or VisualStudio we get the following errors:

The type org.eclipse.jdt.annotation.NonNullByDefault cannot be resolved. It is indirectly referenced from required type org.opendaylight.yangtools.yang.parser.api.YangParserConfiguration{color}{color:#d4d4d4}Java(16777563)

This as per the below analysis, this seems to stem from <scope>provided</scope> dependencies provided by odlparent/pom.xml. Downstreams which do not have those implicit dependencies can observe such missing references.



 Comments   
Comment by Robert Varga [ 13/Mar/23 ]

Can you provide an example project?

Comment by mikael petterson [ 14/Mar/23 ]

You can close it. I could bypass in Eclipse.

Comment by Robert Varga [ 14/Mar/23 ]

Thinking about this a bit – I think I know what is going on.

ODL projects are all derived from odlparent, which provides Eclipse annotations as <scope>provided</scope>, so we do not generally see this issue – but it kinda is a real one, as for our docs artifacts we need to spell them out.

While annotations are completely optional at runtime, at least some of them end up being visible in our API contracts, hence rather than being scope=provided, they should be optional dependencies. This is certainly true of immutables.org and checker-qual (for which we already do some amount of dancing). JDT annotations seem to also fall into this category.

At the end of the day these end up falling into three buckets based on their RetentionPolicy:

  • RetentionPolicy.SOURCE are clearly scope=provided, as they do not leak outside of build project (@MetaInfServices falls here)
  • RetentionPolicy.CLASS are probably scope=compile, optional=true, which means we need to deal with their packaging (i.e. filter for features)
  • RetentionPolicy.RUNTIME are an extension of RetentionPolicy.CLASS, but we also need to evaluate how our supported runtimes interact with them
Comment by mikael petterson [ 15/Mar/23 ]

Hi rovarga 
Yes I just found a way to get around this in Eclipse. I disabled Null analysis.

So there will be no fix until version 13? We use 8.0.9

I guess I can live with it. Thanks for the explanation though.

//mikael

 

Comment by Robert Varga [ 15/Mar/23 ]

That's odlparent-13, which may or may not be Potassium.
The project you are seeing this in can be fixed by adding either

      <dependency>
        <groupId>org.eclipse.jdt</groupId>
        <artifactId>org.eclipse.jdt.annotation</artifactId>
        <version>2.2.700</version>
        <scope>provided</scope>
      </dependency>

(which is what all ODL projects do implicitly) or

      <dependency>
        <groupId>org.eclipse.jdt</groupId>
        <artifactId>org.eclipse.jdt.annotation</artifactId>
        <version>2.2.700</version>
        <optional>true</optional>
      </dependency>

(which what this issue will end up doing, I think)

In both cases you can omit the version if you pick it from odlparent (through a dependencyManagement import)

Comment by Robert Varga [ 30/May/23 ]

An unfortunate side-effect of this is that optional stanza is not propagate via dependencyManagement, requiring users to repeat the declaration.

Comment by Robert Varga [ 30/May/23 ]

So the first cut is in – it requires all dependencies to be explicitly declared, which in turn ends up being quite invasive. We'll see where this goes.

Comment by Robert Varga [ 30/May/23 ]

Okay, so this ends up being ugly beyond words.

The problem is not jdt.annotation, which ends up being an API contract – and hence we just end up 'requires static transitive' it.

The problem are other annotations on public class, which DO NOT form API contracts, like:

  • @SuppressFBWarnings, which we definitely do not want to require transitive to, as they are purely local things to make SpotBugs behave. For that we essentially need to create package-private utility method holders, which are annotated and provide enough rope for the usual code
  • @SuppressModernizer, where we explicitly provide things like bridges to Future.transform(), which invariantly must take Guava's Function. For those we drop the annotation and widen suppression to cover the entire artifact

So we end up battling what is essentially insane tool semantics. I just do not get why a tool like Eclipse would need to resolve an upstream annotation on a private method in a subclass. It is private and retention=CLASS for $DEITY's sake, so the world is not fluffing coming down – but hey, we absolutely MUST resolve it. Okay, yeah, that make some sense – in which universe?! It is by JLS definition a private detail (especially in JPMS world). Why in the seven circles of anti-Valhalla would a subclass ever even care about that?!

Generated at Wed Feb 07 20:28:09 UTC 2024 using Jira 8.20.10#820010-sha1:ace47f9899e9ee25d7157d59aa17ab06aee30d3d.