blob: 9b1b5824af447eae1d0ebb078ba6acab0abd8108 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2014, 2018 Willink Transformations 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:
* R.Dvorak and others - QVTo debugger framework
* E.D.Willink - revised API for OCL debugger framework
*******************************************************************************/
package org.eclipse.ocl.examples.debug.vm.utils;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.ocl.examples.debug.vm.evaluator.VMEvaluationEnvironment;
import org.eclipse.ocl.pivot.NamedElement;
/**
* Helps to build VM stack trace from a given state of OCL code execution.
*/
public class VMStackTraceBuilder {
private static final @NonNull String UNKNOWN_NAME = "<Unknown>"; //$NON-NLS-1$
private static final int UNKNOWN_LINE_NUM = -1;
private @NonNull VMEvaluationEnvironment fEvalEnv;
/**
* Constructs stack trace builder for the given evaluation environment.
*
* @param evalEnv
* the evaluation environment representing the top stack trace
*/
public VMStackTraceBuilder(@NonNull VMEvaluationEnvironment evalEnv) {
fEvalEnv = evalEnv;
}
/**
* Builds the stack trace corresponding to evaluation environments hierarchy
* associated with this builder.
*
* @return list of VM stack elements
*/
public List<VMStackTraceElement> buildStackTrace() {
LinkedList<VMStackTraceElement> elements = new LinkedList<VMStackTraceElement>();
for (VMEvaluationEnvironment nextEnv = fEvalEnv; nextEnv != null; nextEnv = nextEnv.getVMParentEvaluationEnvironment()) {
// skip all the root execution environments as they
// are not bound to any module code locations
VMEvaluationEnvironment parent = nextEnv.getVMParentEvaluationEnvironment();
if (parent != null) {
// skip all stack frames not running in a module,
// IOW possible non VM transformation clients
if (parent.getDebuggableElement() != null) {
elements.addLast(createStackElement(nextEnv));
}
}
}
@SuppressWarnings("unused")VMEvaluationEnvironment rootEnv = fEvalEnv.getVMRootEvaluationEnvironment();
// IVMEvaluationEnvironment<?> aggregatingEnv = EvaluationUtil.getAggregatingContext(rootEnv);
// if(aggregatingEnv != null) {
// List<VMStackTraceElement> aggregatedStackTrace = new VMStackTraceBuilder(aggregatingEnv).buildStackTrace();
// List<VMStackTraceElement> result = new ArrayList<VMStackTraceElement>(elements.size() + aggregatedStackTrace.size());
// result.addAll(elements);
// result.addAll(aggregatedStackTrace);
// return result;
// }
return Collections.unmodifiableList(elements);
}
private @NonNull VMStackTraceElement createStackElement(@NonNull VMEvaluationEnvironment env) {
String unitName = null;
String moduleName = UNKNOWN_NAME;
String operName = UNKNOWN_NAME;
int lineNumber = UNKNOWN_LINE_NUM;
// Type module = null;
NamedElement operation = env.getOperation();
// int resultOffset = getCurrentASTOffset(env);
NamedElement currentExpressionInOCL = env.getDebuggableElement();
// if (currentTransformation == null) {
// throw new IllegalArgumentException("Currently executed model is not set in environment"); //$NON-NLS-1$
// }
moduleName = currentExpressionInOCL.getName();
/* if(operation == null) {
// we must be executing a module instance initialization - synthetic constructor
operName = moduleName;
if (env.getCurrentIP() == module || resultOffset < -1) {
ASTSyntheticNode astNode = ASTSyntheticNodeAccess.getASTNode(module);
if(astNode != null) {
resultOffset = astNode.getStartPosition();
}
}
} else { */
operName = operation.getName();
// EClassifier contextType = QvtOperationalParserUtil.getContextualType(operation);
// if(contextType != null) {
// operName = contextType.getName() + "::" + operName;
// }
// }
/* IModuleSourceInfo sourceInfo = module != null ? ASTBindingHelper.getModuleSourceBinding(module) : null;
if (sourceInfo != null) {
URI uri = sourceInfo.getSourceURI();
unitName = uri.lastSegment();
if(resultOffset >= 0) {
lineNumber = sourceInfo.getLineNumberProvider().getLineNumber(resultOffset);
}
} */
return new VMStackTraceElement(moduleName, operName, unitName, lineNumber);
}
/* private static int getCurrentASTOffset(@NonNull IVMEvaluationEnvironment<?> evalEnv) {
// TODO - for cases that AST does not fill all offset
// traverse up to the enclosing operation scope, taking the closest
// offset which has been initialized
Element currentIPObject = evalEnv.getCurrentIP();
if (currentIPObject instanceof Element) {
Element astNode = (Element) currentIPObject;
if (ASTBindingHelper.getStartPosition(astNode) < 0 && astNode instanceof VariableExp) {
// Remark: special processing for implicit source variables represented as
// synthetic variable expression in AST. These do not have any CST representation
// but are rather synthetic nodes => point to the call AST
EObject astContainer = astNode.eContainer();
if (astContainer instanceof FeatureCallExp) {
astNode = (FeatureCallExp) astContainer;
}
}
return ASTBindingHelper.getStartPosition(astNode);
}
ASTSyntheticNode astNode = ASTSyntheticNodeAccess.getASTNode(currentIPObject);
if(astNode != null) {
return astNode.getStartPosition();
}
return -1;
} */
}