Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
Copyright (c) 2000, 2013 IBM Corporation and others. All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html Contributors: IBM Corporation - initial API and implementation Stephan Herrmann <stephan@cs.tu-berlin.de> - Contributions for bug 292478 - Report potentially null across variable assignment bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null" bug 331649 - [compiler][null] consider null annotations for fields bug 383368 - [compiler][null] syntactic null analysis for field references bug 400761 - [compiler][null] null may be return as boolean without a diagnostic bug 402993 - [null] Follow up of bug 401088: Missing warning about redundant null check bug 403147 - [compiler][null] FUP of bug 400761: consolidate interaction between unboxing, NPE, and deferred checking /
  
  package org.eclipse.jdt.internal.compiler.ast;
  
  
  
  public abstract class Expression extends Statement {
  
  	public Constant constant;
  
  	public int statementEnd = -1;
  
  	//Some expression may not be used - from a java semantic point
  	//of view only - as statements. Other may. In order to avoid the creation
  	//of wrappers around expression in order to tune them as expression
  	//Expression is a subclass of Statement. See the message isValidJavaStatement()
  
  	public int implicitConversion;
  
  public static final boolean isConstantValueRepresentable(Constant constantint constantTypeIDint targetTypeID) {
  	//true if there is no loss of precision while casting.
  	// constantTypeID == constant.typeID
  	if (targetTypeID == constantTypeID)
  		return true;
  	switch (targetTypeID) {
  		case  :
  			switch (constantTypeID) {
  				case  :
  					return true;
  				case  :
  					return constant.doubleValue() == constant.charValue();
  				case  :
  					return constant.floatValue() == constant.charValue();
  				case  :
  					return constant.intValue() == constant.charValue();
  				case  :
  					return constant.shortValue() == constant.charValue();
  				case  :
  					return constant.byteValue() == constant.charValue();
  				case  :
  					return constant.longValue() == constant.charValue();
  				default :
  					return false;//boolean
  			}
  
  		case  :
  			switch (constantTypeID) {
  				case  :
  					return constant.charValue() == constant.floatValue();
  				case  :
  					return constant.doubleValue() == constant.floatValue();
  				case  :
  					return true;
  				case  :
 					return constant.intValue() == constant.floatValue();
 				case  :
 					return constant.shortValue() == constant.floatValue();
 				case  :
 					return constant.byteValue() == constant.floatValue();
 				case  :
 					return constant.longValue() == constant.floatValue();
 				default :
 					return false;//boolean
 			}
 
 		case  :
 			switch (constantTypeID) {
 				case  :
 					return constant.charValue() == constant.doubleValue();
 				case  :
 					return true;
 				case  :
 					return constant.floatValue() == constant.doubleValue();
 				case  :
 					return constant.intValue() == constant.doubleValue();
 				case  :
 					return constant.shortValue() == constant.doubleValue();
 				case  :
 					return constant.byteValue() == constant.doubleValue();
 				case  :
 					return constant.longValue() == constant.doubleValue();
 				default :
 					return false//boolean
 			}
 
 		case  :
 			switch (constantTypeID) {
 				case  :
 					return constant.charValue() == constant.byteValue();
 				case  :
 					return constant.doubleValue() == constant.byteValue();
 				case  :
 					return constant.floatValue() == constant.byteValue();
 				case  :
 					return constant.intValue() == constant.byteValue();
 				case  :
 					return constant.shortValue() == constant.byteValue();
 				case  :
 					return true;
 				case  :
 					return constant.longValue() == constant.byteValue();
 				default :
 					return false//boolean
 			}
 
 		case  :
 			switch (constantTypeID) {
 				case  :
 					return constant.charValue() == constant.shortValue();
 				case  :
 					return constant.doubleValue() == constant.shortValue();
 				case  :
 					return constant.floatValue() == constant.shortValue();
 				case  :
 					return constant.intValue() == constant.shortValue();
 				case  :
 					return true;
 				case  :
 					return constant.byteValue() == constant.shortValue();
 				case  :
 					return constant.longValue() == constant.shortValue();
 				default :
 					return false//boolean
 			}
 
 		case  :
 			switch (constantTypeID) {
 				case  :
 					return constant.charValue() == constant.intValue();
 				case  :
 					return constant.doubleValue() == constant.intValue();
 				case  :
 					return constant.floatValue() == constant.intValue();
 				case  :
 					return true;
 				case  :
 					return constant.shortValue() == constant.intValue();
 				case  :
 					return constant.byteValue() == constant.intValue();
 				case  :
 					return constant.longValue() == constant.intValue();
 				default :
 					return false//boolean
 			}
 
 		case  :
 			switch (constantTypeID) {
 				case  :
 					return constant.charValue() == constant.longValue();
 				case  :
 					return constant.doubleValue() == constant.longValue();
 				case  :
 					return constant.floatValue() == constant.longValue();
 				case  :
 					return constant.intValue() == constant.longValue();
 				case  :
 					return constant.shortValue() == constant.longValue();
 				case  :
 					return constant.byteValue() == constant.longValue();
 				case  :
 					return true;
 				default :
 					return false//boolean
 			}
 
 		default :
 			return false//boolean
 	}
 }
 
 public Expression() {
 	super();
 }
 
 public FlowInfo analyseCode(BlockScope currentScopeFlowContext flowContextFlowInfo flowInfo) {
 	return flowInfo;
 }

More sophisticated for of the flow analysis used for analyzing expressions, and be able to optimize out portions of expressions where no actual value is required.

Parameters:
currentScope
flowContext
flowInfo
valueRequired
Returns:
The state of initialization after the analysis of the current expression
 
 public FlowInfo analyseCode(BlockScope currentScopeFlowContext flowContextFlowInfo flowInfoboolean valueRequired) {
 	return analyseCode(currentScopeflowContextflowInfo);
 }

Returns false if cast is not legal.
 
 public final boolean checkCastTypesCompatibility(Scope scopeTypeBinding castTypeTypeBinding expressionTypeExpression expression) {
 	// see specifications 5.5
 	// handle errors and process constant when needed
 
 	// if either one of the type is null ==>
 	// some error has been already reported some where ==>
 	// we then do not report an obvious-cascade-error.
 
 	if (castType == null || expressionType == nullreturn true;
 
 	// identity conversion cannot be performed upfront, due to side-effects
 	// like constant propagation
 	boolean use15specifics = scope.compilerOptions(). >= .;
 	boolean use17specifics = scope.compilerOptions(). >= .;
 	if (castType.isBaseType()) {
 		if (expressionType.isBaseType()) {
 			if (expressionType == castType) {
 				if (expression != null) {
 					this. = expression.constant//use the same constant
 				}
 				tagAsUnnecessaryCast(scopecastType);
 				return true;
 			}
 			boolean necessary = false;
 			if (expressionType.isCompatibleWith(castType)
 					|| (necessary = BaseTypeBinding.isNarrowing(castType.idexpressionType.id))) {
 				if (expression != null) {
 					expression.implicitConversion = (castType.id << 4) + expressionType.id;
 					if (expression.constant != .) {
 						this. = expression.constant.castTo(expression.implicitConversion);
 					}
 				}
 				if (!necessarytagAsUnnecessaryCast(scopecastType);
 				return true;
 
 			}
 		} else if (use17specifics && expressionType.id == .){
 			// cast from Object to base type allowed from 1.7, see JLS $5.5
 			return true;
 		} else if (use15specifics
 							&& scope.environment().computeBoxingType(expressionType).isCompatibleWith(castType)) { // unboxing - only widening match is allowed
 			tagAsUnnecessaryCast(scopecastType);
 			return true;
 		}
 		return false;
 	} else if (use15specifics
 						&& expressionType.isBaseType()
 						&& scope.environment().computeBoxingType(expressionType).isCompatibleWith(castType)) { // boxing - only widening match is allowed
 		tagAsUnnecessaryCast(scopecastType);
 		return true;
 	}
 
 	switch(expressionType.kind()) {
 		case . :
 			//-----------cast to something which is NOT a base type--------------------------
 			if (expressionType == .) {
 				tagAsUnnecessaryCast(scopecastType);
 				return true//null is compatible with every thing
 			}
 			return false;
 
 			if (castType == expressionType) {
 				tagAsUnnecessaryCast(scopecastType);
 				return true// identity conversion
 			}
 			switch (castType.kind()) {
 					// ( ARRAY ) ARRAY
 					TypeBinding castElementType = ((ArrayBindingcastType).elementsType();
 					TypeBinding exprElementType = ((ArrayBindingexpressionType).elementsType();
 					if (exprElementType.isBaseType() || castElementType.isBaseType()) {
 						if (castElementType == exprElementType) {
 							return true;
 						}
 						return false;
 					}
 					// recurse on array type elements
 					return checkCastTypesCompatibility(scopecastElementTypeexprElementTypeexpression);
 
 					// ( TYPE_PARAMETER ) ARRAY
 					TypeBinding match = expressionType.findSuperTypeOriginatingFrom(castType);
 					if (match == null) {
 						checkUnsafeCast(scopecastTypeexpressionTypenull /*no match*/true);
 					}
 					// recurse on the type variable upper bound
 					return checkCastTypesCompatibility(scope, ((TypeVariableBinding)castType).upperBound(), expressionTypeexpression);
 
 				default:
 					// ( CLASS/INTERFACE ) ARRAY
 					switch (castType.id) {
 							return true;
 							tagAsUnnecessaryCast(scopecastType);
 							return true;
 						default :
 							return false;
 					}
 			}
 
 			TypeBinding match = expressionType.findSuperTypeOriginatingFrom(castType);
 			if (match != null) {
 				return checkUnsafeCast(scopecastTypeexpressionTypematchfalse);
 			}
 			// recursively on the type variable upper bound
 			return checkCastTypesCompatibility(scopecastType, ((TypeVariableBinding)expressionType).upperBound(), expression);
 
 			match = expressionType.findSuperTypeOriginatingFrom(castType);
 			if (match != null) {
 				return checkUnsafeCast(scopecastTypeexpressionTypematchfalse);
 			}
 			// recursively on the type variable upper bound
 			return checkCastTypesCompatibility(scopecastType, ((WildcardBinding)expressionType).expression);
 
 		default:
 			if (expressionType.isInterface()) {
 				switch (castType.kind()) {
 						// ( ARRAY ) INTERFACE
 						switch (expressionType.id) {
 								return true;
 							default :
 								return false;
 						}
 
 						// ( INTERFACE ) TYPE_PARAMETER
 						match = expressionType.findSuperTypeOriginatingFrom(castType);
 						if (match == null) {
 							checkUnsafeCast(scopecastTypeexpressionTypenull /*no match*/true);
 						}
 						// recurse on the type variable upper bound
 						return checkCastTypesCompatibility(scope, ((TypeVariableBinding)castType).upperBound(), expressionTypeexpression);
 
 					default :
 						if (castType.isInterface()) {
 							// ( INTERFACE ) INTERFACE
 							ReferenceBinding interfaceType = (ReferenceBindingexpressionType;
 							match = interfaceType.findSuperTypeOriginatingFrom(castType);
 							if (match != null) {
 								return checkUnsafeCast(scopecastTypeinterfaceTypematchfalse);
 							}
 							match = castType.findSuperTypeOriginatingFrom(interfaceType);
 							if (match != null) {
 								return checkUnsafeCast(scopecastTypeinterfaceTypematchtrue);
 							}
 							if (use15specifics) {
 								checkUnsafeCast(scopecastTypeexpressionTypenull /*no match*/true);
 								// ensure there is no collision between both interfaces: i.e. I1 extends List<String>, I2 extends List<Object>
 									if (interfaceType.hasIncompatibleSuperType((ReferenceBindingcastType)) {
 										return false;
 									}
 								} else if (!castType.isRawType() && interfaceType.hasIncompatibleSuperType((ReferenceBindingcastType)) {
 									return false;
 								}
 							} else {
 								// pre1.5 semantics - no covariance allowed (even if 1.5 compliant, but 1.4 source)
 								// look at original methods rather than the parameterized variants at 1.4 to detect
 								// covariance. Otherwise when confronted with one raw type and one parameterized type,
 								// we could mistakenly detect covariance and scream foul. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=332744
 								MethodBinding[] castTypeMethods = getAllOriginalInheritedMethods((ReferenceBindingcastType);
 								MethodBinding[] expressionTypeMethods = getAllOriginalInheritedMethods((ReferenceBindingexpressionType);
 								int exprMethodsLength = expressionTypeMethods.length;
 								for (int i = 0, castMethodsLength = castTypeMethods.lengthi < castMethodsLengthi++) {
 									for (int j = 0; j < exprMethodsLengthj++) {
 										if ((castTypeMethods[i]. != expressionTypeMethods[j].)
 												&& (CharOperation.equals(castTypeMethods[i].expressionTypeMethods[j].))
 												&& castTypeMethods[i].areParametersEqual(expressionTypeMethods[j])) {
 											return false;
 
 										}
 									}
 								}
 							}
 							return true;
 						} else {
 							// ( CLASS ) INTERFACE
 							if (castType.id == .) { // no runtime error
 								tagAsUnnecessaryCast(scopecastType);
 								return true;
 							}
 							// can only be a downcast
 							match = castType.findSuperTypeOriginatingFrom(expressionType);
 							if (match != null) {
 								return checkUnsafeCast(scopecastTypeexpressionTypematchtrue);
 							}
 							if (((ReferenceBindingcastType).isFinal()) {
 								// no subclass for castType, thus compile-time check is invalid
 								return false;
 							}
 							if (use15specifics) {
 								checkUnsafeCast(scopecastTypeexpressionTypenull /*no match*/true);
 								// ensure there is no collision between both interfaces: i.e. I1 extends List<String>, I2 extends List<Object>
 									if (((ReferenceBinding)castType).hasIncompatibleSuperType((ReferenceBindingexpressionType)) {
 										return false;
 									}
 								} else if (!castType.isRawType() && ((ReferenceBinding)castType).hasIncompatibleSuperType((ReferenceBindingexpressionType)) {
 									return false;
 								}
 							}
 							return true;
 						}
 				}
 			} else {
 				switch (castType.kind()) {
 						// ( ARRAY ) CLASS
 						if (expressionType.id == .) { // potential runtime error
 							if (use15specificscheckUnsafeCast(scopecastTypeexpressionTypeexpressionTypetrue);
 							return true;
 						}
 						return false;
 
 						// ( TYPE_PARAMETER ) CLASS
 						match = expressionType.findSuperTypeOriginatingFrom(castType);
 						if (match == null) {
 							checkUnsafeCast(scopecastTypeexpressionTypenulltrue);
 						}
 						// recurse on the type variable upper bound
 						return checkCastTypesCompatibility(scope, ((TypeVariableBinding)castType).upperBound(), expressionTypeexpression);
 
 					default :
 						if (castType.isInterface()) {
 							// ( INTERFACE ) CLASS
 							ReferenceBinding refExprType = (ReferenceBindingexpressionType;
 							match = refExprType.findSuperTypeOriginatingFrom(castType);
 							if (match != null) {
 								return checkUnsafeCast(scopecastTypeexpressionTypematchfalse);
 							}
 							// unless final a subclass may implement the interface ==> no check at compile time
 							if (refExprType.isFinal()) {
 								return false;
 							}
 							match = castType.findSuperTypeOriginatingFrom(expressionType);
 							if (match != null) {
 								return checkUnsafeCast(scopecastTypeexpressionTypematchtrue);
 							}
 							if (use15specifics) {
 								checkUnsafeCast(scopecastTypeexpressionTypenull /*no match*/true);
 								// ensure there is no collision between both interfaces: i.e. I1 extends List<String>, I2 extends List<Object>
 									if (refExprType.hasIncompatibleSuperType((ReferenceBindingcastType)) {
 										return false;
 									}
 								} else if (!castType.isRawType() && refExprType.hasIncompatibleSuperType((ReferenceBindingcastType)) {
 									return false;
 								}
 							}
 							return true;
 						} else {
 							// ( CLASS ) CLASS
 							match = expressionType.findSuperTypeOriginatingFrom(castType);
 							if (match != null) {
 								if (expression != null && castType.id == .this. = expression.constant// (String) cst is still a constant
 								return checkUnsafeCast(scopecastTypeexpressionTypematchfalse);
 							}
 							match = castType.findSuperTypeOriginatingFrom(expressionType);
 							if (match != null) {
 								return checkUnsafeCast(scopecastTypeexpressionTypematchtrue);
 							}
 							return false;
 						}
 				}
 			}
 	}
 }

Check this expression against potential NPEs, which may occur:
  • if the expression is the receiver in a field access, qualified allocation, array reference or message send incl. implicit message sends like it happens for the collection in a foreach statement.
  • if the expression is subject to unboxing
  • if the expression is the exception in a throw statement
If a risk of NPE is detected report it to the context. If the expression denotes a local variable, mark it as checked, which affects the flow info.

Parameters:
scope the scope of the analysis
flowContext the current flow context
flowInfo the upstream flow info; caveat: may get modified
Returns:
could this expression be checked by the current implementation?
 
 public boolean checkNPE(BlockScope scopeFlowContext flowContextFlowInfo flowInfo) {
 	if (local != null &&
 			(local.type.tagBits & .) == 0) {
 		if ((this. & .) == 0) {
 			flowContext.recordUsingNullReference(scopelocalthis,
 					.flowInfo);
 			// account for possible NPE:
 			if (!flowInfo.isDefinitelyNonNull(local)) {
 				flowContext.recordAbruptExit();
 			}
 		}
 			// from thereon it is set
 		flowContext.markFinallyNullStatus(local.);
 		return true;
 	}
 	return false// not checked
 }

If this expression requires unboxing check if that operation can throw NPE.
 
 protected void checkNPEbyUnboxing(BlockScope scopeFlowContext flowContextFlowInfo flowInfo) {
 	int status;
 	if ((this. & ) != 0
 			&& (this. & .) == 0
 			&& (status = nullStatus(flowInfoflowContext)) != .)
 	{
 		flowContext.recordUnboxing(scopethisstatusflowInfo);
 	}
 }
 
 public boolean checkUnsafeCast(Scope scopeTypeBinding castTypeTypeBinding expressionTypeTypeBinding matchboolean isNarrowing) {
 	if (match == castType) {
 		if (!isNarrowingtagAsUnnecessaryCast(scopecastType);
 		return true;
 	}
 	if (match != null && (!castType.isReifiable() || !expressionType.isReifiable())) {
 		if(isNarrowing
 				? match.isProvablyDistinct(expressionType)
 				: castType.isProvablyDistinct(match)) {
 			return false;
 		}
 	}
 	if (!isNarrowingtagAsUnnecessaryCast(scopecastType);
 	return true;
 }

Base types need that the widening is explicitly done by the compiler using some bytecode like i2f. Also check unsafe type operations.
 
 public void computeConversion(Scope scopeTypeBinding runtimeTypeTypeBinding compileTimeType) {
 	if (runtimeType == null || compileTimeType == null)
 		return;
 	if (this. != 0) return// already set independently
 
 	// it is possible for a Byte to be unboxed to a byte & then converted to an int
 	// but it is not possible for a byte to become Byte & then assigned to an Integer,
 	// or to become an int before boxed into an Integer
 	if (runtimeType != . && runtimeType.isBaseType()) {
 		if (!compileTimeType.isBaseType()) {
 			TypeBinding unboxedType = scope.environment().computeBoxingType(compileTimeType);
 			scope.problemReporter().autoboxing(thiscompileTimeTyperuntimeType);
 			compileTimeType = unboxedType;
 		}
 	} else if (compileTimeType != . && compileTimeType.isBaseType()) {
 		TypeBinding boxedType = scope.environment().computeBoxingType(runtimeType);
 		if (boxedType == runtimeType// Object o = 12;
 			boxedType = compileTimeType;
 		this. = . | (boxedType.id << 4) + compileTimeType.id;
 		scope.problemReporter().autoboxing(thiscompileTimeTypescope.environment().computeBoxingType(boxedType));
 		return;
 	} else if (this. != . && this..typeID() != .) {
 		return;
 	}
 	int compileTimeTypeIDruntimeTypeID;
 	if ((compileTimeTypeID = compileTimeType.id) == .) { // e.g. ? extends String  ==> String (103227)
 		compileTimeTypeID = compileTimeType.erasure(). == . ? . : .;
 	}
 	switch (runtimeTypeID = runtimeType.id) {
 		case  :
 		case  :
 		case  :
 			if (compileTimeTypeID == .) {
 				this. |= (runtimeTypeID << 4) + compileTimeTypeID;
 			} else {
 				this. |= (. << 4) + compileTimeTypeID;
 			}
 			break;
 		case  :
 		case  :
 		case  :
 		case  : //implicitConversion may result in i2i which will result in NO code gen
 		case  :
 			this. |= (runtimeTypeID << 4) + compileTimeTypeID;
 			break;
 		default : // regular object ref
 //				if (compileTimeType.isRawType() && runtimeTimeType.isBoundParameterizedType()) {
 //				    scope.problemReporter().unsafeRawExpression(this, compileTimeType, runtimeTimeType);
 //				}
 	}
 }

Expression statements are plain expressions, however they generate like normal expressions with no value required.

Parameters:
currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
 
 public void generateCode(BlockScope currentScopeCodeStream codeStream) {
 	if ((this. & .) == 0) {
 		return;
 	}
 	generateCode(currentScopecodeStreamfalse);
 }

Every expression is responsible for generating its implicit conversion when necessary.

Parameters:
currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
valueRequired boolean
 
 public void generateCode(BlockScope currentScopeCodeStream codeStreamboolean valueRequired) {
 	if (this. != .) {
 		// generate a constant expression
 		int pc = codeStream.position;
 		codeStream.generateConstant(this.this.);
 		codeStream.recordPositionsFrom(pcthis.);
 	} else {
 		// actual non-constant code generation
 	}
 }

Default generation of a boolean value

Parameters:
currentScope
codeStream
trueLabel
falseLabel
valueRequired
 
 public void generateOptimizedBoolean(BlockScope currentScopeCodeStream codeStreamBranchLabel trueLabelBranchLabel falseLabelboolean valueRequired) {
 	// a label valued to nil means: by default we fall through the case...
 	// both nil means we leave the value on the stack
 
 	generateCode(currentScopecodeStreamvalueRequired && cst == .);
 	if ((cst != .) && (cst.typeID() == .)) {
 		int pc = codeStream.position;
 		if (cst.booleanValue() == true) {
 			// constant == true
 			if (valueRequired) {
 				if (falseLabel == null) {
 					// implicit falling through the FALSE case
 					if (trueLabel != null) {
 						codeStream.goto_(trueLabel);
 					}
 				}
 			}
 		} else {
 			if (valueRequired) {
 				if (falseLabel != null) {
 					// implicit falling through the TRUE case
 					if (trueLabel == null) {
 						codeStream.goto_(falseLabel);
 					}
 				}
 			}
 		}
 		codeStream.recordPositionsFrom(pcthis.);
 		return;
 	}
 	// branching
 	int position = codeStream.position;
 	if (valueRequired) {
 		if (falseLabel == null) {
 			if (trueLabel != null) {
 				// Implicit falling through the FALSE case
 				codeStream.ifne(trueLabel);
 			}
 		} else {
 			if (trueLabel == null) {
 				// Implicit falling through the TRUE case
 				codeStream.ifeq(falseLabel);
 			} else {
 				// No implicit fall through TRUE/FALSE --> should never occur
 			}
 		}
 	}
 	codeStream.recordPositionsFrom(positionthis.);
 }
 
 /* Optimized (java) code generation for string concatenations that involve StringBuffer
  * creation: going through this path means that there is no need for a new StringBuffer
  * creation, further operands should rather be only appended to the current one.
  * By default: no optimization.
  */
 public void generateOptimizedStringConcatenation(BlockScope blockScopeCodeStream codeStreamint typeID) {
 	if (typeID == . && this. != . && this..stringValue().length() == 0) {
 		return// optimize str + ""
 	}
 	generateCode(blockScopecodeStreamtrue);
 }
 
 /* Optimized (java) code generation for string concatenations that involve StringBuffer
  * creation: going through this path means that there is no need for a new StringBuffer
  * creation, further operands should rather be only appended to the current one.
  */
 public void generateOptimizedStringConcatenationCreation(BlockScope blockScopeCodeStream codeStreamint typeID) {
 	codeStream.newStringContatenation();
 	codeStream.dup();
 	switch (typeID) {
 		case  :
 			// in the case the runtime value of valueOf(Object) returns null, we have to use append(Object) instead of directly valueOf(Object)
 			// append(Object) returns append(valueOf(Object)), which means that the null case is handled by the next case.
 			generateCode(blockScopecodeStreamtrue);
 			return;
 		case  :
 			if (this. != .) {
 				String stringValue = this..stringValue();
 				if (stringValue.length() == 0) {  // optimize ""+<str>
 					return;
 				}
 				codeStream.ldc(stringValue);
 			} else {
 				// null case is not a constant
 				generateCode(blockScopecodeStreamtrue);
 			}
 			break;
 		default :
 			generateCode(blockScopecodeStreamtrue);
 			codeStream.invokeStringValueOf(typeID);
 	}
 }
 
 	ArrayList collector = new ArrayList();
 	getAllInheritedMethods0(bindingcollector);
 	for (int i = 0, len = collector.size(); i < leni++) {
 		collector.set(i, ((MethodBinding)collector.get(i)).original());
 	}
 	return (MethodBinding[]) collector.toArray(new MethodBinding[collector.size()]);
 }
 
 private void getAllInheritedMethods0(ReferenceBinding bindingArrayList collector) {
 	if (!binding.isInterface()) return;
 	MethodBinding[] methodBindings = binding.methods();
 	for (int i = 0, max = methodBindings.lengthi < maxi++) {
 		collector.add(methodBindings[i]);
 	}
 	ReferenceBinding[] superInterfaces = binding.superInterfaces();
 	for (int i = 0, max = superInterfaces.lengthi < maxi++) {
 		getAllInheritedMethods0(superInterfaces[i], collector);
 	}
 }
 
 public static Binding getDirectBinding(Expression someExpression) {
 	if ((someExpression.bits & .) != 0) {
 		return null;
 	}
 	if (someExpression instanceof SingleNameReference) {
 		return ((SingleNameReference)someExpression).;
 	} else if (someExpression instanceof FieldReference) {
 		FieldReference fieldRef = (FieldReference)someExpression;
 		if (fieldRef.receiver.isThis() && !(fieldRef.receiver instanceof QualifiedThisReference)) {
 			return fieldRef.binding;
 		}
 	} else if (someExpression instanceof Assignment) {
 		Expression lhs = ((Assignment)someExpression).;
 		if ((lhs.bits & .) != 0) {
 			// i = i = ...; // eq to int i = ...;
 			return getDirectBinding (((Assignment)someExpression).);
 		} else if (someExpression instanceof PrefixExpression) {
 			// i = i++; // eq to ++i;
 			return getDirectBinding (((Assignment)someExpression).);
 		}
 	} else if (someExpression instanceof QualifiedNameReference) {
 		QualifiedNameReference qualifiedNameReference = (QualifiedNameReferencesomeExpression;
 		if (qualifiedNameReference.indexOfFirstFieldBinding != 1
 				&& qualifiedNameReference.otherBindings == null) {
 			// case where a static field is retrieved using ClassName.fieldname
 			return qualifiedNameReference.binding;
 		}
 	} else if (someExpression.isThis()) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=276741
 		return someExpression.resolvedType;
 	}
 //		} else if (someExpression instanceof PostfixExpression) { // recurse for postfix: i++ --> i
 //			// note: "b = b++" is equivalent to doing nothing, not to "b++"
 //			return getDirectBinding(((PostfixExpression) someExpression).lhs);
 	return null;
 }
 
 public boolean isCompactableOperation() {
 	return false;
 }
 
 //Return true if the conversion is done AUTOMATICALLY by the vm
 //while the javaVM is an int based-machine, thus for example pushing
 //a byte onto the stack , will automatically create an int on the stack
 //(this request some work d be done by the VM on signed numbers)
 public boolean isConstantValueOfTypeAssignableToType(TypeBinding constantTypeTypeBinding targetType) {
 
 	if (this. == .)
 		return false;
 	if (constantType == targetType)
 		return true;
 	//No free assignment conversion from anything but to integral ones.
 	if (BaseTypeBinding.isWidening(.constantType.id)
 			&& (BaseTypeBinding.isNarrowing(targetType.id.))) {
 		//use current explicit conversion in order to get some new value to compare with current one
 		return isConstantValueRepresentable(this.constantType.idtargetType.id);
 	}
 	return false;
 }
 
 public boolean isTypeReference() {
 	return false;
 }

Returns the local variable referenced by this node. Can be a direct reference (SingleNameReference) or thru a cast expression etc...
 
 	return null;
 }

Mark this expression as being non null, per a specific tag in the source code.
 
 // this is no more called for now, waiting for inter procedural null reference analysis
 public void markAsNonNull() {
 	this. |= .;
 }
 
 public int nullStatus(FlowInfo flowInfoFlowContext flowContext) {
 
 	if (/* (this.bits & IsNonNull) != 0 || */
 		this. != null && this. != .)
 		return .// constant expression cannot be null
 
 	if (local != null)
 		return flowInfo.nullStatus(local);
 	return .;
 }

Constant usable for bytecode pattern optimizations, but cannot be inlined since it is not strictly equivalent to the definition of constant expressions. In particular, some side-effects may be required to occur (only the end value is known).

Returns:
Constant known to be of boolean type
 
 	return this.;
 }

Returns the type of the expression after required implicit conversions. When expression type gets promoted or inserted a generic cast, the converted type will differ from the resolved type (surface side-effects from #computeConversion(...)).

Returns:
the type after implicit conversion
 
 	TypeBinding convertedType = this.;
 	int runtimeType = (this. & .) >> 4;
 	switch (runtimeType) {
 		case  :
 			convertedType = .;
 			break;
 		case  :
 			convertedType = .;
 			break;
 		case  :
 			convertedType = .;
 			break;
 		case  :
 			convertedType = .;
 			break;
 		case  :
 			convertedType = .;
 			break;
 		case  :
 			convertedType = .;
 			break;
 		case  :
 			convertedType = .;
 			break;
 		case  :
 			convertedType = .;
 			break;
 		default :
 	}
 	if ((this. & .) != 0) {
 		convertedType = scope.environment().computeBoxingType(convertedType);
 	}
 	return convertedType;
 }
 
 public StringBuffer print(int indentStringBuffer output) {
 	printIndent(indentoutput);
 	return printExpression(indentoutput);
 }
 
 public abstract StringBuffer printExpression(int indentStringBuffer output);
 
 public StringBuffer printStatement(int indentStringBuffer output) {
 	return print(indentoutput).append(";"); //$NON-NLS-1$
 }
 
 public void resolve(BlockScope scope) {
 	// drops the returning expression's type whatever the type is.
 	this.resolveType(scope);
 	return;
 }

Resolve the type of this expression in the context of a blockScope

Parameters:
scope
Returns:
Return the actual type of this expression after resolution
 
 public TypeBinding resolveType(BlockScope scope) {
 	// by default... subclasses should implement a better TB if required.
 	return null;
 }

Resolve the type of this expression in the context of a classScope

Parameters:
scope
Returns:
Return the actual type of this expression after resolution
 
 public TypeBinding resolveType(ClassScope scope) {
 	// by default... subclasses should implement a better TB if required.
 	return null;
 }
 
 public TypeBinding resolveTypeExpecting(BlockScope scopeTypeBinding expectedType) {
 	setExpectedType(expectedType); // needed in case of generic method invocation
	TypeBinding expressionType = this.resolveType(scope);
	if (expressionType == nullreturn null;
	if (expressionType == expectedTypereturn expressionType;
	if (!expressionType.isCompatibleWith(expectedType)) {
		if (scope.isBoxingCompatibleWith(expressionTypeexpectedType)) {
			computeConversion(scopeexpectedTypeexpressionType);
else {
			scope.problemReporter().typeMismatchError(expressionTypeexpectedTypethisnull);
			return null;
	return expressionType;
Returns true if the receiver is forced to be of raw type either to satisfy the contract imposed by a super type or because it *is* raw and the current type has no control over it (i.e the rawness originates from some other file.)
public boolean forcedToBeRaw(ReferenceContext referenceContext) {
	if (this instanceof NameReference) {
		final Binding receiverBinding = ((NameReferencethis).;
		if (receiverBinding.isParameter() && (((LocalVariableBindingreceiverBinding). & .) != 0) {
			return true;  // parameter is forced to be raw since super method uses raw types.
else if (receiverBinding instanceof FieldBinding) {
			FieldBinding field = (FieldBindingreceiverBinding;
			if (field.type.isRawType()) {
				if (referenceContext instanceof AbstractMethodDeclaration) {
					AbstractMethodDeclaration methodDecl = (AbstractMethodDeclarationreferenceContext;
					if (field.declaringClass != methodDecl.binding.declaringClass) { // inherited raw field, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=337962
						return true;
else if (referenceContext instanceof TypeDeclaration) {
					TypeDeclaration type = (TypeDeclarationreferenceContext;
					if (field.declaringClass != type.binding) { // inherited raw field, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=337962
						return true;
else if (this instanceof MessageSend) {
		if (!CharOperation.equals(((MessageSendthis)...getFileName(),
				referenceContext.compilationResult().getFileName())) {  // problem is rooted elsewhere
			return true;
else if (this instanceof FieldReference) {
		FieldBinding field = ((FieldReferencethis).;
		if (!CharOperation.equals(field.declaringClass.getFileName(),
				referenceContext.compilationResult().getFileName())) { // problem is rooted elsewhere
			return true;
		if (field.type.isRawType()) {
			if (referenceContext instanceof AbstractMethodDeclaration) {
				AbstractMethodDeclaration methodDecl = (AbstractMethodDeclarationreferenceContext;
				if (field.declaringClass != methodDecl.binding.declaringClass) { // inherited raw field, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=337962
					return true;
else if (referenceContext instanceof TypeDeclaration) {
				TypeDeclaration type = (TypeDeclarationreferenceContext;
				if (field.declaringClass != type.binding) { // inherited raw field, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=337962
					return true;
else if (this instanceof ConditionalExpression) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=337751
		if (ternary.valueIfTrue.forcedToBeRaw(referenceContext) || ternary.valueIfFalse.forcedToBeRaw(referenceContext)) {
			return true;
	return false;
Returns an object which can be used to identify identical JSR sequence targets (see TryStatement subroutine codegen) or null</null> if not reusable
	if (this. != . && (this. & .) == 0) {
		return this.;
	return null;
Record the type expectation before this expression is typechecked. e.g. String s = foo();, foo() will be tagged as being expected of type String Used to trigger proper inference of generic method invocations.

Parameters:
expectedType The type denoting an expectation in the context of an assignment conversion
public void setExpectedType(TypeBinding expectedType) {
    // do nothing by default
public void tagAsNeedCheckCast() {
    // do nothing by default
Record the fact a cast expression got detected as being unnecessary.

Parameters:
scope
castType
public void tagAsUnnecessaryCast(Scope scopeTypeBinding castType) {
    // do nothing by default
	//by default undefined
	//this method is meanly used by the parser in order to transform
	//an expression that is used as a type reference in a cast ....
	//--appreciate the fact that castExpression and ExpressionWithParenthesis
	//--starts with the same pattern.....