APT - patch org.eclipse.jdt.core.559521
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java b/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
index 73434c0..e052931 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
@@ -427,9 +427,8 @@
TypeBinding[] annotationTypes = new TypeBinding[length];
for (int i = 0; i < length; i++) {
Annotation annotation = annotations[i];
- annotation.recipient = recipient;
- annotation.compilerAnnotation = new SourceAnnotation(annotation);
- annotationTypes[i] = annotation.resolveType(scope);
+ annotation.recipient = recipient;
+ annotationTypes[i] = annotation.resolveType(scope);
}
// check duplicate annotations
for (int i = 0; i < length; i++) {
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java b/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java
index a48d8fa..1053019 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java
@@ -19,14 +19,14 @@
*/
public abstract class Annotation extends Expression {
- final static MemberValuePair[] NoValuePairs = new MemberValuePair[0];
+ final static MemberValuePair[] NoValuePairs = new MemberValuePair[0];
public int declarationSourceEnd;
public Binding recipient;
public TypeReference type;
/**
* The representation of this annotation in the type system.
*/
- public SourceAnnotation compilerAnnotation;
+ private SourceAnnotation compilerAnnotation = null;
public static long getRetentionPolicy(char[] policyName) {
if (policyName == null || policyName.length == 0)
@@ -166,15 +166,21 @@
public TypeBinding resolveType(BlockScope scope) {
+ if(this.compilerAnnotation != null)
+ return this.resolvedType;
+
this.constant = NotAConstant;
TypeBinding typeBinding = this.type.resolveType(scope);
- if (typeBinding == null)
+ if (typeBinding == null){
+ this.compilerAnnotation = new SourceAnnotation(this);
return null;
+ }
this.resolvedType = typeBinding;
// ensure type refers to an annotation type
if (!typeBinding.isAnnotationType()) {
scope.problemReporter().typeMismatchError(typeBinding, scope.getJavaLangAnnotationAnnotation(), this.type);
+ this.compilerAnnotation = new SourceAnnotation(this);
return null;
}
@@ -226,7 +232,8 @@
if (!foundValue && (method.modifiers & AccAnnotationDefault) == 0) {
scope.problemReporter().missingValueForAnnotationMember(this, selector);
}
- }
+ }
+
// check unused pairs
for (int i = 0; i < pairsLength; i++) {
if (pairs[i] != null) {
@@ -299,8 +306,14 @@
scope.problemReporter().disallowedTargetForAnnotation(this);
}
}
+ this.compilerAnnotation = new SourceAnnotation(this);
return this.resolvedType;
}
+
+ public SourceAnnotation getCompilerAnnotation()
+ {
+ return this.compilerAnnotation;
+ }
public abstract void traverse(ASTVisitor visitor, BlockScope scope);
public abstract void traverse(ASTVisitor visitor, CompilationUnitScope scope);
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java b/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java
index 363754d..9df5ca3 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java
@@ -119,6 +119,7 @@
}
}
if (type.binding != null) {
+ type.binding.finish();
// null out the type's scope backpointers
type.binding.scope = null;
}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/classfmt/AnnotationInfo.java b/compiler/org/eclipse/jdt/internal/compiler/classfmt/AnnotationInfo.java
index 4a4ac3d..4b2430e 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/classfmt/AnnotationInfo.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/classfmt/AnnotationInfo.java
@@ -81,6 +81,10 @@
* of this annotation. The data structure will not be flushed out.
*
* The tag bits are derived from the following (supported) standard annotation.
+ * java.lang.annotation.Documented,
+ * java.lang.annotation.Retention,
+ * java.lang.annotation.Target, and
+ * java.lang.Deprecated
*
* @param expectRuntimeVisibleAnno <code>true</cod> to indicate that this is a runtime-visible annotation
* @param toplevel <code>false</code> to indicate that an nested annotation is read. <code>true</code>
diff --git a/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java b/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java
index aa6e090..a28a9d4 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java
@@ -323,27 +323,54 @@
*/
private void decodeAnnotations(int offset, boolean runtimeVisible) {
int numberOfAnnotations = u2At(offset + 6);
- int readOffset = offset + 8;
- int index = 0;
- if( numberOfAnnotations > 0 ){
- if( this.annotations == null )
- this.annotations = new AnnotationInfo[numberOfAnnotations];
- else{
- index = this.annotations.length;
- int newTotal = this.annotations.length + numberOfAnnotations;
- final AnnotationInfo[] newAnnos = new AnnotationInfo[newTotal];
- System.arraycopy(this.annotations, 0, newAnnos, 0, this.annotations.length);
- this.annotations = newAnnos;
+ int readOffset = offset + 8;
+
+ if( numberOfAnnotations > 0 ){
+ int numStandardAnnotations = 0;
+ AnnotationInfo[] annos = new AnnotationInfo[numberOfAnnotations];
+ for( int i=0; i<numberOfAnnotations; i++ ){
+ // With the last parameter being 'false', the data structure
+ // will not be flushed out.
+ annos[i] = new AnnotationInfo( reference, readOffset,
+ this.constantPoolOffsets,
+ runtimeVisible, false );
+ readOffset = annos[i].getLength() + readOffset;
+ final long standardTagBits = annos[i].getStandardAnnotationTagBits();
+ this.tagBits |= standardTagBits;
+ // annotation that can be represented by the tag bits
+ // will drop the data structure completely for memory sake.
+ if( standardTagBits != 0 ){
+ annos[i] = null;
+ numStandardAnnotations ++;
+ }
}
+
+ if( numStandardAnnotations != 0 ){
+ if( numStandardAnnotations == numberOfAnnotations )
+ return;
+
+ // need to resize
+ AnnotationInfo[] temp = new AnnotationInfo[numberOfAnnotations - numStandardAnnotations ];
+ int tmpIndex = 0;
+ for( int i=0; i<numberOfAnnotations; i++ ){
+ if( annos[i] != null )
+ temp[tmpIndex ++] = annos[i];
+ }
+ annos = temp;
+ numberOfAnnotations = numberOfAnnotations - numStandardAnnotations;
+ }
+
+ if( this.annotations == null )
+ this.annotations = annos;
+ else{
+
+ final int newTotal = this.annotations.length + numberOfAnnotations;
+ final AnnotationInfo[] newAnnos = new AnnotationInfo[newTotal];
+ System.arraycopy(this.annotations, 0, newAnnos, 0, this.annotations.length );
+ System.arraycopy(annos, 0, newAnnos, this.annotations.length, numberOfAnnotations);
+ this.annotations = newAnnos;
+ }
}
- for (int i = 0; i < numberOfAnnotations; i++, index++) {
- this.annotations[index] = new AnnotationInfo(reference,
- readOffset,
- this.constantPoolOffsets,
- runtimeVisible, false);
- readOffset = this.annotations[index].getLength() + readOffset;
- this.tagBits |= this.annotations[index].getStandardAnnotationTagBits();
- }
}
/**
* Answer the char array that corresponds to the class name of the constant class.
diff --git a/compiler/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java b/compiler/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java
index da3a2e5..d6e08d8 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java
@@ -88,35 +88,55 @@
* annotation attribute.
*/
private void decodeAnnotations(int offset, boolean runtimeVisible) {
-/*
-int actualOffset = offset + structOffset;
-String text = runtimeVisible ? " runtime visible " : " runtime invisible ";
-System.err.println("decoding field_info" + text + "annotation at " + actualOffset);
-*/
int numberOfAnnotations = u2At(offset + 6);
- int readOffset = offset + 8;
- int index=0;
+ int readOffset = offset + 8;
if( numberOfAnnotations > 0 ){
+ int numStandardAnnotations = 0;
+ AnnotationInfo[] annos = new AnnotationInfo[numberOfAnnotations];
+ for (int i = 0; i < numberOfAnnotations; i++) {
+ annos[i] = new AnnotationInfo(reference,
+ readOffset + structOffset,
+ this.constantPoolOffsets,
+ runtimeVisible,
+ false);
+ readOffset = annos[i].getLength() + readOffset;
+ final long stdAnnotationTagBits =
+ annos[i].getStandardAnnotationTagBits();
+ this.tagBits |= stdAnnotationTagBits;
+ // the tag bits represents the annotation, don't need a separate
+ // data structure for that.
+ if(stdAnnotationTagBits != 0){
+ annos[i] = null;
+ numStandardAnnotations ++;
+ }
+ }
+ if( numStandardAnnotations != 0 ){
+ // all of them are standard annotations
+ if( numStandardAnnotations == numberOfAnnotations )
+ return;
+ else{ // need to resize
+ AnnotationInfo[] temp = new AnnotationInfo[numberOfAnnotations - numStandardAnnotations ];
+ int tmpIndex = 0;
+ for( int i=0; i<numberOfAnnotations; i++ ){
+ if( annos[i] != null )
+ temp[tmpIndex ++] = annos[i];
+ }
+ annos = temp;
+ numberOfAnnotations = numberOfAnnotations - numStandardAnnotations;
+ }
+ }
if( this.annotations == null )
- this.annotations = new AnnotationInfo[numberOfAnnotations];
+ this.annotations = annos;
else{
- int curlen = this.annotations.length;
- index = curlen;
+ int curlen = this.annotations.length;
int newTotal = curlen + numberOfAnnotations;
final AnnotationInfo[] newAnnos = new AnnotationInfo[newTotal];
System.arraycopy(this.annotations, 0, newAnnos, 0, curlen);
+ System.arraycopy(annos, 0, newAnnos, curlen, numberOfAnnotations);
this.annotations = newAnnos;
}
}
- for (int i = 0; i < numberOfAnnotations; i++, index++) {
- this.annotations[index] = new AnnotationInfo(reference,
- readOffset + structOffset,
- this.constantPoolOffsets,
- runtimeVisible,
- false);
- readOffset = this.annotations[index].getLength() + readOffset;
- this.tagBits |= this.annotations[index].getStandardAnnotationTagBits();
- }
+
}
/**
* Return the constant of the field.
diff --git a/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java b/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java
index 22a57bf..01ba4c3 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java
@@ -150,12 +150,33 @@
*/
private void decodeMethodAnnotations(int offset, boolean runtimeVisible){
int numberOfAnnotations = u2At(offset + 6);
- final AnnotationInfo[] annos = decodeAnnotations(offset + 8, runtimeVisible, numberOfAnnotations);
+ AnnotationInfo[] annos = decodeAnnotations(offset + 8, runtimeVisible, numberOfAnnotations);
if( numberOfAnnotations > 0 ){
if( runtimeVisible ){
+ int numStandardAnnotations = 0;
for( int i=0; i<numberOfAnnotations; i++ ){
- this.tagBits |= annos[i].getStandardAnnotationTagBits();
+ final long standardAnnoTagBits = annos[i].getStandardAnnotationTagBits();
+ this.tagBits |= standardAnnoTagBits;
+ if(standardAnnoTagBits != 0){
+ annos[i] = null;
+ numStandardAnnotations ++;
+ }
+ }
+
+ if( numStandardAnnotations != 0 ){
+ if( numStandardAnnotations == numberOfAnnotations )
+ return;
+
+ // need to resize
+ AnnotationInfo[] temp = new AnnotationInfo[numberOfAnnotations - numStandardAnnotations ];
+ int tmpIndex = 0;
+ for( int i=0; i<numberOfAnnotations; i++ ){
+ if( annos[i] != null )
+ temp[tmpIndex ++] = annos[i];
+ }
+ annos = temp;
+ numberOfAnnotations = numberOfAnnotations - numStandardAnnotations;
}
}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotationMethodBinding.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotationMethodBinding.java
index baf203b..33d1eaa 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotationMethodBinding.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotationMethodBinding.java
@@ -10,30 +10,52 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
+import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+
/**
- * Annotation method that came from binary.
+ * Annotation method that came from binary or source
* @author tyeung
*
*/
-public class AnnotationMethodBinding extends BinaryMethodBinding
+public class AnnotationMethodBinding extends MethodBinding
{
- private Object defaultValue;
+ private Object defaultValue = null;
+ /**
+ *
+ * @param modifiers
+ * @param selector
+ * @param returnType
+ * @param declaringClass
+ * @param defaultValue <code>null</code> for source method.
+ */
public AnnotationMethodBinding(int modifiers,
char[] selector,
TypeBinding returnType,
- ReferenceBinding declaringClass,
- IAnnotationInstance[] methodAnnotation,
- IAnnotationInstance[][] parameterAnnotations,
+ ReferenceBinding declaringClass,
Object defaultValue)
{
- super(modifiers, selector,
- returnType, NoParameters,
- NoExceptions, declaringClass,
- methodAnnotation, parameterAnnotations );
-
+ super(modifiers, selector, returnType, NoParameters, NoExceptions, declaringClass );
this.defaultValue = defaultValue;
+ setDefaultValue();
}
+ private void setDefaultValue()
+ {
+ if (this.declaringClass instanceof SourceTypeBinding) {
+ TypeDeclaration typeDecl = ((SourceTypeBinding)this.declaringClass).scope.referenceContext;
+ final AbstractMethodDeclaration methodDecl = typeDecl.declarationOf(this);
+ if( methodDecl instanceof AnnotationMethodDeclaration){
+ this.defaultValue = SourceElementValuePair.getValue(((AnnotationMethodDeclaration)methodDecl).defaultValue);
+ }
+ }
+ }
+
+ /**
+ * @return the default value for this annotation method.
+ * Return <code>null</code> if there is no default value
+ */
public Object getDefaultValue()
{
return this.defaultValue;
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotationUtils.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotationUtils.java
new file mode 100644
index 0000000..e645e8b
--- /dev/null
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotationUtils.java
@@ -0,0 +1,138 @@
+/*******************************************************************************
+ * Copyright (c) 2005 BEA Systems, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * tyeung@bea.com - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.lookup;
+
+class AnnotationUtils {
+ /**
+ * Build out the data structure representing the standard annotations.
+ * @param annotationTagBits
+ * @param result to be filled by this method starting from index 0
+ * @param env
+ * @return the number of standard annotations found
+ */
+ static int buildStandardAnnotations(final long annotationTagBits,
+ final IAnnotationInstance[] result,
+ final LookupEnvironment env)
+ {
+ int index = 0;
+ if( (annotationTagBits & TagBits.AnnotationTargetMASK) != 0 )
+ result[index++] = buildTargetAnnotation(annotationTagBits, env);
+ if( (annotationTagBits & TagBits.AnnotationRetentionMASK) != 0 )
+ result[index++] = buildRetentionAnnotation(annotationTagBits, env);
+ if( (annotationTagBits & TagBits.AnnotationDeprecated) != 0 )
+ result[index++] = buildMarkerAnnotation(TypeConstants.CharArray_JAVA_LANG_DEPRECATED_SIG, env);
+ if( (annotationTagBits & TagBits.AnnotationDocumented) != 0 )
+ result[index++] = buildMarkerAnnotation(TypeConstants.CharArray_JAVA_LANG_ANNOTATION_DOCUMENTED_SIG, env);
+ if( (annotationTagBits & TagBits.AnnotationInherited) != 0 )
+ result[index++] = buildMarkerAnnotation(TypeConstants.CharArray_JAVA_LANG_ANNOTATION_INHERITED_SIG, env);
+ if( (annotationTagBits & TagBits.AnnotationOverride) != 0 )
+ result[index++] = buildMarkerAnnotation(TypeConstants.CharArray_JAVA_LANG_OVERRIDE_SIG, env);
+ if( (annotationTagBits & TagBits.AnnotationSuppressWarnings) != 0 )
+ result[index++] = buildMarkerAnnotation(TypeConstants.CharArray_JAVA_LANG_SUPRESSWARNING_SIG, env);
+ return index;
+ }
+
+ static int getNumberOfStandardAnnotations(final long annotationTagBits)
+ {
+ int count = 0;
+ if( (annotationTagBits & TagBits.AnnotationTargetMASK) != 0 ) count ++;
+ if( (annotationTagBits & TagBits.AnnotationRetentionMASK) != 0 ) count ++;
+ if( (annotationTagBits & TagBits.AnnotationDeprecated) != 0 ) count ++;
+ if( (annotationTagBits & TagBits.AnnotationDocumented) != 0 ) count ++;
+ if( (annotationTagBits & TagBits.AnnotationInherited) != 0 ) count ++;
+ if( (annotationTagBits & TagBits.AnnotationOverride) != 0 ) count ++;
+ if( (annotationTagBits & TagBits.AnnotationSuppressWarnings) != 0 ) count ++;
+
+ return count;
+ }
+
+ private static IAnnotationInstance buildMarkerAnnotation(final char[] sig, final LookupEnvironment env)
+ {
+ final ReferenceBinding type = (ReferenceBinding)env.getTypeFromSignature(sig, 0, -1, false, null);
+ return new BinaryAnnotation(type, env);
+ }
+
+ private static IAnnotationInstance buildTargetAnnotation(final long bits, final LookupEnvironment env)
+ {
+ final ReferenceBinding target = (ReferenceBinding)
+ env.getTypeFromSignature(TypeConstants.CharArray_JAVA_LANG_ANNOTATION_TARGET_SIG,
+ 0, -1, false, null);
+ final BinaryAnnotation anno = new BinaryAnnotation(target, env);
+ if( (bits & TagBits.AnnotationTarget) != 0 )
+ return anno;
+
+ ReferenceBinding elementType = (ReferenceBinding)
+ env.getTypeFromSignature(TypeConstants.CharArray_JAVA_LANG_ANNOTATION_ELEMENTTYPE_SIG,
+ 0, -1, false, null);
+ int arraysize = 0;
+ if( (bits & TagBits.AnnotationForAnnotationType) != 0 ) arraysize ++;
+ if( (bits & TagBits.AnnotationForConstructor) != 0 ) arraysize ++;
+ if( (bits & TagBits.AnnotationForField) != 0 ) arraysize ++;
+ if( (bits & TagBits.AnnotationForLocalVariable) != 0 ) arraysize ++;
+ if( (bits & TagBits.AnnotationForMethod) != 0 ) arraysize ++;
+ if( (bits & TagBits.AnnotationForPackage) != 0 ) arraysize ++;
+ if( (bits & TagBits.AnnotationForParameter) != 0 ) arraysize ++;
+ if( (bits & TagBits.AnnotationForType) != 0 ) arraysize ++;
+
+ final Object[] value = new Object[arraysize];
+ if( arraysize > 0 ){
+ elementType = BinaryTypeBinding.resolveType(elementType, env, false);
+ int index = 0;
+ if( (bits & TagBits.AnnotationForAnnotationType) != 0 )
+ value[index++] = elementType.getField(TypeConstants.UPPER_ANNOTATION_TYPE, true);
+ if( (bits & TagBits.AnnotationForConstructor) != 0 )
+ value[index++] = elementType.getField(TypeConstants.UPPER_CONSTRUCTOR, true);
+ if( (bits & TagBits.AnnotationForField) != 0 )
+ value[index++] = elementType.getField(TypeConstants.UPPER_FIELD, true);
+ if( (bits & TagBits.AnnotationForLocalVariable) != 0 )
+ value[index++] = elementType.getField(TypeConstants.UPPER_LOCAL_VARIABLE, true);
+ if( (bits & TagBits.AnnotationForMethod) != 0 )
+ value[index++] = elementType.getField(TypeConstants.UPPER_METHOD, true);
+ if( (bits & TagBits.AnnotationForPackage) != 0 )
+ value[index++] = elementType.getField(TypeConstants.UPPER_PACKAGE, true);
+ if( (bits & TagBits.AnnotationForParameter) != 0 )
+ value[index++] = elementType.getField(TypeConstants.UPPER_PARAMETER, true);
+ if( (bits & TagBits.AnnotationForType) != 0 )
+ value[index++] = elementType.getField(TypeConstants.TYPE, true);
+ }
+
+ anno.pairs = new IElementValuePair[]{ new BinaryElementValuePair(anno, TypeConstants.VALUE, value) };
+ return anno;
+ }
+
+ private static IAnnotationInstance buildRetentionAnnotation(final long bits, final LookupEnvironment env)
+ {
+ final ReferenceBinding retention = (ReferenceBinding)
+ env.getTypeFromSignature(TypeConstants.CharArray_JAVA_LANG_ANNOTATION_RETENTION_SIG,
+ 0, -1, false, null);
+ ReferenceBinding retentionPolicy = (ReferenceBinding)
+ env.getTypeFromSignature(TypeConstants.CharArray_JAVA_LANG_ANNOTATION_RETENTIONPOLICY_SIG,
+ 0, -1, false, null);
+
+ final BinaryAnnotation anno = new BinaryAnnotation(retention, env);
+
+ Object value = null;
+ {
+ retentionPolicy = BinaryTypeBinding.resolveType(retentionPolicy, env, false);
+ if( (bits & TagBits.AnnotationRuntimeRetention) != 0 )
+ value = retentionPolicy.getField(TypeConstants.UPPER_RUNTIME, true);
+ else if( (bits & TagBits.AnnotationClassRetention) != 0 )
+ value = retentionPolicy.getField(TypeConstants.UPPER_CLASS, true);
+ else if( (bits & TagBits.AnnotationSourceRetention) != 0 )
+ value = retentionPolicy.getField(TypeConstants.UPPER_SOURCE, true);
+
+ }
+ anno.pairs = new IElementValuePair[]{ new BinaryElementValuePair(anno, TypeConstants.VALUE, value) };
+ return anno;
+
+ }
+
+}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryAnnotation.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryAnnotation.java
index 067bdda..c5e8fd2 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryAnnotation.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryAnnotation.java
@@ -24,7 +24,7 @@
BinaryAnnotation(ReferenceBinding binding, LookupEnvironment env)
{
this.typeBinding = binding;
- this.pairs = null;
+ this.pairs = TypeConstants.NoElementValuePairs;
this.env = env;
}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
index e8a684f..615a923 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
@@ -47,10 +47,9 @@
private MethodBinding[] methods;
private ReferenceBinding[] memberTypes;
protected TypeVariableBinding[] typeVariables;
-private IAnnotationInstance[] annotations;
// For the link with the principle structure
-private LookupEnvironment environment;
+LookupEnvironment environment;
public static ReferenceBinding resolveType(ReferenceBinding type, LookupEnvironment environment, boolean convertGenericToRawType) {
if (type instanceof UnresolvedReferenceBinding)
@@ -179,8 +178,6 @@
return availableMethods;
}
-public IAnnotationInstance[] getAnnotations(){ return this.annotations; }
-
void cachePartsFrom(IBinaryType binaryType, boolean needFieldsAndMethods) {
// default initialization for super-interfaces early, in case some aborting compilation error occurs,
// and still want to use binaries passed that point (e.g. type hierarchy resolver, see bug 63748).
@@ -308,7 +305,7 @@
{
final int len = pairs == null ? 0 : pairs.length;
anno.pairs = NoElementValuePairs;
- if( len > 1 ){
+ if( len > 0 ){
anno.pairs = new IElementValuePair[len];
for( int i = 0; i < len; i++ ){
anno.pairs[i] = new BinaryElementValuePair(anno,
@@ -331,7 +328,8 @@
else if( binaryValue instanceof IEnumConstantReference ){
final IEnumConstantReference ref = (IEnumConstantReference)binaryValue;
- final ReferenceBinding enumType = environment.getTypeFromConstantPoolName(ref.getTypeName(), 0, -1, false);
+ ReferenceBinding enumType = (ReferenceBinding)environment.getTypeFromSignature(ref.getTypeName(), 0, -1, false, null);
+ enumType = BinaryTypeBinding.resolveType(enumType, this.environment, false);
return enumType.getField(ref.getEnumConstantName(), false);
}
else if( binaryValue instanceof Object[] ){
@@ -367,13 +365,9 @@
: environment.getTypeFromTypeSignature(new SignatureWrapper(fieldSignature), NoTypeVariables, this);
IAnnotationInstance[] fieldAnnos = createAnnotations(binaryField.getAnnotations());
FieldBinding field =
- new BinaryFieldBinding(
- binaryField.getName(),
- type,
- binaryField.getModifiers() | AccUnresolved,
- this,
- binaryField.getConstant(),
- fieldAnnos);
+ new FieldBinding( binaryField.getName(), type, binaryField.getModifiers() | AccUnresolved,
+ this, binaryField.getConstant() );
+ field.setAnnotations(fieldAnnos);
field.id = i; // ordinal
if (use15specifics)
field.tagBits |= binaryField.getTagBits();
@@ -503,31 +497,18 @@
final MethodBinding result;
if( method.isConstructor() )
- result = new BinaryMethodBinding(methodModifiers,
- parameters,
- exceptions,
- this,
- methodAnnos,
- paramAnnotations);
+ result = new MethodBinding(methodModifiers, parameters, exceptions, this);
+
else{
- if( isAnnotationType() ){
- result = new AnnotationMethodBinding(methodModifiers,
- method.getSelector(),
- returnType,
- this,
- methodAnnos,
- paramAnnotations,
- getMemberValue(method.getDefaultValue()));
+ if( isAnnotationType() ){
+ if( method instanceof org.eclipse.jdt.internal.compiler.classfmt.MethodInfo )
+ result = new AnnotationMethodBinding(methodModifiers, method.getSelector(), returnType, this, getMemberValue(method.getDefaultValue()));
+ else
+ throw new IllegalStateException(method.getClass().getName());
}
- else result = new BinaryMethodBinding(methodModifiers,
- method.getSelector(),
- returnType,
- parameters,
- exceptions,
- this,
- methodAnnos,
- paramAnnotations);
+ else result = new MethodBinding(methodModifiers, method.getSelector(), returnType, parameters, exceptions, this);
}
+ result.setExtendedModifiers(methodAnnos, paramAnnotations);
if (use15specifics)
result.tagBits |= method.getTagBits();
@@ -918,6 +899,24 @@
this.tagBits &= ~HasUnresolvedTypeVariables;
return this.typeVariables;
}
+
+public IAnnotationInstance[] getAnnotations()
+{
+ final long annotationTagBits = getAnnotationTagBits();
+ // TODO: add a flag so we don't repeat this process.
+ final int numStdAnnotations = AnnotationUtils.getNumberOfStandardAnnotations(annotationTagBits);
+ if( numStdAnnotations == 0 ) return this.annotations;
+
+ final int nonStandard = this.annotations == null ? 0 : this.annotations.length;
+ final int total = numStdAnnotations + nonStandard;
+ final IAnnotationInstance[] result = new BinaryAnnotation[total];
+ final int index = AnnotationUtils.buildStandardAnnotations(annotationTagBits, result, this.environment);
+ if( nonStandard != 0 ){
+ System.arraycopy(this.annotations, 0, result, index, this.annotations.length);
+ }
+ return result;
+}
+
public String toString() {
String s = ""; //$NON-NLS-1$
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java
index 258654e..a34180c 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java
@@ -24,20 +24,27 @@
super(null, null, 0, null);
// for creating problem field
}
-public FieldBinding(char[] name, TypeBinding type, int modifiers, ReferenceBinding declaringClass, Constant constant) {
+
+public FieldBinding(char[] name, TypeBinding type, int modifiers, ReferenceBinding declaringClass, Constant constant)
+{
super(name, type, modifiers, constant);
this.declaringClass = declaringClass;
}
+
public FieldBinding(FieldDeclaration field, TypeBinding type, int modifiers, ReferenceBinding declaringClass) {
this(field.name, type, modifiers, declaringClass, null);
field.binding = this; // record binding in declaration
}
+
// special API used to change field declaring class for runtime visibility check
public FieldBinding(FieldBinding initialFieldBinding, ReferenceBinding declaringClass) {
- super(initialFieldBinding.name, initialFieldBinding.type, initialFieldBinding.modifiers, initialFieldBinding.constant());
+ super(initialFieldBinding.name, initialFieldBinding.type, initialFieldBinding.modifiers,
+ initialFieldBinding.constant());
this.declaringClass = declaringClass;
this.id = initialFieldBinding.id;
+ this.annotations = initialFieldBinding.annotations;
}
+
/* API
* Answer the receiver's binding type from Binding.BindingID.
*/
@@ -188,11 +195,78 @@
TypeDeclaration typeDecl = ((SourceTypeBinding)originalField.declaringClass).scope.referenceContext;
FieldDeclaration fieldDecl = typeDecl.declarationOf(originalField);
if (fieldDecl != null)
- ASTNode.resolveAnnotations(isStatic() ? typeDecl.staticInitializerScope : typeDecl.initializerScope, fieldDecl.annotations, originalField);
+ ASTNode.resolveAnnotations(isStatic() ? typeDecl.staticInitializerScope : typeDecl.initializerScope, fieldDecl.annotations, originalField);
}
return originalField.tagBits;
}
+private boolean isBinary()
+{
+ return this.declaringClass != null && this.declaringClass.isBinaryBinding();
+}
+
+public IAnnotationInstance[] getAnnotations()
+{
+ if(this.annotations == null )
+ buildAnnotations();
+ // binary annotations can be encoded in tag bits.
+ if( isBinary() ){
+ final int current = this.annotations.length;
+ final long annotationTagBits = getAnnotationTagBits();
+ final int numStandardAnnos = AnnotationUtils.getNumberOfStandardAnnotations(annotationTagBits);
+ if( numStandardAnnos == 0 )
+ return this.annotations;
+ else{
+ final LookupEnvironment env = ((BinaryTypeBinding)this.declaringClass).environment;
+ final int total = current + numStandardAnnos;
+ final BinaryAnnotation[] result = new BinaryAnnotation[total];
+ final int index = AnnotationUtils.buildStandardAnnotations(annotationTagBits, result, env);
+ if( current == 0 )
+ return result;
+ else{
+ System.arraycopy(this.annotations, 0, result, index, current);
+ return result;
+ }
+ }
+ }
+ else
+ return this.annotations;
+}
+
+void buildAnnotations()
+{
+ if( this.annotations != null ) return;
+ this.annotations = NoAnnotations;
+ FieldBinding originalField = this.original();
+ // length field of an array don't have a declaring class.
+ if( originalField.declaringClass != null && originalField.declaringClass instanceof SourceTypeBinding){
+ TypeDeclaration typeDecl = ((SourceTypeBinding)originalField.declaringClass).scope.referenceContext;
+ FieldDeclaration fieldDecl = typeDecl.declarationOf(originalField);
+
+ if (fieldDecl != null){
+ final Annotation[] fieldAnnos = fieldDecl.annotations;
+ final int len = fieldAnnos == null ? 0 : fieldAnnos.length;
+ if( len > 0 )
+ {
+ this.annotations = new IAnnotationInstance[len];
+ for( int i = 0; i < len; i++ ){
+ final BlockScope scope = isStatic() ? typeDecl.staticInitializerScope : typeDecl.initializerScope;
+ fieldAnnos[i].resolveType(scope);
+ this.annotations[i] = fieldAnnos[i].getCompilerAnnotation();
+ }
+ }
+ }
+ }
+}
+
+protected void setAnnotations(final IAnnotationInstance[] annos )
+{
+ if( annos == null )
+ this.annotations = NoAnnotations;
+ else
+ this.annotations = annos;
+}
+
/* Answer true if the receiver has default visibility
*/
@@ -281,28 +355,4 @@
}
return null;
}
-
-public IAnnotationInstance[] getAnnotations() {
- // make sure we check the annotations for problems
- getAnnotationTagBits();
- IAnnotationInstance[] result = NoAnnotations;
- // length field of an array don't have a declaring class.
- if( this.declaringClass != null && !this.declaringClass.isBinaryBinding() ){
- TypeDeclaration typeDecl = ((SourceTypeBinding)this.declaringClass).scope.referenceContext;
- FieldDeclaration fieldDecl = typeDecl.declarationOf(this);
-
- if (fieldDecl != null){
- final Annotation[] fieldAnnos = fieldDecl.annotations;
- final int len = fieldAnnos == null ? 0 : fieldAnnos.length;
- if( len > 0 )
- {
- result = new IAnnotationInstance[len];
- for( int i = 0; i < len; i++ ){
- result[i] = fieldAnnos[i].compilerAnnotation;
- }
- }
- }
- }
- return result;
-}
}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java
index 1fa40ad..a9c0105 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java
@@ -40,6 +40,7 @@
public LocalVariableBinding(char[] name, TypeBinding type, int modifiers, boolean isArgument) {
super(name, type, modifiers, isArgument ? Constant.NotAConstant : null);
this.isArgument = isArgument;
+ this.annotations = null;
}
// regular local variable or argument
@@ -47,6 +48,7 @@
this(declaration.name, type, modifiers, isArgument);
this.declaration = declaration;
+ this.annotations = null;
}
/* API
@@ -132,21 +134,29 @@
}
public IAnnotationInstance[] getAnnotations()
- {
+ {
+ if(this.annotations != null)
+ return this.annotations;
+ buildAnnotations();
+ return this.annotations;
+ }
+
+ private void buildAnnotations()
+ {
+ this.annotations = NoAnnotations;
if( this.isArgument && this.declaration != null){
final Annotation[] argAnnos = declaration.annotations;
final int numAnnotations = argAnnos == null ? 0 : argAnnos.length;
- IAnnotationInstance[] result = NoAnnotations;
+
if( numAnnotations > 0 ){
- result = new SourceAnnotation[numAnnotations];
+ this.annotations = new SourceAnnotation[numAnnotations];
// check for errors
ASTNode.resolveAnnotations(declaringScope, argAnnos, this);
for( int j=0; j<numAnnotations; j++ ){
- result[j] = new SourceAnnotation(argAnnos[j]);
+ this.annotations[j] = new SourceAnnotation(argAnnos[j]);
}
}
}
- return null;
}
public String toString() {
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java
index aa1d252..e4ea865 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java
@@ -14,20 +14,38 @@
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
-import org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.codegen.ConstantPool;
-public class MethodBinding extends Binding implements BaseTypes, TypeConstants {
-
+public class MethodBinding extends Binding implements BaseTypes, TypeConstants
+{
+ protected static final IAnnotationInstance[][] NoAnnotationsAtAll = new IAnnotationInstance[0][0];
public int modifiers;
public char[] selector;
public TypeBinding returnType;
public TypeBinding[] parameters;
public ReferenceBinding[] thrownExceptions;
public ReferenceBinding declaringClass;
- public TypeVariableBinding[] typeVariables = NoTypeVariables;
+ public TypeVariableBinding[] typeVariables = NoTypeVariables;
+
+ /**
+ * In the majority of the time, there will no annotations at all.
+ * We will try to optimized the storage by packing both
+ * method and parameter annotation into one field.
+ *
+ * If there are no annotations and no parameter annotations,
+ * this will be a zero-length array.
+ * If this is an array of size 1, then method annotations are intialized and there
+ * may or may not be parameter annotations.
+ * If there are ever any parameter annotations, this will be an array of size > 1.
+ * </code>null</code> in the array means not initialized.
+ * If the field is <code>null</code> this means it is not initalized at all.
+ * Binary types should always initialize this field;
+ * Method annotations are always at index 0 and parameter annotations
+ * always start at index 1 if they are ever present.
+ */
+ protected IAnnotationInstance[][] extendedModifiers = null;
char[] signature;
public long tagBits;
@@ -35,6 +53,7 @@
// for creating problem or synthetic method
}
public MethodBinding(int modifiers, char[] selector, TypeBinding returnType, TypeBinding[] parameters, ReferenceBinding[] thrownExceptions, ReferenceBinding declaringClass) {
+
this.modifiers = modifiers;
this.selector = selector;
this.returnType = returnType;
@@ -49,18 +68,23 @@
this.modifiers |= AccStrictfp;
}
}
+
+// constructor for creating binding representing constructor
public MethodBinding(int modifiers, TypeBinding[] parameters, ReferenceBinding[] thrownExceptions, ReferenceBinding declaringClass) {
this(modifiers, TypeConstants.INIT, VoidBinding, parameters, thrownExceptions, declaringClass);
}
+
// special API used to change method declaring class for runtime visibility check
-public MethodBinding(MethodBinding initialMethodBinding, ReferenceBinding declaringClass) {
+protected MethodBinding(MethodBinding initialMethodBinding, ReferenceBinding declaringClass) {
this.modifiers = initialMethodBinding.modifiers;
this.selector = initialMethodBinding.selector;
this.returnType = initialMethodBinding.returnType;
this.parameters = initialMethodBinding.parameters;
this.thrownExceptions = initialMethodBinding.thrownExceptions;
this.declaringClass = declaringClass;
+ this.extendedModifiers = initialMethodBinding.extendedModifiers;
}
+
/* Answer true if the argument types & the receiver's parameters are equal
*/
public final boolean areParametersEqual(MethodBinding method) {
@@ -367,6 +391,165 @@
return modifiers & AccJustFlag;
}
+void buildAnnotations()
+{
+ if( this.extendedModifiers != null ) return;
+ IAnnotationInstance[] methodAnnotations = buildMethodAnnotations();
+ IAnnotationInstance[][] paramAnnotations = buildParamAnnotations();
+ setExtendedModifiers(methodAnnotations, paramAnnotations);
+}
+
+public void setExtendedModifiers(final IAnnotationInstance[] methodAnnotations,
+ final IAnnotationInstance[][] parameterAnnotations )
+{
+ final int numMethodAnnos = methodAnnotations == null ? 0 : methodAnnotations.length;
+ final int numParams = parameterAnnotations == null ? 0 : parameterAnnotations.length;
+ if( numMethodAnnos == 0 && numParams == 0 )
+ this.extendedModifiers = NoAnnotationsAtAll;
+ else if( numParams == 0 )
+ // no even going to create that spot.
+ this.extendedModifiers = new IAnnotationInstance[][]{ methodAnnotations };
+ else{
+ this.extendedModifiers = new IAnnotationInstance[numParams + 1][];
+ this.extendedModifiers[0] = methodAnnotations;
+ int extModIndex = 1;
+ for( int pIndex=0; pIndex<numParams; pIndex++, extModIndex ++ ){
+ this.extendedModifiers[extModIndex] = parameterAnnotations[pIndex];
+ if( this.extendedModifiers[extModIndex] == null )
+ this.extendedModifiers[extModIndex] = NoAnnotations;
+ }
+ }
+}
+
+private IAnnotationInstance[] buildMethodAnnotations()
+{
+ IAnnotationInstance[] methodAnno = NoAnnotations;
+ MethodBinding originalMethod = this.original();
+ if(!isBinary())
+ {
+ TypeDeclaration typeDecl = ((SourceTypeBinding)originalMethod.declaringClass).scope.referenceContext;
+ AbstractMethodDeclaration methodDecl = typeDecl.declarationOf(originalMethod);
+
+ if (methodDecl != null){
+ final int len = methodDecl.annotations == null ? 0 : methodDecl.annotations.length;
+ if( len > 0 ){
+ methodAnno = new IAnnotationInstance[len];
+ for( int i=0; i<len; i++ ){
+ methodDecl.annotations[i].resolveType(methodDecl.scope);
+ methodAnno[i] = methodDecl.annotations[i].getCompilerAnnotation();
+ }
+ }
+ }
+ }
+ return methodAnno;
+}
+
+private IAnnotationInstance[][] buildParamAnnotations()
+{
+ IAnnotationInstance[][] result = null;
+ MethodBinding originalMethod = this.original();
+ if(!isBinary())
+ {
+ TypeDeclaration typeDecl = ((SourceTypeBinding)originalMethod.declaringClass).scope.referenceContext;
+ AbstractMethodDeclaration methodDecl = typeDecl.declarationOf(originalMethod);
+ if(methodDecl != null ){
+ final Argument[] args = methodDecl.arguments;
+ final int numArgs = args == null ? 0 : args.length;
+ for( int argIndex=0; argIndex<numArgs; argIndex++ )
+ {
+ final Argument arg = args[argIndex];
+ final Annotation[] argAnnos = arg.annotations;
+ final int numAnnotations = argAnnos == null ? 0 : argAnnos.length;
+ if( numAnnotations > 0 ){
+ if( result == null ){
+ result = new IAnnotationInstance[numArgs][];
+ for( int i=0; i<numArgs; i++ )
+ result[i] = NoAnnotations;
+ }
+ result[argIndex] = new SourceAnnotation[numAnnotations];
+ // check for errors
+ ASTNode.resolveAnnotations(methodDecl.scope, argAnnos, this);
+ for( int j=0; j<numAnnotations; j++ ){
+ argAnnos[j].resolveType(methodDecl.scope);
+ result[argIndex][j] = argAnnos[j].getCompilerAnnotation();
+ }
+ }
+ }
+ }
+ }
+
+ return result;
+}
+
+private boolean isBinary()
+{
+ final MethodBinding originalMethod = this.original();
+ return originalMethod.declaringClass != null &&
+ originalMethod.declaringClass.isBinaryBinding();
+}
+
+/**
+ * @return the annotations annotating this method.
+ * Return a zero-length array if none is found.
+ */
+public IAnnotationInstance[] getAnnotations()
+{
+ if( this.extendedModifiers == null )
+ buildAnnotations();
+ final boolean isBinary = isBinary();
+ // part of the binary annotations are in the tag bits
+ if( isBinary ){
+ final long stdAnnoTagBits = getAnnotationTagBits();
+ final int numStandardAnnotations = AnnotationUtils.getNumberOfStandardAnnotations(stdAnnoTagBits);
+ final int current = this.extendedModifiers.length == 0 ? 0 :
+ this.extendedModifiers[0].length;
+ if( numStandardAnnotations == 0 ){
+ if(this.extendedModifiers.length == 0)
+ return NoAnnotations;
+ else
+ return this.extendedModifiers[0];
+ }
+ else{
+ final LookupEnvironment env = ((BinaryTypeBinding)this.declaringClass).environment;
+ final int total = numStandardAnnotations + current;
+ final BinaryAnnotation[] result = new BinaryAnnotation[total];
+ final int index = AnnotationUtils.buildStandardAnnotations(stdAnnoTagBits, result, env);
+ if( current == 0 )
+ return result;
+ else{
+ System.arraycopy(this.extendedModifiers[0], 0, result, index, current);
+ return result;
+ }
+ }
+ }
+ else{
+ if( this.extendedModifiers.length == 0 )
+ return NoAnnotations;
+ else
+ return this.extendedModifiers[0];
+ }
+}
+
+/**
+ * @param index the index of the parameter of interest
+ * @return the annotations on the <code>index</code>th parameter
+ * @throws ArrayIndexOutOfBoundsException when <code>index</code> is not valid
+ */
+public IAnnotationInstance[] getParameterAnnotations(final int index)
+{
+ getAnnotationTagBits();
+ final int len = this.extendedModifiers.length;
+ if( len < 2 )
+ return NoAnnotations;
+ else{
+ final int extModIndex = index + 1;
+ if( extModIndex < 1 || extModIndex >= len )
+ throw new ArrayIndexOutOfBoundsException("length = " + len + " index = " + index ); //$NON-NLS-1$ //$NON-NLS-2$
+ return this.extendedModifiers[extModIndex];
+ }
+}
+
+
/**
* Compute the tagbits for standard annotations. For source types, these could require
* lazily resolving corresponding annotation nodes, in case of forward references.
@@ -378,93 +561,11 @@
TypeDeclaration typeDecl = ((SourceTypeBinding)originalMethod.declaringClass).scope.referenceContext;
AbstractMethodDeclaration methodDecl = typeDecl.declarationOf(originalMethod);
if (methodDecl != null)
- ASTNode.resolveAnnotations(methodDecl.scope, methodDecl.annotations, originalMethod);
+ ASTNode.resolveAnnotations(methodDecl.scope, methodDecl.annotations, originalMethod);
}
return originalMethod.tagBits;
}
-/**
- * @return the annotations annotating this method.
- * Return a zero-length array if none is found.
- */
-public IAnnotationInstance[] getAnnotations()
-{
- // make sure they are checked for problems/
- // this call will also initialize the 'compilerAnnotation' field.
- getAnnotationTagBits();
- IAnnotationInstance[] methodAnno = NoAnnotations;
- if(this.declaringClass != null && this.declaringClass instanceof SourceTypeBinding )
- {
- TypeDeclaration typeDecl = ((SourceTypeBinding)declaringClass).scope.referenceContext;
- AbstractMethodDeclaration methodDecl = typeDecl.declarationOf(this);
-
- if (methodDecl != null){
- final int len = methodDecl.annotations == null ? 0 : methodDecl.annotations.length;
- if( len > 0 ){
- methodAnno = new IAnnotationInstance[len];
- for( int i=0; i<len; i++ ){
- methodAnno[i] = methodDecl.annotations[i].compilerAnnotation;
- }
- }
- }
- }
- return methodAnno;
-}
-
-/**
- * @param index the index of the parameter of interest
- * @return the annotations on the <code>index</code>th parameter
- * @throws ArrayIndexOutOfBoundsException when <code>index</code> is not valid
- */
-public IAnnotationInstance[] getParameterAnnotations(final int index)
-{
- IAnnotationInstance[] result = NoAnnotations;
- if(this.declaringClass != null && this.declaringClass instanceof SourceTypeBinding )
- {
- TypeDeclaration typeDecl = ((SourceTypeBinding)this.declaringClass).scope.referenceContext;
- AbstractMethodDeclaration methodDecl = typeDecl.declarationOf(this);
- if(methodDecl != null ){
- final Argument[] args = methodDecl.arguments;
- final int numArgs = args == null ? 0 : args.length;
- if( numArgs == 0 || index < 0 || index >= numArgs )
- throw new IllegalArgumentException("number of parameters = " + numArgs + //$NON-NLS-1$
- " index = " + index ); //$NON-NLS-1$
- final Argument arg = args[index];
- final Annotation[] argAnnos = arg.annotations;
- final int numAnnotations = argAnnos == null ? 0 : argAnnos.length;
-
- if( numAnnotations > 0 ){
- result = new SourceAnnotation[numAnnotations];
- // check for errors
- ASTNode.resolveAnnotations(methodDecl.scope, argAnnos, this);
- for( int j=0; j<numAnnotations; j++ ){
- result[j] = argAnnos[j].compilerAnnotation;
- }
- }
- }
- }
-
- return result;
-}
-
-/**
- * @return the default value iff this is an annotation method.
- * Return <code>null</code> if there is no default value or
- * if this is not an annotaion method.
- */
-public Object getDefaultValue()
-{
- if(this.declaringClass != null && this.declaringClass instanceof SourceTypeBinding )
- {
- TypeDeclaration typeDecl = ((SourceTypeBinding)this.declaringClass).scope.referenceContext;
- final AbstractMethodDeclaration methodDecl = typeDecl.declarationOf(this);
- if( methodDecl instanceof AnnotationMethodDeclaration){
- return SourceElementValuePair.getValue(((AnnotationMethodDeclaration)methodDecl).defaultValue);
- }
- }
- return null;
-}
-
public TypeVariableBinding getTypeVariable(char[] variableName) {
for (int i = this.typeVariables.length; --i >= 0;)
if (CharOperation.equals(this.typeVariables[i].sourceName, variableName))
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java
index 1114282..715795f 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java
@@ -293,12 +293,10 @@
if (declaringClass.isInterface()) // interface or annotation type
modifiers |= AccPublic | AccAbstract;
- method.binding = new MethodBinding(modifiers,
- method.selector,
- null,
- null,
- null,
- declaringClass);
+ if( declaringClass.isAnnotationType() )
+ method.binding = new AnnotationMethodBinding(modifiers, method.selector, null, declaringClass, null);
+ else
+ method.binding = new MethodBinding(modifiers, method.selector, null, null, null, declaringClass);
checkAndSetModifiersForMethod(method.binding);
}
this.isStatic = method.binding.isStatic();
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java
index 734662a..47deacd 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java
@@ -154,9 +154,4 @@
{
return original().getParameterAnnotations(index);
}
-
- public Object getDefaultValue()
- {
- return original().getDefaultValue();
- }
}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
index d534a2f..db4f742 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
@@ -36,6 +36,7 @@
char[] fileName;
char[] constantPoolName;
char[] signature;
+ protected IAnnotationInstance[] annotations;
public FieldBinding[] availableFields() {
return fields();
@@ -861,6 +862,6 @@
*/
public IAnnotationInstance[] getAnnotations()
{
- return NoAnnotations;
+ return this.annotations;
}
}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceAnnotation.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceAnnotation.java
index 80398a1..3ccbb33 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceAnnotation.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceAnnotation.java
@@ -2,6 +2,8 @@
import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
+import org.eclipse.jdt.internal.compiler.ast.NormalAnnotation;
+import org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation;
/**
* Annotation that came from source.
@@ -9,27 +11,38 @@
*
*/
public class SourceAnnotation implements IAnnotationInstance, TypeConstants
-{
- private final Annotation astAnnotation;
+{
+ private ReferenceBinding type;
private final IElementValuePair[] pairs;
public SourceAnnotation(Annotation astAnnotation)
- {
- this.astAnnotation = astAnnotation;
- final MemberValuePair[] astPairs = astAnnotation.memberValuePairs();
- int numberOfPairs = astPairs == null ? 0 : astPairs.length;
- if( numberOfPairs == 0 )
- this.pairs = NoElementValuePairs;
- else{
- this.pairs = new SourceElementValuePair[numberOfPairs];
- for( int i=0; i<numberOfPairs; i++ ){
- this.pairs[i] = new SourceElementValuePair(astPairs[i]);
+ {
+ this.type = (ReferenceBinding)astAnnotation.resolvedType;
+ if( astAnnotation instanceof NormalAnnotation ){
+ final MemberValuePair[] astPairs = ((NormalAnnotation)astAnnotation).memberValuePairs;
+ final int numberOfPairs = astPairs == null ? 0 : astPairs.length;
+ if( numberOfPairs > 0 ){
+ this.pairs = new SourceElementValuePair[numberOfPairs];
+ for( int i=0; i<numberOfPairs; i++ ){
+ this.pairs[i] = new SourceElementValuePair(astPairs[i]);
+ }
}
- }
+ else
+ this.pairs = NoElementValuePairs;
+ }
+ else if( astAnnotation instanceof SingleMemberAnnotation ){
+ final MemberValuePair astPair = ((SingleMemberAnnotation)astAnnotation).singlePair;
+ if( astPair != null )
+ this.pairs = new SourceElementValuePair[]{ new SourceElementValuePair(astPair) };
+ else
+ this.pairs = NoElementValuePairs;
+ }
+ else
+ this.pairs = NoElementValuePairs;
}
public ReferenceBinding getAnnotationType() {
- return (ReferenceBinding)this.astAnnotation.resolvedType;
+ return this.type;
}
public IElementValuePair[] getElementValuePairs() { return this.pairs; }
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceElementValuePair.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceElementValuePair.java
index 3c0e84b..8fab89b 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceElementValuePair.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceElementValuePair.java
@@ -4,37 +4,40 @@
import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer;
import org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess;
import org.eclipse.jdt.internal.compiler.ast.Expression;
+import org.eclipse.jdt.internal.compiler.ast.FieldReference;
import org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
+import org.eclipse.jdt.internal.compiler.ast.NameReference;
+import org.eclipse.jdt.internal.compiler.ast.Reference;
+import org.eclipse.jdt.internal.compiler.env.IConstants;
import org.eclipse.jdt.internal.compiler.impl.Constant;
public class SourceElementValuePair implements IElementValuePair
-{
- private final MemberValuePair astPair;
- private Object value = null;
+{
+ private final char[] name;
+ private final MethodBinding binding;
+ private final Object value;
SourceElementValuePair(final MemberValuePair pair)
{
- this.astPair = pair;
+ this.name = pair.name;
+ this.binding = pair.binding;
+ this.value = getValue(pair.value);
}
public char[] getMemberName()
- { return this.astPair.name; }
+ { return this.name; }
public MethodBinding getMethodBinding() {
- return this.astPair.binding;
+ return this.binding;
}
public TypeBinding getType() {
- if(this.astPair.binding == null) return null;
- return this.astPair.binding.returnType;
+ if(this.binding == null) return null;
+ return this.binding.returnType;
}
public Object getValue() {
- if( this.value != null ) return this.value;
-
- final Expression expression = this.astPair.value;
- this.value = getValue(expression);
- return this.value;
+ return this.value;
}
static Object getValue(Expression expression)
@@ -42,10 +45,24 @@
if( expression == null ) return null;
Constant constant = expression.constant;
// literals would hit this case.
- if( constant != null ) return constant;
+ if( constant != null && constant != Constant.NotAConstant) return constant;
if( expression instanceof Annotation )
- return new SourceAnnotation( (Annotation)expression );
+ return new SourceAnnotation( (Annotation)expression );
+ else if(expression instanceof Reference){
+ FieldBinding fieldBinding = null;
+ if(expression instanceof FieldReference )
+ fieldBinding = ((FieldReference)expression).fieldBinding();
+ else if(expression instanceof NameReference ){
+ final Binding binding = ((NameReference)expression).binding;
+ if( binding != null && binding.kind() == Binding.FIELD )
+ fieldBinding = (FieldBinding)binding;
+ }
+
+ if( fieldBinding != null && (fieldBinding.modifiers & IConstants.AccEnum) > 0 ){
+ return fieldBinding;
+ }
+ }
else if( expression instanceof ArrayInitializer )
{
@@ -61,8 +78,7 @@
final ClassLiteralAccess classLiteral = (ClassLiteralAccess)expression;
return classLiteral.targetType;
}
- // something that isn't a compile time constant.
- else
- return null;
+ // something that isn't a compile time constant.
+ return null;
}
}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
index 018dc2b..0992443 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
@@ -634,19 +634,25 @@
return this.tagBits;
}
-public IAnnotationInstance[] getAnnotations() {
- // make sure we first go resolve the annoations and report any problems found.
- getAnnotationTagBits();
+public IAnnotationInstance[] getAnnotations()
+{
+ if( this.annotations == null )
+ buildAnnotations();
+ return this.annotations;
+}
+
+private void buildAnnotations()
+{
+ if( this.annotations != null ) return;
+ this.annotations = NoAnnotations;
final TypeDeclaration typeDecl = this.scope.referenceContext;
final int numAnnotations = typeDecl.annotations == null ? 0 : typeDecl.annotations.length;
- if( numAnnotations == 0 )
- return NoAnnotations;
- else{
- final IAnnotationInstance[] instances = new IAnnotationInstance[numAnnotations];
- for( int i=0; i<numAnnotations; i++ ){
- instances[i] = new SourceAnnotation(typeDecl.annotations[i]);
+ if( numAnnotations > 0 ){
+ this.annotations = new IAnnotationInstance[numAnnotations];
+ for( int i=0; i<numAnnotations; i++ ){
+ typeDecl.annotations[i].resolveType(typeDecl.staticInitializerScope);
+ this.annotations[i] = typeDecl.annotations[i].getCompilerAnnotation();
}
- return instances;
}
}
@@ -910,12 +916,8 @@
this.synthetics[RECEIVER_TYPE_EMUL].put(targetField, fieldMap);
}
FieldBinding updatedField = (FieldBinding) fieldMap.get(newDeclaringClass);
- if (updatedField == null){
- if( targetField instanceof BinaryFieldBinding )
- updatedField = new BinaryFieldBinding((BinaryFieldBinding)targetField, newDeclaringClass);
- else
- updatedField = new FieldBinding(targetField, newDeclaringClass);
-
+ if (updatedField == null){
+ updatedField = new FieldBinding( targetField, newDeclaringClass);
fieldMap.put(newDeclaringClass, updatedField);
}
return updatedField;
@@ -933,11 +935,7 @@
}
MethodBinding updatedMethod = (MethodBinding) methodMap.get(newDeclaringClass);
if (updatedMethod == null){
- if( targetMethod instanceof BinaryMethodBinding )
- updatedMethod = new BinaryMethodBinding((BinaryMethodBinding)targetMethod, newDeclaringClass);
- else
- updatedMethod = new MethodBinding(targetMethod, newDeclaringClass);
-
+ updatedMethod = new MethodBinding(targetMethod, newDeclaringClass);
methodMap.put(newDeclaringClass, updatedMethod);
}
return updatedMethod;
@@ -1385,4 +1383,19 @@
for (int i = memberTypes.length; --i >= 0;)
((SourceTypeBinding) memberTypes[i]).verifyMethods(verifier);
}
+/*
+ * Called when the ast information is about to be null-ed out.
+ */
+public void finish()
+{
+ buildAnnotations();
+ if(this.methods != null){
+ for( int i=0, len=this.methods.length; i<len; i++ )
+ this.methods[i].buildAnnotations();
+ }
+ if(this.fields != null){
+ for( int i=0, len=this.fields.length; i<len; i++)
+ this.fields[i].buildAnnotations();
+ }
+}
}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java
index 6ba984f..5f3c9cd 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java
@@ -33,6 +33,15 @@
char[] CharArray_JAVA_IO_OBJECTINPUTSTREAM = "java.io.ObjectInputStream".toCharArray(); //$NON-NLS-1$
char[] CharArray_JAVA_IO_OBJECTOUTPUTSTREAM = "java.io.ObjectOutputStream".toCharArray(); //$NON-NLS-1$
char[] CharArray_JAVA_IO_OBJECTSTREAMFIELD = "java.io.ObjectStreamField".toCharArray(); //$NON-NLS-1$
+ char[] CharArray_JAVA_LANG_DEPRECATED_SIG = "Ljava/lang/Deprecated;".toCharArray(); //$NON-NLS-1$
+ char[] CharArray_JAVA_LANG_OVERRIDE_SIG = "Ljava/lang/Override;".toCharArray(); //$NON-NLS-1$
+ char[] CharArray_JAVA_LANG_SUPRESSWARNING_SIG = "Ljava/lang/SupressWarning;".toCharArray(); //$NON-NLS-1$
+ char[] CharArray_JAVA_LANG_ANNOTATION_DOCUMENTED_SIG = "Ljava/lang/annotation/Documented;".toCharArray(); //$NON-NLS-1$
+ char[] CharArray_JAVA_LANG_ANNOTATION_INHERITED_SIG = "Ljava/lang/annotation/Inherited;".toCharArray(); //$NON-NLS-1$
+ char[] CharArray_JAVA_LANG_ANNOTATION_RETENTION_SIG = "Ljava/lang/annotation/Retention;".toCharArray(); //$NON-NLS-1$
+ char[] CharArray_JAVA_LANG_ANNOTATION_TARGET_SIG = "Ljava/lang/annotation/Target;".toCharArray(); //$NON-NLS-1$
+ char[] CharArray_JAVA_LANG_ANNOTATION_RETENTIONPOLICY_SIG = "Ljava/lang/annotation/RetentionPolicy;".toCharArray(); //$NON-NLS-1$
+ char[] CharArray_JAVA_LANG_ANNOTATION_ELEMENTTYPE_SIG = "Ljava/lang/annotation/ElementType;".toCharArray(); //$NON-NLS-1$
char[] ANONYM_PREFIX = "new ".toCharArray(); //$NON-NLS-1$
char[] ANONYM_SUFFIX = "(){}".toCharArray(); //$NON-NLS-1$
char[] WILDCARD_NAME = { '?' };
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/VariableBinding.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/VariableBinding.java
index 6efe750..dbcc32f 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/VariableBinding.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/VariableBinding.java
@@ -12,7 +12,7 @@
import org.eclipse.jdt.internal.compiler.impl.Constant;
-public abstract class VariableBinding extends Binding {
+public abstract class VariableBinding extends Binding implements TypeConstants {
public int modifiers;
public TypeBinding type;
@@ -20,6 +20,7 @@
private Constant constant;
public int id; // for flow-analysis (position in flowInfo bit vector)
public long tagBits;
+ protected IAnnotationInstance[] annotations;
public VariableBinding(char[] name, TypeBinding type, int modifiers, Constant constant) {
this.name = name;
@@ -55,7 +56,10 @@
* @return the annotations iff this is a field, enum constant or parameter.
* Return null otherwise.
*/
- public abstract IAnnotationInstance[] getAnnotations();
+ public IAnnotationInstance[] getAnnotations()
+ {
+ return this.annotations;
+ }
public String toString() {
String s = (type != null) ? type.debugName() : "UNDEFINED TYPE"; //$NON-NLS-1$
diff --git a/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java b/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java
index 984bf04..52aba01 100644
--- a/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java
+++ b/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java
@@ -269,7 +269,7 @@
if (binding != null) {
return binding;
}
- binding = new PackageBinding(packageBinding);
+ binding = new PackageBinding(packageBinding, this);
this.bindingTables.compilerBindingsToASTBindings.put(packageBinding, binding);
return binding;
}
@@ -362,6 +362,7 @@
}
synchronized IResolvedAnnotation getAnnotationInstance(org.eclipse.jdt.internal.compiler.lookup.IAnnotationInstance internalInstance){
+ if( internalInstance == null ) return null;
IResolvedAnnotation domInstance =
(IResolvedAnnotation) this.bindingTables.compilerBindingsToASTBindings.get(internalInstance);
if (domInstance != null) {
@@ -1426,7 +1427,7 @@
org.eclipse.jdt.internal.compiler.ast.Annotation internalAstNode =
(org.eclipse.jdt.internal.compiler.ast.Annotation) oldNode;
- IResolvedAnnotation domAnnotation = this.getAnnotationInstance(internalAstNode.compilerAnnotation);
+ IResolvedAnnotation domAnnotation = this.getAnnotationInstance(internalAstNode.getCompilerAnnotation());
if (domAnnotation == null) {
return null;
}
diff --git a/dom/org/eclipse/jdt/core/dom/MethodBinding.java b/dom/org/eclipse/jdt/core/dom/MethodBinding.java
index 2c4009e..dadc4a6 100644
--- a/dom/org/eclipse/jdt/core/dom/MethodBinding.java
+++ b/dom/org/eclipse/jdt/core/dom/MethodBinding.java
@@ -422,7 +422,7 @@
if( isAnnotationMember() ){
final Object internalObject =
((org.eclipse.jdt.internal.compiler.lookup.AnnotationMethodBinding)this.binding).getDefaultValue();
- return ResolvedMemberValuePair.buildDOMValue(internalObject, this.binding.returnType, this.resolver);
+ return ResolvedMemberValuePair.buildDOMValue(internalObject, this.resolver);
}
return null;
}
diff --git a/dom/org/eclipse/jdt/core/dom/PackageBinding.java b/dom/org/eclipse/jdt/core/dom/PackageBinding.java
index 0bba13a..eb5bea3 100644
--- a/dom/org/eclipse/jdt/core/dom/PackageBinding.java
+++ b/dom/org/eclipse/jdt/core/dom/PackageBinding.java
@@ -30,7 +30,7 @@
private String name;
private String[] components;
- PackageBinding(org.eclipse.jdt.internal.compiler.lookup.PackageBinding binding) {
+ PackageBinding(org.eclipse.jdt.internal.compiler.lookup.PackageBinding binding, BindingResolver resolver) {
this.binding = binding;
}
@@ -149,8 +149,7 @@
}
public IResolvedAnnotation[] getAnnotations() {
- // TODO Auto-generated method stub
- throw new RuntimeException("Not implemented yet"); //$NON-NLS-1$
+ throw new UnsupportedOperationException("NYI"); //$NON-NLS-1$
}
/*
diff --git a/dom/org/eclipse/jdt/core/dom/ResolvedAnnotation.java b/dom/org/eclipse/jdt/core/dom/ResolvedAnnotation.java
index 7b6b991..ced5457 100644
--- a/dom/org/eclipse/jdt/core/dom/ResolvedAnnotation.java
+++ b/dom/org/eclipse/jdt/core/dom/ResolvedAnnotation.java
@@ -10,6 +10,13 @@
*******************************************************************************/
package org.eclipse.jdt.core.dom;
+import java.util.Arrays;
+import java.util.Comparator;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.lookup.AnnotationMethodBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+
/**
* Internal class
*/
@@ -19,10 +26,16 @@
private final org.eclipse.jdt.internal.compiler.lookup.IAnnotationInstance internalAnnotation;
private final BindingResolver bindingResolver;
+ /**
+ * @param anno
+ * @param resolver
+ */
ResolvedAnnotation(org.eclipse.jdt.internal.compiler.lookup.IAnnotationInstance anno,
BindingResolver resolver )
{
internalAnnotation = anno;
+ if( internalAnnotation == null )
+ throw new IllegalStateException();
bindingResolver = resolver;
}
@@ -35,17 +48,76 @@
public IResolvedMemberValuePair[] getDeclaredMemberValuePairs() {
final org.eclipse.jdt.internal.compiler.lookup.IElementValuePair[] internalPair =
this.internalAnnotation.getElementValuePairs();
- final int len = internalPair.length;
+ final int len = internalPair.length;
IResolvedMemberValuePair[] pairs = ResolvedMemberValuePair.NoPair;
- for( int i=0; i<len; i++ ){
- pairs[i] = new ResolvedMemberValuePair(internalPair[i],this.bindingResolver);
+ if( len > 0 )
+ {
+ pairs = new ResolvedMemberValuePair[len];
+ for( int i=0; i<len; i++ ){
+ pairs[i] = new ResolvedMemberValuePair(internalPair[i],this.bindingResolver);
+ }
}
return pairs;
}
public IResolvedMemberValuePair[] getAllMemberValuePairs() {
- // TODO missing implementation
- throw new RuntimeException("Not implemented yet"); //$NON-NLS-1$
+ final ReferenceBinding typeBinding = this.internalAnnotation.getAnnotationType();
+ IResolvedMemberValuePair[] pairs = ResolvedMemberValuePair.NoPair;
+ final org.eclipse.jdt.internal.compiler.lookup.MethodBinding[] methods = typeBinding.methods();
+ final int len = methods == null ? 0 : methods.length;
+ if(typeBinding != null && len > 0 ){
+ final org.eclipse.jdt.internal.compiler.lookup.IElementValuePair[] internalPair =
+ this.internalAnnotation.getElementValuePairs();
+ final int declaredLen = internalPair == null ? 0 : internalPair.length;
+ final Object[] names = declaredLen < len ? new Object[declaredLen] : null;
+ for( int i=0; i<declaredLen; i++ ){
+ pairs[i] = new ResolvedMemberValuePair(internalPair[i], this.bindingResolver);
+ names[i] = internalPair[i].getMemberName();
+ }
+ if( declaredLen < len ){
+ final MemberComparator comparator = new MemberComparator();
+ Arrays.sort(names, comparator);
+ int pIndex = declaredLen;
+ for( int i=0; i<len; i++, pIndex++ ){
+ final char[] selector = methods[i].selector;
+ final int index = Arrays.binarySearch(names, selector, comparator);
+ if( index < 0 )
+ pairs[pIndex] = new ResolvedDefaultValuePair((AnnotationMethodBinding)methods[i], this.bindingResolver);
+ }
+ }
+ }
+ return pairs;
}
+ public String toString()
+ {
+ final ITypeBinding annoType = getAnnotationType();
+
+ final StringBuffer buffer = new StringBuffer();
+ buffer.append('@');
+ if(annoType != null)
+ buffer.append(annoType.getName());
+ buffer.append('(');
+ final IResolvedMemberValuePair[] pairs = getDeclaredMemberValuePairs();
+ for( int i = 0, len = pairs.length; i<len; i++ ){
+ if( i != 0 )
+ buffer.append(", "); //$NON-NLS-1$
+ buffer.append(pairs[i].toString());
+ }
+ buffer.append(')');
+ return buffer.toString();
+
+ }
+
+ private static class MemberComparator implements Comparator
+ {
+ public int compare(Object arg0, Object arg1)
+ {
+ // throws ClassCastException if either one of the arguments is not
+ // a char[]
+ final char[] c0 = (char[])arg0;
+ final char[] c1 = (char[])arg1;
+ return CharOperation.compareWith(c0, c1);
+ }
+ }
}
diff --git a/dom/org/eclipse/jdt/core/dom/ResolvedDefaultValuePair.java b/dom/org/eclipse/jdt/core/dom/ResolvedDefaultValuePair.java
new file mode 100644
index 0000000..b7da76e
--- /dev/null
+++ b/dom/org/eclipse/jdt/core/dom/ResolvedDefaultValuePair.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2005 BEA Systems, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * tyeung@bea.com - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import org.eclipse.jdt.core.dom.BindingResolver;
+import org.eclipse.jdt.core.dom.IMethodBinding;
+import org.eclipse.jdt.core.dom.IResolvedMemberValuePair;
+
+/**
+ * Member value pair which compose of default values.
+ */
+class ResolvedDefaultValuePair implements IResolvedMemberValuePair
+{
+ private final org.eclipse.jdt.internal.compiler.lookup.MethodBinding method;
+ private final Object domValue;
+ private final BindingResolver bindingResolver;
+
+ ResolvedDefaultValuePair(org.eclipse.jdt.internal.compiler.lookup.AnnotationMethodBinding binding, final BindingResolver resolver )
+ {
+ this.method = binding;
+ this.domValue = ResolvedMemberValuePair.buildDOMValue(binding.getDefaultValue(), resolver);
+ this.bindingResolver = resolver;
+ }
+ public String getName() {
+ return new String( this.method.selector );
+ }
+
+ public IMethodBinding getMemberBinding() {
+ return this.bindingResolver.getMethodBinding(this.method);
+ }
+
+ public Object getValue() {
+ return this.domValue;
+ }
+
+ public void toString(StringBuffer buffer) {
+ buffer.append(getName());
+ buffer.append(" = "); //$NON-NLS-1$
+ appendValue(getValue(), buffer);
+ }
+
+ static void appendValue(Object value, StringBuffer buffer) {
+ if( value instanceof Object[] ){
+ appendValue((Object[])value, buffer);
+ }
+ else{
+ if(value instanceof ITypeBinding ){
+ buffer.append( ((ITypeBinding)value).getName() );
+ buffer.append( ".class" ); //$NON-NLS-1$
+ }
+ else
+ buffer.append(value);
+ }
+ }
+
+ private static void appendValue(Object[] values, StringBuffer buffer) {
+ buffer.append('{');
+ for( int i=0, len=values.length; i<len; i++ ){
+ if( i != 0 )
+ buffer.append(", "); //$NON-NLS-1$
+ appendValue(values[i], buffer);
+
+ }
+ buffer.append('}');
+ }
+
+ public String toString() {
+ final StringBuffer buffer = new StringBuffer();
+ toString(buffer);
+ return buffer.toString();
+ }
+}
diff --git a/dom/org/eclipse/jdt/core/dom/ResolvedMemberValuePair.java b/dom/org/eclipse/jdt/core/dom/ResolvedMemberValuePair.java
index 5959802..2c4b8b7 100644
--- a/dom/org/eclipse/jdt/core/dom/ResolvedMemberValuePair.java
+++ b/dom/org/eclipse/jdt/core/dom/ResolvedMemberValuePair.java
@@ -18,78 +18,79 @@
*/
class ResolvedMemberValuePair implements IResolvedMemberValuePair
{
- static final ResolvedMemberValuePair[] NoPair = new ResolvedMemberValuePair[0];
+ static final ResolvedMemberValuePair[] NoPair = new ResolvedMemberValuePair[0];
private static final Object NoValue = new Object();
+ private static final Object[] EmptyArray = new Object[0];
+
private final org.eclipse.jdt.internal.compiler.lookup.IElementValuePair internalPair;
private Object value = null;
private final BindingResolver bindingResolver;
ResolvedMemberValuePair(final org.eclipse.jdt.internal.compiler.lookup.IElementValuePair pair,
- BindingResolver resolver)
- {
+ BindingResolver resolver) {
this.internalPair = pair;
this.bindingResolver = resolver;
}
- private void init()
- {
- final org.eclipse.jdt.internal.compiler.lookup.TypeBinding type = this.internalPair.getType();
- this.value = buildDOMValue(this.internalPair.getValue(), type, this.bindingResolver);
+ private void init() {
+ this.value = buildDOMValue(this.internalPair.getValue(), this.bindingResolver);
if( this.value == null )
this.value = NoValue;
}
static Object buildDOMValue(final Object internalObject,
- org.eclipse.jdt.internal.compiler.lookup.TypeBinding type,
- BindingResolver resolver)
- {
- if( internalObject == null || type == null ) return null;
- switch(type.id)
- {
- case TypeIds.T_boolean:
- return new Boolean( ((Constant)internalObject).booleanValue() );
- case TypeIds.T_byte:
- return new Byte( ((Constant)internalObject).byteValue() );
- case TypeIds.T_char:
- return new Character( ((Constant)internalObject).charValue() );
- case TypeIds.T_double:
- return new Double( ((Constant)internalObject).doubleValue() );
- case TypeIds.T_float:
- return new Float( ((Constant)internalObject).floatValue() );
- case TypeIds.T_int:
- return new Integer( ((Constant)internalObject).intValue() );
- case TypeIds.T_long:
- return new Long( ((Constant)internalObject).longValue() );
- case TypeIds.T_short:
- return new Short( ((Constant)internalObject).shortValue() );
- case TypeIds.T_JavaLangString:
- return internalObject;
- case TypeIds.T_JavaLangClass:
- return resolver.getTypeBinding((org.eclipse.jdt.internal.compiler.lookup.TypeBinding)internalObject);
- }
+ BindingResolver resolver) {
+ if( internalObject == null ) return null;
- if( type.isAnnotationType() ){
+ if( internalObject instanceof Constant )
+ {
+ final Constant constant = (Constant)internalObject;
+ switch( constant.typeID() )
+ {
+ case TypeIds.T_boolean:
+ return new Boolean( constant.booleanValue() );
+ case TypeIds.T_byte:
+ return new Byte( constant.byteValue() );
+ case TypeIds.T_char:
+ return new Character( constant.charValue() );
+ case TypeIds.T_double:
+ return new Double( constant.doubleValue() );
+ case TypeIds.T_float:
+ return new Float( constant.floatValue() );
+ case TypeIds.T_int:
+ return new Integer( constant.intValue() );
+ case TypeIds.T_long:
+ return new Long( constant.longValue() );
+ case TypeIds.T_short:
+ return new Short( constant.shortValue() );
+ case TypeIds.T_JavaLangString:
+ return constant.stringValue();
+ }
+ }
+ else if( internalObject instanceof org.eclipse.jdt.internal.compiler.lookup.TypeBinding){
+ return resolver.getTypeBinding((org.eclipse.jdt.internal.compiler.lookup.TypeBinding)internalObject);
+ }
+ if( internalObject instanceof org.eclipse.jdt.internal.compiler.lookup.IAnnotationInstance ) {
return new ResolvedAnnotation(
(org.eclipse.jdt.internal.compiler.lookup.IAnnotationInstance)internalObject,
resolver);
}
- else if( type.isEnum() ){
+ else if( internalObject instanceof org.eclipse.jdt.internal.compiler.lookup.FieldBinding ) {
return resolver.getVariableBinding((org.eclipse.jdt.internal.compiler.lookup.FieldBinding)internalObject);
}
- else if( type.isArrayType() ){
+ else if( internalObject instanceof Object[] ) {
final Object[] iElements = (Object[])internalObject;
final int len = iElements.length;
- Object[] values = null;
- if( len > 0){
- final org.eclipse.jdt.internal.compiler.lookup.TypeBinding elementType =
- ((org.eclipse.jdt.internal.compiler.lookup.ArrayBinding)type).leafComponentType;
+ Object[] values = EmptyArray;
+ if( len > 0){
values = new Object[len];
for( int i=0; i<len; i++ ){
- values[i] = buildDOMValue(iElements[i], elementType, resolver);
+ values[i] = buildDOMValue(iElements[i], resolver);
}
}
- }
- throw new IllegalStateException(); // should never get here.
+ return values;
+ }
+ throw new IllegalStateException(internalObject.toString()); // should never get here.
}
public String getName() {
@@ -106,4 +107,17 @@
init();
return value == NoValue ? null : this.value;
}
+
+ public void toString(StringBuffer buffer) {
+ buffer.append(getName());
+ buffer.append(" = "); //$NON-NLS-1$
+ ResolvedDefaultValuePair.appendValue(getValue(), buffer);
+ }
+
+ public String toString() {
+ final StringBuffer buffer = new StringBuffer();
+ toString(buffer);
+ return buffer.toString();
+ }
}
+
diff --git a/model/org/eclipse/jdt/core/JavaCore.java b/model/org/eclipse/jdt/core/JavaCore.java
index 4f32ee9..0dd1e6c 100644
--- a/model/org/eclipse/jdt/core/JavaCore.java
+++ b/model/org/eclipse/jdt/core/JavaCore.java
@@ -1019,6 +1019,7 @@
* Add a compilation participant listener dynamically. It is not necessary
* to call this for listeners registered with the compilationParticipants
* extension point.
+ *
* @param icp the listener
* @param eventMask the set of events for which the listener will be notified,
* built by ORing together values from CompilationParticipantEvent.
@@ -1534,15 +1535,20 @@
* listeners that have requested notification of at least one of
* the events in the flags mask.
* The first time this is called, it loads listeners from plugins,
- * which may cause plugins to be loaded. If this is called on
- * multiple threads simultaneously, or if loading a plugin causes
- * this to be reentered, it may return an incomplete list of listeners,
- * but it is guaranteed not to crash or deadlock.
+ * which may cause plugins to be loaded.
+ *
+ * <p>
+ * Note that a deadlock situation can occur if a plugin's <code>start()</code>
+ * method blocks on a thread that calls <code>getCompilationParticipants()</code>.
+ * See <code>JavaModelManager.CompilationParticipants.getCompilationParticipants()</code>
+ * for a complete description of the circumstances under which this deadlock can occur.
+ *
* @param eventMask an ORed combination of values from ICompilationParticipant.
* @return an immutable list of ICompilationParticipant.
+ * @see JavaModelManager.CompilationParticipants#getCompilationParticipants
*/
public static List getCompilationParticipants(int eventMask) {
- return JavaModelManager.getJavaModelManager().getCompilationParticipants().get(eventMask);
+ return JavaModelManager.getJavaModelManager().getCompilationParticipants().getCompilationParticipants(eventMask);
}
/**
diff --git a/model/org/eclipse/jdt/internal/core/CompilationUnit.java b/model/org/eclipse/jdt/internal/core/CompilationUnit.java
index d0a6af5..b7136bb 100644
--- a/model/org/eclipse/jdt/internal/core/CompilationUnit.java
+++ b/model/org/eclipse/jdt/internal/core/CompilationUnit.java
@@ -16,9 +16,7 @@
import org.eclipse.core.runtime.*;
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.core.compiler.ICompilationParticipant;
import org.eclipse.jdt.core.compiler.IProblem;
-import org.eclipse.jdt.core.compiler.PostReconcileCompilationEvent;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.IProblemFactory;
@@ -27,10 +25,8 @@
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
-import org.eclipse.jdt.internal.core.JavaModelManager.PerWorkingCopyInfo;
import org.eclipse.jdt.internal.core.util.MementoTokenizer;
import org.eclipse.jdt.internal.core.util.Util;
-
/**
* @see ICompilationUnit
*/
@@ -44,19 +40,7 @@
protected String name;
public WorkingCopyOwner owner;
-
- /**
- * indicates if a NoOpProblemRequestor should be used when
- * calling getPerWorkingCopyInfo
- */
- private boolean useNoOpProblemRequestor = false;
- /**
- * indicates if we should treat this working copy as inconsistent
- * even if there wasn't a change in the underlying buffer.
- */
- private boolean forceInconsistent = false;
-
/**
* Constructs a handle to a compilation unit with the given name in the
@@ -773,12 +757,8 @@
* Returns the per working copy info for the receiver, or null if none exist.
* Note: the use count of the per working copy info is NOT incremented.
*/
-public JavaModelManager.PerWorkingCopyInfo getPerWorkingCopyInfo() {
-
- if ( useNoOpProblemRequestor )
- return new PerWorkingCopyInfo( this, NO_OP_PROBLEM_REQUESTOR );
- else
- return JavaModelManager.getJavaModelManager().getPerWorkingCopyInfo(this, false/*don't create*/, false/*don't record usage*/, null/*no problem requestor needed*/);
+public JavaModelManager.PerWorkingCopyInfo getPerWorkingCopyInfo() {
+ return JavaModelManager.getJavaModelManager().getPerWorkingCopyInfo(this, false/*don't create*/, false/*don't record usage*/, null/*no problem requestor needed*/);
}
/*
@@ -921,10 +901,7 @@
* @see IOpenable#isConsistent()
*/
public boolean isConsistent() {
- if ( forceInconsistent )
- return false;
- else
- return JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().get(this) == null;
+ return JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().get(this) == null;
}
/**
*
@@ -1111,54 +1088,8 @@
ReconcileWorkingCopyOperation op = null;
- List l = JavaCore.getCompilationParticipants(ICompilationParticipant.POST_RECONCILE_EVENT);
- if ( l != null && l.size() > 0 ) {
- // we always need an AST to pass into compilation participants
- op = new ReconcileWorkingCopyOperation(this, true /*createAST*/, AST.JLS3, forceProblemDetection, workingCopyOwner);
-
- // TODO: try not to use these two try-catch blocks here...
- try {
- try {
- useNoOpProblemRequestor = true;
- forceInconsistent = ! this.isConsistent();
- op.runOperation(monitor);
- }
- finally {
- useNoOpProblemRequestor = false;
- }
-
- Iterator it = l.iterator();
- while ( it.hasNext() ) {
- ICompilationParticipant p = (ICompilationParticipant)it.next();
- PostReconcileCompilationEvent prce = new PostReconcileCompilationEvent( this, op.ast, getJavaProject() );
- p.notify( prce );
- // TODO: do something with the result of notify...
- }
-
- // save off the original AST
- org.eclipse.jdt.core.dom.CompilationUnit originalAst = op.ast;
-
- // if there were ICompilationParticipants, we will reconcile again and return the ast from the second reconcile
- // this causes the client to receive an AST that is correct with respect to any changes that occurred in the
- // ast as a result of files being added by compilation participants. This second reconcile also causes any
- // problems to be reported to the correct problemRequestor, instead of the no-op problemRequestor.
- op = new ReconcileWorkingCopyOperation(this, createAST, astLevel, forceProblemDetection, workingCopyOwner);
- op.runOperation(monitor);
-
- // if the original AST was null, assume that the working copy was consistent.
- // and return null.
- if ( originalAst == null )
- return null;
- }
- finally {
- forceInconsistent = false;
- }
- }
- else
- {
- op = new ReconcileWorkingCopyOperation(this, createAST, astLevel, forceProblemDetection, workingCopyOwner);
- op.runOperation(monitor);
- }
+ op = new ReconcileWorkingCopyOperation(this, createAST, astLevel, forceProblemDetection, workingCopyOwner);
+ op.runOperation(monitor);
return op.ast;
}
@@ -1236,14 +1167,4 @@
((CompilationUnitElementInfo) getElementInfo()).timestamp = timeStamp;
}
-
-
-private final static NoOpProblemRequestor NO_OP_PROBLEM_REQUESTOR = new NoOpProblemRequestor();
-private final static class NoOpProblemRequestor implements IProblemRequestor {
- public void acceptProblem(IProblem problem) { /* no-op */ }
- public void beginReporting() { /* no-op */ }
- public void endReporting() { /* no-op */ }
- public boolean isActive() { return true; }
-}
-
}
diff --git a/model/org/eclipse/jdt/internal/core/JavaModelManager.java b/model/org/eclipse/jdt/internal/core/JavaModelManager.java
index e76004e..26fd646 100644
--- a/model/org/eclipse/jdt/internal/core/JavaModelManager.java
+++ b/model/org/eclipse/jdt/internal/core/JavaModelManager.java
@@ -174,14 +174,24 @@
* listeners that have requested notification of at least one of
* the events in the flags mask.
* The first time this is called, it loads listeners from plugins,
- * which may cause plugins to be loaded. If this is called on
- * multiple threads simultaneously, or if loading a plugin causes
- * this to be reentered, it may return an incomplete list of listeners,
- * but it is guaranteed not to crash or deadlock.
+ * which may cause plugins to be loaded.
+ *
+ * <p>
+ * The initialization of ICompilationParticipants is synchronized. A deadlock may
+ * occur if all of the following conditions are true:
+ *
+ * <li>A plugin defines <code>ICompilationParticipants</code></li>
+ * <li>That plugin's <code>start()</code> method spawns a thread which causes
+ * <code>getCompilationParticipants()</code> to be invoked</li>
+ * <li>The <code>start()</code> method blocks waiting for the spawned thread to complete.</li>
+ *
+ * Note that a build and reconcile operations will cause <code>getCompilationParticipants()</code> to
+ * be called.
+ *
* @param eventMask an ORed combination of values from ICompilationParticipant.
* @return an immutable list of ICompilationParticipant.
*/
- public List get(int eventMask) {
+ public List getCompilationParticipants(int eventMask) {
initPlugins();
List filteredICPs = new ArrayList();
Iterator it;
@@ -204,16 +214,15 @@
return Collections.unmodifiableList(filteredICPs);
}
- private void initPlugins() {
- synchronized (this) {
- if (null != pluginCPs) {
- return;
- }
- pluginCPs = new HashMap();
+ private synchronized void initPlugins() {
+ if (null != pluginCPs) {
+ return;
}
+ pluginCPs = new HashMap();
+
IExtensionPoint extension = Platform.getExtensionRegistry().getExtensionPoint(
JavaCore.PLUGIN_ID, COMPILATION_PARTICIPANT_EXTPOINT_ID);
- if (extension == null)
+ if (extension == null)
return;
IExtension[] extensions = extension.getExtensions();
for(int iExtension = 0; iExtension < extensions.length; iExtension++){
diff --git a/model/org/eclipse/jdt/internal/core/ReconcileWorkingCopyOperation.java b/model/org/eclipse/jdt/internal/core/ReconcileWorkingCopyOperation.java
index 3cec2ff..75a069d 100644
--- a/model/org/eclipse/jdt/internal/core/ReconcileWorkingCopyOperation.java
+++ b/model/org/eclipse/jdt/internal/core/ReconcileWorkingCopyOperation.java
@@ -10,22 +10,25 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core;
+import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.compiler.ICompilationParticipant;
+import org.eclipse.jdt.core.compiler.PostReconcileCompilationEvent;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
-import org.eclipse.jdt.internal.core.util.Messages;
+import org.eclipse.jdt.internal.core.util.Util;
/**
* Reconcile a working copy and signal the changes through a delta.
*/
public class ReconcileWorkingCopyOperation extends JavaModelOperation {
- public static boolean PERF = false;
-
+
boolean createAST;
int astLevel;
boolean forceProblemDetection;
@@ -47,9 +50,11 @@
if (this.progressMonitor != null){
if (this.progressMonitor.isCanceled())
throw new OperationCanceledException();
- this.progressMonitor.beginTask(Messages.element_reconciling, 2);
+ this.progressMonitor.beginTask(Util.bind("element.reconciling"), 2); //$NON-NLS-1$
}
+ notifyCompilationParticipants();
+
CompilationUnit workingCopy = getWorkingCopy();
boolean wasConsistent = workingCopy.isConsistent();
try {
@@ -120,5 +125,22 @@
return status;
}
+ private void notifyCompilationParticipants() {
+
+ List l = JavaCore.getCompilationParticipants(ICompilationParticipant.POST_RECONCILE_EVENT);
+ CompilationUnit workingCopy = getWorkingCopy();
+
+ // we want to go through ICompilationParticipant only if there are participants
+ // and the compilation unit is not consistent or we are forcing problem detection
+ if ( ( l != null && l.size() > 0 ) && ( !workingCopy.isConsistent() || forceProblemDetection )) {
+ PostReconcileCompilationEvent prce = new PostReconcileCompilationEvent( workingCopy, workingCopy.getJavaProject() );
+ Iterator it = l.iterator();
+ while ( it.hasNext() ) {
+ ICompilationParticipant p = (ICompilationParticipant)it.next();
+ p.notify( prce );
+ // TODO: do something with the result of notify...
+ }
+ }
+ }
}
diff --git a/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java b/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java
index d2ff2cb..d941f25 100644
--- a/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java
+++ b/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java
@@ -226,15 +226,13 @@
/**
* notify the ICompilationParticipants of the pre-build event
*/
-private Set notifyCompilationParticipants(ICompilationUnit[] sourceUnits) {
+private void notifyCompilationParticipants(ICompilationUnit[] sourceUnits, Set newFiles, Set deletedFiles, Map extraDependencies ) {
List cps = JavaCore
.getCompilationParticipants( ICompilationParticipant.PRE_BUILD_EVENT );
if ( cps.isEmpty() ) {
- return Collections.EMPTY_SET;
+ return;
}
- extraDependencyMap = new HashMap();
-
IFile[] files = new IFile[sourceUnits.length];
for ( int i = 0; i < files.length; i++ ) {
if ( sourceUnits[i] instanceof SourceFile ) {
@@ -247,7 +245,6 @@
PreBuildCompilationEvent pbce = new PreBuildCompilationEvent( files,
javaBuilder.javaProject );
- Set newFiles = new HashSet();
java.util.Iterator it = cps.iterator();
while ( it.hasNext() ) {
ICompilationParticipant p = ( ICompilationParticipant ) it.next();
@@ -262,10 +259,25 @@
newFiles.add( f[i] );
}
- mergeMaps( pbcr.getNewDependencies(), extraDependencyMap );
+ f = pbcr.getDeletedFiles();
+ if ( f != null ) {
+ for ( int i = 0; i < f.length; i++ )
+ deletedFiles.add( f[i] );
+ }
+
+ mergeMaps( pbcr.getNewDependencies(), extraDependencies );
}
}
- return newFiles;
+
+ if ( newFiles.size() > 0 ) {
+ Set newFiles_2 = new HashSet();
+ Set deletedFiles_2 = new HashSet();
+ ICompilationUnit[] newFileArray = ifileSet2SourceFileArray( newFiles );
+ notifyCompilationParticipants( newFileArray, newFiles_2, deletedFiles_2, extraDependencies );
+ newFiles.addAll( newFiles_2 );
+ deletedFiles.addAll( deletedFiles_2 );
+ }
+
}
/**
@@ -299,27 +311,80 @@
*/
protected ClasspathMultiDirectory getSourceLocationForFile(IFile file) {
ClasspathMultiDirectory md = null;
- if ( file.exists() ) {
- md = sourceLocations[0];
- if ( sourceLocations.length > 1 ) {
- IPath sourceFileFullPath = file.getFullPath();
- for ( int j = 0, m = sourceLocations.length; j < m; j++ ) {
- if ( sourceLocations[j].sourceFolder.getFullPath()
- .isPrefixOf( sourceFileFullPath ) ) {
- md = sourceLocations[j];
- if ( md.exclusionPatterns == null
- && md.inclusionPatterns == null )
- break;
- if ( !Util.isExcluded( file, md.inclusionPatterns,
- md.exclusionPatterns ) )
- break;
- }
+ md = sourceLocations[0];
+ if ( sourceLocations.length > 1 ) {
+ IPath sourceFileFullPath = file.getFullPath();
+ for ( int j = 0, m = sourceLocations.length; j < m; j++ ) {
+ if ( sourceLocations[j].sourceFolder.getFullPath()
+ .isPrefixOf( sourceFileFullPath ) ) {
+ md = sourceLocations[j];
+ if ( md.exclusionPatterns == null
+ && md.inclusionPatterns == null )
+ break;
+ if ( !Util.isExcluded( file, md.inclusionPatterns,
+ md.exclusionPatterns ) )
+ break;
}
}
}
return md;
}
+/**
+ * copies IFile entries in a Set<IFile> into SourceFile entries into a SourceFile[].
+ * Copying starts at the specified start position.
+ */
+private void ifileSet2SourceFileArray( Set ifiles, SourceFile[] sourceFiles, int start ) {
+ Iterator it = ifiles.iterator();
+ while ( it.hasNext() ) {
+ IFile f = ( IFile ) it.next();
+ sourceFiles[start++] = new SourceFile( f, getSourceLocationForFile( f ) );
+ }
+}
+
+/**
+ * Given a Set<IFile>, this method returns a SourceFile[] where each entry
+ * in the array corresponds to an entry in the set.
+ */
+private SourceFile[] ifileSet2SourceFileArray( Set ifiles ) {
+ SourceFile[] sf = new SourceFile[ ifiles.size() ];
+ ifileSet2SourceFileArray( ifiles, sf, 0 );
+ return sf;
+}
+
+private SourceFile[] updateSourceUnits( SourceFile[] units, Set newFiles, Set deletedFiles ) {
+ if ( newFiles.size() == 0 && deletedFiles.size() == 0 )
+ return units;
+ else if ( deletedFiles.size() == 0 ) {
+ // files have only been added
+ SourceFile[] newUnits = new SourceFile[ units.length + newFiles.size() ];
+ System.arraycopy( units, 0, newUnits, 0, units.length );
+ ifileSet2SourceFileArray( newFiles, newUnits, units.length );
+ return newUnits;
+ }
+ else {
+ // files have been added & deleted. Deal with deleted files first. If
+ // someone reports that a file has been added and deleted, then it will be
+ // added.
+ HashSet unitSet = new HashSet();
+ for ( int i=0; i<units.length; i++ )
+ unitSet.add( units[i].getFile() );
+ Iterator it = deletedFiles.iterator();
+ while ( it.hasNext() ) {
+ IFile f = (IFile) it.next();
+ if ( unitSet.contains( f ) )
+ unitSet.remove( f );
+ handleFileDeletedByCompilationParticipant( f );
+ }
+ unitSet.addAll( newFiles );
+ return ifileSet2SourceFileArray( unitSet );
+ }
+}
+
+protected void handleFileDeletedByCompilationParticipant( IFile f )
+{
+ // noop
+}
void compile(SourceFile[] units, SourceFile[] additionalUnits) {
if (units.length == 0) return;
@@ -344,20 +409,14 @@
try {
inCompiler = true;
- // notify compilation participants, and add any new files created
- // by the participants into the set of files being compiled.
- Set newFiles = notifyCompilationParticipants( units );
- if ( newFiles != null && newFiles.size() > 0 ) {
- SourceFile[] newUnits = new SourceFile[units.length + newFiles.size()];
- System.arraycopy( units, 0, newUnits, 0, units.length );
- Iterator it = newFiles.iterator();
- int idx = units.length;
- while ( it.hasNext() ) {
- IFile f = ( IFile ) it.next();
- newUnits[idx++] = new SourceFile( f, getSourceLocationForFile( f ) );
- }
- units = newUnits;
- }
+ // notify compilation participants,
+ Set newFiles = new HashSet();
+ Set deletedFiles = new HashSet();
+ extraDependencyMap = new HashMap();
+ notifyCompilationParticipants( units, newFiles, deletedFiles, extraDependencyMap );
+
+ // update units array with the new & deleted files
+ units = updateSourceUnits( units, newFiles, deletedFiles );
compiler.compile(units);
@@ -397,33 +456,21 @@
char[][] simpleRefs = result.simpleNameReferences;
if ( extraDependencyMap != null && extraDependencyMap.size() > 0 ) {
- //IFile f = javaBuilder.currentProject.getFile( new String( result.fileName ));
IFile f = ResourcesPlugin.getWorkspace().getRoot().getFile( new Path( new String( result.fileName ) ));
Set s = (Set)extraDependencyMap.get( f );
if ( s != null && s.size() > 0 ) {
- // Set<String>
- Set simpleNameSet = new HashSet();
- Set qualifiedNameSet = new HashSet();
+ NameSet simpleNameSet = new NameSet( simpleRefs.length + s.size() );
+ QualifiedNameSet qualifiedNameSet = new QualifiedNameSet( qualifiedRefs.length + s.size() );
//
// add in all of the existing refs to the sets to filter out duplicates
//
- for ( int i = 0; i< simpleRefs.length; i++ ) {
- simpleNameSet.add( new String( simpleRefs[i] ) );
- }
-
- for ( int i = 0; i< qualifiedRefs.length; i++ ) {
-
- StringBuffer sb = new StringBuffer();
- int len = qualifiedRefs[i].length - 1;
- for ( int j = 0; j < len; j++ ) {
- sb.append( qualifiedRefs[i][j] );
- sb.append( "." ); //$NON-NLS-1$
- }
- sb.append( qualifiedRefs[i][len] );
- qualifiedNameSet.add( sb.toString() );
- }
-
+ for ( int i = 0; i< simpleRefs.length; i++ )
+ simpleNameSet.add( simpleRefs[i] );
+
+ for ( int i = 0; i< qualifiedRefs.length; i++ )
+ qualifiedNameSet.add( qualifiedRefs[i] );
+
//
// get all of the the parts of the new dependencies into sets
// for a dependency "a.b.c.d", we want the qualifiedNameSet to include
@@ -432,47 +479,34 @@
//
Iterator it = s.iterator();
while ( it.hasNext() ) {
- String rpart = (String) it.next();
- int idx = rpart.indexOf( '.', 0 );
- while ( idx > -1 ) {
- qualifiedNameSet.add( rpart );
- String lpart = rpart.substring( 0, idx );
- rpart = rpart.substring( idx + 1, rpart.length() );
- simpleNameSet.add( lpart );
- idx = rpart.indexOf( '.', idx + 1 );
+ char[] array = ((String) it.next() ).toCharArray();
+ char[][] parts = CharOperation.splitOn('.', array );
+ for ( int i = 0; i<parts.length; i++ )
+ simpleNameSet.add( parts[i] );
+
+ for( int i = parts.length - 1; i > 0; --i ) {
+ qualifiedNameSet.add( parts );
+ parts = CharOperation.subarray( parts, 0, i );
}
- simpleNameSet.add( rpart );
}
-
+
//
- // now turn the set of simple names into a char[][]
+ // strip out any null entries in the arrays retrieved from the sets.
//
- char[][] newSimpleNameArray = new char[ simpleNameSet.size() ][];
- it = simpleNameSet.iterator();
- int i = 0;
- while ( it.hasNext() ) {
- String str = (String) it.next();
- newSimpleNameArray[i] = str.toCharArray();
- i++;
- }
+ simpleRefs = new char[ simpleNameSet.elementSize][];
+ char[][] names = simpleNameSet.names;
+ int j = 0;
+ for ( int i = 0; i<names.length; i++ )
+ if ( names[i] != null)
+ simpleRefs[j++] = names[i];
- //
- // turn the set of qnames into a char[][][]
- //
- char[][][] newQualifiedNameArray = new char[ qualifiedNameSet.size() ][][];
- it = qualifiedNameSet.iterator();
- i = 0;
- while ( it.hasNext() ) {
- String str = (String) it.next();
- String[] parts = str.split( "\\." ); //$NON-NLS-1$
- newQualifiedNameArray[i] = new char[ parts.length ][];
- for ( int j = 0; j < parts.length; j++ ) {
- newQualifiedNameArray[i][j] = parts[j].toCharArray();
- }
- i++;
- }
- qualifiedRefs = newQualifiedNameArray;
- simpleRefs = newSimpleNameArray;
+ qualifiedRefs = new char[ qualifiedNameSet.elementSize ][][];
+ j = 0;
+ char[][][] qnames = qualifiedNameSet.qualifiedNames;
+ for ( int i = 0; i< qnames.length; i++ )
+ if ( qnames[i] != null )
+ qualifiedRefs[j++] = qnames[i];
+
}
}
diff --git a/model/org/eclipse/jdt/internal/core/builder/BatchImageBuilder.java b/model/org/eclipse/jdt/internal/core/builder/BatchImageBuilder.java
index b623720..e026e78 100644
--- a/model/org/eclipse/jdt/internal/core/builder/BatchImageBuilder.java
+++ b/model/org/eclipse/jdt/internal/core/builder/BatchImageBuilder.java
@@ -14,7 +14,8 @@
import org.eclipse.core.runtime.*;
import org.eclipse.jdt.core.JavaCore;
-import org.eclipse.jdt.internal.core.util.Messages;
+import org.eclipse.jdt.core.compiler.ICompilationParticipant;
+import org.eclipse.jdt.core.compiler.CleanCompilationEvent;
import org.eclipse.jdt.internal.core.util.Util;
import java.util.*;
@@ -31,12 +32,12 @@
System.out.println("FULL build"); //$NON-NLS-1$
try {
- notifier.subTask(Messages.build_cleaningOutput);
+ notifier.subTask(Util.bind("build.cleaningOutput")); //$NON-NLS-1$
JavaBuilder.removeProblemsAndTasksFor(javaBuilder.currentProject);
cleanOutputFolders(true);
notifier.updateProgressDelta(0.1f);
- notifier.subTask(Messages.build_analyzingSources);
+ notifier.subTask(Util.bind("build.analyzingSources")); //$NON-NLS-1$
ArrayList sourceFiles = new ArrayList(33);
addAllSourceFiles(sourceFiles);
notifier.updateProgressDelta(0.15f);
@@ -98,13 +99,33 @@
}
}
+private void notifyCompilationParticipantsOfClean()
+{
+ List cps = JavaCore.getCompilationParticipants(
+ ICompilationParticipant.CLEAN_EVENT );
+
+ if ( cps.isEmpty() )
+ return;
+
+ CleanCompilationEvent pbce = new CleanCompilationEvent( javaBuilder.javaProject );
+
+ java.util.Iterator it = cps.iterator();
+ while ( it.hasNext() ) {
+ ICompilationParticipant p = ( ICompilationParticipant ) it.next();
+ p.notify( pbce );
+ }
+}
+
protected void cleanOutputFolders(boolean copyBack) throws CoreException {
boolean deleteAll = JavaCore.CLEAN.equals(
javaBuilder.javaProject.getOption(JavaCore.CORE_JAVA_BUILD_CLEAN_OUTPUT_FOLDER, true));
if (deleteAll) {
+
+ notifyCompilationParticipantsOfClean();
+
ArrayList visited = new ArrayList(sourceLocations.length);
for (int i = 0, l = sourceLocations.length; i < l; i++) {
- notifier.subTask(Messages.build_cleaningOutput);
+ notifier.subTask(Util.bind("build.cleaningOutput")); //$NON-NLS-1$
ClasspathMultiDirectory sourceLocation = sourceLocations[i];
if (sourceLocation.hasIndependentOutputFolder) {
IContainer outputFolder = sourceLocation.binaryFolder;
@@ -189,7 +210,7 @@
// When, if ever, does a builder need to copy resources files (not .java or .class) into the output folder?
// If we wipe the output folder at the beginning of the build then all 'extra' resources must be copied to the output folder.
- notifier.subTask(Messages.build_copyingResources);
+ notifier.subTask(Util.bind("build.copyingResources")); //$NON-NLS-1$
final int segmentCount = sourceLocation.sourceFolder.getFullPath().segmentCount();
final char[][] exclusionPatterns = sourceLocation.exclusionPatterns;
final char[][] inclusionPatterns = sourceLocation.inclusionPatterns;
@@ -219,7 +240,7 @@
createProblemFor(
resource,
null,
- Messages.bind(Messages.build_duplicateResource, (new String[] {id})),
+ Util.bind("build.duplicateResource", id), //$NON-NLS-1$
javaBuilder.javaProject.getOption(JavaCore.CORE_JAVA_BUILD_DUPLICATE_RESOURCE, true));
return false;
}
diff --git a/model/org/eclipse/jdt/internal/core/builder/IncrementalImageBuilder.java b/model/org/eclipse/jdt/internal/core/builder/IncrementalImageBuilder.java
index 653bb23..60e0538 100644
--- a/model/org/eclipse/jdt/internal/core/builder/IncrementalImageBuilder.java
+++ b/model/org/eclipse/jdt/internal/core/builder/IncrementalImageBuilder.java
@@ -20,7 +20,6 @@
import org.eclipse.jdt.internal.compiler.problem.*;
import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
-import org.eclipse.jdt.internal.core.util.Messages;
import org.eclipse.jdt.internal.core.util.Util;
import java.io.*;
@@ -71,7 +70,7 @@
try {
resetCollections();
- notifier.subTask(Messages.build_analyzingDeltas);
+ notifier.subTask(Util.bind("build.analyzingDeltas")); //$NON-NLS-1$
IResourceDelta sourceDelta = (IResourceDelta) deltas.get(javaBuilder.currentProject);
if (sourceDelta != null)
if (!findSourceFiles(sourceDelta)) return false;
@@ -90,7 +89,7 @@
}
notifier.updateProgressDelta(0.10f);
- notifier.subTask(Messages.build_analyzingSources);
+ notifier.subTask(Util.bind("build.analyzingSources")); //$NON-NLS-1$
addAffectedSourceFiles();
notifier.updateProgressDelta(0.05f);
@@ -242,6 +241,51 @@
return true;
}
+protected void handleFileDeletedByCompilationParticipant( IFile f )
+{
+ try
+ {
+ ClasspathMultiDirectory md = getSourceLocationForFile( f );
+ int segmentCount = md.sourceFolder.getFullPath().segmentCount();
+ IPath typePath = f.getFullPath().removeFirstSegments(segmentCount).removeFileExtension();
+ String typeLocator = f.getProjectRelativePath().toString();
+ char[][] definedTypeNames = newState.getDefinedTypeNamesFor(typeLocator);
+ if (definedTypeNames == null) { // defined a single type matching typePath
+ removeClassFile(typePath, md.binaryFolder);
+ /*
+ if ((sourceDelta.getFlags() & IResourceDelta.MOVED_TO) != 0) {
+ // remove problems and tasks for a compilation unit that is being moved (to another package or renamed)
+ // if the target file is a compilation unit, the new cu will be recompiled
+ // if the target file is a non-java resource, then markers are removed
+ // see bug 2857
+ IResource movedFile = javaBuilder.workspaceRoot.getFile(sourceDelta.getMovedToPath());
+ JavaBuilder.removeProblemsAndTasksFor(movedFile);
+ }
+ */
+ } else {
+ if (JavaBuilder.DEBUG)
+ System.out.println("Found removed source file " + typePath.toString()); //$NON-NLS-1$
+ addDependentsOf(typePath, true); // add dependents of the source file since it may be involved in a name collision
+ if (definedTypeNames.length > 0) { // skip it if it failed to successfully define a type
+ IPath packagePath = typePath.removeLastSegments(1);
+ for (int i = 0, l = definedTypeNames.length; i < l; i++)
+ removeClassFile(packagePath.append(new String(definedTypeNames[i])), md.binaryFolder);
+ }
+ }
+ newState.removeLocator(typeLocator);
+ }
+ catch ( CoreException ce )
+ {
+ // TODO: handle this exception
+ ce.printStackTrace();
+ }
+ catch( Exception e )
+ {
+ e.printStackTrace();
+ }
+}
+
+
protected void findAffectedSourceFiles(IResourceDelta binaryDelta, int segmentCount, StringSet structurallyChangedTypes) {
// When a package becomes a type or vice versa, expect 2 deltas,
// one on the folder & one on the class file
diff --git a/search/org/eclipse/jdt/core/search/SearchPattern.java b/search/org/eclipse/jdt/core/search/SearchPattern.java
index 84f57f6..cd5666e 100644
--- a/search/org/eclipse/jdt/core/search/SearchPattern.java
+++ b/search/org/eclipse/jdt/core/search/SearchPattern.java
@@ -802,7 +802,9 @@
* @return a search pattern on the given string pattern, or <code>null</code> if the string pattern is ill-formed
*/
public static SearchPattern createPattern(String stringPattern, int searchFor, int limitTo, int matchRule) {
- if (stringPattern == null || stringPattern.length() == 0) return null;
+ // Null string not allowed, empty string only allowed for Package seach (default package)
+ if (stringPattern == null || stringPattern.length() == 0 && searchFor != IJavaSearchConstants.PACKAGE)
+ return null;
// Ignore additional nature flags
limitTo &= ~(IJavaSearchConstants.IGNORE_DECLARING_TYPE+IJavaSearchConstants.IGNORE_RETURN_TYPE);
@@ -1087,10 +1089,8 @@
} catch (JavaModelException e) {
return null;
}
- IType declaringClass = method.getDeclaringType();
- if (ignoreDeclaringType) {
- if (isConstructor) declaringSimpleName = declaringClass.getElementName().toCharArray();
- } else {
+ if (!ignoreDeclaringType) {
+ IType declaringClass = method.getDeclaringType();
declaringSimpleName = declaringClass.getElementName().toCharArray();
declaringQualification = declaringClass.getPackageFragment().getElementName().toCharArray();
char[][] enclosingNames = enclosingTypeNames(declaringClass);