Bug 6584 - Need a way to get class files for a java file (or CU)
Summary: Need a way to get class files for a java file (or CU)
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 2.0   Edit
Hardware: PC All
: P3 enhancement with 3 votes (vote)
Target Milestone: 3.3 M6   Edit
Assignee: Olivier Thomann CLA
QA Contact:
URL:
Whiteboard:
Keywords:
: 51278 (view as bug list)
Depends on:
Blocks: 170310
  Show dependency tree
 
Reported: 2001-12-05 09:26 EST by Dani Megert CLA
Modified: 2007-03-20 07:34 EDT (History)
12 users (show)

See Also:


Attachments
Anonymous naming example (3.25 KB, text/plain)
2006-11-28 17:36 EST, Andrey Loskutov CLA
no flags Details
First draft (148.51 KB, patch)
2007-03-12 14:07 EDT, Olivier Thomann CLA
no flags Details | Diff
Regression tests (43.14 KB, patch)
2007-03-12 14:08 EDT, Olivier Thomann CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Dani Megert CLA 2001-12-05 09:26:29 EST
The JAR Packager currently goes through all .class files and looks if the source 
file name (==> internal API usage:(ClassFileReader.sourceFileName()) matches the  
given java file.

I need a better way to get all .class file paths (in the output folder) to a 
given .java file.

Of course it would also work, if the functionality is on ICompilationUnit.
Comment 1 Philipe Mulet CLA 2001-12-05 09:55:25 EST
This isn't on 2.0 plan for the moment. The trick is that it needs to be 
correlated with buid states and duplicated units (across multiple source 
folders).

Also, I think once we get there, there should be some way to gather the 
transitive closure of type to export (with excluding rules).
Comment 2 Jerome Lanneluc CLA 2003-04-25 07:20:05 EDT
Would need to return a set of IPath to the .class files.
Comment 3 Philipe Mulet CLA 2003-04-25 07:51:41 EDT
Kent - how feasible would it be to provide such an API ?
Comment 4 Philipe Mulet CLA 2003-10-28 04:55:53 EST
Also see similar request for surfacing the reference information: bug 45264
Comment 5 Jerome Lanneluc CLA 2004-02-06 07:43:52 EST
*** Bug 51278 has been marked as a duplicate of this bug. ***
Comment 6 Philipe Mulet CLA 2004-04-28 10:56:07 EDT
Defer. Will reconsider post 3.0
Comment 7 Jerome Lanneluc CLA 2004-09-23 06:26:16 EDT
Considering for 3.1
Comment 8 Frederic Fusier CLA 2005-02-17 11:07:05 EST
Not for 3.1 (it seems that blocked bug has been resolved using another way...)
Comment 9 Morten Christensen CLA 2006-02-19 05:24:21 EST
Well, I also need this feature and it has not been resolved for me.
Comment 10 Frederic Fusier CLA 2006-02-20 10:17:27 EST
API changes has been frozen at milestone 3.2 M5. So, Unfortunately it's too late, to put this change into 3.2 release. If you still need this feature for next release, then reopen the bug after 3.2 ship.
Comment 11 Philipe Mulet CLA 2006-09-15 05:14:55 EDT
Let's add it on the 3.3 plan.
Comment 12 Philipe Mulet CLA 2006-09-15 05:47:53 EDT
If autobuild is on, we may want to find the information directly from the build state. If not, then it would require scanning the classfile in proper folder, to check whether their source attribute denotes the proper file.
Comment 13 Philipe Mulet CLA 2006-09-15 05:48:17 EDT
If autobuild is on, we may want to find the information directly from the build state. If not, then it would require scanning ALL classfiles in proper folder, to check whether their source attribute denotes the proper file.
Comment 14 Andrey Loskutov CLA 2006-09-15 07:50:08 EDT
to comment 13 : if autobuild off and we will scan for class names, what happens with anonymous classes then?
In general, it would be very nice to have class file name assotiated with anonymous classes too.
Comment 15 Olivier Thomann CLA 2006-11-24 12:02:19 EST
What answer do you expect when:
1) no build has been run yet
2) the debug attributes were off (i.e. no source attribute)
3) The .class files are out of date ?

