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.ArrayBinding;
17 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
18 import net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding;
19 import net.sourceforge.phpdt.internal.compiler.lookup.ReferenceBinding;
20 import net.sourceforge.phpdt.internal.compiler.lookup.Scope;
21 import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
23 public class InstanceOfExpression extends OperatorExpression {
25 public Expression expression;
27 public TypeReference type;
29 public InstanceOfExpression(Expression expression, TypeReference type,
32 this.expression = expression;
34 this.bits |= operator << OperatorSHIFT;
35 this.sourceStart = expression.sourceStart;
36 this.sourceEnd = type.sourceEnd;
39 public FlowInfo analyseCode(BlockScope currentScope,
40 FlowContext flowContext, FlowInfo flowInfo) {
42 return expression.analyseCode(currentScope, flowContext, flowInfo)
43 .unconditionalInits();
46 public final boolean areTypesCastCompatible(BlockScope scope,
47 TypeBinding castType, TypeBinding expressionType) {
49 // see specifications p.68
50 // A more cpmplete version of this method is provided on
51 // CastExpression (it deals with constant and need runtime checkcast)
53 if (castType == expressionType)
56 // by grammatical construction, the first test is ALWAYS false
57 // if (castTb.isBaseType())
58 // { if (expressionTb.isBaseType())
60 // (expression.isConstantValueOfTypeAssignableToType(expressionTb,castTb))
63 // { if (expressionTb==castTb)
66 // { if (scope.areTypesCompatible(expressionTb,castTb))
69 // if (BaseTypeBinding.isNarrowing(castTb.id,expressionTb.id))
75 { // -------------checkcast to something which is NOT a
76 // basetype----------------------------------
78 // null is compatible with every thing ....
79 if (NullBinding == expressionType) {
82 if (expressionType.isArrayType()) {
83 if (castType.isArrayType()) {
84 // ------- (castTb.isArray) expressionTb.isArray -----------
85 TypeBinding expressionEltTb = ((ArrayBinding) expressionType)
87 if (expressionEltTb.isBaseType())
88 // <---stop the recursion-------
89 return ((ArrayBinding) castType).elementsType(scope) == expressionEltTb;
90 // recursivly on the elts...
91 return areTypesCastCompatible(scope,
92 ((ArrayBinding) castType).elementsType(scope),
95 if (castType.isClass()) {
96 // ------(castTb.isClass) expressionTb.isArray
98 if (scope.isJavaLangObject(castType))
102 if (castType.isInterface()) {
103 // ------- (castTb.isInterface) expressionTb.isArray
105 if (scope.isJavaLangCloneable(castType)
106 || scope.isJavaIoSerializable(castType)) {
114 if (expressionType.isBaseType()) {
117 if (expressionType.isClass()) {
118 if (castType.isArrayType()) {
119 // ---- (castTb.isArray) expressionTb.isClass -------
120 if (scope.isJavaLangObject(expressionType)) {
126 if (castType.isClass()) { // ----- (castTb.isClass)
127 // expressionTb.isClass ------
128 if (expressionType.isCompatibleWith(castType))
131 if (castType.isCompatibleWith(expressionType)) {
137 if (castType.isInterface()) {
138 // ----- (castTb.isInterface) expressionTb.isClass -------
139 if (((ReferenceBinding) expressionType).isFinal()) {
140 // no subclass for expressionTb, thus compile-time check
142 if (expressionType.isCompatibleWith(castType))
152 if (expressionType.isInterface()) {
153 if (castType.isArrayType()) {
154 // ----- (castTb.isArray) expressionTb.isInterface ------
155 if (scope.isJavaLangCloneable(expressionType)
156 || scope.isJavaIoSerializable(expressionType))
157 // potential runtime error
163 if (castType.isClass()) {
164 // ----- (castTb.isClass) expressionTb.isInterface --------
165 if (scope.isJavaLangObject(castType))
167 if (((ReferenceBinding) castType).isFinal()) {
168 // no subclass for castTb, thus compile-time check is
170 if (castType.isCompatibleWith(expressionType)) {
177 if (castType.isInterface()) {
178 // ----- (castTb.isInterface) expressionTb.isInterface
180 if ((Scope.compareTypes(castType, expressionType) == NotRelated)) {
181 MethodBinding[] castTbMethods = ((ReferenceBinding) castType)
183 int castTbMethodsLength = castTbMethods.length;
184 MethodBinding[] expressionTbMethods = ((ReferenceBinding) expressionType)
186 int expressionTbMethodsLength = expressionTbMethods.length;
187 for (int i = 0; i < castTbMethodsLength; i++) {
188 for (int j = 0; j < expressionTbMethodsLength; j++) {
189 if (castTbMethods[i].selector == expressionTbMethods[j].selector) {
190 if (castTbMethods[i].returnType != expressionTbMethods[j].returnType) {
192 .areParametersEqual(expressionTbMethods[j])) {
211 * Code generation for instanceOfExpression
213 * @param currentScope
214 * net.sourceforge.phpdt.internal.compiler.lookup.BlockScope
216 * net.sourceforge.phpdt.internal.compiler.codegen.CodeStream
217 * @param valueRequired
220 // public void generateCode(
221 // BlockScope currentScope,
222 // CodeStream codeStream,
223 // boolean valueRequired) {
225 // int pc = codeStream.position;
226 // expression.generateCode(currentScope, codeStream, true);
227 // codeStream.instance_of(type.resolvedType);
228 // if (!valueRequired)
230 // codeStream.recordPositionsFrom(pc, this.sourceStart);
232 public TypeBinding resolveType(BlockScope scope) {
234 constant = NotAConstant;
235 TypeBinding expressionType = expression.resolveType(scope);
236 TypeBinding checkType = type.resolveType(scope);
237 if (expressionType == null || checkType == null)
240 if (!areTypesCastCompatible(scope, checkType, expressionType)) {
241 scope.problemReporter().notCompatibleTypesError(this,
242 expressionType, checkType);
245 this.resolvedType = BooleanBinding;
246 return BooleanBinding;
249 public StringBuffer printExpressionNoParenthesis(int indent,
250 StringBuffer output) {
252 expression.printExpression(indent, output).append(" instanceof "); //$NON-NLS-1$
253 return type.print(0, output);
256 public String toStringExpressionNoParenthesis() {
258 return expression.toStringExpression() + " instanceof " + //$NON-NLS-1$
262 public void traverse(ASTVisitor visitor, BlockScope scope) {
264 if (visitor.visit(this, scope)) {
265 expression.traverse(visitor, scope);
266 type.traverse(visitor, scope);
268 visitor.endVisit(this, scope);