1 /*******************************************************************************
2 * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v0.5
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v05.html
9 * IBM Corporation - initial API and implementation
10 ******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.ast;
13 import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
14 import net.sourceforge.phpdt.internal.compiler.codegen.*;
15 import net.sourceforge.phpdt.internal.compiler.flow.*;
16 import net.sourceforge.phpdt.internal.compiler.lookup.*;
18 public class AllocationExpression
20 implements InvocationSite {
22 public TypeReference type;
23 public Expression[] arguments;
24 public MethodBinding binding;
26 MethodBinding syntheticAccessor;
28 public AllocationExpression() {
32 public FlowInfo analyseCode(
33 BlockScope currentScope,
34 FlowContext flowContext,
37 // must verify that exceptions potentially thrown by this expression are caught in the method
40 if (arguments != null) {
41 for (int i = 0, count = arguments.length; i < count; i++) {
44 .analyseCode(currentScope, flowContext, flowInfo)
45 .unconditionalInits();
48 // record some dependency information for exception types
49 ReferenceBinding[] thrownExceptions;
50 if (((thrownExceptions = binding.thrownExceptions).length) != 0) {
51 // check exception handling
52 flowContext.checkExceptionHandlers(
58 manageEnclosingInstanceAccessIfNecessary(currentScope);
59 manageSyntheticAccessIfNecessary(currentScope);
63 public Expression enclosingInstance() {
67 public void generateCode(
68 BlockScope currentScope,
69 CodeStream codeStream,
70 boolean valueRequired) {
72 int pc = codeStream.position;
73 ReferenceBinding allocatedType = binding.declaringClass;
75 codeStream.new_(allocatedType);
79 // better highlight for allocation: display the type individually
80 codeStream.recordPositionsFrom(pc, type.sourceStart);
82 // handling innerclass instance allocation
83 if (allocatedType.isNestedType()) {
84 codeStream.generateSyntheticArgumentValues(
90 // generate the arguments for constructor
91 if (arguments != null) {
92 for (int i = 0, count = arguments.length; i < count; i++) {
93 arguments[i].generateCode(currentScope, codeStream, true);
97 if (syntheticAccessor == null) {
98 codeStream.invokespecial(binding);
100 // synthetic accessor got some extra arguments appended to its signature, which need values
102 max = syntheticAccessor.parameters.length - binding.parameters.length;
105 codeStream.aconst_null();
107 codeStream.invokespecial(syntheticAccessor);
109 codeStream.recordPositionsFrom(pc, this.sourceStart);
112 public boolean isSuperAccess() {
117 public boolean isTypeAccess() {
122 /* Inner emulation consists in either recording a dependency
123 * link only, or performing one level of propagation.
125 * Dependency mechanism is used whenever dealing with source target
126 * types, since by the time we reach them, we might not yet know their
129 public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope) {
131 ReferenceBinding allocatedType;
133 // perform some emulation work in case there is some and we are inside a local type only
134 if ((allocatedType = binding.declaringClass).isNestedType()
135 && currentScope.enclosingSourceType().isLocalType()) {
137 if (allocatedType.isLocalType()) {
138 ((LocalTypeBinding) allocatedType).addInnerEmulationDependent(
142 // request cascade of accesses
144 // locally propagate, since we already now the desired shape for sure
145 currentScope.propagateInnerEmulation(allocatedType, false, false);
146 // request cascade of accesses
151 public void manageSyntheticAccessIfNecessary(BlockScope currentScope) {
153 if (binding.isPrivate()
154 && (currentScope.enclosingSourceType() != binding.declaringClass)) {
159 .isPrivateConstructorAccessChangingVisibility) {
160 binding.tagForClearingPrivateModifier();
161 // constructor will not be dumped as private, no emulation required thus
164 ((SourceTypeBinding) binding.declaringClass).addSyntheticMethod(binding);
165 currentScope.problemReporter().needToEmulateMethodAccess(binding, this);
170 public TypeBinding resolveType(BlockScope scope) {
172 // Propagate the type checking to the arguments, and check if the constructor is defined.
173 constant = NotAConstant;
174 TypeBinding typeBinding = type.resolveType(scope);
175 // will check for null after args are resolved
177 // buffering the arguments' types
178 TypeBinding[] argumentTypes = NoParameters;
179 if (arguments != null) {
180 boolean argHasError = false;
181 int length = arguments.length;
182 argumentTypes = new TypeBinding[length];
183 for (int i = 0; i < length; i++)
184 if ((argumentTypes[i] = arguments[i].resolveType(scope)) == null)
189 if (typeBinding == null)
192 if (!typeBinding.canBeInstantiated()) {
193 scope.problemReporter().cannotInstantiate(type, typeBinding);
196 ReferenceBinding allocatedType = (ReferenceBinding) typeBinding;
197 if (!(binding = scope.getConstructor(allocatedType, argumentTypes, this))
199 if (binding.declaringClass == null)
200 binding.declaringClass = allocatedType;
201 scope.problemReporter().invalidConstructor(this, binding);
204 if (isMethodUseDeprecated(binding, scope))
205 scope.problemReporter().deprecatedMethod(binding, this);
207 if (arguments != null)
208 for (int i = 0; i < arguments.length; i++)
209 arguments[i].implicitWidening(binding.parameters[i], argumentTypes[i]);
210 return allocatedType;
213 public void setActualReceiverType(ReferenceBinding receiverType) {
217 public void setDepth(int i) {
221 public void setFieldIndex(int i) {
225 public String toStringExpression() {
227 String s = "new " + type.toString(0); //$NON-NLS-1$
228 if (arguments == null)
229 s = s + "()"; //$NON-NLS-1$
231 s = s + "("; //$NON-NLS-1$
232 for (int i = 0; i < arguments.length; i++) {
233 s = s + arguments[i].toStringExpression();
234 if (i == (arguments.length - 1))
235 s = s + ")"; //$NON-NLS-1$
237 s = s + ", "; //$NON-NLS-1$
243 public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
245 if (visitor.visit(this, scope)) {
247 type.traverse(visitor, scope);
248 if (arguments != null) {
249 argumentsLength = arguments.length;
250 for (int i = 0; i < argumentsLength; i++)
251 arguments[i].traverse(visitor, scope);
254 visitor.endVisit(this, scope);