Community
Participate
Working Groups
Error I get when compiling: The declared package does not match the expected package com.mycompany.package.subpackage I inherited some Java code from a company whose Java developers used reflection to load classes at run time that implemented an interface. These classes all had to be in the same package (com.mycompany.package). Because there were hundreds of these classes, they were organized in sub-directories such as com/mycompany/package/guitoolkit. Both JavaC and Jikes don't complain about this behavior - they compile the java classes to the com/mycompany.package directory. The Java Language Specification leaves this behavior up to the implementor of the compiler. I consider this to be a feature request, not a specific bug, although it forces me to not use Eclipse for compilation of this project.
Affected Source file is CompilationUnitScope.java in org.eclipse.jdt.internal.compiler.lookup Jeff
Batch compilers, like the Eclipse batch compiler, can take files located anywhere since there are all fed at once for batch compiling. However, in the case of an incremental compiler which will lazily discover files as it compiles, available files must be located in appropriate folders. You can try to compile your code with javac and not put your sources on the list of files to compile but rather directly on the classpath where they will be looked up. Your setup will cause necessary types to be not found. If you could reorganize these sources, I would suggest you use several source folders, like 'guitoolkit' so as to contain the various fragments of the same package.
You could use Ant scripts to compile your sources with a batch compiler. Closing
Incorrectly marked for verification.
This misfeature is a really ugly sore on eclipse. Deriving package name from directory structure is not part of the spec for filesystem based implementations. Please fix this
Well needless to say, we disagree. Gregg: How do you currently build/compile your source files?
I use Kawa as my IDE because it lets me add source files from anywhere and compile all of them into a single tree using 'javac -d'. This means that when I am using an old jar file in a new application, and I need to investigate a stack back trace, I can quickly add that source tree, and see it with my other files. When I compile it, the output goes into my classes directory, which is first in the classpath. If I need to make changes to those files, my SCM (perforce) will be used to check out the file. I make my changes, test them, and then submit the changes. Then, I can use that jar files Ant built to build the new version for production. The Java Language spec dictates that the package statement provides the package of the class. i.e. 7.3 Compilation Units CompilationUnit is the goal symbol (§2.1) for the syntactic grammar (§2.3) of Java programs. It is defined by the following productions: CompilationUnit: PackageDeclarationopt ImportDeclarationsopt TypeDeclarationsopt ImportDeclarations: ImportDeclaration ImportDeclarations ImportDeclaration TypeDeclarations: TypeDeclaration TypeDeclarations TypeDeclaration Types declared in different compilation units can depend on each other, circularly. A Java compiler must arrange to compile all such types at the same time. A compilation unit consists of three parts, each of which is optional: A package declaration (§7.4), giving the fully qualified name (§6.7) of the package to which the compilation unit belongs. A compilation unit that has no package declaration is part of an unnamed package (§7.4.2). import declarations (§7.5) that allow types from other packages to be referred to using their simple names Top level type declarations (§7.6) of class and interface types Which compilation units are observable is determined by the host system. However, all the compilation units of the package java and its subpackages lang and io must always be observable. The observability of a compilation unit influences the observability of its package (§7.4.3). Every compilation unit automatically and implicitly imports every public type name declared by the predefined package java.lang, so that the names of all those types are available as simple names, as described in §7.5.3. And then in 7.4 7.4 Package Declarations A package declaration appears within a compilation unit to indicate the package to which the compilation unit belongs. 7.4.1 Named Packages A package declaration in a compilation unit specifies the name (§6.2) of the package to which the compilation unit belongs. PackageDeclaration: package PackageName ; The package name mentioned in a package declaration must be the fully qualified name (§6.7) of the package. I don't see any allowance for the compiler/platform to arbitrarily choose the package. What is in the package statement is what is to be used.
No action planned. This isn't a bug but rather a standard rule for organizing sources and predictabily find them (without scanning directories all the time). There was numerous debate on that topic a long time ago, and we reached some consensus.
The spec says that the package statement must be used to control what package a source file compiles into, plain and simple. This needs to be fixed so that this is the behavior of the compiler. If other parts of the IDE don't work due to directory structure assumptions, then I would say that those pieces of the IDE are broken too. But, I can see that this is about your opinion and mantra for source file and directory organization. What other developers need to make use of eclipse doesn't seem to matter. Seems like this is just more of the IBM way of thinking. Our way or the highway... So much for open source...
Gregg: Insulting people is not going to win you anything. As was already mentioned, this discussion has already happened WITHIN the Eclipse Open Source Community. Look at the date on this PR, it was over a year ago & your the first person to voice a dissenting opinion in the last 16 months. So keep your insults to yourself.
I am sorry that you feel insulted. I feel like I am talking to a brick wall. I know many well seasoned java programmers that have tried eclipse, and just deleted it at the sight of this issue and other issues. Regarding the time frame that you last visited this issue, perhaps the interested people already had an IDE that worked for them at that point and weren't flocking to eclipse to give it a whirl just because it was the lastest thing to hit the streets. This is strickly a language support issue. The spec says that the compiler must honor the package statement. The Eclipse built-in compiler does not. I'm not trying to be hateful or insulting. I do not do that casually. I am using the words I am using because I don't understand your position on this issue. The language spec says you are wrong. Like it or not, that's the truth!
Email from Gregg Wonderly: I found this draft sitting around and am not sure that I sent it to you. Please excuse the duplicate if so. This issue is important to me and I want to make sure that I have conveyed my concerns. >Note that on a batch compiler command line, one can specify source folders >on the classpath, and these have to be at locations exactly matching their >package declarations. We simply generalized this approach and made it the >default law, so that our tool could pick arbitrary sources on the classpath >without needing the help for external maps from type to files etc... Okay, so you want to optimize how the IDE works. But, the problem is you are still violating the language spec. The package statement is part of the language requirements. If the compiler is reading the source file, it is seeing the package statement. As it is compiling, it must use the package statement to control what package it puts the compiled class file output into. If the rest of the IDE breaks, then it, also is ignoring the language specification. Optimizations are great, right up to the point that they create more compromises in the design of the software then the apparent optimizations that are being attempted. I guess I'd think that if this one issue makes a world of difference in the performance of the IDE, then there is a lot more speed to be gained elsewhere, and fixing this issue is only the first thing that needs to be done. What you could do is provide a factory, static method for source file location tracking. When the compiler sees the package statement, and finds it to be different from the directory structure, then it should put an entry into the map. The factory method should do a get out of the map, and if there is no entry, it should return the package name passed. This way, those that have the ability to choose where their source files are, can put them into a directory structure that matches the package. They would not have 100's or 1000's of entries in the map. If one doesn't have that choice, then the compiler still meets the language spec, and the other parts of the IDE can still function with a disjoint source set. The size of the map will me purportional to the size of the total number of class files. If the compiler can recompile all source files at once, then the map can fit in memory too, with a proportionally small requirement for more RAM... It really is a big issue for many people that I have talked to. But, I suppose that it is possible that I've been doing Java development successfully just using 'javac -d ... -classpath ...' for 7 years and the directory trees that I've been using really don't work, and I really am not more productive when I don't have to navigate through 5 levels of directory trees when I am browsing with Windows Explorer, or using CD to move around in a source tree while recompiling on linux machines via SSH... But, I am not convinced it's just a dream yet... Your ideas and thoughts are not without merit regarding directory structure Phillpe. However, they are not universal, nor is it a reality that such order can exist always...
Thanks for your comment, I agree that we somewhat dictate a little too much what is good practice vs. what is not. For this very topic, the package clause in the source file will always be used to generate the file properly. If it doesn't match the directory location, we will also flag it. However, we will lookup a type based on the directory structure, rather than considering every single file and parsing them to figure which package they sit in. As I said, other compiler vendors do the same when performing source lookup, we are not different. We could indeed build a map (then need to refresh, etc...) and lookup through this map, this would require extra work, but is doable. At the moment, we don't think this would be cost effective. Also, one clarification. The compiler is never compiling all files in memory at once. It would blow up almost immediately unless your memory limit is super high. We only preserve in memory the signatures we need to compile files against each other, but only process one unit at a time in memory.
>For this very topic, the package clause in the source file will always be >used to generate the file properly. If it doesn't match the directory >location, we will also insist on it. >However, we will lookup a type based on the directory structure, rather >than considering every single file and parsing them to figure which package >they sit in. As I said, other compiler vendors do the same when performing >source lookup, we are no different. Javac does not appear to do this, as I can compile all of my class files with it on the command line. But, I suspect that it might. >We could indeed build a map (then need to refresh, etc...) and lookup >through this map, this would require extra work, but is doable. Here's how I see this issue being resolved. 1) The IDE has to initially know what files it knows about. When the IDE is made aware of a source file, it should find the package statement (the parse can stop at the first keyword that is not 'package') and update the map. 2) When the user edits a source file, the IDE can inspect the file on a Save or SaveAs request to make note of any change in the 'package'. 3) When an incremental compile is done, any to-be-compiled files are already being parsed, the 'package' can be updated at that time. 4) When the IDE first starts up, each time, I am assuming that the IDE must look for new files because it knows about files based to directory trees, not individual lists of files. This would also be the time to find package statements and update the map. You have already taken the time and effort to have the compiler be aware of this exact issue and have it issue a warning about the directory not matching the package statement. At that moment, the map should be updated and the warning changed to tell the user that the package has been set to the package statement and that there might be extraneous class files visible from the old package perhaps. I am just not convinced that this is a hard problem. The MAP is a very remedial piece of memory compared to the signature information that the compiler must track for each file. So, I am not convinced that there is a memory issue. Certainly, maintaining the map might be a bit of a pain, but if you make it an option, then those that have trees that are package structured can turn this off, and not encounter any measurable performance difference. Those who have source trees that aren't perfect, can still make use of the hard work of the eclipse team and not have to go off and create competing IDEs just to get work done...
*** Bug 48407 has been marked as a duplicate of this bug. ***
For what it's worth, I've always wanted to have my sources in a flat folder structure where all package folders are siblings and use the actual dot spearated package names as folder names. The hierarchic folder structure that is common in all tools (and not just Eclipse) does not reflect the logical organization of the software. I also find the flat structure much easier to browse and work with.
*** Bug 328398 has been marked as a duplicate of this bug. ***
We're now 10 years in the future, and this is something I've come across in three different projects in three different companies (and I've only seen three) over the last year. The unifying theme: Before me the developers on the projects were predominantly using IntelliJ, and IntelliJ doesn't care and compiles the classes in "wrong" packages. Some of them were the result of wild refactorings after whose the classes ended up with incorrect package declarations. I fixed those, but it's a big pain to explain to all the affected teams why I'm touching "their" code and proposing changes for them when they can't even see a warning. Some of the classes were generated by source-generating tools, in my case ANTLR (two different companies). Again, fixable, but annoying, and seems to be coming up fairly often. In the world where there are teams made of only IntelliJ devs who didn't even make their projects against the spec - maven and javac are still working fine - it's a problem to come and say "Hello, I'm your new dev and because I use a different, non-compliant tool, we need to touch dozens of classes mostly in a non-meaningful way". And that world is here, where I live I'm a minority as an eclipser. Oh, and this came up lately here: https://twitter.com/nipafx/status/1356535487515807744 Is eclipse after 10 years in a place where a change of this behaviour is no longer that costly / hard to do? If nothing changed, I assume this will not be reopened, but if at some point somebody refactored and/or consolidated package-recognizing logic, maybe it's time to alleviate this little limitation of ours and make the check an optional warning?