| /***************************************************************************** |
| * 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.cdteditor.sync; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression; |
| import org.eclipse.cdt.core.dom.ast.IASTExpression; |
| import org.eclipse.cdt.core.dom.ast.IASTExpressionList; |
| import org.eclipse.cdt.core.dom.ast.IASTFieldReference; |
| import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; |
| import org.eclipse.cdt.core.dom.ast.IASTName; |
| import org.eclipse.cdt.core.dom.ast.IASTNode; |
| import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; |
| import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression; |
| import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition; |
| import org.eclipse.cdt.core.model.CoreModel; |
| import org.eclipse.cdt.core.model.ITranslationUnit; |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.IWorkspace; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.papyrus.commands.Activator; |
| import org.eclipse.papyrus.robotics.ros2.cdteditor.sync.PortInfo.ProviderKind; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.swt.widgets.FileDialog; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.uml2.uml.Classifier; |
| |
| public class SyncPortsFromSource { |
| |
| 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 EXTERNAL_FILES = "External Files"; //$NON-NLS-1$ |
| |
| public static void updatePorts(Classifier cl, IASTNode node) { |
| List<PortInfo> portInfoList = new ArrayList<PortInfo>(); |
| scanFunctions(node, portInfoList); |
| for (PortInfo pi : portInfoList) { |
| System.err.println(pi.dtQName); |
| // NamedElement namedElemParamType = ElementUtils.getQualifiedElementFromRS(element, expr2); |
| } |
| } |
| |
| 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; |
| } |
| if (fctName.equals(CREATE_SERVICE)) { |
| return ProviderKind.SERVER; |
| } |
| if (fctName.equals(CREATE_SUBSCRIPTION)) { |
| return ProviderKind.SUBSCRIBER; |
| } |
| if (fctName.equals(CREATE_PUBLISHER)) { |
| return ProviderKind.PUBLISHER; |
| } |
| return null; |
| } |
| |
| public static PortInfo obtainCallDetails(ProviderKind pk, IASTExpression expr1, IASTExpression expr2) { |
| IASTExpression expr2b = ((IASTBinaryExpression) expr1).getOperand2(); |
| IASTExpression topicExpr = null; |
| if (expr2 instanceof IASTUnaryExpression) { |
| IASTExpression arguments = ((IASTUnaryExpression) expr2).getOperand(); |
| if (arguments instanceof IASTExpressionList) { |
| topicExpr = ((IASTExpressionList) arguments).getExpressions()[0]; |
| } else { |
| topicExpr = arguments; |
| } |
| } |
| String topicName = topicExpr.toString(); |
| // remove quotes |
| if (topicName.startsWith("\"") && topicName.length()>=2) { //$NON-NLS-1$ |
| topicName = topicName.substring(1, topicName.length()-1); |
| } |
| PortInfo portInfo = new PortInfo(); |
| portInfo.pk = pk; |
| portInfo.dtQName = getASTName(expr2b); |
| portInfo.topic = topicName; |
| return portInfo; |
| } |
| |
| public static void scanBody(IASTNode node, List<PortInfo> portList) { |
| if (node instanceof IASTBinaryExpression) { |
| IASTBinaryExpression expr = (IASTBinaryExpression) node; |
| IASTExpression expr1 = expr.getOperand1(); |
| IASTExpression expr2 = expr.getOperand2(); |
| if (expr1 instanceof IASTBinaryExpression) { |
| IASTExpression expr1b = ((IASTBinaryExpression) expr1).getOperand1(); |
| String fieldName = getASTName(expr1b); |
| |
| if (fieldName != null) { |
| ProviderKind pk = getProviderFromCall(fieldName); |
| if (pk != null) { |
| PortInfo portInfo = obtainCallDetails(pk, expr1, expr2); |
| if (portInfo != null) { |
| portList.add(portInfo); |
| } |
| } |
| } |
| } |
| } |
| for (IASTNode child : node.getChildren()) { |
| // recurse into all children |
| scanBody(child, portList); |
| } |
| } |
| |
| public static void tst() { |
| IWorkspace ws = ResourcesPlugin.getWorkspace(); |
| IProject project = ws.getRoot().getProject(EXTERNAL_FILES); |
| |
| try { |
| if (!project.exists()) |
| project.create(null); |
| if (!project.isOpen()) |
| project.open(null); |
| Shell shell = Display.getDefault().getActiveShell(); |
| String name = (1 == 0) ? "/local/home/ansgar/prog/ros2/demos/demo_nodes_cpp/src/services/add_two_ints_client.cpp" : new FileDialog(shell, SWT.OPEN).open(); |
| if (name == null) |
| return; |
| IPath location = new Path(name); |
| IFile srcFile = project.getFile(location.lastSegment()); |
| boolean exists = srcFile.exists(); |
| if (exists) { |
| srcFile.delete(false, null); |
| } |
| srcFile.createLink(location, IResource.NONE, null); |
| |
| |
| ITranslationUnit itu = (ITranslationUnit) CoreModel.getDefault().create(srcFile); |
| |
| IASTTranslationUnit ast = itu.getAST(); |
| scanFunctions(ast, new ArrayList<PortInfo>()); |
| |
| } catch (CoreException e) { |
| Activator.log.error(e); |
| } |
| } |
| } |