If we cannot return a reliable answer, then this is useless anyway.
Comment 16 Andrey Loskutov CLA 2006-11-24 12:19:50 EST
(in reply to comment 15)
For my purposes (I need .class file for given IJavaElement or at least IType) I would like to know:

"what the compiler would do if it would generate class files from given source", and "where it then would happen" (think on different output folders etc). In this case it is not important if the classes are out of date or not generated yet.

Currently it is very hard to compute all the information about where the particular class file would be generated and in case of inner/member/anon. type which name it would have.
Comment 17 Olivier Thomann CLA 2006-11-24 14:04:17 EST
(In reply to comment #16)
> "what the compiler would do if it would generate class files from given
> source", and "where it then would happen" (think on different output folders
> etc). In this case it is not important if the classes are out of date or not
> generated yet.
You can get the list of IType for ICompilationUnit.
From there, you know all the top level types.
It is not difficult to get the output folder for a specific ICompilationUnit.
Then you can get all .class files whose names are prefixed with the top level type names inside the given output location.
This can be done without adding any new APIs. The API would simply be a helper method and I am not too tempted to do this.

> Currently it is very hard to compute all the information about where the
> particular class file would be generated and in case of inner/member/anon. type
> which name it would have.
If the build is not done yet, we would need to "compile" the source to get this information. We could do it without generating the .class files, but this would be costly to do it that way. The names of generated anonymous and local types are computed very late (during the code generation in order to prevent generating them in case they are not reachable).
Comment 18 Olivier Thomann CLA 2006-11-24 14:04:39 EST
Also, why do you need this information ?
Comment 19 Emmanuel Geay CLA 2006-11-24 15:14:24 EST
(In reply to comment #18)
> Also, why do you need this information ?
> 

I'd personally answer to that question by: Any kind of analysis which is Java bytecode-based. Which represents many static analysis tools for instance. Let's imagine the following scenario. An end-user selects in Eclipse IDE a scope of analysis, a type or a method for instance for a dedicated analysis. Find out the right binary code for the scope selected requires a significant amount of code, to be done properly as emphasized before. In essence, if we would have to deal only with the top level types, I agree that it wouldn't be such a big deal, and an utility class would be sufficient enough. Now once we have to consider nested types and even more annoying anonymous types, this utility class tends to become a real module :-S Such request "For one source Java element, what is the bytecode related to?" sounds sufficiently helpful for many different things in my point of view. Concerning the case where the code wouldn't be yet compiled, I believe it would be quite acceptable to return nothing... rather that trying to produce the bytecode on the fly. Management of such cases is really client-dependent in my point if view.
I finish my comment with one question. You said "The names of generated anonymous and local types are computed very late (during the code generation in order to prevent generating them in case they are not reachable)". Does that mean it would be too tricky to provide such info?... After all, I'd say personally that this is the all purpose of this request :)
Comment 20 Andrey Loskutov CLA 2006-11-24 15:32:38 EST
(in reply to comment 17):
> You can get the list of IType for ICompilationUnit.
> From there, you know all the top level types.

Unfortunately this works only for *top level* types - all the anonymous/member types are *not* in the list.

> It is not difficult to get the output folder for a specific ICompilationUnit.
> Then you can get all .class files whose names are prefixed with the top level
> type names inside the given output location.
> This can be done without adding any new APIs. The API would simply be a helper
> method and I am not too tempted to do this.

I agree with you.

> If the build is not done yet, we would need to "compile" the source to 
> get this information. We could do it without generating the .class files, but > this would be costly to do it that way. 

I agree, and this would be 100% ok to throw an "Not generated/known yet" exception in this case.

> The names of generated anonymous and local types are computed very 
> late (during the code generation in order 
> to prevent generating them in case they are not reachable).

My intension was to get the assotiated class name for selected JavaElement - to see/compare the generated bytecode (see [1]). To do so, I have currently too much of very dirty code with some hardcoded assumptions about how the anonymous/member class names *may* look like after compilation :o) Currently there is no other way as hacking around, and this is the reason for me to support this enh. request. 

