This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.
Summary: | Allow exclusion of packages/classes in classpath | ||
---|---|---|---|
Product: | java | Reporter: | maxnitribitt <maxnitribitt> |
Component: | Source | Assignee: | Svata Dedic <sdedic> |
Status: | RESOLVED WONTFIX | ||
Severity: | blocker | CC: | dcaoyuan, dstrupl, issues, jglick, markiewb, mkleint, musilt2, vieiro |
Priority: | P2 | ||
Version: | 6.x | ||
Hardware: | All | ||
OS: | All | ||
URL: | http://lahoda.info/hg/nb-patches/raw-file/tip/170231-excludes-on-compile-classpath | ||
Issue Type: | ENHANCEMENT | Exception Reporter: | |
Bug Depends on: | |||
Bug Blocks: | 49026 | ||
Attachments: | Something to be qfold'ed in |
Description
maxnitribitt
2009-08-11 20:50:51 UTC
The API in ClassPath does permit you to specify that only part of a binary entry should be used, but the Java indexer simply ignores this information as far as I know, so no one bothers specifying it. (Includes/excludes are currently used only for ClassPath.SOURCE.) NetBeans module projects do _not_ offer only "appropriate" classes in code completion, fix imports, etc. due to the lack of this feature. Public packages are enforced only during the build. Could also be used to prevent sun.** classes from being used in a project accidentally. I remember there was some effort to implement this as an editor hint, but I think it would be cleaner for the JavaPlatform.getBootstrapLibraries() to exclude these classes from the start. That would also leave the decision on which classes to exclude ultimately in the control of the project's ClassPathProvider, which in the case of BOOT would normally delegate to the JavaPlatform. AccessibilityQueryImplementation controls only the icons of packages displayed in the Projects node. It currently has no effect on anything else. (Anyway it would be useless for implementing this feature because the list of packages "accessible" depends in general on who is doing the accessing, and AQ does not represent the accessor. For example, with NetBeans module projects, an implementation dependency gives you access to all packages.) The situation with project dependencies is actually worse than for binary-only dependencies. If you had a dependency that existed only in binary form, as a hackish workaround at least you could "distill" a public package JAR (akin to what the module build harness does) and substitute that in the IDE classpath. But when there is a source association (such as when the JAR is known to be the output of a project), you need to implement SourceForBinaryQueryImplementation accordingly, and in that case the Java parser would completely ignore the contents of the JAR and just scan the dependency's source tree. Summary of request: any parser-aware features which can offer classes found in ClassPath.COMPILE or .BOOT should check whether the classpath actually includes that class. (For example, you can use ClassPath.Entry.includes("fully/qualified/Name.class").) If not, treat the class as missing: code completion should not offer it, Fix Imports should not consider it, usages should be flagged as errors by the background compiler, etc. Changes to the inclusion set (PROP_INCLUDES) should trigger a rescan of the depending project. Note: for efficiency you could try to avoid parsing excluded packages when the depending project is opened. But it is OK to parse them so long as they are not visibly offered, and anyway another depending project might not exclude those packages. *** Issue 168906 has been marked as a duplicate of this issue. *** Conceptually not so difficult, IMO, although the practical implications might be non-trivial. Especially possible performance regressions need to be prevented. In the Java support, the support would be split into (at least) two parts, IMO: -the parser should automatically ignore excluded classes - many features would then get the exclusion support for free, as they solely use the parser data -the output from the class index needs to be filtered - not sure if that could be done on the API level, or if the individual features would need to implement the check themselves. Also, the PROP_INCLUDES event is insufficient - it does not cover changes that happened while the IDE was not running. A textual includes/excludes specification needs to be stored persistently in the cache and checked on start-up. This will require an API change, IMO. Not sure if this belongs in java.source or parsing.api. An incl/excl spec in Ant patternset format may be trivial for some clients, harder for others; the API does not assume that the incl/excl is computed in any particular way. Are you sure this is necessary? Perhaps just persist the set of resource paths that were actually included and thus considered whenever doing a scan of a source root (or JAR). When the IDE is restarted and the same root is activated again, you will already be doing an up-to-date check anyway; if this results in a different set of resource paths, you know some classes have been added or removed. In fact I would guess the parser cache already does everything it needs to, since of course files can be added or removed during IDE shutdown even when there are no excludes. And you already need to be doing something for excludes in ClassPath.SOURCE, right? *** Issue 167848 has been marked as a duplicate of this issue. *** According to issue #167848 at least part of this regressed in 6.7. Jan please comment and generally take over this issue from Rasta... Issue #167848 is about excludes on source path, which where supported in 6.0-6.5, and which indeed regressed in 6.7 (fixed in current trunk, AFAIK). Not a true duplicate of this issue: as I understand this issue, it is about excludes on compile classpath (which was/is not supported by Java infrastructure in any release so far). I have an experimental patch for exclusion support on compile/bootclasspath here: http://lahoda.info/hg/nb-patches/raw-file/tip/170231-excludes-on-compile-classpath Comments to the current version of the patch: -very experimental -the apisupport.project part is a placeholder only (includes anything that has /api/ or /spi/ in path, nothing else). I probably won't be able to provide correct implementation for apisupport.project. Jesse, it would be awesome if you could provide an impl. for apisupport.project, so I could try to actually use the patch in my daily work. Thanks in advance. -changes to include/exclude filter do not force rescan/reindex. With the current API, we would (IMO) need to store all included and excluded files used during indexing, and check whether they are still included/excluded on each start, at least. I see several problems with this: a) I currently do not know where to record the includes/excludes (CacheClassPath might be a reasonable place, but I am not sure) b) there may be very many tested files for a big project - the list of these would need to be serialized to disk, deserialized on start and passed to ClassPath.includes. This seems to me like a waste of I/O and CPU power (esp. if no exclude pattern is specified). If we could get a small string token from the SPI, that would somehow identify the exclude pattern, it could save a lot of trouble. Note that for ClassPath.SOURCE the situation is a bit different: we stat all the source files (to check the timestamp), so passing the name to CP.includes is not so big problem (would be better if CP.includes would take CharSequence instead of String, but that hopefully does make a big difference). -I made a simple extension to the ClassPath SPI to simplify implementation of FilteringPathResourceImplementation, but that is not crucial for the changes in Java parsing infrastructure. -the patch filters results from ClassIndex to only include the included results automatically. Parser should also only see included classes. No changes to individual features should be necessary (unless the changes in ClassIndex are proven to be too slow). Not quite sure if the filtering of getPackageNames is correct - also depends on implementations of the exclude filter. -performance is mostly untested. I did a very quick perf. test in ClassIndex (and there was significant perf. hit only in one case, possibly GC). Needs to be tested more deeply. Would you mind if I turned the patch into a branch in the prototypes repo as per http://wiki.netbeans.org/PrototypesRepo#Patch_Branches ? That would make it much easier (I think) to collaborate on its development. If you would rather not, I can try to create a separate patch for apisupport to apply on top of what you have. Still not sure my comment #4 was answered, specifically why you need to do much work to handle changes in the set of included classes (say for COMPILE). There are three cases I can think of: 1. The entry "prefers sources" (e.g. subproject dependency). You already have some cache which I assume fixes the file stats (size & lastmod?) of all the corresponding **/*.java files. If the includes set changes, this would be no different from sources appearing or disappearing e.g. as after a VCS update - for which you would already be rescanning. 2. The entry does not prefer sources, but is an unpacked dir (probably rare). Essentially the same as #1, but you have stats for **/*.class. 3. The entry does not prefer sources and it is JAR. In this case you do need to store an extra piece of information representing the include set, but it should be of constant size and not need any SPI changes. For example, concatenate the names of all included classes and take the CRC-32; if this hash is different than when the cache was last updated, treat the JAR just like it had been rebuilt. Perhaps you are worried that in case #3 each class name needs to be passed to the includes(...) method to compute the hash? This method should be very fast (if no special incl/excl configured, just returns true immediately), but you would need to at least read the JAR entry names, which might otherwise have been unnecessary. If this must be avoided, rather than forcing the SPI to supply an Ant patternset (which might be completely inappropriate for some impls), ask it for an opaque hash. This could be as simple as public interface FilteringPathResourceImplementation2 extends FilteringPathResourceImplementation { /** hash of the algorithm used by {@link #includes} */ long includesHash(); } For the API side, ClassPath.Entry.hashCode could incorporate this hash if filter iof FPRI2, so java.source could simply use the CP.E.hC as a key into the index rather than the bare JAR URL as now. Well, the patch queue suits better my needs, but if you prefer a branch on prototypes, I have nothing against it (I think I easily can merge the changes from prototypes to my patch queue). Regarding the changes in the exclude pattern: I think it should work this way: consider api.progress/src and apisupport.project/src (which depends on a.prog/src). The (Java) cache for api.progress/src should contain classfiles for all Java source files defined in the source root (more precisely, for all classes/files that are included on the source path of api.progress/src). When indexing/compiling apisupport.project/src, only classes that are included on the compile classpath should be visible. When the exclude pattern changes when the IDE is shut down (e.g. the dependency is changed to implementation dependency), there is currently no process that would check whether the include/exclude pattern changed. The exclude pattern for source path of api.progress/src did not change, not timestamp changed, so no Java files "appeared/disappeared". Only the exclude pattern of the compile classpath changed, but to detect that with the current excludes API, it would mean that we would need to check whether classes in the cache of api.progress/src are included or excluded while indexing/compiling apisupport.project/src (+store the list of included/excluded classes, at least the classes that were queries while building the root). I do not think this is desirable, and would not scale well (if there would be 100 modules depending of api.progress/src, we would need to check the include property of the classfiles 100 times). The idea with the hash would work fine, I think. I would still prefer a string token (format unspecified, could be the RE pattern for J2SE project, and simple constants like "api"/"impl" for apisupport.project), as that would improve debuggability, but that is not so critical. Created attachment 92732 [details]
Something to be qfold'ed in
Thank you very much for the patch. I have merged it into the existing patch (might make sense to eventually split the patch into three parts - api, apisupport and java). I am currently running a build with this patch, to see if it works reasonably. *** Bug 180429 has been marked as a duplicate of this bug. *** What is the current state of this old issue? STARTED since 2009-12-14? While I initially advocated for this, I have to come to think that it is unnecessary: higher-level approaches are more flexible. First of all, regardless of what the IDE does, your framework needs to detect private package violations and treat them as build errors, as e.g. nbm-maven-plugin does and MENFORCER-138 [1] will allow—or at least flag them in an analysis tool run after the build, such as JDepend, Lattix, or mvn dependency:analyze. That said, the IDE’s editor ought to give you early warning of such mistakes, but merely denying the existence of the private packages is rather extreme. org.netbeans.modules.whitelist (*) lets you mark “forbidden” usages in the editor with more finesse: individual methods/fields in a type may be distinguished, overrides may be distinguished from calls (**), and most importantly a textual description can be given rather than just a blank “type not found” error. In the future this API could probably be integrated with the Java editor hints API so that detected violations could actually be resolved by: - acknowledging the problem and deleting the import/call, perhaps replacing with an alternative where known (e.g. using Jackpot declarative hints) - requesting friend access, in the case of a NB module (***) - adding mandatory attributes to an OSGi import declaration (§3.7.7) - modifying the export policies of the API module, when its source project is known - explicitly declaring a transitive dependency, when that was the only violation (common in NB module development) - suppressing the warning (in case the user knows better) (*) Currently a friend API only but could be promoted. (**) Not yet implemented but planned for in the API. Useful e.g. for OSGi projects which conventionally distinguish “provider” from “consumer” interfaces: OSGi Core 4.3 spec §3.7.3. (***) Or in some other way requesting more access, e.g. as proposed [2]. [1] https://jira.codehaus.org/browse/MENFORCER-138 [2] http://wiki.netbeans.org/NbmPackageStability#Marking_stability_of_import I have run into an issue involving jBoss AS 7.1.3.Final. jboss-client.jar contains the JBoss Logging Annotation Processor, namely org.jboss.logging.processor.apt.LoggingToolsProcessor This annotation processor interferes with NetBeans' annotation processors. Is there a way to exclude this class from the classpath? I'm using this (via Additional Compiler Options) but it seems like a hack: -Xlint -Xlint:-serial -processor org.netbeans.modules.openide.windows.TopComponentProcessor,org.netbeans.modules.openide.util.NbBundleProcessor,org.netbeans.modules.openide.awt.ActionProcessor,org.netbeans.modules.settings.convertors.ConvertorProcessor @cappicard please use the user list. Your problem is unrelated—you just need to configure the project to not run this AP. Do not discuss more here. |