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.phpeclipse.internal.compiler.ast;
13 import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
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
29 implements InvocationSite {
31 public TypeReference type;
32 public Expression[] arguments;
33 public MethodBinding binding;
35 MethodBinding syntheticAccessor;
37 public AllocationExpression() {
40 public FlowInfo analyseCode(
41 BlockScope currentScope,
42 FlowContext flowContext,
45 // check captured variables are initialized in current context (26134)
46 checkCapturedLocalInitializationIfNecessary(this.binding.declaringClass, currentScope, flowInfo);
49 if (arguments != null) {
50 for (int i = 0, count = arguments.length; i < count; i++) {
53 .analyseCode(currentScope, flowContext, flowInfo)
54 .unconditionalInits();
57 // record some dependency information for exception types
58 ReferenceBinding[] thrownExceptions;
59 if (((thrownExceptions = this.binding.thrownExceptions).length) != 0) {
60 // check exception handling
61 flowContext.checkExceptionHandlers(
67 manageEnclosingInstanceAccessIfNecessary(currentScope);
68 manageSyntheticAccessIfNecessary(currentScope);
73 public void checkCapturedLocalInitializationIfNecessary(ReferenceBinding checkedType, BlockScope currentScope, FlowInfo flowInfo) {
75 if (checkedType.isLocalType()
76 && !checkedType.isAnonymousType()
77 && !currentScope.isDefinedInType(checkedType)) { // only check external allocations
78 NestedTypeBinding nestedType = (NestedTypeBinding) checkedType;
79 SyntheticArgumentBinding[] syntheticArguments = nestedType.syntheticOuterLocalVariables();
80 if (syntheticArguments != null)
81 for (int i = 0, count = syntheticArguments.length; i < count; i++){
82 SyntheticArgumentBinding syntheticArgument = syntheticArguments[i];
83 LocalVariableBinding targetLocal;
84 if ((targetLocal = syntheticArgument.actualOuterLocalVariable) == null) continue;
85 if (targetLocal.declaration != null && !flowInfo.isDefinitelyAssigned(targetLocal)){
86 currentScope.problemReporter().uninitializedLocalVariable(targetLocal, this);
93 public Expression enclosingInstance() {
97 // public void generateCode(
98 // BlockScope currentScope,
99 // CodeStream codeStream,
100 // boolean valueRequired) {
102 // int pc = codeStream.position;
103 // ReferenceBinding allocatedType = binding.declaringClass;
105 // codeStream.new_(allocatedType);
106 // if (valueRequired) {
109 // // better highlight for allocation: display the type individually
110 // codeStream.recordPositionsFrom(pc, type.sourceStart);
112 // // handling innerclass instance allocation - enclosing instance arguments
113 // if (allocatedType.isNestedType()) {
114 // codeStream.generateSyntheticEnclosingInstanceValues(
117 // enclosingInstance(),
120 // // generate the arguments for constructor
121 // if (arguments != null) {
122 // for (int i = 0, count = arguments.length; i < count; i++) {
123 // arguments[i].generateCode(currentScope, codeStream, true);
126 // // handling innerclass instance allocation - outer local arguments
127 // if (allocatedType.isNestedType()) {
128 // codeStream.generateSyntheticOuterArgumentValues(
133 // // invoke constructor
134 // if (syntheticAccessor == null) {
135 // codeStream.invokespecial(binding);
137 // // synthetic accessor got some extra arguments appended to its signature, which need values
139 // max = syntheticAccessor.parameters.length - binding.parameters.length;
142 // codeStream.aconst_null();
144 // codeStream.invokespecial(syntheticAccessor);
146 // codeStream.recordPositionsFrom(pc, this.sourceStart);
149 public boolean isSuperAccess() {
154 public boolean isTypeAccess() {
159 /* Inner emulation consists in either recording a dependency
160 * link only, or performing one level of propagation.
162 * Dependency mechanism is used whenever dealing with source target
163 * types, since by the time we reach them, we might not yet know their
166 public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope) {
168 ReferenceBinding allocatedType;
170 // perform some emulation work in case there is some and we are inside a local type only
171 if ((allocatedType = binding.declaringClass).isNestedType()
172 && currentScope.enclosingSourceType().isLocalType()) {
174 if (allocatedType.isLocalType()) {
175 ((LocalTypeBinding) allocatedType).addInnerEmulationDependent(currentScope, false);
176 // request cascade of accesses
178 // locally propagate, since we already now the desired shape for sure
179 currentScope.propagateInnerEmulation(allocatedType, false);
180 // request cascade of accesses
185 public void manageSyntheticAccessIfNecessary(BlockScope currentScope) {
187 if (binding.isPrivate()
188 && (currentScope.enclosingSourceType() != binding.declaringClass)) {
193 // .isPrivateConstructorAccessChangingVisibility) {
194 // binding.tagForClearingPrivateModifier();
195 // // constructor will not be dumped as private, no emulation required thus
198 ((SourceTypeBinding) binding.declaringClass).addSyntheticMethod(binding, isSuperAccess());
199 currentScope.problemReporter().needToEmulateMethodAccess(binding, this);
204 public TypeBinding resolveType(BlockScope scope) {
206 // Propagate the type checking to the arguments, and check if the constructor is defined.
207 constant = NotAConstant;
208 this.resolvedType = type.resolveType(scope);
209 // will check for null after args are resolved
211 // buffering the arguments' types
212 TypeBinding[] argumentTypes = NoParameters;
213 if (arguments != null) {
214 boolean argHasError = false;
215 int length = arguments.length;
216 argumentTypes = new TypeBinding[length];
217 for (int i = 0; i < length; i++)
218 if ((argumentTypes[i] = arguments[i].resolveType(scope)) == null)
221 return this.resolvedType;
223 if (this.resolvedType == null)
226 if (!this.resolvedType.canBeInstantiated()) {
227 scope.problemReporter().cannotInstantiate(type, this.resolvedType);
228 return this.resolvedType;
230 ReferenceBinding allocatedType = (ReferenceBinding) this.resolvedType;
231 if (!(binding = scope.getConstructor(allocatedType, argumentTypes, this))
233 if (binding.declaringClass == null)
234 binding.declaringClass = allocatedType;
235 scope.problemReporter().invalidConstructor(this, binding);
236 return this.resolvedType;
238 if (isMethodUseDeprecated(binding, scope))
239 scope.problemReporter().deprecatedMethod(binding, this);
241 if (arguments != null)
242 for (int i = 0; i < arguments.length; i++)
243 arguments[i].implicitWidening(binding.parameters[i], argumentTypes[i]);
244 return allocatedType;
247 public void setActualReceiverType(ReferenceBinding receiverType) {
251 public void setDepth(int i) {
255 public void setFieldIndex(int i) {
259 public String toStringExpression() {
261 String s = "new " + type.toString(0); //$NON-NLS-1$
262 if (arguments == null)
263 s = s + "()"; //$NON-NLS-1$
265 s = s + "("; //$NON-NLS-1$
266 for (int i = 0; i < arguments.length; i++) {
267 s = s + arguments[i].toStringExpression();
268 if (i == (arguments.length - 1))
269 s = s + ")"; //$NON-NLS-1$
271 s = s + ", "; //$NON-NLS-1$
277 public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
279 if (visitor.visit(this, scope)) {
281 type.traverse(visitor, scope);
282 if (arguments != null) {
283 argumentsLength = arguments.length;
284 for (int i = 0; i < argumentsLength; i++)
285 arguments[i].traverse(visitor, scope);
288 visitor.endVisit(this, scope);