I know that only the compiler knows all this stuff but it would be very nice to have it also somehow after compilation.

[1] http://andrei.gmxhome.de/bytecode/index.html
Comment 21 Olivier Thomann CLA 2006-11-27 16:37:25 EST
What we could propose is:
- retrieve all .class files related to a ICompilationUnit, IType, IPackageFragment and IPackageFragmentRoot.
- this would include the resources that are copied to the output folder for IPackageFragment and IPackageFragmentRoot.
- if the .class files are not in synch, then the answer might be wrong (it would be based on last .class files generated).

If this is ok, then the question would be what kind of answer you expect? paths? fully paths? local paths?
Comment 22 Andrey Loskutov CLA 2006-11-27 17:22:56 EST
> What we could propose is:
> - retrieve all .class files related to a ICompilationUnit, IType,
> IPackageFragment and IPackageFragmentRoot.

Sounds good. So it would be also possible to get .class name to given anonymous (or member) IType? For example, if I have selected anonymous class in Java editor - I have IJavaElement (IType) as selection and could ask it which .class file name it have assotiated with?

> - if the .class files are not in synch, then the answer might be wrong (it
> would be based on last .class files generated).

I'm not sure if some kind of "IllegalStateException" may be thrown in this case? How one could distinguish between "good" and "bad" answers? Why this may happen - e.g. auto build is off? What if the classes weren't generated at all (if classes are built with Ant/Maven instead of Eclipse compiler)? Which answer it would then have - "null"?

> If this is ok, then the question would be what kind of answer you expect?
> paths? fully paths? local paths?

In the current code we are using absulute paths to pass them to the FileInputStream and then disassemble/analyze the bytecode. So it would be handy to have full absolute OS paths. If it would be relative paths we would need additional (unneeded) work to resolve the possible path variables/linked resources/different output folders etc by ourselves (I guess compiler uses absolute file names to write the bytecode :).
Comment 23 Dani Megert CLA 2006-11-28 03:00:10 EST
Adding Marting since he now owns the JAR Packager. The proposed collection of files would definitely reduce the code on our side.
Comment 24 Kent Johnson CLA 2006-11-28 10:36:23 EST
Because of links and the new Eclipse resource file system, we should answer resources or relative paths instead of absolute paths.

How do we propose to get the path for an anonymous type? Recompile the file?
Comment 25 Olivier Thomann CLA 2006-11-28 11:03:05 EST
(In reply to comment #22)
> Sounds good. So it would be also possible to get .class name to given anonymous
> (or member) IType? For example, if I have selected anonymous class in Java
> editor - I have IJavaElement (IType) as selection and could ask it which .class
> file name it have assotiated with?
Member types are not a problem. Anonymous types yes. I mean it is doable, but far from being efficient. I need to investigate the performance in this case. If this is reallly inefficient, we might only consider top level IType.

> I'm not sure if some kind of "IllegalStateException" may be thrown in this
> case? How one could distinguish between "good" and "bad" answers? Why this may
> happen - e.g. auto build is off? What if the classes weren't generated at all
> (if classes are built with Ant/Maven instead of Eclipse compiler)? Which answer
> it would then have - "null"?
When no .class files are available, it would answer an empty collection or array.
I don't like null.

> In the current code we are using absulute paths to pass them to the
> FileInputStream and then disassemble/analyze the bytecode. So it would be handy
> to have full absolute OS paths. If it would be relative paths we would need
> additional (unneeded) work to resolve the possible path variables/linked
> resources/different output folders etc by ourselves (I guess compiler uses
> absolute file names to write the bytecode :).
yes, but we are talking about the java model. So I think relative paths to the corresponding project would be a good answer. There is no much left to get the absolute paths if you really need them.
Comment 26 Andrey Loskutov CLA 2006-11-28 17:36:52 EST
Created attachment 54680 [details]
Anonymous naming example

> Member types are not a problem. Anonymous types yes. 

I fully agree. This is why it is very important to get this info from core and not compute it by hand. (btw, I discover again a bug in my code by creating the example how difficult is to calculate the right anonymous class name). 

Please see the attachment, where many anonymous classes are created in different methods (object initializer, constructor, static initializer, instance member and static member). The strings are just for better oriantation in bytecode, the comments behind strings shows what is generated by Eclipse compiler. And the generated names are not just reflecting the order in the source code - one can see, that compiler has a not immediately obvious rule in which the anon. class names are generated :)

