blob: 21c42864cfcdfe13ea0f45132734461ddfae8aa2 [file] [log] [blame]
/*****************************************************************************
* 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);
}
}
}