/******************************************************************************* * Copyright © 2011, 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 * *******************************************************************************/ package org.eclipse.edt.compiler.internal.core.validation.statement; import java.util.HashMap; import java.util.Map; import org.eclipse.edt.compiler.core.ast.AbstractASTVisitor; import org.eclipse.edt.compiler.core.ast.AnnotationExpression; import org.eclipse.edt.compiler.core.ast.DefaultASTVisitor; import org.eclipse.edt.compiler.core.ast.Expression; import org.eclipse.edt.compiler.core.ast.NestedFunction; import org.eclipse.edt.compiler.core.ast.Node; import org.eclipse.edt.compiler.core.ast.ParenthesizedExpression; import org.eclipse.edt.compiler.core.ast.ReturnStatement; import org.eclipse.edt.compiler.core.ast.SetValuesExpression; import org.eclipse.edt.compiler.internal.core.builder.IMarker; import org.eclipse.edt.compiler.internal.core.builder.IProblemRequestor; import org.eclipse.edt.compiler.internal.core.lookup.ICompilerOptions; import org.eclipse.edt.compiler.internal.core.validation.type.TypeValidator; import org.eclipse.edt.compiler.internal.util.BindingUtil; import org.eclipse.edt.mof.egl.Field; import org.eclipse.edt.mof.egl.Function; import org.eclipse.edt.mof.egl.FunctionMember; import org.eclipse.edt.mof.egl.Type; public class ReturnStatementValidator extends DefaultASTVisitor { private IProblemRequestor problemRequestor; public ReturnStatementValidator(IProblemRequestor problemRequestor, ICompilerOptions compilerOptions) { this.problemRequestor = problemRequestor; } @Override public boolean visit(final ReturnStatement returnStatement) { Node current = returnStatement.getParent(); final FunctionMember[] fBinding = new Function[1]; ParentASTVisitor visitor = new ParentASTVisitor() { @Override public boolean visit(NestedFunction nFunction) { bcontinue = false; fBinding[0] = (Function)nFunction.getName().resolveMember(); if (fBinding[0] != null) { returnField = ((Function)fBinding[0]).getReturnField(); } return false; } }; while ((current != null) && visitor.canContinue() ) { current.accept(visitor); current = current.getParent(); } if (returnStatement.getParenthesizedExprOpt() != null && !visitor.hasReturnType()){ problemRequestor.acceptProblem(returnStatement, IProblemRequestor.RETURN_VALUE_WO_RETURN_DEF); } validateNoSetValues(returnStatement); if (visitor.hasReturnType() && returnStatement.getParenthesizedExprOpt() != null) { Map<Expression, Type> rhsExprMap = new HashMap<Expression, Type>(); TypeValidator.collectExprsForTypeCompatibility(returnStatement.getParenthesizedExprOpt(), rhsExprMap); for (Map.Entry<Expression, Type> entry : rhsExprMap.entrySet()) { boolean compatible = BindingUtil.isMoveCompatible(visitor.getReturnType(), visitor.getReturnField(), entry.getValue(), entry.getKey()); if (!compatible) { problemRequestor.acceptProblem(entry.getKey(), IProblemRequestor.RETURN_STATEMENT_TYPE_INCOMPATIBLE, new String[] { BindingUtil.getShortTypeString(entry.getKey(), entry.getValue()), BindingUtil.getShortTypeString(visitor.getReturnType())}); } } } if (returnStatement.getParenthesizedExprOpt() != null) { returnStatement.getParenthesizedExprOpt().accept(new DefaultASTVisitor() { @Override public boolean visit(AnnotationExpression annotationExpression) { problemRequestor.acceptProblem( annotationExpression.getOffset(), annotationExpression.getOffset()+1, IMarker.SEVERITY_ERROR, IProblemRequestor.UNEXPECTED_TOKEN, new String[] {"@"}); return false; } @Override public boolean visit(ParenthesizedExpression parenthesizedExpression) { return true; } }); } return false; } protected void validateNoSetValues(ReturnStatement returnStatement){ returnStatement.accept(new AbstractASTVisitor(){ @Override public boolean visit(SetValuesExpression setValuesExpression) { problemRequestor.acceptProblem(setValuesExpression, IProblemRequestor.SET_VALUES_BLOCK_NOT_VALID_AS_RETURN_ARG); return false; } }); } private class ParentASTVisitor extends AbstractASTVisitor { Field returnField; boolean bcontinue; public ParentASTVisitor (){ bcontinue = true; } public boolean hasReturnType(){ return returnField != null && returnField.getType() != null; } public Type getReturnType() { return returnField == null ? null : returnField.getType(); } public Field getReturnField() { return returnField; } public boolean canContinue(){ return bcontinue; } } }