And this is not only about *where* anon. class is declared, but the class names/generating order rule is *also* depends on the targeted class version - before 1.5 (class version <=48) and 1.5 and greater (class version >48). So for clients it's really really hard to compute proper class name for given anon. class.

> I mean it is doable, but far from being efficient. 

I'm not sure why it should be not efficient - it seems that the clients of such an API currently spend much more time by regenerating/creating all required info by hand (and may make mistakes by doing that manually). Or did you mean it would really slowdown compiler performance?

> I need to investigate the performance in this case.
> If this is reallly inefficient, we might only consider top level IType.

But for top level types it's already very easy to calculate class names, we do not need a new API for that? The real difficulties starts with anonymous classes and inner classes which may be nested in anonymous classes and so on. Top level classes are not the problem at all...
Comment 27 Olivier Thomann CLA 2006-11-30 15:17:40 EST
(In reply to comment #26)
> And this is not only about *where* anon. class is declared, but the class
> names/generating order rule is *also* depends on the targeted class version -
> before 1.5 (class version <=48) and 1.5 and greater (class version >48). So for
> clients it's really really hard to compute proper class name for given anon.
> class.
Right now I have a solution that seems to slow to me. It handles fine all anonymous classes in your example.

> I'm not sure why it should be not efficient - it seems that the clients of such
> an API currently spend much more time by regenerating/creating all required
> info by hand (and may make mistakes by doing that manually). Or did you mean it
> would really slowdown compiler performance?
This has no impact on the compiler since it is an API on the model side.
 
Rigth now we have two choices:
1) look at the already generated .class files and see which ones would match the corresponding IType. This might lead to inconsistencies if the .class files are out of date with the corresponding source. Cannot directly be used for anonymous types.
2) use the source of the corresponding compilation unit to "recompute" the name of the types inside the compilation unit and match them with the IType.
This is the way to go for anonymous types. This guaranties that the .class files names will match the generated .class files if both are in sync. This way can also be used for top level and member types.
The only problem with this one is that it is a bit too slow. I'll see if I can speed it up.

One more question:
should this API validate that the resources exist or simply returns a list of "potential" .class files names generated for a specific IType or ICompilationUnit?
Comment 28 Andrey Loskutov CLA 2006-11-30 15:40:00 EST
(In reply to comment 27)

Point 2) seems to be the better choice for me too, and for *my* needs the validation is not necessary in this case. It sounds that the API would return a list of *possible* class files/resources, even if the class files are not generated at all, so the validation wouldn't make much sense. I think it would be easy for clients to perform validation, once they know which files may be affected.
Comment 29 Sergey Bushkov CLA 2006-11-30 15:57:47 EST
(In reply to comments 28, 27)

Agreed, too - it's more useful to get which class file _should_ be there, than which one matches better ;) Also, you can have boolean parameter, say "force" - to re-compile class if it's out of sync.

