| /******************************************************************************* |
| * Copyright (c) 2009, 2018 R.Dvorak and others. |
| * 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 |
| * http://www.eclipse.org/legal/epl-v20.html |
| * |
| * Contributors: |
| * Radek Dvorak - initial API and implementation |
| *******************************************************************************/ |
| /** |
| * |
| */ |
| package org.eclipse.m2m.qvt.oml.debug.core.vm; |
| |
| import java.util.HashSet; |
| import java.util.Set; |
| |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.emf.common.util.URI; |
| import org.eclipse.emf.ecore.EClassifier; |
| import org.eclipse.m2m.internal.qvt.oml.ast.binding.ASTBindingHelper; |
| import org.eclipse.m2m.internal.qvt.oml.common.util.LineNumberProvider; |
| import org.eclipse.m2m.internal.qvt.oml.expressions.Module; |
| import org.eclipse.m2m.qvt.oml.debug.core.QVTODebugCore; |
| import org.eclipse.m2m.qvt.oml.ecore.ImperativeOCL.BlockExp; |
| import org.eclipse.ocl.expressions.LoopExp; |
| import org.eclipse.ocl.expressions.OCLExpression; |
| import org.eclipse.ocl.utilities.ASTNode; |
| |
| class IterateBreakpointHelper { |
| |
| private final Set<VMBreakpoint> fBreakpoints; |
| private final VMBreakpointManager fBPM; |
| |
| IterateBreakpointHelper(VMBreakpointManager breakpointManager) { |
| fBPM = breakpointManager; |
| fBreakpoints = new HashSet<VMBreakpoint>(); |
| } |
| |
| VMBreakpoint stepIterateElement(LoopExp<EClassifier, ?> element, UnitLocation currentLocation) { |
| Module currentModule = currentLocation.getModule(); |
| |
| LineNumberProvider lineNumProvider = getLineNumberProvider(currentModule); |
| if(lineNumProvider == null) { |
| return null; |
| } |
| |
| OCLExpression<EClassifier> body = element.getBody(); |
| if (body == null) { |
| return null; |
| } |
| |
| int bodyLine = lineNumProvider.getLineNumber(body.getStartPosition()); |
| int elementLine = lineNumProvider.getLineNumber(element.getStartPosition()); |
| |
| ASTNode iterateBreakpointedElement = body; |
| |
| // ensure we can suspend after stepping within iterator if it's body |
| // is spread across multiple lines |
| if (body instanceof BlockExp) { |
| BlockExp blockExp = (BlockExp) body; |
| int bodyEndLine = lineNumProvider.getLineNumber(blockExp.getEndPosition()); |
| if ((bodyEndLine == elementLine) || blockExp.getBody().isEmpty()) { |
| return null; |
| } |
| |
| iterateBreakpointedElement = blockExp.getBody().get(0); |
| } else if (bodyLine == elementLine) { |
| return null; |
| } |
| |
| |
| URI unitURI = currentLocation.getURI(); |
| VMBreakpoint breakpoint = createIterateBreakpoint(unitURI, |
| iterateBreakpointedElement, elementLine); |
| |
| return breakpoint; |
| } |
| |
| boolean isIterateBreakpoint(VMBreakpoint breakpoint) { |
| return fBreakpoints.contains(breakpoint); |
| } |
| |
| VMBreakpoint createIterateBreakpoint(URI unitURI, ASTNode breakpointedElement, int line) { |
| VMBreakpoint breakpoint = null; |
| try { |
| breakpoint = fBPM.createVMPrivateBreakpoint(unitURI, breakpointedElement, line, false); |
| fBreakpoints.add(breakpoint); |
| } catch (CoreException e) { |
| QVTODebugCore.log(e.getStatus()); |
| } |
| return breakpoint; |
| } |
| |
| void removeIterateBreakpoint(VMBreakpoint breakpoint) { |
| fBPM.removeBreakpoint(breakpoint); |
| fBreakpoints.remove(breakpoint); |
| } |
| |
| void removeAllIterateBreakpoints() { |
| for (VMBreakpoint brk : fBreakpoints) { |
| fBPM.removeBreakpoint(brk); |
| } |
| |
| fBreakpoints.clear(); |
| } |
| |
| private LineNumberProvider getLineNumberProvider(Module module) { |
| return ASTBindingHelper.getModuleSourceBinding(module).getLineNumberProvider(); |
| } |
| } |