KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > eval > CodeSnippetAllocationExpression


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.eval;
12
13 import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
14 import org.eclipse.jdt.internal.compiler.ast.CastExpression;
15 import org.eclipse.jdt.internal.compiler.ast.Expression;
16 import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
17 import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
18 import org.eclipse.jdt.internal.compiler.impl.Constant;
19 import org.eclipse.jdt.internal.compiler.lookup.Binding;
20 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
21 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
22 import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
23 import org.eclipse.jdt.internal.compiler.lookup.ProblemMethodBinding;
24 import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
25 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
26 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
27 import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
28
29 public class CodeSnippetAllocationExpression extends AllocationExpression implements ProblemReasons, EvaluationConstants {
30     EvaluationContext evaluationContext;
31     FieldBinding delegateThis;
32 /**
33  * CodeSnippetAllocationExpression constructor comment.
34  */

35 public CodeSnippetAllocationExpression(EvaluationContext evaluationContext) {
36     this.evaluationContext = evaluationContext;
37 }
38 public void generateCode(
39     BlockScope currentScope,
40     CodeStream codeStream,
41     boolean valueRequired) {
42
43     int pc = codeStream.position;
44     ReferenceBinding allocatedType = this.codegenBinding.declaringClass;
45
46     if (this.codegenBinding.canBeSeenBy(allocatedType, this, currentScope)) {
47         codeStream.new_(allocatedType);
48         if (valueRequired) {
49             codeStream.dup();
50         }
51         // better highlight for allocation: display the type individually
52
codeStream.recordPositionsFrom(pc, this.type.sourceStart);
53
54         // handling innerclass instance allocation - enclosing instance arguments
55
if (allocatedType.isNestedType()) {
56             codeStream.generateSyntheticEnclosingInstanceValues(
57                 currentScope,
58                 allocatedType,
59                 enclosingInstance(),
60                 this);
61         }
62         // generate the arguments for constructor
63
if (this.arguments != null) {
64             for (int i = 0, count = this.arguments.length; i < count; i++) {
65                 this.arguments[i].generateCode(currentScope, codeStream, true);
66             }
67         }
68         // handling innerclass instance allocation - outer local arguments
69
if (allocatedType.isNestedType()) {
70             codeStream.generateSyntheticOuterArgumentValues(
71                 currentScope,
72                 allocatedType,
73                 this);
74         }
75         // invoke constructor
76
codeStream.invokespecial(this.codegenBinding);
77     } else {
78         // private emulation using reflect
79
codeStream.generateEmulationForConstructor(currentScope, this.codegenBinding);
80         // generate arguments
81
if (this.arguments != null) {
82             int argsLength = this.arguments.length;
83             codeStream.generateInlinedValue(argsLength);
84             codeStream.newArray(currentScope.createArrayType(currentScope.getType(TypeConstants.JAVA_LANG_OBJECT, 3), 1));
85             codeStream.dup();
86             for (int i = 0; i < argsLength; i++) {
87                 codeStream.generateInlinedValue(i);
88                 this.arguments[i].generateCode(currentScope, codeStream, true);
89                 TypeBinding parameterBinding = this.codegenBinding.parameters[i];
90                 if (parameterBinding.isBaseType() && parameterBinding != TypeBinding.NULL) {
91                     codeStream.generateBoxingConversion(this.codegenBinding.parameters[i].id);
92                 }
93                 codeStream.aastore();
94                 if (i < argsLength - 1) {
95                     codeStream.dup();
96                 }
97             }
98         } else {
99             codeStream.generateInlinedValue(0);
100             codeStream.newArray(currentScope.createArrayType(currentScope.getType(TypeConstants.JAVA_LANG_OBJECT, 3), 1));
101         }
102         codeStream.invokeJavaLangReflectConstructorNewInstance();
103         codeStream.checkcast(allocatedType);
104     }
105     codeStream.recordPositionsFrom(pc, this.sourceStart);
106 }
107 /* Inner emulation consists in either recording a dependency
108  * link only, or performing one level of propagation.
109  *
110  * Dependency mechanism is used whenever dealing with source target
111  * types, since by the time we reach them, we might not yet know their
112  * exact need.
113  */

114 public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
115     // not supported yet
116
}
117 public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
118         if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) {
119
120         // if constructor from parameterized type got found, use the original constructor at codegen time
121
this.codegenBinding = this.binding.original();
122         }
123 }
124 public TypeBinding resolveType(BlockScope scope) {
125     // Propagate the type checking to the arguments, and check if the constructor is defined.
126
this.constant = Constant.NotAConstant;
127     this.resolvedType = this.type.resolveType(scope, true /* check bounds*/); // will check for null after args are resolved
128

129     // buffering the arguments' types
130
boolean argsContainCast = false;
131     TypeBinding[] argumentTypes = Binding.NO_PARAMETERS;
132     if (this.arguments != null) {
133         boolean argHasError = false;
134         int length = this.arguments.length;
135         argumentTypes = new TypeBinding[length];
136         for (int i = 0; i < length; i++) {
137             Expression argument = this.arguments[i];
138             if (argument instanceof CastExpression) {
139                 argument.bits |= DisableUnnecessaryCastCheck; // will check later on
140
argsContainCast = true;
141             }
142             if ((argumentTypes[i] = argument.resolveType(scope)) == null) {
143                 argHasError = true;
144             }
145         }
146         if (argHasError) {
147             return this.resolvedType;
148         }
149     }
150     if (this.resolvedType == null) {
151         return null;
152     }
153     if (!this.resolvedType.canBeInstantiated()) {
154         scope.problemReporter().cannotInstantiate(this.type, this.resolvedType);
155         return this.resolvedType;
156     }
157     ReferenceBinding allocatedType = (ReferenceBinding) this.resolvedType;
158     if (!(this.binding = scope.getConstructor(allocatedType, argumentTypes, this)).isValidBinding()) {
159         if (this.binding instanceof ProblemMethodBinding
160             && ((ProblemMethodBinding) this.binding).problemId() == NotVisible) {
161             if (this.evaluationContext.declaringTypeName != null) {
162                 this.delegateThis = scope.getField(scope.enclosingSourceType(), DELEGATE_THIS, this);
163                 if (this.delegateThis == null) {
164                     if (this.binding.declaringClass == null) {
165                         this.binding.declaringClass = allocatedType;
166                     }
167                     scope.problemReporter().invalidConstructor(this, this.binding);
168                     return this.resolvedType;
169                 }
170             } else {
171                 if (this.binding.declaringClass == null) {
172                     this.binding.declaringClass = allocatedType;
173                 }
174                 scope.problemReporter().invalidConstructor(this, this.binding);
175                 return this.resolvedType;
176             }
177             CodeSnippetScope localScope = new CodeSnippetScope(scope);
178             MethodBinding privateBinding = localScope.getConstructor((ReferenceBinding)this.delegateThis.type, argumentTypes, this);
179             if (!privateBinding.isValidBinding()) {
180                 if (this.binding.declaringClass == null) {
181                     this.binding.declaringClass = allocatedType;
182                 }
183                 scope.problemReporter().invalidConstructor(this, this.binding);
184                 return this.resolvedType;
185             } else {
186                 this.binding = privateBinding;
187             }
188         } else {
189             if (this.binding.declaringClass == null) {
190                 this.binding.declaringClass = allocatedType;
191             }
192             scope.problemReporter().invalidConstructor(this, this.binding);
193             return this.resolvedType;
194         }
195     }
196     if (isMethodUseDeprecated(this.binding, scope, true)) {
197         scope.problemReporter().deprecatedMethod(this.binding, this);
198     }
199     if (arguments != null) {
200         for (int i = 0; i < arguments.length; i++) {
201             TypeBinding parameterType = binding.parameters[i];
202             TypeBinding argumentType = argumentTypes[i];
203             arguments[i].computeConversion(scope, parameterType, argumentType);
204             if (argumentType.needsUncheckedConversion(parameterType)) {
205                 scope.problemReporter().unsafeTypeConversion(arguments[i], argumentType, parameterType);
206             }
207         }
208         if (argsContainCast) {
209             CastExpression.checkNeedForArgumentCasts(scope, null, allocatedType, binding, this.arguments, argumentTypes, this);
210         }
211     }
212     if (allocatedType.isRawType() && this.binding.hasSubstitutedParameters()) {
213         scope.problemReporter().unsafeRawInvocation(this, this.binding);
214     }
215     return allocatedType;
216 }
217 }
218
Popular Tags