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.CodeStream;
15 import net.sourceforge.phpdt.internal.compiler.flow.FlowContext;
16 import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
17 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
18 import net.sourceforge.phpdt.internal.compiler.lookup.InvocationSite;
19 import net.sourceforge.phpdt.internal.compiler.lookup.LocalTypeBinding;
20 import net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding;
21 import net.sourceforge.phpdt.internal.compiler.lookup.ReferenceBinding;
22 import net.sourceforge.phpdt.internal.compiler.lookup.SourceTypeBinding;
23 import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
25 public class AllocationExpression
27 implements InvocationSite {
29 public TypeReference type;
30 public Expression[] arguments;
31 public MethodBinding binding;
33 MethodBinding syntheticAccessor;
35 public AllocationExpression() {
39 public FlowInfo analyseCode(
40 BlockScope currentScope,
41 FlowContext flowContext,
44 // must verify that exceptions potentially thrown by this expression are caught in the method
47 if (arguments != null) {
48 for (int i = 0, count = arguments.length; i < count; i++) {
51 .analyseCode(currentScope, flowContext, flowInfo)
52 .unconditionalInits();
55 // record some dependency information for exception types
56 ReferenceBinding[] thrownExceptions;
57 if (((thrownExceptions = binding.thrownExceptions).length) != 0) {
58 // check exception handling
59 flowContext.checkExceptionHandlers(
65 manageEnclosingInstanceAccessIfNecessary(currentScope);
66 manageSyntheticAccessIfNecessary(currentScope);
70 public Expression enclosingInstance() {
74 public void generateCode(
75 BlockScope currentScope,
76 CodeStream codeStream,
77 boolean valueRequired) {
79 int pc = codeStream.position;
80 ReferenceBinding allocatedType = binding.declaringClass;
82 codeStream.new_(allocatedType);
86 // better highlight for allocation: display the type individually
87 codeStream.recordPositionsFrom(pc, type.sourceStart);
89 // handling innerclass instance allocation
90 if (allocatedType.isNestedType()) {
91 codeStream.generateSyntheticArgumentValues(
97 // generate the arguments for constructor
98 if (arguments != null) {
99 for (int i = 0, count = arguments.length; i < count; i++) {
100 arguments[i].generateCode(currentScope, codeStream, true);
103 // invoke constructor
104 if (syntheticAccessor == null) {
105 codeStream.invokespecial(binding);
107 // synthetic accessor got some extra arguments appended to its signature, which need values
109 max = syntheticAccessor.parameters.length - binding.parameters.length;
112 codeStream.aconst_null();
114 codeStream.invokespecial(syntheticAccessor);
116 codeStream.recordPositionsFrom(pc, this.sourceStart);
119 public boolean isSuperAccess() {
124 public boolean isTypeAccess() {
129 /* Inner emulation consists in either recording a dependency
130 * link only, or performing one level of propagation.
132 * Dependency mechanism is used whenever dealing with source target
133 * types, since by the time we reach them, we might not yet know their
136 public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope) {
138 ReferenceBinding allocatedType;
140 // perform some emulation work in case there is some and we are inside a local type only
141 if ((allocatedType = binding.declaringClass).isNestedType()
142 && currentScope.enclosingSourceType().isLocalType()) {
144 if (allocatedType.isLocalType()) {
145 ((LocalTypeBinding) allocatedType).addInnerEmulationDependent(
149 // request cascade of accesses
151 // locally propagate, since we already now the desired shape for sure
152 currentScope.propagateInnerEmulation(allocatedType, false, false);
153 // request cascade of accesses
158 public void manageSyntheticAccessIfNecessary(BlockScope currentScope) {
160 if (binding.isPrivate()
161 && (currentScope.enclosingSourceType() != binding.declaringClass)) {
166 .isPrivateConstructorAccessChangingVisibility) {
167 binding.tagForClearingPrivateModifier();
168 // constructor will not be dumped as private, no emulation required thus
171 ((SourceTypeBinding) binding.declaringClass).addSyntheticMethod(binding);
172 currentScope.problemReporter().needToEmulateMethodAccess(binding, this);
177 public TypeBinding resolveType(BlockScope scope) {
179 // Propagate the type checking to the arguments, and check if the constructor is defined.
180 constant = NotAConstant;
181 TypeBinding typeBinding = type.resolveType(scope);
182 // will check for null after args are resolved
184 // buffering the arguments' types
185 TypeBinding[] argumentTypes = NoParameters;
186 if (arguments != null) {
187 boolean argHasError = false;
188 int length = arguments.length;
189 argumentTypes = new TypeBinding[length];
190 for (int i = 0; i < length; i++)
191 if ((argumentTypes[i] = arguments[i].resolveType(scope)) == null)
196 if (typeBinding == null)
199 if (!typeBinding.canBeInstantiated()) {
200 scope.problemReporter().cannotInstantiate(type, typeBinding);
203 ReferenceBinding allocatedType = (ReferenceBinding) typeBinding;
204 if (!(binding = scope.getConstructor(allocatedType, argumentTypes, this))
206 if (binding.declaringClass == null)
207 binding.declaringClass = allocatedType;
208 scope.problemReporter().invalidConstructor(this, binding);
211 if (isMethodUseDeprecated(binding, scope))
212 scope.problemReporter().deprecatedMethod(binding, this);
214 if (arguments != null)
215 for (int i = 0; i < arguments.length; i++)
216 arguments[i].implicitWidening(binding.parameters[i], argumentTypes[i]);
217 return allocatedType;
220 public void setActualReceiverType(ReferenceBinding receiverType) {
224 public void setDepth(int i) {
228 public void setFieldIndex(int i) {
232 public String toStringExpression() {
234 String s = "new " + type.toString(0); //$NON-NLS-1$
235 if (arguments == null)
236 s = s + "()"; //$NON-NLS-1$
238 s = s + "("; //$NON-NLS-1$
239 for (int i = 0; i < arguments.length; i++) {
240 s = s + arguments[i].toStringExpression();
241 if (i == (arguments.length - 1))
242 s = s + ")"; //$NON-NLS-1$
244 s = s + ", "; //$NON-NLS-1$
250 public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
252 if (visitor.visit(this, scope)) {
254 type.traverse(visitor, scope);
255 if (arguments != null) {
256 argumentsLength = arguments.length;
257 for (int i = 0; i < argumentsLength; i++)
258 arguments[i].traverse(visitor, scope);
261 visitor.endVisit(this, scope);