I have another concern - sometimes there is a need to get _all_ .class files generated for particular source file. E.g., user selects a source file, and then all the generated bytecode should be passed to analyzer, etc. The current solution is to get all members from IType (methods, fields, etc), then get their members (possibly anonymous classes), etc. - recursively - and get .class files for such types. If it's possible to return such information from encapsulated data - that would be nice.
Comment 30 Olivier Thomann CLA 2006-11-30 16:04:23 EST
What about this?
/**
* Returns the list of relative paths to the workspace of the generated resources for this element.
*
* If returns for element of type:
* <ul>
* <li>{@link #JAVA_PROJECT}, {@link #PACKAGE_FRAGMENT_ROOT}, {@link #PACKAGE_FRAGMENT}: all generated resources
* for all compilation units contained in this element plus all the non-java resources of this element.</li>
* <li>{@link #TYPE}: all generated .class files</li>
* <li>{@link #COMPILATION_UNIT}: all generated .class files for each type contained in this element</li>
* <li>All other types of element would return an empty list</li>
* </ul>
*
* The returned value is accurate only and only if this element is synchronized with the build state.
*
* @return a list of absolute paths of the generated resources for this element
* @throws JavaModelException
*/
List getGeneratedResources() throws JavaModelException;

I hope that this means that all anonymous/local/member/top level types are returned when an ICompilation unit is passed in.
This also implies that IMethod, IField and IInitializer will always returns an empty list.
Let me know what you think?
Comment 31 Olivier Thomann CLA 2006-11-30 16:17:31 EST
I would not throw a JavaModelException.
If something goes wrong trying to access the java element, then an empty list would be returned.
Comment 32 Andrey Loskutov CLA 2006-11-30 16:18:17 EST
to comment 30:
- javadoc comment says at the top: "Returns the list of relative paths to the workspace", on the bottom: "@return a list of absolute paths".
- third line: "If returns" shouldn't be "I*t* returns"
- as long JDT does not uses generics, I would prefer IPath[] as return value
- you do not include all types in a IMember because of performance reasons? It would be convinient to get all .class files which may be generated out of one particulare method. I personally do not need it, but it may be useful?

