Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/ReturnStatement.java')
-rw-r--r--bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/ReturnStatement.java301
1 files changed, 175 insertions, 126 deletions
diff --git a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/ReturnStatement.java b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/ReturnStatement.java
index 515cbb1b..b0fff98e 100644
--- a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/ReturnStatement.java
+++ b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/ReturnStatement.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2012 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
@@ -13,6 +13,7 @@ package org.eclipse.wst.jsdt.internal.compiler.ast;
import org.eclipse.wst.jsdt.core.ast.IASTNode;
import org.eclipse.wst.jsdt.core.ast.IExpression;
import org.eclipse.wst.jsdt.core.ast.IReturnStatement;
+import org.eclipse.wst.jsdt.core.infer.InferredType;
import org.eclipse.wst.jsdt.internal.compiler.ASTVisitor;
import org.eclipse.wst.jsdt.internal.compiler.flow.FlowContext;
import org.eclipse.wst.jsdt.internal.compiler.flow.FlowInfo;
@@ -31,146 +32,194 @@ public class ReturnStatement extends Statement implements IReturnStatement {
public SubRoutineStatement[] subroutines;
public LocalVariableBinding saveValueVariable;
public int initStateIndex = -1;
-
-public ReturnStatement(Expression expression, int sourceStart, int sourceEnd) {
- this.sourceStart = sourceStart;
- this.sourceEnd = sourceEnd;
- this.expression = expression ;
-}
-
-public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
- if (this.expression != null) {
- flowInfo = this.expression.analyseCode(currentScope, flowContext, flowInfo);
+
+ /**
+ * <p>
+ * {@link InferredType} returned by this return statement.
+ * </p>
+ */
+ private InferredType fInferredType;
+
+ /**
+ * <p>
+ * <code>true</code> if this return statement is actually returning a
+ * type, rather then the instance of a type. <code>false</code> if this
+ * return statement is returning an instance of a type rather then the
+ * type itself.
+ * </p>
+ */
+ private boolean fIsType;
+
+ public ReturnStatement(Expression expression, int sourceStart, int sourceEnd) {
+ this.sourceStart = sourceStart;
+ this.sourceEnd = sourceEnd;
+ this.expression = expression ;
+ this.fInferredType = null;
+ this.fIsType = false;
}
-
- // compute the return sequence (running the finally blocks)
- FlowContext traversedContext = flowContext;
- int subCount = 0;
- boolean saveValueNeeded = false;
- boolean hasValueToSave = this.expression != null
- && this.expression.constant == Constant.NotAConstant
- && !(this.expression instanceof NullLiteral);
- do {
- SubRoutineStatement sub;
- if ((sub = traversedContext.subroutine()) != null) {
- if (this.subroutines == null){
- this.subroutines = new SubRoutineStatement[5];
- }
- if (subCount == this.subroutines.length) {
- System.arraycopy(this.subroutines, 0, (this.subroutines = new SubRoutineStatement[subCount*2]), 0, subCount); // grow
- }
- this.subroutines[subCount++] = sub;
- if (sub.isSubRoutineEscaping()) {
- saveValueNeeded = false;
- this.bits |= ASTNode.IsAnySubRoutineEscaping;
- break;
- }
+
+ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+ if (this.expression != null) {
+ flowInfo = this.expression.analyseCode(currentScope, flowContext, flowInfo);
}
- traversedContext.recordReturnFrom(flowInfo.unconditionalInits());
-
- if (traversedContext instanceof InsideSubRoutineFlowContext) {
- ASTNode node = traversedContext.associatedNode;
- if (node instanceof TryStatement) {
- TryStatement tryStatement = (TryStatement) node;
- flowInfo.addInitializationsFrom(tryStatement.subRoutineInits); // collect inits
- if (hasValueToSave) {
- if (this.saveValueVariable == null){ // closest subroutine secret variable is used
- prepareSaveValueLocation(tryStatement);
+
+ // compute the return sequence (running the finally blocks)
+ FlowContext traversedContext = flowContext;
+ int subCount = 0;
+ boolean saveValueNeeded = false;
+ boolean hasValueToSave = this.expression != null
+ && this.expression.constant == Constant.NotAConstant
+ && !(this.expression instanceof NullLiteral);
+ do {
+ SubRoutineStatement sub;
+ if ((sub = traversedContext.subroutine()) != null) {
+ if (this.subroutines == null){
+ this.subroutines = new SubRoutineStatement[5];
+ }
+ if (subCount == this.subroutines.length) {
+ System.arraycopy(this.subroutines, 0, (this.subroutines = new SubRoutineStatement[subCount*2]), 0, subCount); // grow
+ }
+ this.subroutines[subCount++] = sub;
+ if (sub.isSubRoutineEscaping()) {
+ saveValueNeeded = false;
+ this.bits |= ASTNode.IsAnySubRoutineEscaping;
+ break;
+ }
+ }
+ traversedContext.recordReturnFrom(flowInfo.unconditionalInits());
+
+ if (traversedContext instanceof InsideSubRoutineFlowContext) {
+ ASTNode node = traversedContext.associatedNode;
+ if (node instanceof TryStatement) {
+ TryStatement tryStatement = (TryStatement) node;
+ flowInfo.addInitializationsFrom(tryStatement.subRoutineInits); // collect inits
+ if (hasValueToSave) {
+ if (this.saveValueVariable == null){ // closest subroutine secret variable is used
+ prepareSaveValueLocation(tryStatement);
+ }
+ saveValueNeeded = true;
}
- saveValueNeeded = true;
}
+ } else if (traversedContext instanceof InitializationFlowContext) {
+ currentScope.problemReporter().cannotReturnOutsideFunction(this);
+ return FlowInfo.DEAD_END;
}
- } else if (traversedContext instanceof InitializationFlowContext) {
- currentScope.problemReporter().cannotReturnOutsideFunction(this);
- return FlowInfo.DEAD_END;
+ } while ((traversedContext = traversedContext.parent) != null);
+
+ // resize subroutines
+ if ((this.subroutines != null) && (subCount != this.subroutines.length)) {
+ System.arraycopy(this.subroutines, 0, (this.subroutines = new SubRoutineStatement[subCount]), 0, subCount);
}
- } while ((traversedContext = traversedContext.parent) != null);
-
- // resize subroutines
- if ((this.subroutines != null) && (subCount != this.subroutines.length)) {
- System.arraycopy(this.subroutines, 0, (this.subroutines = new SubRoutineStatement[subCount]), 0, subCount);
+
+ // secret local variable for return value (note that this can only occur in a real method)
+ if (saveValueNeeded) {
+ if (this.saveValueVariable != null) {
+ this.saveValueVariable.useFlag = LocalVariableBinding.USED;
+ }
+ } else {
+ this.saveValueVariable = null;
+ if ( this.expression != null && this.expression.resolvedType == TypeBinding.BOOLEAN) {
+ this.expression.bits |= ASTNode.IsReturnedValue;
+ }
+ }
+ return FlowInfo.DEAD_END;
}
-
- // secret local variable for return value (note that this can only occur in a real method)
- if (saveValueNeeded) {
- if (this.saveValueVariable != null) {
- this.saveValueVariable.useFlag = LocalVariableBinding.USED;
+
+ public boolean needValue() {
+ return this.saveValueVariable != null
+ || ((this.bits & ASTNode.IsAnySubRoutineEscaping) == 0);
+ }
+
+ public void prepareSaveValueLocation(TryStatement targetTryStatement){
+ this.saveValueVariable = targetTryStatement.secretReturnValue;
+ }
+
+ public StringBuffer printStatement(int tab, StringBuffer output){
+ printIndent(tab, output).append("return "); //$NON-NLS-1$
+ if (this.expression != null )
+ this.expression.printExpression(0, output) ;
+ return output.append(';');
+ }
+
+ public void resolve(BlockScope scope) {
+ MethodScope methodScope = scope.methodScope();
+
+ if(methodScope==null) {
+ /* return statement outside of a method */
+ scope.problemReporter().cannotReturnOutsideFunction(this);
+ return;
+ }
+
+ MethodBinding methodBinding = null;
+ TypeBinding methodType =
+ (methodScope.referenceContext instanceof AbstractMethodDeclaration)
+ ? ((methodBinding = ((AbstractMethodDeclaration) methodScope.referenceContext).binding) == null
+ ? null
+ : methodBinding.returnType)
+ : TypeBinding.ANY;
+ TypeBinding expressionType;
+ if (this.expression == null) {
+ if (methodType != null && !methodType.isAnyType()) scope.problemReporter().shouldReturn(methodType, this);
+ return;
}
- } else {
- this.saveValueVariable = null;
- if ( this.expression != null && this.expression.resolvedType == TypeBinding.BOOLEAN) {
- this.expression.bits |= ASTNode.IsReturnedValue;
+ this.expression.setExpectedType(methodType); // needed in case of generic method invocation
+ if ((expressionType = this.expression.resolveType(scope)) == null) return;
+ if (methodType == null)
+ return;
+
+ if (methodType != expressionType) // must call before computeConversion() and typeMismatchError()
+ scope.compilationUnitScope().recordTypeConversion(methodType, expressionType);
+ if (this.expression.isConstantValueOfTypeAssignableToType(expressionType, methodType)
+ || expressionType.isCompatibleWith(methodType)) {
+
+ return;
}
+ if(methodBinding != null && !methodBinding.isConstructor())
+ scope.problemReporter().typeMismatchError(expressionType, methodType, this.expression);
}
- return FlowInfo.DEAD_END;
-}
-
-public boolean needValue() {
- return this.saveValueVariable != null
- || ((this.bits & ASTNode.IsAnySubRoutineEscaping) == 0);
-}
-
-public void prepareSaveValueLocation(TryStatement targetTryStatement){
- this.saveValueVariable = targetTryStatement.secretReturnValue;
-}
-
-public StringBuffer printStatement(int tab, StringBuffer output){
- printIndent(tab, output).append("return "); //$NON-NLS-1$
- if (this.expression != null )
- this.expression.printExpression(0, output) ;
- return output.append(';');
-}
-
-public void resolve(BlockScope scope) {
- MethodScope methodScope = scope.methodScope();
-
- if(methodScope==null) {
- /* return statement outside of a method */
- scope.problemReporter().cannotReturnOutsideFunction(this);
- return;
+
+ public void traverse(ASTVisitor visitor, BlockScope scope) {
+ if (visitor.visit(this, scope)) {
+ if (this.expression != null)
+ this.expression.traverse(visitor, scope);
+ }
+ visitor.endVisit(this, scope);
}
-
- MethodBinding methodBinding = null;
- TypeBinding methodType =
- (methodScope.referenceContext instanceof AbstractMethodDeclaration)
- ? ((methodBinding = ((AbstractMethodDeclaration) methodScope.referenceContext).binding) == null
- ? null
- : methodBinding.returnType)
- : TypeBinding.ANY;
- TypeBinding expressionType;
- if (this.expression == null) {
- if (methodType != null && !methodType.isAnyType()) scope.problemReporter().shouldReturn(methodType, this);
- return;
+
+ public int getASTType() {
+ return IASTNode.RETURN_STATEMENT;
+
+ }
+
+ public IExpression getExpression() {
+ return this.expression;
}
- this.expression.setExpectedType(methodType); // needed in case of generic method invocation
- if ((expressionType = this.expression.resolveType(scope)) == null) return;
- if (methodType == null)
- return;
-
- if (methodType != expressionType) // must call before computeConversion() and typeMismatchError()
- scope.compilationUnitScope().recordTypeConversion(methodType, expressionType);
- if (this.expression.isConstantValueOfTypeAssignableToType(expressionType, methodType)
- || expressionType.isCompatibleWith(methodType)) {
- return;
+ /**
+ * @see org.eclipse.wst.jsdt.core.ast.IReturnStatement#setInferredType(org.eclipse.wst.jsdt.core.infer.InferredType)
+ */
+ public void setInferredType(InferredType type) {
+ this.fInferredType = type;
}
- if(methodBinding != null && !methodBinding.isConstructor())
- scope.problemReporter().typeMismatchError(expressionType, methodType, this.expression);
-}
-public void traverse(ASTVisitor visitor, BlockScope scope) {
- if (visitor.visit(this, scope)) {
- if (this.expression != null)
- this.expression.traverse(visitor, scope);
+ /**
+ * @see org.eclipse.wst.jsdt.core.ast.IReturnStatement#getInferredType()
+ */
+ public InferredType getInferredType() {
+ return this.fInferredType;
}
- visitor.endVisit(this, scope);
-}
-public int getASTType() {
- return IASTNode.RETURN_STATEMENT;
-}
+ /**
+ * @see org.eclipse.wst.jsdt.core.ast.IReturnStatement#setIsType(boolean)
+ */
+ public void setIsType(boolean isType) {
+ this.fIsType = isType;
+ }
-public IExpression getExpression() {
- return this.expression;
-}
-}
+ /**
+ * @see org.eclipse.wst.jsdt.core.ast.IReturnStatement#isType()
+ */
+ public boolean isType() {
+ return this.fIsType;
+ }
+} \ No newline at end of file

Back to the top