| /***************************************************************************** |
| * Copyright (c) 2020 CEA LIST. |
| * |
| * |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * Contributors: |
| * Ansgar Radermacher ansgar.radermacher@cea.fr |
| * |
| *****************************************************************************/ |
| |
| package org.eclipse.papyrus.robotics.ros2.reverse.fromfile; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.eclipse.cdt.core.dom.ast.IASTExpression; |
| import org.eclipse.cdt.core.dom.ast.IASTFieldReference; |
| import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression; |
| import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; |
| import org.eclipse.cdt.core.dom.ast.IASTIdExpression; |
| import org.eclipse.cdt.core.dom.ast.IASTName; |
| import org.eclipse.cdt.core.dom.ast.IASTNode; |
| import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition; |
| import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId; |
| import org.eclipse.papyrus.robotics.ros2.reverse.PortInfo; |
| import org.eclipse.papyrus.robotics.ros2.reverse.PortInfo.ProviderKind; |
| import org.eclipse.uml2.uml.Class; |
| import org.eclipse.uml2.uml.Port; |
| |
| public class ReversePortsFromSource { |
| |
| private static final String CREATE_PUBLISHER = "create_publisher"; //$NON-NLS-1$ |
| private static final String CREATE_SUBSCRIPTION = "create_subscription"; //$NON-NLS-1$ |
| private static final String CREATE_SERVICE = "create_service"; //$NON-NLS-1$ |
| private static final String CREATE_CLIENT = "create_client"; //$NON-NLS-1$ |
| private static final String CREATE_ACTION_SRV = "rclcpp_action::create_server"; //$NON-NLS-1$ |
| private static final String CREATE_ACTION_CLI = "rclcpp_action::create_client"; //$NON-NLS-1$ |
| |
| public static void updatePorts(Class clazz, IASTNode node) { |
| List<PortInfo> portInfoList = new ArrayList<PortInfo>(); |
| scanFunctions(node, portInfoList); |
| |
| for (PortInfo pi : portInfoList) { |
| Port port = clazz.createOwnedPort(pi.dtQName, null); |
| System.err.println(pi.dtQName); |
| } |
| } |
| |
| public static void scanFunctions(IASTNode node, List<PortInfo> portInfoList) { |
| |
| for (IASTNode child : node.getChildren()) { |
| if (child instanceof IASTFunctionDefinition) { |
| IASTFunctionDefinition definition = (IASTFunctionDefinition) child; |
| scanBody(definition.getBody(), portInfoList); |
| } |
| if (child instanceof ICPPASTNamespaceDefinition) { |
| // recurse into namespaces |
| scanFunctions(child, portInfoList); |
| } |
| } |
| } |
| public static String getASTName(IASTExpression expr) { |
| if (expr instanceof IASTFieldReference) { |
| IASTName fieldName = ((IASTFieldReference) expr).getFieldName(); |
| if (fieldName != null) { |
| return fieldName.toString(); |
| } |
| return ""; //$NON-NLS-1$ |
| } else { |
| return expr.toString(); |
| } |
| } |
| |
| public static ProviderKind getProviderFromCall(String fctName) { |
| if (fctName.equals(CREATE_CLIENT)) { |
| return ProviderKind.CLIENT; |
| } |
| else if (fctName.equals(CREATE_SERVICE)) { |
| return ProviderKind.SERVER; |
| } |
| else if (fctName.equals(CREATE_SUBSCRIPTION)) { |
| return ProviderKind.SUBSCRIBER; |
| } |
| else if (fctName.equals(CREATE_PUBLISHER)) { |
| return ProviderKind.PUBLISHER; |
| } |
| else if (fctName.equals(CREATE_ACTION_SRV)) { |
| return ProviderKind.ACTION_SRV; |
| } |
| else if (fctName.equals(CREATE_ACTION_CLI)) { |
| return ProviderKind.ACTION_CLI; |
| } |
| return null; |
| } |
| |
| /** |
| * This function obtains the PortInfo from AST data |
| * @param pk |
| * @param fCallExpr the function call expression |
| * @param templateId the template-id |
| */ |
| public static PortInfo obtainCallDetails(ProviderKind pk, IASTFunctionCallExpression fCallExpr, ICPPASTTemplateId templateId) { |
| String topicName = fCallExpr.getArguments()[0].toString(); |
| PortInfo portInfo = new PortInfo(); |
| portInfo.pk = pk; |
| portInfo.dtQName = templateId.getTemplateArguments()[0].toString(); |
| portInfo.topic = topicName; |
| return portInfo; |
| } |
| |
| public static void scanBody(IASTNode node, List<PortInfo> portList) { |
| if (node instanceof IASTFunctionCallExpression) { |
| IASTFunctionCallExpression fCallExpr = (IASTFunctionCallExpression) node; |
| IASTExpression nameExpr = fCallExpr.getFunctionNameExpression(); |
| if (nameExpr instanceof IASTIdExpression) { |
| IASTIdExpression nameId = (IASTIdExpression) nameExpr; |
| IASTName astName = nameId.getName(); |
| if (astName instanceof ICPPASTTemplateId) { |
| // all ROS2 "ports" are created by binding one or more concrete message types |
| // e.g. create_publisher<geometry_msgs::msg::PoseArray>(...) |
| ICPPASTTemplateId templateId = (ICPPASTTemplateId) astName; |
| String fctName = templateId.getTemplateName().toString(); |
| ProviderKind pk = getProviderFromCall(fctName); |
| if (pk != null) { |
| PortInfo portInfo = obtainCallDetails(pk, fCallExpr, templateId); |
| if (portInfo != null) { |
| portList.add(portInfo); |
| } |
| } |
| } |
| } |
| } |
| for (IASTNode child : node.getChildren()) { |
| // recurse into all children |
| scanBody(child, portList); |
| } |
| } |
| } |