Comment 33 Olivier Thomann CLA 2006-11-30 16:58:55 EST
(In reply to comment #32)
> to comment 30:
> - javadoc comment says at the top: "Returns the list of relative paths to the
> workspace", on the bottom: "@return a list of absolute paths".
> - third line: "If returns" shouldn't be "I*t* returns"
Yes two mistakes. Fixed.

> - as long JDT does not uses generics, I would prefer IPath[] as return value
Doable.

> - you do not include all types in a IMember because of performance reasons? It
> would be convenient to get all .class files which may be generated out of one
> particular method. I personally do not need it, but it may be useful?
For performance reason, yes. This implies that I need to "recompile" the corresponding compilation unit. This is what I have to do for nested types already. I'd like to improve the performance as much as possible before committing anything.
Comment 34 Andrey Loskutov CLA 2006-11-30 17:17:56 EST
> This is what I have to do for nested types
> already. I'd like to improve the performance as much as possible 
> before committing anything.

Hmm, now I'm wondering if the method signature should be similar to org.eclipse.core.resources.IResource#accept(...) methods: 
/* [...]
 * @param depth the depth to which members of this resource should be
 * visited.  One of <code>DEPTH_ZERO</code>, <code>DEPTH_ONE</code>,
 * or <code>DEPTH_INFINITE</code>.
 * @see IResource#DEPTH_ZERO
 * @see IResource#DEPTH_ONE
 * @see IResource#DEPTH_INFINITE
 */
Path[] getGeneratedResources(int depth);

This would allow reduce overhead for those clients which doesn't need *all* (DEPTH_INFINITE) resources (like me :o) but also allow you to support all IMember types (again, I do not need it, but it seems to fit to this case).

BTW, this would also fix the problem with nested types: if I'm interested *only* in the one specific .class file generated for given anonymous IType, how I could distinguish this class name from other names, if this class contains nested classes??? I have no idea... Using the DEPTH_ZERO argument it wouldn't be a problem at all. Otherwise I would need to guess that the first element is the "root" class?

If you do not like the "depth", so shouldn't we specify in javadoc, that the first element (if any) corresponds to the "root" class if the argument is IType?
Comment 35 Andrey Loskutov CLA 2006-11-30 17:21:50 EST
Sorry, it sould be read as
*I*Path[] getGeneratedResources(int depth);
Comment 36 Olivier Thomann CLA 2006-11-30 20:34:34 EST
I don't like the idea of a depth. The outermost type has always the shortest name by construction.
This is enough to distinguish the outermost enclosing type from others.
Any other opinions on this?
Comment 37 Dani Megert CLA 2006-12-01 02:44:53 EST
NOTE: since you provide an API that returns the genereate resources, looking at the Java source files might not lead to the correct result because some resource might also not be in-sync i.e. need a build.
==> I would provide an API where the client can tell whether to do a build upfront or not (e.g. if auto-build is on you can assume that the class files are OK).

>should this API validate that the resources exist or simply returns a list of
>"potential" .class files names generated for a specific IType or
>ICompilationUnit?
I don't think this is needed since the client needs to check this anyway because the file might be deleted in-between.

It might be more efficient to not create IPath objects as a return value. Maybe we could return a string representing the relative path, so that clients can use new File(projectPath, relativePathString)? This might reduce the used memory when getting the list for a large project.

Regarding the depth: -1. In my opinion this makes no sense when asking for generated resources.

On what Java elements would this API be available?
Comment 38 Dani Megert CLA 2006-12-01 03:38:16 EST
>It might be more efficient to not create IPath objects as a return value. Maybe
>we could return a string representing the relative path, so that clients can
>use new File(projectPath, relativePathString)? This might reduce the used
>memory when getting the list for a large project.

Dani needs coffee. Actually, the output folders are resources and hence no fiddling with java.io.File ==> we should directly return IResource.
Comment 39 Philipe Mulet CLA 2006-12-01 03:41:37 EST
If client wants a build to occur prior, then why not simply requesting one ? This API would only map sources to existing classfiles (best effort). If classfiles are inconsistent, then it wouldn't perform perfectly, but still would be resilient.
You wouldn't want a full build to occur while calling this API.
Comment 40 Olivier Thomann CLA 2006-12-01 09:42:20 EST
(In reply to comment #37)
> On what Java elements would this API be available?
I would expect it to work on IJavaProject/IPackageFragmentRoot/IPackageFragment/IType.
IType includes all kinds of types (anonymous, local, member, top-level).

I can return the IResource directly.

Now the question is what happens if there is no build state available. Should I use the code that "recompile" the compilation unit to extract all the names or I simply return an empty collection (array or list)?

In order to map the nested IType, I have no other solution but to use an ASTParser on the ICompilationUnit.
Comment 41 Olivier Thomann CLA 2006-12-01 10:31:03 EST
So this would end up with this method defined on org.eclipse.jdt.core.IJavaElement:
/**
 * Returns the resources that correspond to the generated resources for this element,
 * or an empty array if none.
 * 
 * <p>If returns for element of type:</p>
 * <ul>
 * <li>{@link #JAVA_PROJECT}, {@link #PACKAGE_FRAGMENT_ROOT}, {@link #PACKAGE_FRAGMENT}: all generated resources 
 * for all compilation units contained in this element plus all the non-java resources of this element.</li>
 * <li>{@link #TYPE}: all generated .class files</li>
 * <li>{@link #COMPILATION_UNIT}: all generated .class files for each type contained in this element</li>
 * <li>All other types of element would return an empty array</li>
 * </ul>
 * 
 * The returned value is accurate only and only if this element is synchronized with the build state.
 * 
 * @return the resources that correspond to the generated resources for this element, or an empty array if none
 */
IResource[] getGeneratedResources();

Any comment ?
Comment 42 Andrey Loskutov CLA 2006-12-01 10:46:30 EST
to comment 40:
 - I would prefer to return empty array if the build state is unknown

to comment 41:
 - You may add a notice, that this API is valid only if *internal* compiler is used to build Java projects (so the "build state" mean ECJ build state), and in case of external build tools like Ant/maven the answer is also undefined/empty.

BTW, you still have a typo: "If returns for" -> "It returns for" :o)
Comment 43 Olivier Thomann CLA 2006-12-01 10:54:34 EST
/**
 * Returns the resources that correspond to the generated resources for this element,
 * or an empty array if none.
 * 
 * <p>It returns for element of type:</p>
 * <ul>
 * <li>{@link #JAVA_PROJECT}, {@link #PACKAGE_FRAGMENT_ROOT}, {@link #PACKAGE_FRAGMENT}: all generated resources 
 * for all compilation units contained in this element plus all the non-java resources of this element.</li>
 * <li>{@link #TYPE}: all generated .class files</li>
 * <li>{@link #COMPILATION_UNIT}: all generated .class files for each type contained in this element</li>
 * <li>All other types of element would return an empty array</li>
 * </ul>
 * 
 * <p>The returned value is accurate if and only if this element is synchronized with the build state. Note this assumes
 * that the Eclipse java builder is used to build the project of this element. If this is not the case, an empty array
 * is returned.</p>
 * 
 * @return the resources that correspond to the generated resources for this element, or an empty array if none
 */
IResource[] getGeneratedResources();
Comment 44 Olivier Thomann CLA 2006-12-07 14:20:10 EST
I would remove the inclusion of non-java resources. These could be retrieved separately.
I would only preserve generated resources (generated by the java builder). It is not possible to "guess" what could be the generated resources when the java builder is not used.
This refers java-like resources (sqlj, aspectj,...). If another builder is used to create the .class files from the java-like resources, we cannot guess which ones they would be. So I am not sure this new API would improve the code in the JAR packager.
Any comment on this?
Comment 45 Martin Aeschlimann CLA 2006-12-08 03:27:35 EST
Makes sense. For the JAR exporter we would be happy to know what resources are being copied as well, but of course only what the Java builder does. I think it would be good to have the with the same API.
Comment 46 Olivier Thomann CLA 2006-12-08 10:16:56 EST
(In reply to comment #45)
> Makes sense. For the JAR exporter we would be happy to know what resources are
> being copied as well, but of course only what the Java builder does. I think it
> would be good to have the with the same API.
These should be the non-java resources of the corresponding package, shouldn't they? And you already have an API to get them.
If I return both (.class files and copied resources), it is not possible to easily have only the .class files generated.
Comment 47 Martin Aeschlimann CLA 2006-12-08 10:42:59 EST
It actually requires some knowledge to find out
- where the non-Java resources go (project output folder or source folder specific output folder)
- which of them go there (with the 'Fitered resources' setting from the Compiler> Build Path page)
So we would be glad to also get that information.

My thinking is that if somebody is only intersted about class files, then he probably uses the API with ICompilationUnit as argument. With IPackageFragment you also get non-java resource.
Or we add a boolean to the new method that specifies if non-Java resources should be considered as well.
Comment 48 Olivier Thomann CLA 2006-12-12 21:48:28 EST
Move to 3.3M5 since this is getting late for M4 and it is still unclear what we really can do.
I'll try to get a new proposal soon for this issue.
Comment 49 Olivier Thomann CLA 2007-02-01 11:29:49 EST
For now I cannot come up with a good API.
The case described in comment 26 can easily be handled using existing DOM API and the bindings.
So let's focus at the beginning of 3.3M6 cycle to determine what can be a useful API.
We would base it on the Java builder since we cannot guess what builder is used to build a certain file (SQLJ or AspectJ files for example).
If anybody has a suggestion, please speak up.
Comment 50 Olivier Thomann CLA 2007-02-26 11:34:21 EST
We could get this:

List getGeneratedResources() throws JavaModelException;
This would be defined on org.eclipse.jdt.core.IRegion. This would return results based on the Java builder.

Any comment?
Comment 51 Martin Aeschlimann CLA 2007-02-26 11:50:53 EST
Rather not on IRegion, which just defines a set of Java elements. But somthing like 

JavaCore.getGeneratedResources(IRegion) : IResource[]

makes sense to me.
Comment 52 Olivier Thomann CLA 2007-02-26 12:10:24 EST
I would pass an extra argument to tell if non-java resources are included or not.
Comment 53 Martin Aeschlimann CLA 2007-02-26 12:13:06 EST
sounds good to me!
Comment 54 Olivier Thomann CLA 2007-02-26 12:54:37 EST
So we would end up with:
/**
 * Returns an array that contains the resources generated by the Java builder when building the
 * compilation units contained in the given region.
 *
 * @param region the given region
 * @param includesNonJavaResources a flag that indicates if non-java resources should be included
 *
 * @return an array that contains the resources generated by the Java builder when building the
 * compilation units contained in the given region
 * @exception JavaModelException if an element in the given region does not exist or if an
 *		exception occurs while accessing its corresponding resource
 * @exception IllegalArgumentException if the given region is <code>null</code>
 */
public static IResource[] getGeneratedResources(IRegion region, boolean includesNonJavaResources) throws JavaModelException;

Let me know asap if you have any concern with this.
The case described in comment 26 can be done without any new API. If you need details for this, let me know.
Comment 55 Andrey Loskutov CLA 2007-02-26 14:22:24 EST
(In reply to comment #54)

> The case described in comment 26 can be done without any new API. If you need
> details for this, let me know.

Olivier, I would like to know how to get all this anonymous class names.

Comment 56 Olivier Thomann CLA 2007-03-12 14:07:58 EDT
Created attachment 60584 [details]
First draft

I'd like feedback on this API.
Please let me know if some cases are not handled.
Comment 57 Olivier Thomann CLA 2007-03-12 14:08:26 EDT
Created attachment 60585 [details]
Regression tests
Comment 58 Martin Aeschlimann CLA 2007-03-13 04:14:37 EDT
API looks good to me.
Comment 59 Philipe Mulet CLA 2007-03-13 12:01:16 EDT
+1 since we have commitment from UI to consume this API for 3.3.
Comment 60 Olivier Thomann CLA 2007-03-13 12:05:07 EDT
Released for 3.3M6.
Martin,
please give it a try and let me know asap if you find any problem with it.
Regression tests added in org.eclipse.jdt.core.tests.builder.GetResourcesTests
Comment 61 Philipe Mulet CLA 2007-03-13 12:15:10 EDT
Martin - if you are not consuming it in JAR exporter for 3.3, I propose we actually defer this feature addition until we have a client for it for real. I wouldn't want us to commit to an API without a usecase for it, and then first thing we would need to do in next iteration is to deprecate it to build the real one...

Any thoughts from other possible consumers ? (from CC list)
Comment 62 Tobias Widmer CLA 2007-03-13 12:27:52 EDT
This would be particularly useful for code instrumentation tooling such as Code Coverage tools. Usually, the instrumentation- or coverage scope is revealed to the user in source elements such as CUs. The code instrumentor implementation then has to find all classfiles which where generated from a CU.

This API reduces the code to compute this mapping, and possibly results in better performance than solutions which are not using this API.
Comment 63 Dani Megert CLA 2007-03-13 12:34:43 EDT
I think it should be pretty simple to switch to the new API in the JAR Exporter for 3.3 as this is concentrated in a single method. So - +1 to add this API for 3.3.
Comment 64 David Audel CLA 2007-03-20 07:34:28 EDT
Verified for 3.3 M6 using build I20070320-0010