/*******************************************************************************
* Copyright (c) 2000, 2012 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.corext.refactoring.code.flow;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.Assert;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.IVariable;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCatchHandler;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTryBlockStatement;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
public class FlowContext extends LocalVariableIndex {
private static class ComputeMode {
}
public static final ComputeMode MERGE = new ComputeMode();
public static final ComputeMode ARGUMENTS = new ComputeMode();
public static final ComputeMode RETURN_VALUES = new ComputeMode();
private boolean fConsiderAccessMode;
private boolean fLoopReentranceMode;
private ComputeMode fComputeMode;
private IVariable[] fLocals;
private final List<ICPPASTCatchHandler[]> fExceptionStack;
public FlowContext(IASTFunctionDefinition functionDefinition) {
super(functionDefinition);
fExceptionStack= new ArrayList<ICPPASTCatchHandler[]>(3);
}
public void setConsiderAccessMode(boolean b) {
fConsiderAccessMode= b;
}
public void setComputeMode(ComputeMode mode) {
fComputeMode= mode;
}
void setLoopReentranceMode(boolean b) {
fLoopReentranceMode= b;
}
int getArrayLength() {
return getNumLocalVariables();
}
boolean considerAccessMode() {
return fConsiderAccessMode;
}
boolean isLoopReentranceMode() {
return fLoopReentranceMode;
}
boolean computeMerge() {
return fComputeMode == MERGE;
}
boolean computeArguments() {
return fComputeMode == ARGUMENTS;
}
boolean computeReturnValues() {
return fComputeMode == RETURN_VALUES;
}
public IVariable getLocalFromIndex(int index) {
if (fLocals == null || index > fLocals.length)
return null;
return fLocals[index];
}
/**
* Adds a local variable to the context.
* @param localVariable the local variable to manage.
*/
void manageLocal(IVariable localVariable) {
int index = getIndexFromLocal(localVariable);
if (index >= 0) {
if (fLocals == null)
fLocals= new IVariable[getNumLocalVariables()];
fLocals[index] = localVariable;
}
}
//---- Exception handling --------------------------------------------------------
void pushExceptions(ICPPASTTryBlockStatement node) {
ICPPASTCatchHandler[] catchHandlers = node.getCatchHandlers();
fExceptionStack.add(catchHandlers);
}
void popExceptions() {
Assert.isTrue(fExceptionStack.size() > 0);
fExceptionStack.remove(fExceptionStack.size() - 1);
}
boolean isExceptionCaught(IType exceptionType) {
for (ICPPASTCatchHandler[] catchHandlers : fExceptionStack) {
for (ICPPASTCatchHandler catchHandler : catchHandlers) {
if (catchHandler.isCatchAll())
return true;
IASTDeclaration caughtException= catchHandler.getDeclaration();
if (caughtException instanceof IASTSimpleDeclaration) {
IASTDeclarator[] declarators = ((IASTSimpleDeclaration) caughtException).getDeclarators();
IType caughtType = CPPVisitor.createType(declarators[0]);
while (caughtType != null) {
// 15.3
if (caughtType.isSameType(exceptionType))
return true;
// TODO(sprigogin): Implement the rest of 15.3 matching logic.
}
}
}
}
return false;
}
}