/******************************************************************************* * Copyright © 2012, 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.mof.eglx.jtopen.validation; import org.eclipse.edt.compiler.core.ast.AbstractASTVisitor; import org.eclipse.edt.compiler.core.ast.CallStatement; import org.eclipse.edt.compiler.core.ast.Expression; import org.eclipse.edt.compiler.core.ast.SimpleName; import org.eclipse.edt.compiler.internal.core.builder.IMarker; import org.eclipse.edt.compiler.internal.core.lookup.FunctionArgumentValidator; import org.eclipse.edt.compiler.internal.core.validation.AbstractStatementValidator; import org.eclipse.edt.compiler.internal.util.BindingUtil; import org.eclipse.edt.mof.egl.Function; import org.eclipse.edt.mof.egl.Library; import org.eclipse.edt.mof.egl.Member; import org.eclipse.edt.mof.egl.NamedElement; import org.eclipse.edt.mof.egl.Part; import org.eclipse.edt.mof.egl.utils.TypeUtils; import org.eclipse.edt.mof.eglx.jtopen.ext.Utils; import org.eclipse.edt.mof.eglx.jtopen.messages.IBMiResourceKeys; public class IBMiProgramCallStatementValidator extends AbstractStatementValidator { public boolean visit(CallStatement callStatement){ Member targFunction = callStatement.getInvocationTarget().resolveMember(); if (!(targFunction instanceof Function)) { //error...target must be a function if callback or error routine specified problemRequestor.acceptProblem(callStatement.getInvocationTarget(), IBMiResourceKeys.FUNCTION_CALL_TARGET_MUST_BE_FUNCTION, IMarker.SEVERITY_ERROR, new String[] {}, IBMiResourceKeys.getResourceBundleForKeys()); return false; } if (targFunction.getAnnotation("eglx.jtopen.annotations.IBMiProgram") == null) { problemRequestor.acceptProblem(callStatement, IBMiResourceKeys.IBMIPROGRAM_MUST_BE_SPECIFIED, IMarker.SEVERITY_ERROR, new String[] {((Function)targFunction).getCaseSensitiveName()}, IBMiResourceKeys.getResourceBundleForKeys()); return false; } //validate the arguments against the parms callStatement.accept(new FunctionArgumentValidator((Function)targFunction, problemRequestor, compilerOptions)); callStatement.getInvocationTarget().accept( new AbstractASTVisitor() { public boolean visit(org.eclipse.edt.compiler.core.ast.QualifiedName qualifiedName){ if(qualifiedName.getQualifier() instanceof SimpleName && qualifiedName.getQualifier().resolveElement() instanceof Part && !(qualifiedName.getQualifier().resolveElement() instanceof Library)){ problemRequestor.acceptProblem(qualifiedName.getQualifier(), IBMiResourceKeys.IBMIPROGRAM_TARGET_IS_SERVICE_QUALIFIED, IMarker.SEVERITY_ERROR, new String[] {}, IBMiResourceKeys.getResourceBundleForKeys()); return false; } return true; } }); //if the function returns a value, a returns is required if (((Function)targFunction).getReturnType() != null && (callStatement.getCallSynchronizationValues() == null || callStatement.getCallSynchronizationValues().getReturns() == null)) { problemRequestor.acceptProblem(callStatement.getInvocationTarget(), IBMiResourceKeys.IBMIPROGRAM_CALLBACK_OR_RETURNS_REQUIRED, IMarker.SEVERITY_ERROR, new String[] {}, IBMiResourceKeys.getResourceBundleForKeys()); } if (callStatement.getUsing() == null && targFunction.getAnnotation("eglx.lang.Resource") == null) { problemRequestor.acceptProblem(callStatement, IBMiResourceKeys.IBMIPROGRAM_USING_HAS_NO_CONNECTION, IMarker.SEVERITY_ERROR, new String[] {}, IBMiResourceKeys.getResourceBundleForKeys()); } if (callStatement.getUsing() != null && !Utils.isIBMiConnection(callStatement.getUsing().resolveType())) { problemRequestor.acceptProblem(callStatement, IBMiResourceKeys.WRONG_USING_CLAUSE_TYPE, IMarker.SEVERITY_ERROR, new String[] {BindingUtil.getShortTypeString(callStatement.getUsing().resolveType(), true)}, IBMiResourceKeys.getResourceBundleForKeys()); } if (callStatement.getCallSynchronizationValues() != null) { if (callStatement.getCallSynchronizationValues().getReturns() != null) { //If a returns is specified, the function must return a value if (((Function)targFunction).getReturnType() == null) { problemRequestor.acceptProblem(callStatement.getCallSynchronizationValues().getReturns(), IBMiResourceKeys.IBMIPROGRAM_RETURNS_NOT_ALLOWED, IMarker.SEVERITY_ERROR, new String[] {targFunction.getCaseSensitiveName()}, IBMiResourceKeys.getResourceBundleForKeys()); } else { //Ensure that the returns type of the call is compatible with the function's return type Expression callReturnsExpr = callStatement.getCallSynchronizationValues().getReturns().getExpression(); Member callReturnsMember = callReturnsExpr.resolveMember(); if (callReturnsMember.getType() instanceof NamedElement && !TypeUtils.areCompatible(((Function)targFunction).getReturnType().getClassifier(), (NamedElement)callReturnsMember.getType())){ problemRequestor.acceptProblem(callStatement.getCallSynchronizationValues().getReturns(), IBMiResourceKeys.IBMIPROGRAM_RETURNS_NOT_COMPAT_WITH_FUNCTION, IMarker.SEVERITY_ERROR, new String[] {BindingUtil.getTypeName((Function)targFunction), ((Function)targFunction).getCaseSensitiveName(), BindingUtil.getTypeName(callReturnsMember), callReturnsExpr.getCanonicalString()}, IBMiResourceKeys.getResourceBundleForKeys()); } } } //validate callback/error routine if (callStatement.getCallSynchronizationValues().getReturnTo() != null) { problemRequestor.acceptProblem(callStatement.getCallSynchronizationValues().getReturnTo(), IBMiResourceKeys.IBMIPROGRAM_CALLBACK_NOT_SUPPORTED, IMarker.SEVERITY_ERROR, new String[] {}, IBMiResourceKeys.getResourceBundleForKeys()); } if (callStatement.getCallSynchronizationValues().getOnException() != null) { problemRequestor.acceptProblem(callStatement.getCallSynchronizationValues().getOnException(), IBMiResourceKeys.IBMIPROGRAM_CALLBACK_NOT_SUPPORTED, IMarker.SEVERITY_ERROR, new String[] {}, IBMiResourceKeys.getResourceBundleForKeys()); } } return false; } }