| Summary: | PackageElements.getEnclosedElements() returns empty set | ||||||
|---|---|---|---|---|---|---|---|
| Product: | [Eclipse Project] JDT | Reporter: | Stephen Haberman <stephen> | ||||
| Component: | APT | Assignee: | Generic inbox for the JDT-APT component <jdt-apt-inbox> | ||||
| Status: | CLOSED WONTFIX | QA Contact: | |||||
| Severity: | normal | ||||||
| Priority: | P3 | CC: | eclipse | ||||
| Version: | 3.5 | ||||||
| Target Milestone: | --- | ||||||
| Hardware: | PC | ||||||
| OS: | Windows Vista | ||||||
| Whiteboard: | stalebug | ||||||
| Attachments: |
|
||||||
|
Description
Stephen Haberman
Created attachment 140824 [details]
processor example that uses PackageElement.getEnclosedElements()
I admit I may be using the API wrong, but in javac I'm watching for annotations on PackageElements and then walking into child TypeElements and it works fine. What makes me most cautious is how package annotations will work with small only-changed compile cycles. E.g. in a javac everything-at-once, it is pretty easy to reason about. But in Eclipse, if a package is annotated, when that annotation is first added, I'd expect to get an event for the package, and then see all of the classes (e.g. A, B, and C) in it (which is not happening right now). But when class D is added to the package, without an annotation directly on it, but on its package, will the processor still get fired for the class and/or package, so that I can now handle D? Granted, this is getting ahead of myself, and not really the point of this bug--stepping through, PackageElementImpl.getEnclosedElements has a typeNames variable that stays null because the "nameEnvironment instanceof FileSystem" check fails and so the set/list that is returned is always empty. Let me know if I'm doing something wrong. Thanks. Bug or no, my strong recommendation would be to avoid PackageElement.getEnclosedElements(). Implementing it requires inspecting the contents of every jar file on the classpath; with large jars, this can blow through the package cache, meaning it can have severe performance impact. Package annotations are one of the less well defined, and less well tested, areas of the spec - as you might imagine, convincing the compiler to pay attention to an illegal type name is not trivial. And you are quite right that incremental behavior is very poorly defined in this case. There may well be a bug here; I'll investigate. But if it's possible to change your annotation design or your processor design so that you don't need to find all the elements in a package, that would be my recommendation. Avoiding package annotations sound fine to me--it is just a convenience, not a requirement. In projects that use my annotation processor, I foresee annotating every class in the domain model with the same annotation, so that all domain classes get processed. A package annotation would be more convenient, but not strictly required. FWIW, in my use case, I wouldn't need the entire classpath searched, as I'm really only interested in classes that live immediately next to the "package-info.java" file on the file system. Perhaps that is what the current implementation is trying to do, with the FileSystem cast that isn't working out. (In reply to comment #4) > FWIW, in my use case, I wouldn't need the entire classpath searched, as I'm > really only interested in classes that live immediately next to the > "package-info.java" file on the file system. I think that's probably the common use case. Unfortunately it's not the spec, and APT doesn't have any way to know whether you want the sane behavior or the specified behavior :-) A package fragment can live anywhere; indeed, one of the problems with package annotations is that there's no definition for what happens if package-info.java is found in more than one place. Also, there's no rule that says a package annotation can only be in package-info.java; that's just convention. Strictly speaking, any package declaration (on any type in the package) can be annotated and it is supposed to have the same effect. In practice, in an incremental compiler, it becomes one of those things that doesn't work well. (In reply to comment #5) > A package fragment can live anywhere; indeed, one of > the problems with package annotations is that there's no definition for what > happens if package-info.java is found in more than one place. I should clarify: JLS 3ed. 7.4.1.1 says "at most one annotated package declaration is permitted for a given package". It's just that we may have to search arbitrarily far to find it, and to ensure it's the only one. But anyway, the issue here is not so much the use of package annotations, as it is the use of PackageElement.getEnclosedElements(). It is reasonably efficient (although a bit tricky for APT, especially around incremental compilation) to ask for the annotations on a package; but there is no way for us to find all the elements within a package, without searching the entire classpath for contributing package fragments. This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet. If you have further information on the current state of the bug, please add it. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant. -- The automated Eclipse Genie. |