Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 90344

Summary: Building JSR 175 annotation into binding and exposing them through DOM
Product: [Eclipse Project] JDT Reporter: Theodora Yeung <tyeung>
Component: CoreAssignee: 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:
Description Flags
Containing patches for this bug
none
First patch for this bug (in another setup)
none
Patch for the APT branch that passes all jdt.core tests
none
patch to o.e.jdt.core/dom (APT branch) with improvements none

Description Theodora Yeung CLA 2005-04-05 14:54:42 EDT
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();
}
Comment 1 Theodora Yeung CLA 2005-04-13 23:23:50 EDT
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.
Comment 2 Theodora Yeung CLA 2005-04-13 23:29:14 EDT
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.)
Comment 3 Theodora Yeung CLA 2005-04-14 13:24:47 EDT
The patches attached passed all the jdt.core tests. 
Comment 4 Theodora Yeung CLA 2005-04-14 17:20:55 EDT
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.
Comment 5 Jim des Rivieres CLA 2005-04-15 01:34:26 EDT
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
Comment 6 Theodora Yeung CLA 2005-04-15 16:10:33 EDT
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

Comment 7 Jim des Rivieres CLA 2005-04-15 17:12:22 EDT
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.
Comment 8 Philipe Mulet CLA 2005-04-16 02:52:44 EDT
The compiler never needs the annotation info for package anywhere; only use
could be to feed some downstream tools appropriately.
Comment 9 Jim des Rivieres CLA 2005-04-16 20:23:25 EDT
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?
Comment 10 Theodora Yeung CLA 2005-04-18 22:20:04 EDT
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? 
Comment 11 Philipe Mulet CLA 2005-04-19 04:03:29 EDT
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.
Comment 12 Theodora Yeung CLA 2005-05-18 20:37:50 EDT
Proposeadding IResolvedMemberValuePair.isDefault(). 
This will be particularly useful when client iterate over the array of member 
value pairs that they obtain from IResolvedAnnotation.getAllMemberValuePairs()
Comment 13 Jim des Rivieres CLA 2005-05-19 08:31:25 EDT
Adding IResolvedMemberValuePair.isDefault() would make good sense.
Comment 14 Theodora Yeung CLA 2005-08-04 16:34:12 EDT
Work is completed and checked into CVS. closing.
Comment 15 Theodora Yeung CLA 2005-10-20 18:24:13 EDT
Closing all completed bugs reports
Comment 16 Theodora Yeung CLA 2005-10-20 18:24:31 EDT
-
Comment 17 Philipe Mulet CLA 2006-02-03 11:30:49 EST
*** Bug 90886 has been marked as a duplicate of this bug. ***
Comment 18 Frederic Fusier CLA 2006-04-14 10:43:11 EDT
This was fixed in 3.1 APT branch...
Comment 19 Frederic Fusier CLA 2006-04-14 10:48:17 EDT
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...