| Summary: | Building JSR 175 annotation into binding and exposing them through DOM | ||
|---|---|---|---|
| Product: | [Eclipse Project] JDT | Reporter: | Theodora Yeung <tyeung> |
| Component: | Core | Assignee: | Jim des Rivieres <jeem> |
| Status: | CLOSED FIXED | QA Contact: | |
| Severity: | enhancement | ||
| Priority: | P3 | CC: | carl_mcconnell, frederic_fusier, ghoren, philippe_mulet |
| Version: | 3.1 | ||
| Target Milestone: | 3.1 | ||
| Hardware: | PC | ||
| OS: | Windows XP | ||
| Whiteboard: | |||
| Attachments: | |||
Created attachment 19892 [details]
Containing patches for this bug
After unzipping the file, there are two directories, "ALL" and "API".
The directory named "ALL" has the diff for everything that I have done.
The files in there directory matches the directories under
"org.eclipse.jdt.core" in CVS.
The directory named "API" only has diff for new API.
The subdirectory named "dom" has API diff for the dom component and the one
named "compiler" has API diff for the compiler component.
The individual files in there are diffs for individual java files matched by
name. e.g compiler/MethodBinding.txt contains the diff for
org.eclipse/jdt/internal/compiler/lookup/MethodBinding.java
Please review.
I am still in the process of testing the new code and most likely will not pass
all the required tests. The purpose of this patch is simply to get some
feedback on the API as well as the implementation approach.
Created attachment 19893 [details] First patch for this bug (in another setup) I have added another attachment which is contains the patch itself for everything I have done in org.eclipse.jdt.core. Unlike the previous attachment, it is not a zip. This patch may include diff/patches for bug 87718 from Mike Kauffman. (We work off the same code base, outside CVS, and it is hard to generate a patch just for the work I have done.) The patches attached passed all the jdt.core tests. Created attachment 19925 [details]
Patch for the APT branch that passes all jdt.core tests
A new patch that compiles correctly under 1.4 that passes all the jdt.core
tests. This patch is for APT branch of org.eclip.jdt.core.
Created attachment 19927 [details]
patch to o.e.jdt.core/dom (APT branch) with improvements
Theodora, I've reviewed the DOM API portion of the patch. I believe the
proposed API additions will give client the access they need to annotation. I
have some suggested renamings and some small improvements.
public interface IResolvedAnnotation
ITypeBinding getAnnotationType();
IResolvedMemberValuePair[] getDeclaredMemberValuePairs();
IResolvedMemberValuePair[] getAllMemberValuePairs();
- rename from IAnnotationInstance to suggest it is resolved info like bindings
- add getAllMemberValuePairs to return implicit defaulted pairs as well; the
full list is what many clients will want
public interface IResolvedMemberValuePair
public String getName();
public IMethodBinding getMemberBinding();
public Object getValue();
- rename from IElementValuePair to suggest it is resolved info like bindings
- rename getElementValue -> getValue for consistency with
MemberValuePair.getValue
- rename getMethodBinding -> getMemberBinding
- delete getElementType; unnecessary; client can do
getMemberBinding().getResultType()
Annotation
public IResolvedAnnotation resolveAnnotation();
CompilationUnit
public ASTNode findDeclaringNode(IResolvedAnnotation resolvedAnnotation) {
- fine as proposed
IBinding
public IResolvedAnnotation[] getAnnotations();
- pull method up from ITypeBinding, IVariableBinding, IMethodBinding so that
package annotations are exposed as well
- change spec to return empty list rather than null, to make it more convenient
for clients
IMethodBinding
public IResolvedAnnotation[] getParameterAnnotations(int paramIndex);
public boolean isAnnotationMember();
public Object getDefaultValue();
- rename isAnnotationMethod -> isAnnotationMember for greater consistency (
the node type is named AnnotationTypeMember)
The patch is for the o.e.jdt.core/dom subtree only (APT branch) and has fleshed
out specs for everything.
Some of the other things I noticed
- all new API needs to be tagged with @since so that we have a record when the
API entered the platform. I didn't know what Philippe and you have discussed,
so I marked all the new classes and method @since 3.2 on the assumption that
they will appear only on 3.2.
- since there is new API involved, the test suites will need to be upgraded as
well to include tests for the new API elements
- the implementation classes AnnotationInstance and ElementValuePair are
public; since I doubt you intended these to be exposed as API, then should to
be package-private
- it would help if the code formatting followed the same conventions used
elsewhere in JDT Core
Thanks for the feedback. Will adjust the API and implementation as suggested. The one question I have is what exactly should the behavior be for IPackageBinding.getAnnotations(). Unlike types, fields or methods, there may be mutiple places that declared a package. I noticed that the jdt supports the recommended way of declaring package annotation which is through package- info.java. Does this mean that IPackageBinding.getAnnotations() should only return annotations declared at the package declaration inside package- info.java? So, if in some source file where there are package annotations, these annotatons should be ignored from the perspective of IPackageBinding.getAnnotations()? I don't think the information from package-info.java is being utilized. org.eclipse.jdt.internal.compiler.lookup.PackageBinding.getAnnotationTagBits() is always returning 0 as it didn't override the implementation at Binding. Is that correct? The reason I asked is that I am wondering how to get this piece of information back into the system. Thanks. Theodora Yeung The discussion section in JLS3 7.4.1.1 strongly recommends that the package declaration inside package-info.java be consider the only legitimate place to annotate a package declaration. So IPackageBinding.getAnnotations() should return those annotations. Frederic, perhaps you could take a look at the what's happing to the package annotations in the compiler. The compiler never needs the annotation info for package anywhere; only use could be to feed some downstream tools appropriately. A tool would expect to be able to access package annotations if there are any. How difficult would it be to retain the information when the package-info.java is compiled? I believe today, when package-info.java gets compiled, package-info.class gets generated. The annotation information is held by the by the synthetic type "package-info". The problem I have tody is not knowing how to retrieve this information back out from inside the compiler. I think if "package-info" is in binary form the problem can easily be solved. I Could simply go look for the type name "package-info" with the proper package name. However, if package-info.java exists, i.e. the package info is in source, then this approach would fail. The NameEnvironment would find the file and be able to create the proper compilation unit. However, the type does not actually exist in source, and the search fail. It seems like I am going around this problem the wrong way. Is there anyway to look for a file and parse it from the LookupEnvironment? We could imagine having the DOM AST binding support be able to read package-info.class in order to look for annotations. This might be confusing in the presence of package-info.java as well. Note that in the latter case, one can use the DOM AST to find out about source annotations. Proposeadding IResolvedMemberValuePair.isDefault(). This will be particularly useful when client iterate over the array of member value pairs that they obtain from IResolvedAnnotation.getAllMemberValuePairs() Adding IResolvedMemberValuePair.isDefault() would make good sense. Work is completed and checked into CVS. closing. Closing all completed bugs reports - *** Bug 90886 has been marked as a duplicate of this bug. *** This was fixed in 3.1 APT branch... Wrong change, changes was done in JDT/Core component. However, we have no input in buildnotes as it was done in APT branch. Set target as 3.1 but does not reflect the reality... |
The following is an outline for injecting annotation information into the type system bindings and making it available to DOM API users. Please comment and forward to a wider audience as necessary. 1)org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation objects will be created when the class file is first read. Just like the IBinaryType and IBinaryField objects inside the jdt compiler. 2)org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation will be turned into an org.eclipse.jdt.internal.compiler.lookup.Annotation at the same time when a IBinaryType is turned into a BinaryTypeBinding which occur during LookupEnvironment.createBinaryTypeFrom(IBinaryType, ...). 3)Also proposing a new class named "AnnotationBuilder", which has a similar role to the "BindingResolver" as both are responsible for turning the internal presentation of type system objects into the DOM version for public consumption. This propsed approached is very similar to how binary types are injected into the system. /* * New API added to * <code>org.eclipse.jdt.internal.compiler.env.IBinaryType</code>, * <code>org.eclipse.jdt.internal.compiler.env.IBinaryMethod</code> * <code>org.eclipse.jdt.internal.compiler.env.IBinaryField</code> */ public IBinaryAnnotation[] getAnnotations(); /** * This represents the data structure that would hold class file information * about each annotation instance. * This is parallel to {@link IBinaryType}, {@link IBinaryMethod} and * {@link IBinaryField}. * * Belongs in package "org.eclipse.jdt.internal.compiler.env". * Implementation of this interface will reside in package * "org.eclipse.jdt.internal.compiler.classfmt" and will be created at the * same time when the class file is first read. */ public interface IBinaryAnnotation { /** * @return the fully qualified name of the annotation type. */ char[] getTypeName(); /** * @return the list of member value pairs of the annotation */ IBinaryMemberValuePair[] getMemberValuePairs(); } /** * This represents the data structure that would hold class file information * about a member value pair of an annotaiton. * * Belongs in package "org.eclipse.jdt.internal.compiler.env". * Implementation of this interface will reside in package * "org.eclipse.jdt.internal.compiler.classfmt" */ public interface IBinaryMemberValuePair { /** @return the name of the member */ char[] getMemberName(); /** * Return * {@link org.eclipse.jdt.internal.compiler.impl.Constant} for compile-time * constant of type int, float, char, String etc. * Return * {@link org.eclipse.jdt.internal.compiler.env.IBinaryField} for enum * constant. * Return * {@link org.eclipse.jdt.internal.compiler.env.IAnnotation} for * annotation type. * Return <code>char</code>[] for member of {@link java.lang.Class} type * which contains the name of the type referenced. * Return <code>Object</code>[] for array type. * @return the value of this member value pair */ Object getMemberValue(); } /* * Adding the following APT to * <code>org.eclipse.jdt.internal.compiler.lookup.Binding</code> */ /** * @return the annotations that annotated this binding. */ Annotation[] getAnnotations(); /** * This is the API that presents an unified view of binary and source * anntotation. * This is also the API that will represent annotations in the type system * bindings. * * Belongs in package {@link org.eclipse.jdt.internal.compiler.lookup} */ public class Annotation { /** * @return the type of the annotation. */ org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding getAnnotationType() { throw new UnsupportedOperationException("NYI"); } /** * @return the list of member value pairs of the annotation */ AnnotationMemberValuePair[] getMemberValuePairs() { throw new UnsupportedOperationException("NYI"); } } /** * This is the API that presents an unified view of binary and source * anntotation member value pairs. * * Belongs in package {@link org.eclipse.jdt.internal.compiler.lookup} */ public class AnnotationMemberValuePair { /** * @return the method binding that declared this member value pair */ org.eclipse.jdt.internal.compiler.lookup.MethodBinding getMethodBinding() { throw new UnsupportedOperationException("NYI"); } /** * Return {@link org.eclipse.jdt.internal.compiler.impl.Constant} for * compile-time constant of type int, float, char, String etc. * Return {@link org.eclipse.jdt.internal.compiler.lookup.FieldBinding} * for enum constant. * Return {@link org.eclipse.jdt.internal.compiler.lookup.Annotation} for * annotation type. * Return {@link org.eclipse.jdt.internal.compiler.lookup.TypeBinding} for * member of {@link java.lang.Class} type. * Return <code>Object</code>[] for array type. * @return the value of this member value pair */ Object getMemberValue() { throw new UnsupportedOperationException("NYI"); } } Propose DOM API to expose JSR 175 annoation to clients. /* * New API added to org.eclipse.jdt.core.dom.IBinding */ /** * @return the JSR 175 annotations that annotate the binding. */ public IAnnotation[] getAnnotations(); /** * Represents an instance of JSR 175 that appears in source or from binary. * Belong to package {@link org.eclipse.jdt.core.dom} */ public interface IAnnotation{ /** * @return the type of the annotation. */ public ITypeBinding getType(); /** * @return the array of declared member value pairs of the annotation. */ public IMemberPair[] getDeclaredMemberPairs(); } /** * Belong to package {@link org.eclipse.jdt.core.dom} */ public interface IMemberPair { /** * @return the name of the member */ public String getName(); /** * Returns the compile-time constant value of the member value pair, * if one is available. * This may return null if bindings are not requested when * the DOM/AST is being built. * <p> * If the type of the value is a primitive type, the result * is the boxed equivalent (i.e., int returned as an <code>Integer</code>); * If the type of the value is <code>String</code>, the result is the * string itself. * Return <code>IVariableBinding</code> if the value is an enum constant. * If the value is of type {@link java.lang.Class}, return * <code>ITypeBinding</code> * that corresponds to the type referenced through the class literal. * (i.e., return the <code>ITypeBinding</code> that corresponds to the * primitive type "int" if the value is "int.class".) * Return {@link IAnnotation} if the value is a JSR 175 annotation. * Return an {@link java.lang.Object} array if the value is of array type. * Return <code>null</code> if the value is not a compile-time constant. * </p> * * @return the compile-time constant of the member value, or * <code>null</code> if it not have one or if bindings were not requested * when the AST was created * @since 3.1 */ public Object getValue(); }