1 /*******************************************************************************
2 * Copyright (c) 2000, 2003 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package net.sourceforge.phpdt.internal.compiler.ast;
13 import net.sourceforge.phpdt.internal.compiler.ASTVisitor;
14 import net.sourceforge.phpdt.internal.compiler.flow.FlowContext;
15 import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
16 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
17 import net.sourceforge.phpdt.internal.compiler.lookup.InvocationSite;
18 import net.sourceforge.phpdt.internal.compiler.lookup.LocalTypeBinding;
19 import net.sourceforge.phpdt.internal.compiler.lookup.LocalVariableBinding;
20 import net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding;
21 import net.sourceforge.phpdt.internal.compiler.lookup.NestedTypeBinding;
22 import net.sourceforge.phpdt.internal.compiler.lookup.ReferenceBinding;
23 import net.sourceforge.phpdt.internal.compiler.lookup.SourceTypeBinding;
24 import net.sourceforge.phpdt.internal.compiler.lookup.SyntheticArgumentBinding;
25 import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
27 public class AllocationExpression extends Expression implements InvocationSite {
29 public TypeReference type;
31 public Expression[] arguments;
33 public MethodBinding binding;
35 MethodBinding syntheticAccessor;
37 public AllocationExpression() {
40 public FlowInfo analyseCode(BlockScope currentScope,
41 FlowContext flowContext, FlowInfo flowInfo) {
43 // check captured variables are initialized in current context (26134)
44 checkCapturedLocalInitializationIfNecessary(
45 this.binding.declaringClass, currentScope, flowInfo);
48 if (arguments != null) {
49 for (int i = 0, count = arguments.length; i < count; i++) {
50 flowInfo = arguments[i].analyseCode(currentScope, flowContext,
51 flowInfo).unconditionalInits();
54 // record some dependency information for exception types
55 ReferenceBinding[] thrownExceptions;
56 if (((thrownExceptions = this.binding.thrownExceptions).length) != 0) {
57 // check exception handling
58 flowContext.checkExceptionHandlers(thrownExceptions, this,
59 flowInfo, currentScope);
61 manageEnclosingInstanceAccessIfNecessary(currentScope);
62 manageSyntheticAccessIfNecessary(currentScope);
67 public void checkCapturedLocalInitializationIfNecessary(
68 ReferenceBinding checkedType, BlockScope currentScope,
71 if (checkedType.isLocalType() && !checkedType.isAnonymousType()
72 && !currentScope.isDefinedInType(checkedType)) { // only
76 NestedTypeBinding nestedType = (NestedTypeBinding) checkedType;
77 SyntheticArgumentBinding[] syntheticArguments = nestedType
78 .syntheticOuterLocalVariables();
79 if (syntheticArguments != null)
80 for (int i = 0, count = syntheticArguments.length; i < count; i++) {
81 SyntheticArgumentBinding syntheticArgument = syntheticArguments[i];
82 LocalVariableBinding targetLocal;
83 if ((targetLocal = syntheticArgument.actualOuterLocalVariable) == null)
85 // if (targetLocal.declaration != null &&
86 // !flowInfo.isDefinitelyAssigned(targetLocal)){
87 // currentScope.problemReporter().uninitializedLocalVariable(targetLocal,
95 public Expression enclosingInstance() {
99 // public void generateCode(
100 // BlockScope currentScope,
101 // CodeStream codeStream,
102 // boolean valueRequired) {
104 // int pc = codeStream.position;
105 // ReferenceBinding allocatedType = binding.declaringClass;
107 // codeStream.new_(allocatedType);
108 // if (valueRequired) {
111 // // better highlight for allocation: display the type individually
112 // codeStream.recordPositionsFrom(pc, type.sourceStart);
114 // // handling innerclass instance allocation - enclosing instance arguments
115 // if (allocatedType.isNestedType()) {
116 // codeStream.generateSyntheticEnclosingInstanceValues(
119 // enclosingInstance(),
122 // // generate the arguments for constructor
123 // if (arguments != null) {
124 // for (int i = 0, count = arguments.length; i < count; i++) {
125 // arguments[i].generateCode(currentScope, codeStream, true);
128 // // handling innerclass instance allocation - outer local arguments
129 // if (allocatedType.isNestedType()) {
130 // codeStream.generateSyntheticOuterArgumentValues(
135 // // invoke constructor
136 // if (syntheticAccessor == null) {
137 // codeStream.invokespecial(binding);
139 // // synthetic accessor got some extra arguments appended to its signature,
142 // max = syntheticAccessor.parameters.length - binding.parameters.length;
145 // codeStream.aconst_null();
147 // codeStream.invokespecial(syntheticAccessor);
149 // codeStream.recordPositionsFrom(pc, this.sourceStart);
152 public boolean isSuperAccess() {
157 public boolean isTypeAccess() {
163 * Inner emulation consists in either recording a dependency link only, or
164 * performing one level of propagation.
166 * Dependency mechanism is used whenever dealing with source target types,
167 * since by the time we reach them, we might not yet know their exact need.
169 public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope) {
171 ReferenceBinding allocatedType;
173 // perform some emulation work in case there is some and we are inside a
175 if ((allocatedType = binding.declaringClass).isNestedType()
176 && currentScope.enclosingSourceType().isLocalType()) {
178 if (allocatedType.isLocalType()) {
179 ((LocalTypeBinding) allocatedType).addInnerEmulationDependent(
180 currentScope, false);
181 // request cascade of accesses
183 // locally propagate, since we already now the desired shape for
185 currentScope.propagateInnerEmulation(allocatedType, false);
186 // request cascade of accesses
191 public void manageSyntheticAccessIfNecessary(BlockScope currentScope) {
193 if (binding.isPrivate()
194 && (currentScope.enclosingSourceType() != binding.declaringClass)) {
199 // .isPrivateConstructorAccessChangingVisibility) {
200 // binding.tagForClearingPrivateModifier();
201 // // constructor will not be dumped as private, no emulation
204 syntheticAccessor = ((SourceTypeBinding) binding.declaringClass)
205 .addSyntheticMethod(binding, isSuperAccess());
206 currentScope.problemReporter().needToEmulateMethodAccess(binding,
212 public StringBuffer printExpression(int indent, StringBuffer output) {
214 output.append("new "); //$NON-NLS-1$
215 type.printExpression(0, output);
217 if (arguments != null) {
218 for (int i = 0; i < arguments.length; i++) {
220 output.append(", "); //$NON-NLS-1$
221 arguments[i].printExpression(0, output);
224 return output.append(')');
227 public TypeBinding resolveType(BlockScope scope) {
229 // Propagate the type checking to the arguments, and check if the
230 // constructor is defined.
231 constant = NotAConstant;
232 this.resolvedType = type.resolveType(scope);
233 // will check for null after args are resolved
235 // buffering the arguments' types
236 TypeBinding[] argumentTypes = NoParameters;
237 if (arguments != null) {
238 boolean argHasError = false;
239 int length = arguments.length;
240 argumentTypes = new TypeBinding[length];
241 for (int i = 0; i < length; i++)
242 if ((argumentTypes[i] = arguments[i].resolveType(scope)) == null)
245 return this.resolvedType;
247 if (this.resolvedType == null)
250 if (!this.resolvedType.canBeInstantiated()) {
251 scope.problemReporter().cannotInstantiate(type, this.resolvedType);
252 return this.resolvedType;
254 ReferenceBinding allocatedType = (ReferenceBinding) this.resolvedType;
255 if (!(binding = scope
256 .getConstructor(allocatedType, argumentTypes, this))
258 if (binding.declaringClass == null)
259 binding.declaringClass = allocatedType;
260 scope.problemReporter().invalidConstructor(this, binding);
261 return this.resolvedType;
263 if (isMethodUseDeprecated(binding, scope))
264 scope.problemReporter().deprecatedMethod(binding, this);
266 if (arguments != null)
267 for (int i = 0; i < arguments.length; i++)
268 arguments[i].implicitWidening(binding.parameters[i],
270 return allocatedType;
273 public void setActualReceiverType(ReferenceBinding receiverType) {
277 public void setDepth(int i) {
281 public void setFieldIndex(int i) {
285 public String toStringExpression() {
287 String s = "new " + type.toString(0); //$NON-NLS-1$
288 if (arguments == null)
289 s = s + "()"; //$NON-NLS-1$
291 s = s + "("; //$NON-NLS-1$
292 for (int i = 0; i < arguments.length; i++) {
293 s = s + arguments[i].toStringExpression();
294 if (i == (arguments.length - 1))
295 s = s + ")"; //$NON-NLS-1$
297 s = s + ", "; //$NON-NLS-1$
303 public void traverse(ASTVisitor visitor, BlockScope scope) {
305 if (visitor.visit(this, scope)) {
307 type.traverse(visitor, scope);
308 if (arguments != null) {
309 argumentsLength = arguments.length;
310 for (int i = 0; i < argumentsLength; i++)
311 arguments[i].traverse(visitor, scope);
314 visitor.endVisit(this, scope);