/** Adapted from {@link TypeDeclaration#traverse}. */ private void traverse(TypeDeclaration type) { // Don't visit javadoc. // Don't visit annotations. if (type.superclass != null) { type.superclass.traverse(this, type.scope); } if (type.superInterfaces != null) { int length = type.superInterfaces.length; for (int i = 0; i < length; i++) { type.superInterfaces[i].traverse(this, type.scope); } } if (type.typeParameters != null) { int length = type.typeParameters.length; for (int i = 0; i < length; i++) { type.typeParameters[i].traverse(this, type.scope); } } if (type.memberTypes != null) { int length = type.memberTypes.length; for (int i = 0; i < length; i++) { type.memberTypes[i].traverse(this, type.scope); } } if (type.fields != null) { int length = type.fields.length; for (int i = 0; i < length; i++) { FieldDeclaration field; if ((field = type.fields[i]).isStatic()) { field.traverse(this, type.staticInitializerScope); } else { field.traverse(this, type.initializerScope); } } } if (type.methods != null) { int length = type.methods.length; for (int i = 0; i < length; i++) { type.methods[i].traverse(this, type.scope); } } }
public Constant constant() { Constant fieldConstant = this.constant; if (fieldConstant == null) { if (isFinal()) { // The field has not been yet type checked. // It also means that the field is not coming from a class that // has already been compiled. It can only be from a class within // compilation units to process. Thus the field is NOT from a BinaryTypeBinbing FieldBinding originalField = original(); if (originalField.declaringClass instanceof SourceTypeBinding) { SourceTypeBinding sourceType = (SourceTypeBinding) originalField.declaringClass; if (sourceType.scope != null) { TypeDeclaration typeDecl = sourceType.scope.referenceContext; FieldDeclaration fieldDecl = typeDecl.declarationOf(originalField); MethodScope initScope = originalField.isStatic() ? typeDecl.staticInitializerScope : typeDecl.initializerScope; boolean old = initScope.insideTypeAnnotation; try { initScope.insideTypeAnnotation = false; fieldDecl.resolve(initScope); // side effect on binding } finally { initScope.insideTypeAnnotation = old; } fieldConstant = originalField.constant == null ? Constant.NotAConstant : originalField.constant; } else { fieldConstant = Constant.NotAConstant; // shouldn't occur per construction (paranoid null check) } } else { fieldConstant = Constant.NotAConstant; // shouldn't occur per construction (paranoid null check) } } else { fieldConstant = Constant.NotAConstant; } this.constant = fieldConstant; } return fieldConstant; }
/* API * Answer the receiver's binding type from Binding.BindingID. */ public FieldBinding( FieldDeclaration field, TypeBinding type, int modifiers, ReferenceBinding declaringClass) { this(field.name, type, modifiers, declaringClass, null); field.binding = this; // record binding in declaration }
@Override public boolean handle( AnnotationValues<Synchronized> annotation, Annotation source, EclipseNode annotationNode) { int p1 = source.sourceStart - 1; int p2 = source.sourceStart - 2; long pos = (((long) p1) << 32) | p2; EclipseNode methodNode = annotationNode.up(); if (methodNode == null || methodNode.getKind() != Kind.METHOD || !(methodNode.get() instanceof MethodDeclaration)) { annotationNode.addError("@Synchronized is legal only on methods."); return true; } MethodDeclaration method = (MethodDeclaration) methodNode.get(); if (method.isAbstract()) { annotationNode.addError("@Synchronized is legal only on concrete methods."); return true; } char[] lockName = annotation.getInstance().value().toCharArray(); boolean autoMake = false; if (lockName.length == 0) { autoMake = true; lockName = method.isStatic() ? STATIC_LOCK_NAME : INSTANCE_LOCK_NAME; } if (fieldExists(new String(lockName), methodNode) == MemberExistsResult.NOT_EXISTS) { if (!autoMake) { annotationNode.addError("The field " + new String(lockName) + " does not exist."); return true; } FieldDeclaration fieldDecl = new FieldDeclaration(lockName, 0, -1); Eclipse.setGeneratedBy(fieldDecl, source); fieldDecl.declarationSourceEnd = -1; fieldDecl.modifiers = (method.isStatic() ? Modifier.STATIC : 0) | Modifier.FINAL | Modifier.PRIVATE; // We use 'new Object[0];' because quite unlike 'new Object();', empty arrays *ARE* // serializable! ArrayAllocationExpression arrayAlloc = new ArrayAllocationExpression(); Eclipse.setGeneratedBy(arrayAlloc, source); arrayAlloc.dimensions = new Expression[] {new IntLiteral(new char[] {'0'}, 0, 0)}; Eclipse.setGeneratedBy(arrayAlloc.dimensions[0], source); arrayAlloc.type = new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, new long[] {0, 0, 0}); Eclipse.setGeneratedBy(arrayAlloc.type, source); fieldDecl.type = new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, new long[] {0, 0, 0}); Eclipse.setGeneratedBy(fieldDecl.type, source); fieldDecl.initialization = arrayAlloc; injectFieldSuppressWarnings(annotationNode.up().up(), fieldDecl); } if (method.statements == null) return false; Block block = new Block(0); Eclipse.setGeneratedBy(block, source); block.statements = method.statements; Expression lockVariable; if (method.isStatic()) lockVariable = new QualifiedNameReference( new char[][] {methodNode.up().getName().toCharArray(), lockName}, new long[] {pos, pos}, p1, p2); else { lockVariable = new FieldReference(lockName, pos); ThisReference thisReference = new ThisReference(p1, p2); Eclipse.setGeneratedBy(thisReference, source); ((FieldReference) lockVariable).receiver = thisReference; } Eclipse.setGeneratedBy(lockVariable, source); method.statements = new Statement[] {new SynchronizedStatement(lockVariable, block, 0, 0)}; Eclipse.setGeneratedBy(method.statements[0], source); methodNode.rebuild(); return true; }