/******************************************************************************* * Copyright (c) 2000, 2003 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/cpl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package net.sourceforge.phpdt.internal.compiler.ast; import net.sourceforge.phpdt.internal.compiler.ASTVisitor; import net.sourceforge.phpdt.internal.compiler.CompilationResult; import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope; import net.sourceforge.phpdt.internal.compiler.lookup.LocalTypeBinding; import net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding; import net.sourceforge.phpdt.internal.compiler.lookup.MethodScope; import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding; import net.sourceforge.phpdt.internal.compiler.problem.AbortType; public class AnonymousLocalTypeDeclaration extends LocalTypeDeclaration { public static final char[] ANONYMOUS_EMPTY_NAME = new char[] {}; public QualifiedAllocationExpression allocation; public AnonymousLocalTypeDeclaration(CompilationResult compilationResult) { super(compilationResult); modifiers = AccDefault; name = ANONYMOUS_EMPTY_NAME; } // use a default name in order to th name lookup // to operate just like a regular type (which has a name) // without checking systematically if the naem is null .... public MethodBinding createsInternalConstructorWithBinding( MethodBinding inheritedConstructorBinding) { // Add to method'set, the default constuctor that just recall the // super constructor with the same arguments String baseName = "$anonymous"; //$NON-NLS-1$ TypeBinding[] argumentTypes = inheritedConstructorBinding.parameters; int argumentsLength = argumentTypes.length; // the constructor ConstructorDeclaration cd = new ConstructorDeclaration( this.compilationResult); cd.selector = new char[] { 'x' }; // no maining cd.sourceStart = sourceStart; cd.sourceEnd = sourceEnd; cd.modifiers = modifiers & AccVisibilityMASK; cd.isDefaultConstructor = true; if (argumentsLength > 0) { Argument[] arguments = (cd.arguments = new Argument[argumentsLength]); for (int i = argumentsLength; --i >= 0;) { arguments[i] = new Argument((baseName + i).toCharArray(), 0L, null /* type ref */, AccDefault); } } // the super call inside the constructor cd.constructorCall = SuperReference.implicitSuperConstructorCall(); cd.constructorCall.sourceStart = sourceStart; cd.constructorCall.sourceEnd = sourceEnd; if (argumentsLength > 0) { Expression[] args; args = cd.constructorCall.arguments = new Expression[argumentsLength]; for (int i = argumentsLength; --i >= 0;) { args[i] = new SingleNameReference((baseName + i).toCharArray(), 0L); } } // adding the constructor in the methods list if (methods == null) { methods = new AbstractMethodDeclaration[] { cd }; } else { AbstractMethodDeclaration[] newMethods; System .arraycopy( methods, 0, newMethods = new AbstractMethodDeclaration[methods.length + 1], 1, methods.length); newMethods[0] = cd; methods = newMethods; } // ============BINDING UPDATE========================== cd.binding = new MethodBinding(cd.modifiers, // methodDeclaration argumentsLength == 0 ? NoParameters : argumentTypes, // arguments // bindings inheritedConstructorBinding.thrownExceptions, // exceptions binding); // declaringClass cd.scope = new MethodScope(scope, cd, true); cd.bindArguments(); cd.constructorCall.resolve(cd.scope); if (binding.methods == null) { binding.methods = new MethodBinding[] { cd.binding }; } else { MethodBinding[] newMethods; System.arraycopy(binding.methods, 0, newMethods = new MethodBinding[binding.methods.length + 1], 1, binding.methods.length); newMethods[0] = cd.binding; binding.methods = newMethods; } // =================================================== return cd.binding; } public void resolve(BlockScope scope) { if (binding != null) { // remember local types binding for innerclass emulation propagation scope.referenceCompilationUnit().record((LocalTypeBinding) binding); } // scope and binding are provided in updateBindingSuperclass resolve(); updateMaxFieldCount(); } public String toString(int tab) { return toStringBody(tab); } /** * Iteration for a local anonymous innertype * */ public void traverse(ASTVisitor visitor, BlockScope blockScope) { if (ignoreFurtherInvestigation) return; try { if (visitor.visit(this, blockScope)) { int fieldsLength; int methodsLength; int memberTypesLength; // is bound to the actual type from the allocation // expression // therefore it has already been iterated at this point. if (memberTypes != null) { memberTypesLength = memberTypes.length; for (int i = 0; i < memberTypesLength; i++) memberTypes[i].traverse(visitor, scope); } if (fields != null) { fieldsLength = fields.length; for (int i = 0; i < fieldsLength; i++) { FieldDeclaration field; if ((field = fields[i]).isStatic()) { // local type cannot have static fields } else { field.traverse(visitor, initializerScope); } } } if (methods != null) { methodsLength = methods.length; for (int i = 0; i < methodsLength; i++) methods[i].traverse(visitor, scope); } } visitor.endVisit(this, blockScope); } catch (AbortType e) { } } }