mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-09-10 03:53:21 +02:00
- added control flow graph - initial commit
This commit is contained in:
parent
6b922df8c2
commit
62c9bdecc9
31 changed files with 1360 additions and 343 deletions
|
@ -11,6 +11,7 @@ Require-Bundle: org.eclipse.core.runtime,
|
||||||
Bundle-ActivationPolicy: lazy
|
Bundle-ActivationPolicy: lazy
|
||||||
Export-Package: org.eclipse.cdt.codan.core.cxx,
|
Export-Package: org.eclipse.cdt.codan.core.cxx,
|
||||||
org.eclipse.cdt.codan.core.cxx.internal.model;x-friends:="org.eclipse.cdt.codan.checkers.ui,org.eclipse.cdt.codan.ui,org.eclipse.cdt.codan.ui.cxx",
|
org.eclipse.cdt.codan.core.cxx.internal.model;x-friends:="org.eclipse.cdt.codan.checkers.ui,org.eclipse.cdt.codan.ui,org.eclipse.cdt.codan.ui.cxx",
|
||||||
|
org.eclipse.cdt.codan.core.cxx.internal.model.cfg;x-friends:="org.eclipse.cdt.codan.core.test",
|
||||||
org.eclipse.cdt.codan.core.cxx.model
|
org.eclipse.cdt.codan.core.cxx.model
|
||||||
Bundle-RequiredExecutionEnvironment: J2SE-1.5
|
Bundle-RequiredExecutionEnvironment: J2SE-1.5
|
||||||
Bundle-Vendor: Eclipse CDT
|
Bundle-Vendor: Eclipse CDT
|
||||||
|
|
|
@ -0,0 +1,106 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2009 Alena Laskavaia
|
||||||
|
* 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:
|
||||||
|
* Alena Laskavaia - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.codan.core.cxx.internal.model.cfg;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import org.eclipse.cdt.codan.internal.core.cfg.AbstractBasicBlock;
|
||||||
|
import org.eclipse.cdt.codan.internal.core.cfg.ConnectorNode;
|
||||||
|
import org.eclipse.cdt.codan.internal.core.cfg.DecisionNode;
|
||||||
|
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock;
|
||||||
|
import org.eclipse.cdt.codan.provisional.core.model.cfg.IExitNode;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTDeclarationStatement;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTExpressionStatement;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTIfStatement;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTReturnStatement;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTStatement;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: add description
|
||||||
|
*/
|
||||||
|
public class ControlFlowGraphBuilder {
|
||||||
|
CxxStartNode start;
|
||||||
|
Collection<IExitNode> exits;
|
||||||
|
Collection<IBasicBlock> dead;
|
||||||
|
CxxExitNode returnExit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param def
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public CxxControlFlowGraph build(IASTFunctionDefinition def) {
|
||||||
|
IASTStatement body = def.getBody();
|
||||||
|
start = new CxxStartNode(null);
|
||||||
|
exits = new ArrayList<IExitNode>();
|
||||||
|
dead = new ArrayList<IBasicBlock>();
|
||||||
|
IBasicBlock last = createSubGraph(start, body);
|
||||||
|
if (!(last instanceof IExitNode)) {
|
||||||
|
returnExit = new CxxExitNode(last, start, null);
|
||||||
|
addOutgoing(last, returnExit);
|
||||||
|
}
|
||||||
|
return new CxxControlFlowGraph(start, exits);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param start2
|
||||||
|
* @param body
|
||||||
|
*/
|
||||||
|
private IBasicBlock createSubGraph(IBasicBlock prev, IASTNode body) {
|
||||||
|
if (body instanceof IASTCompoundStatement) {
|
||||||
|
IASTCompoundStatement comp = (IASTCompoundStatement) body;
|
||||||
|
IASTNode[] children = comp.getChildren();
|
||||||
|
for (int i = 0; i < children.length; i++) {
|
||||||
|
IASTNode node = children[i];
|
||||||
|
IBasicBlock last = createSubGraph(prev, node);
|
||||||
|
prev = last;
|
||||||
|
}
|
||||||
|
} else if (body instanceof IASTExpressionStatement
|
||||||
|
|| body instanceof IASTDeclarationStatement) {
|
||||||
|
CxxPlainNode node = new CxxPlainNode(prev, body);
|
||||||
|
addOutgoing(prev, node);
|
||||||
|
return node;
|
||||||
|
} else if (body instanceof IASTIfStatement) {
|
||||||
|
DecisionNode node = new DecisionNode(prev);
|
||||||
|
addOutgoing(prev, node);
|
||||||
|
ConnectorNode conn = new ConnectorNode();
|
||||||
|
node.setConnectorNode(conn);
|
||||||
|
IBasicBlock els = createSubGraph(node, ((IASTIfStatement) body)
|
||||||
|
.getElseClause());
|
||||||
|
conn.addIncoming(els);
|
||||||
|
addOutgoing(els, conn);
|
||||||
|
IBasicBlock then = createSubGraph(node, ((IASTIfStatement) body)
|
||||||
|
.getThenClause());
|
||||||
|
conn.addIncoming(then);
|
||||||
|
addOutgoing(then, conn);
|
||||||
|
return conn;
|
||||||
|
} else if (body instanceof IASTReturnStatement) {
|
||||||
|
CxxExitNode node = new CxxExitNode(prev, start, body);
|
||||||
|
addOutgoing(prev, node);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param prev
|
||||||
|
* @param node
|
||||||
|
*/
|
||||||
|
private void addOutgoing(IBasicBlock prev, IBasicBlock node) {
|
||||||
|
if (prev instanceof IExitNode) {
|
||||||
|
dead.add(node);
|
||||||
|
} else if (prev instanceof AbstractBasicBlock) {
|
||||||
|
((AbstractBasicBlock) prev).addOutgoing(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2009 Alena Laskavaia
|
||||||
|
* 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:
|
||||||
|
* Alena Laskavaia - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.codan.core.cxx.internal.model.cfg;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.codan.internal.core.cfg.ControlFlowGraph;
|
||||||
|
import org.eclipse.cdt.codan.provisional.core.model.cfg.IExitNode;
|
||||||
|
import org.eclipse.cdt.codan.provisional.core.model.cfg.IStartNode;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: add description
|
||||||
|
*/
|
||||||
|
public class CxxControlFlowGraph extends ControlFlowGraph {
|
||||||
|
/**
|
||||||
|
* @param start
|
||||||
|
* @param exitNodes
|
||||||
|
*/
|
||||||
|
public CxxControlFlowGraph(IStartNode start, Collection<IExitNode> exitNodes) {
|
||||||
|
super(start, exitNodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CxxControlFlowGraph build(IASTFunctionDefinition def) {
|
||||||
|
return new ControlFlowGraphBuilder().build(def);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see java.lang.Object#toString()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return super.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2009 Alena Laskavaia
|
||||||
|
* 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:
|
||||||
|
* Alena Laskavaia - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.codan.core.cxx.internal.model.cfg;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.codan.internal.core.cfg.ExitNode;
|
||||||
|
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock;
|
||||||
|
import org.eclipse.cdt.codan.provisional.core.model.cfg.IExitNode;
|
||||||
|
import org.eclipse.cdt.codan.provisional.core.model.cfg.IStartNode;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: add description
|
||||||
|
*/
|
||||||
|
public class CxxExitNode extends ExitNode implements IExitNode {
|
||||||
|
/**
|
||||||
|
* @param prev
|
||||||
|
* @param start
|
||||||
|
*/
|
||||||
|
public CxxExitNode(IBasicBlock prev, IStartNode start, IASTNode node) {
|
||||||
|
super(prev, start);
|
||||||
|
setNode(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see java.lang.Object#toString()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
if (getNode()!=null)
|
||||||
|
return getNode().getRawSignature();
|
||||||
|
return "return; // fake";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param node
|
||||||
|
* the node to set
|
||||||
|
*/
|
||||||
|
public void setNode(IASTNode node) {
|
||||||
|
setData(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the node
|
||||||
|
*/
|
||||||
|
public IASTNode getNode() {
|
||||||
|
return (IASTNode) getData();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String toStringData() {
|
||||||
|
if (getNode() == null)
|
||||||
|
return "";
|
||||||
|
return getNode().getRawSignature();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2009 Alena Laskavaia
|
||||||
|
* 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:
|
||||||
|
* Alena Laskavaia - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.codan.core.cxx.internal.model.cfg;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.codan.internal.core.cfg.PlainNode;
|
||||||
|
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: add description
|
||||||
|
*/
|
||||||
|
public class CxxPlainNode extends PlainNode {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param prev
|
||||||
|
* @param body
|
||||||
|
*/
|
||||||
|
public CxxPlainNode(IBasicBlock prev, IASTNode body) {
|
||||||
|
super(prev, null);
|
||||||
|
this.setNode(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see java.lang.Object#toString()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getNode().getRawSignature();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param node the node to set
|
||||||
|
*/
|
||||||
|
public void setNode(IASTNode node) {
|
||||||
|
setData(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the node
|
||||||
|
*/
|
||||||
|
public IASTNode getNode() {
|
||||||
|
return (IASTNode) getData();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String toStringData() {
|
||||||
|
if (getNode() == null)
|
||||||
|
return "";
|
||||||
|
return getNode().getRawSignature();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2009 Alena Laskavaia
|
||||||
|
* 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:
|
||||||
|
* Alena Laskavaia - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.cdt.codan.core.cxx.internal.model.cfg;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.codan.internal.core.cfg.StartNode;
|
||||||
|
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: add description
|
||||||
|
*/
|
||||||
|
public class CxxStartNode extends StartNode {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param next
|
||||||
|
*/
|
||||||
|
public CxxStartNode(IBasicBlock next) {
|
||||||
|
super(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see java.lang.Object#toString()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "start";
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,7 +10,8 @@ Require-Bundle: org.eclipse.core.runtime,
|
||||||
org.eclipse.core.resources;bundle-version="3.5.0",
|
org.eclipse.core.resources;bundle-version="3.5.0",
|
||||||
org.eclipse.cdt.core.tests,
|
org.eclipse.cdt.core.tests,
|
||||||
org.junit;bundle-version="3.8.2",
|
org.junit;bundle-version="3.8.2",
|
||||||
org.eclipse.cdt.codan.core;bundle-version="1.0.0"
|
org.eclipse.cdt.codan.core;bundle-version="1.0.0",
|
||||||
|
org.eclipse.cdt.codan.core.cxx;bundle-version="1.0.0"
|
||||||
Bundle-ActivationPolicy: lazy
|
Bundle-ActivationPolicy: lazy
|
||||||
Bundle-RequiredExecutionEnvironment: J2SE-1.5
|
Bundle-RequiredExecutionEnvironment: J2SE-1.5
|
||||||
Bundle-Vendor: Eclipse CDT
|
Bundle-Vendor: Eclipse CDT
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2009 Alena Laskavaia
|
||||||
|
* 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:
|
||||||
|
* Alena Laskavaia - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.codan.core.cfg;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.codan.core.cxx.internal.model.cfg.ControlFlowGraphBuilder;
|
||||||
|
import org.eclipse.cdt.codan.core.test.CodanTestCase;
|
||||||
|
import org.eclipse.cdt.codan.internal.core.cfg.ControlFlowGraph;
|
||||||
|
import org.eclipse.cdt.core.CCorePlugin;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.c.CASTVisitor;
|
||||||
|
import org.eclipse.cdt.core.index.IIndex;
|
||||||
|
import org.eclipse.cdt.core.model.CoreModel;
|
||||||
|
import org.eclipse.cdt.core.model.ICElement;
|
||||||
|
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||||
|
import org.eclipse.core.resources.IFile;
|
||||||
|
import org.eclipse.core.resources.IResource;
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.core.runtime.Path;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: add description
|
||||||
|
*/
|
||||||
|
public class ControlFlowGraphTest extends CodanTestCase {
|
||||||
|
ControlFlowGraph graph;
|
||||||
|
void processFile(IFile file) throws CoreException, InterruptedException {
|
||||||
|
// create translation unit and access index
|
||||||
|
ICElement model = CoreModel.getDefault().create(file);
|
||||||
|
if (!(model instanceof ITranslationUnit))
|
||||||
|
return; // not a C/C++ file
|
||||||
|
ITranslationUnit tu = (ITranslationUnit) model;
|
||||||
|
IIndex index = CCorePlugin.getIndexManager().getIndex(tu.getCProject());
|
||||||
|
// lock the index for read access
|
||||||
|
index.acquireReadLock();
|
||||||
|
try {
|
||||||
|
// create index based ast
|
||||||
|
IASTTranslationUnit ast = tu.getAST(index,
|
||||||
|
ITranslationUnit.AST_SKIP_INDEXED_HEADERS);
|
||||||
|
// traverse the ast using the visitor pattern.
|
||||||
|
processAst(ast);
|
||||||
|
} finally {
|
||||||
|
index.releaseReadLock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ast
|
||||||
|
*/
|
||||||
|
private void processAst(IASTTranslationUnit ast) {
|
||||||
|
CASTVisitor visitor = new CASTVisitor() {
|
||||||
|
{
|
||||||
|
shouldVisitDeclarations = true;
|
||||||
|
}
|
||||||
|
public int visit(IASTDeclaration decl) {
|
||||||
|
if (decl instanceof IASTFunctionDefinition) {
|
||||||
|
graph = new ControlFlowGraphBuilder().build((IASTFunctionDefinition) decl);
|
||||||
|
return PROCESS_ABORT;
|
||||||
|
}
|
||||||
|
return PROCESS_CONTINUE;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ast.accept(visitor);
|
||||||
|
|
||||||
|
}
|
||||||
|
void buildCfg() {
|
||||||
|
try {
|
||||||
|
Path path = new Path(currentFile.toString());
|
||||||
|
IResource el = cproject.getProject().findMember(currentFile.getName());
|
||||||
|
processFile((IFile) el);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
fail(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-
|
||||||
|
<code file="test1.c">
|
||||||
|
main() {
|
||||||
|
int a;
|
||||||
|
a=1;
|
||||||
|
}
|
||||||
|
</code>
|
||||||
|
*/
|
||||||
|
public void test1() {
|
||||||
|
load("test1.c");
|
||||||
|
buildCfg();
|
||||||
|
graph.print(graph.getStartNode());
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,208 +10,20 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.codan.core.test;
|
package org.eclipse.cdt.codan.core.test;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.io.PrintStream;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import org.eclipse.cdt.codan.core.CodanRuntime;
|
import org.eclipse.cdt.codan.core.CodanRuntime;
|
||||||
import org.eclipse.cdt.codan.core.model.IProblemReporter;
|
import org.eclipse.cdt.codan.core.model.IProblemReporter;
|
||||||
import org.eclipse.cdt.core.CCorePlugin;
|
|
||||||
import org.eclipse.cdt.core.dom.IPDOMManager;
|
|
||||||
import org.eclipse.cdt.core.model.ICProject;
|
|
||||||
import org.eclipse.cdt.core.testplugin.CProjectHelper;
|
|
||||||
import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
|
|
||||||
import org.eclipse.core.resources.IMarker;
|
import org.eclipse.core.resources.IMarker;
|
||||||
import org.eclipse.core.resources.IProject;
|
|
||||||
import org.eclipse.core.resources.IResource;
|
|
||||||
import org.eclipse.core.resources.IWorkspace;
|
|
||||||
import org.eclipse.core.resources.IWorkspaceRunnable;
|
|
||||||
import org.eclipse.core.resources.ResourcesPlugin;
|
|
||||||
import org.eclipse.core.runtime.CoreException;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
import org.eclipse.core.runtime.IProgressMonitor;
|
|
||||||
import org.eclipse.core.runtime.NullProgressMonitor;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Alena
|
* @author Alena
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class CheckerTestCase extends BaseTestCase {
|
public class CheckerTestCase extends CodanTestCase {
|
||||||
ArrayList<File> tempFiles = new ArrayList<File>();
|
|
||||||
protected File tmpDir;
|
|
||||||
private ICProject cproject;
|
|
||||||
private IMarker[] markers;
|
private IMarker[] markers;
|
||||||
private File currentFile;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Override for c++
|
|
||||||
*
|
|
||||||
* @return is c++ tests
|
|
||||||
*/
|
|
||||||
public boolean isCpp() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
super.setUp();
|
|
||||||
removeLeftOverProjects();
|
|
||||||
cproject = createProject(isCpp());
|
|
||||||
tmpDir = cproject.getProject().getLocation().makeAbsolute().toFile();
|
|
||||||
}
|
|
||||||
|
|
||||||
public File load(String file) {
|
|
||||||
CodanCoreTestActivator plugin = CodanCoreTestActivator.getDefault();
|
|
||||||
String name = getClass().getName();
|
|
||||||
String classFile = name.replaceAll("\\.", "/");
|
|
||||||
classFile += ".java";
|
|
||||||
InputStream st = null;
|
|
||||||
File f = null;
|
|
||||||
try {
|
|
||||||
if (plugin != null) {
|
|
||||||
URL resource = plugin.getBundle().getResource(
|
|
||||||
"src/" + classFile);
|
|
||||||
st = resource.openStream();
|
|
||||||
} else {
|
|
||||||
st = getClass().getResourceAsStream(classFile);
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
fail("Cannot find java file: " + classFile);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
f = saveFile(st, file);
|
|
||||||
st.close();
|
|
||||||
currentFile = f;
|
|
||||||
} catch (IOException e) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
static final Pattern filePattern = Pattern.compile("file=\"(.*)\"");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param st
|
|
||||||
* @param file
|
|
||||||
* @return
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
private File saveFile(InputStream st, String file) throws IOException {
|
|
||||||
BufferedReader r = new BufferedReader(new InputStreamReader(st));
|
|
||||||
String line;
|
|
||||||
File testFile = new File(tmpDir, file);
|
|
||||||
tempFiles.add(testFile);
|
|
||||||
PrintStream wr = new PrintStream(testFile);
|
|
||||||
try {
|
|
||||||
boolean print = false;
|
|
||||||
while ((line = r.readLine()) != null) {
|
|
||||||
if (line.contains("<code ")) {
|
|
||||||
Matcher m = filePattern.matcher(line);
|
|
||||||
if (m.find()) {
|
|
||||||
String userFile = m.group(1);
|
|
||||||
if (userFile.equals(file)) {
|
|
||||||
print = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (line.contains("</code>")) {
|
|
||||||
print = false;
|
|
||||||
} else if (print) {
|
|
||||||
wr.println(line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
wr.close();
|
|
||||||
}
|
|
||||||
return testFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void tearDown() throws CoreException {
|
|
||||||
if (cproject != null) {
|
|
||||||
try {
|
|
||||||
cproject.getProject().delete(
|
|
||||||
IResource.FORCE
|
|
||||||
| IResource.ALWAYS_DELETE_PROJECT_CONTENT,
|
|
||||||
new NullProgressMonitor());
|
|
||||||
} catch (CoreException e) {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws CoreException
|
|
||||||
*/
|
|
||||||
private void removeLeftOverProjects() throws CoreException {
|
|
||||||
final IWorkspace workspace = ResourcesPlugin.getWorkspace();
|
|
||||||
IProject[] projects = workspace.getRoot().getProjects();
|
|
||||||
for (int i = 0; i < projects.length; i++) {
|
|
||||||
IProject p = projects[i];
|
|
||||||
if (p.getName().startsWith("Codan")) {
|
|
||||||
p.delete(IResource.FORCE
|
|
||||||
| IResource.ALWAYS_DELETE_PROJECT_CONTENT,
|
|
||||||
new NullProgressMonitor());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ICProject createProject(final boolean cpp) throws CoreException {
|
|
||||||
final ICProject cprojects[] = new ICProject[1];
|
|
||||||
ModelJoiner mj = new ModelJoiner();
|
|
||||||
try {
|
|
||||||
// Create the cproject
|
|
||||||
final String projectName = "CodanProjTest_"
|
|
||||||
+ System.currentTimeMillis();
|
|
||||||
final IWorkspace workspace = ResourcesPlugin.getWorkspace();
|
|
||||||
workspace.run(new IWorkspaceRunnable() {
|
|
||||||
public void run(IProgressMonitor monitor) throws CoreException {
|
|
||||||
// Create the cproject
|
|
||||||
ICProject cproject = cpp ? CProjectHelper.createCCProject(
|
|
||||||
projectName, null, IPDOMManager.ID_NO_INDEXER)
|
|
||||||
: CProjectHelper.createCProject(projectName, null,
|
|
||||||
IPDOMManager.ID_NO_INDEXER);
|
|
||||||
cprojects[0] = cproject;
|
|
||||||
}
|
|
||||||
}, null);
|
|
||||||
mj.join();
|
|
||||||
// Index the cproject
|
|
||||||
CCorePlugin.getIndexManager().setIndexerId(cprojects[0],
|
|
||||||
IPDOMManager.ID_FAST_INDEXER);
|
|
||||||
// wait until the indexer is done
|
|
||||||
assertTrue(CCorePlugin.getIndexManager().joinIndexer(360000,
|
|
||||||
new NullProgressMonitor()));
|
|
||||||
} finally {
|
|
||||||
mj.dispose();
|
|
||||||
}
|
|
||||||
return cprojects[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void loadFiles() throws CoreException {
|
|
||||||
ModelJoiner mj = new ModelJoiner();
|
|
||||||
try {
|
|
||||||
final IWorkspace workspace = ResourcesPlugin.getWorkspace();
|
|
||||||
workspace.run(new IWorkspaceRunnable() {
|
|
||||||
public void run(IProgressMonitor monitor) throws CoreException {
|
|
||||||
cproject.getProject().refreshLocal(1, monitor);
|
|
||||||
}
|
|
||||||
}, null);
|
|
||||||
mj.join();
|
|
||||||
// Index the cproject
|
|
||||||
CCorePlugin.getIndexManager().setIndexerId(cproject,
|
|
||||||
IPDOMManager.ID_FAST_INDEXER);
|
|
||||||
// wait until the indexer is done
|
|
||||||
assertTrue(CCorePlugin.getIndexManager().joinIndexer(360000,
|
|
||||||
new NullProgressMonitor()));
|
|
||||||
} finally {
|
|
||||||
mj.dispose();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param i
|
* @param i
|
||||||
|
@ -243,31 +55,6 @@ public class CheckerTestCase extends BaseTestCase {
|
||||||
assertTrue("Error on line " + i + " not found ", found);
|
assertTrue("Error on line " + i + " not found ", found);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param pos
|
|
||||||
* @return
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
private int pos2line(int pos) throws IOException {
|
|
||||||
FileInputStream st = new FileInputStream(currentFile);
|
|
||||||
try {
|
|
||||||
int c;
|
|
||||||
int line = 1;
|
|
||||||
int cur = 0;
|
|
||||||
while ((c = st.read()) != -1) {
|
|
||||||
if (c == '\n')
|
|
||||||
line++;
|
|
||||||
if (cur >= pos)
|
|
||||||
return line;
|
|
||||||
cur++;
|
|
||||||
}
|
|
||||||
;
|
|
||||||
} finally {
|
|
||||||
st.close();
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void checkNoErrors() {
|
public void checkNoErrors() {
|
||||||
assertTrue("Found errors but should not", markers == null
|
assertTrue("Found errors but should not", markers == null
|
||||||
|| markers.length == 0);
|
|| markers.length == 0);
|
||||||
|
|
|
@ -0,0 +1,205 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2009 Alena Laskavaia
|
||||||
|
* 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:
|
||||||
|
* Alena Laskavaia - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.codan.core.test;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.CCorePlugin;
|
||||||
|
import org.eclipse.cdt.core.dom.IPDOMManager;
|
||||||
|
import org.eclipse.cdt.core.model.ICProject;
|
||||||
|
import org.eclipse.cdt.core.testplugin.CProjectHelper;
|
||||||
|
import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
|
||||||
|
import org.eclipse.core.resources.IProject;
|
||||||
|
import org.eclipse.core.resources.IResource;
|
||||||
|
import org.eclipse.core.resources.IWorkspace;
|
||||||
|
import org.eclipse.core.resources.IWorkspaceRunnable;
|
||||||
|
import org.eclipse.core.resources.ResourcesPlugin;
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
import org.eclipse.core.runtime.NullProgressMonitor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: add description
|
||||||
|
*/
|
||||||
|
public class CodanTestCase extends BaseTestCase {
|
||||||
|
ArrayList<File> tempFiles = new ArrayList<File>();
|
||||||
|
protected File tmpDir;
|
||||||
|
protected ICProject cproject;
|
||||||
|
protected File currentFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public CodanTestCase() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param name
|
||||||
|
*/
|
||||||
|
public CodanTestCase(String name) {
|
||||||
|
super(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override for c++
|
||||||
|
*
|
||||||
|
* @return is c++ tests
|
||||||
|
*/
|
||||||
|
public boolean isCpp() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
removeLeftOverProjects();
|
||||||
|
cproject = createProject(isCpp());
|
||||||
|
tmpDir = cproject.getProject().getLocation().makeAbsolute().toFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
public File load(String file) {
|
||||||
|
Class clazz = getClass();
|
||||||
|
InputStream st = null;
|
||||||
|
try {
|
||||||
|
st = TestUtils.getJavaFileText(clazz);
|
||||||
|
} catch (IOException e) {
|
||||||
|
fail("Cannot find java file: " + clazz + ": " + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
File testFile = new File(tmpDir, file);
|
||||||
|
tempFiles.add(testFile);
|
||||||
|
TestUtils.saveFile(st, testFile);
|
||||||
|
st.close();
|
||||||
|
currentFile = testFile;
|
||||||
|
try {
|
||||||
|
cproject.getProject().refreshLocal(1, null);
|
||||||
|
} catch (CoreException e) {
|
||||||
|
// hmm
|
||||||
|
}
|
||||||
|
return testFile;
|
||||||
|
} catch (IOException e) {
|
||||||
|
fail("Cannot save test: " + file + ": " + e.getMessage());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tearDown() throws CoreException {
|
||||||
|
if (cproject != null) {
|
||||||
|
try {
|
||||||
|
cproject.getProject().delete(
|
||||||
|
IResource.FORCE
|
||||||
|
| IResource.ALWAYS_DELETE_PROJECT_CONTENT,
|
||||||
|
new NullProgressMonitor());
|
||||||
|
} catch (CoreException e) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws CoreException
|
||||||
|
*/
|
||||||
|
private void removeLeftOverProjects() throws CoreException {
|
||||||
|
final IWorkspace workspace = ResourcesPlugin.getWorkspace();
|
||||||
|
IProject[] projects = workspace.getRoot().getProjects();
|
||||||
|
for (int i = 0; i < projects.length; i++) {
|
||||||
|
IProject p = projects[i];
|
||||||
|
if (p.getName().startsWith("Codan")) {
|
||||||
|
p.delete(IResource.FORCE
|
||||||
|
| IResource.ALWAYS_DELETE_PROJECT_CONTENT,
|
||||||
|
new NullProgressMonitor());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ICProject createProject(final boolean cpp) throws CoreException {
|
||||||
|
final ICProject cprojects[] = new ICProject[1];
|
||||||
|
ModelJoiner mj = new ModelJoiner();
|
||||||
|
try {
|
||||||
|
// Create the cproject
|
||||||
|
final String projectName = "CodanProjTest_"
|
||||||
|
+ System.currentTimeMillis();
|
||||||
|
final IWorkspace workspace = ResourcesPlugin.getWorkspace();
|
||||||
|
workspace.run(new IWorkspaceRunnable() {
|
||||||
|
public void run(IProgressMonitor monitor) throws CoreException {
|
||||||
|
// Create the cproject
|
||||||
|
ICProject cproject = cpp ? CProjectHelper.createCCProject(
|
||||||
|
projectName, null, IPDOMManager.ID_NO_INDEXER)
|
||||||
|
: CProjectHelper.createCProject(projectName, null,
|
||||||
|
IPDOMManager.ID_NO_INDEXER);
|
||||||
|
cprojects[0] = cproject;
|
||||||
|
}
|
||||||
|
}, null);
|
||||||
|
mj.join();
|
||||||
|
// Index the cproject
|
||||||
|
CCorePlugin.getIndexManager().setIndexerId(cprojects[0],
|
||||||
|
IPDOMManager.ID_FAST_INDEXER);
|
||||||
|
// wait until the indexer is done
|
||||||
|
assertTrue(CCorePlugin.getIndexManager().joinIndexer(360000,
|
||||||
|
new NullProgressMonitor()));
|
||||||
|
} finally {
|
||||||
|
mj.dispose();
|
||||||
|
}
|
||||||
|
return cprojects[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void loadFiles() throws CoreException {
|
||||||
|
ModelJoiner mj = new ModelJoiner();
|
||||||
|
try {
|
||||||
|
final IWorkspace workspace = ResourcesPlugin.getWorkspace();
|
||||||
|
workspace.run(new IWorkspaceRunnable() {
|
||||||
|
public void run(IProgressMonitor monitor) throws CoreException {
|
||||||
|
cproject.getProject().refreshLocal(1, monitor);
|
||||||
|
}
|
||||||
|
}, null);
|
||||||
|
mj.join();
|
||||||
|
// Index the cproject
|
||||||
|
CCorePlugin.getIndexManager().setIndexerId(cproject,
|
||||||
|
IPDOMManager.ID_FAST_INDEXER);
|
||||||
|
// wait until the indexer is done
|
||||||
|
assertTrue(CCorePlugin.getIndexManager().joinIndexer(360000,
|
||||||
|
new NullProgressMonitor()));
|
||||||
|
} finally {
|
||||||
|
mj.dispose();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param pos
|
||||||
|
* @return
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
protected int pos2line(int pos) throws IOException {
|
||||||
|
FileInputStream st = new FileInputStream(currentFile);
|
||||||
|
try {
|
||||||
|
int c;
|
||||||
|
int line = 1;
|
||||||
|
int cur = 0;
|
||||||
|
while ((c = st.read()) != -1) {
|
||||||
|
if (c == '\n')
|
||||||
|
line++;
|
||||||
|
if (cur >= pos)
|
||||||
|
return line;
|
||||||
|
cur++;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
} finally {
|
||||||
|
st.close();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2009 Alena Laskavaia
|
||||||
|
* 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:
|
||||||
|
* Alena Laskavaia - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.cdt.codan.core.test;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: add description
|
||||||
|
*/
|
||||||
|
public class TestUtils {
|
||||||
|
static final Pattern filePattern = Pattern.compile("file=\"(.*)\"");
|
||||||
|
/**
|
||||||
|
* @param st
|
||||||
|
* @param testFile
|
||||||
|
* @return
|
||||||
|
* @throws FileNotFoundException
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public static File saveFile(InputStream st, File testFile)
|
||||||
|
throws FileNotFoundException, IOException {
|
||||||
|
BufferedReader r = new BufferedReader(new InputStreamReader(st));
|
||||||
|
String line;
|
||||||
|
PrintStream wr = new PrintStream(testFile);
|
||||||
|
try {
|
||||||
|
boolean print = false;
|
||||||
|
while ((line = r.readLine()) != null) {
|
||||||
|
if (line.contains("<code ")) {
|
||||||
|
Matcher m = filePattern.matcher(line);
|
||||||
|
if (m.find()) {
|
||||||
|
String userFile = m.group(1);
|
||||||
|
if (userFile.equals(testFile.getName())) {
|
||||||
|
print = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (line.contains("</code>")) {
|
||||||
|
print = false;
|
||||||
|
} else if (print) {
|
||||||
|
wr.println(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
wr.close();
|
||||||
|
}
|
||||||
|
return testFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param clazz
|
||||||
|
* @return
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public static InputStream getJavaFileText(Class clazz) throws IOException {
|
||||||
|
CodanCoreTestActivator plugin = CodanCoreTestActivator.getDefault();
|
||||||
|
String classFile = clazz.getName().replaceAll("\\.", "/");
|
||||||
|
classFile += ".java";
|
||||||
|
InputStream st = null;
|
||||||
|
|
||||||
|
if (plugin != null) {
|
||||||
|
URL resource = plugin.getBundle().getResource(
|
||||||
|
"src/" + classFile);
|
||||||
|
st = resource.openStream();
|
||||||
|
} else {
|
||||||
|
st = clazz.getResourceAsStream(classFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
return st;
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,4 +16,6 @@ Export-Package: org.eclipse.cdt.codan.core,
|
||||||
org.eclipse.cdt.codan.core.cxx,
|
org.eclipse.cdt.codan.core.cxx,
|
||||||
org.eclipse.cdt.codan.core.test,
|
org.eclipse.cdt.codan.core.test,
|
||||||
org.eclipse.cdt.codan.ui",
|
org.eclipse.cdt.codan.ui",
|
||||||
org.eclipse.cdt.codan.internal.core.model;x-friends:="org.eclipse.cdt.codan.core.cxx,org.eclipse.cdt.codan.core.test,org.eclipse.cdt.codan.ui"
|
org.eclipse.cdt.codan.internal.core.cfg;x-friends:="org.eclipse.cdt.codan.core.cxx",
|
||||||
|
org.eclipse.cdt.codan.internal.core.model;x-friends:="org.eclipse.cdt.codan.core.cxx,org.eclipse.cdt.codan.core.test,org.eclipse.cdt.codan.ui",
|
||||||
|
org.eclipse.cdt.codan.provisional.core.model.cfg
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
package org.eclipse.cdt.codan.internal.core.cfg;
|
|
||||||
|
|
||||||
import java.util.Iterator;
|
|
||||||
|
|
||||||
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock;
|
|
||||||
|
|
||||||
public abstract class AbstarctBasicBlock implements IBasicBlock {
|
|
||||||
static class OneElementIterator<T> implements Iterator<T> {
|
|
||||||
private T o;
|
|
||||||
|
|
||||||
public OneElementIterator(T o) {
|
|
||||||
this.o = o;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasNext() {
|
|
||||||
return o != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public T next() {
|
|
||||||
T x = o;
|
|
||||||
o = null;
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void remove() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
package org.eclipse.cdt.codan.internal.core.cfg;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock;
|
||||||
|
|
||||||
|
public abstract class AbstractBasicBlock implements IBasicBlock {
|
||||||
|
private Object data;
|
||||||
|
|
||||||
|
public Object getData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(Object data) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static class OneElementIterator<V> implements Iterator<V> {
|
||||||
|
private V o;
|
||||||
|
|
||||||
|
public OneElementIterator(V o) {
|
||||||
|
this.o = o;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasNext() {
|
||||||
|
return o != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public V next() {
|
||||||
|
V x = o;
|
||||||
|
o = null;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void addOutgoing(IBasicBlock node);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String toStringData() {
|
||||||
|
if (getData() == null)
|
||||||
|
return "";
|
||||||
|
return getData().toString();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package org.eclipse.cdt.codan.internal.core.cfg;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock;
|
||||||
|
import org.eclipse.cdt.codan.provisional.core.model.cfg.ISingleIncoming;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstrat node with one incoming arc
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public abstract class AbstractSingleIncomingNode extends AbstractBasicBlock
|
||||||
|
implements ISingleIncoming {
|
||||||
|
final IBasicBlock prev;
|
||||||
|
|
||||||
|
public AbstractSingleIncomingNode(IBasicBlock prev) {
|
||||||
|
super();
|
||||||
|
this.prev = prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Iterator<IBasicBlock> getIncomingIterator() {
|
||||||
|
return new OneElementIterator<IBasicBlock>(prev);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIncomingSize() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IBasicBlock getIncoming() {
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
package org.eclipse.cdt.codan.internal.core.cfg;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock;
|
||||||
|
import org.eclipse.cdt.codan.provisional.core.model.cfg.ISingleOutgoing;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract impl of basic block with single outgoing arc
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public abstract class AbstractSingleOutgoingNode extends AbstractBasicBlock
|
||||||
|
implements ISingleOutgoing {
|
||||||
|
private IBasicBlock next;
|
||||||
|
|
||||||
|
public AbstractSingleOutgoingNode(IBasicBlock next) {
|
||||||
|
super();
|
||||||
|
this.next = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Iterator<IBasicBlock> getOutgoingIterator() {
|
||||||
|
return new OneElementIterator<IBasicBlock>(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getOutgoingSize() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IBasicBlock getOutgoing() {
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOutgoing(IBasicBlock exit) {
|
||||||
|
if (this.next != null)
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Cannot modify already exiting connector"); //$NON-NLS-1$
|
||||||
|
this.next = exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see
|
||||||
|
* org.eclipse.cdt.codan.internal.core.cfg.AbstractBasicBlock#addOutgoing
|
||||||
|
* (org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void addOutgoing(IBasicBlock node) {
|
||||||
|
setOutgoing(node);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2009 Alena Laskavaia
|
||||||
|
* 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:
|
||||||
|
* Alena Laskavaia - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.codan.internal.core.cfg;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock;
|
||||||
|
import org.eclipse.cdt.codan.provisional.core.model.cfg.IConnectorNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: add description
|
||||||
|
*/
|
||||||
|
public class ConnectorNode extends AbstractSingleOutgoingNode implements
|
||||||
|
IConnectorNode {
|
||||||
|
ArrayList<IBasicBlock> incoming = new ArrayList<IBasicBlock>(2);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param next
|
||||||
|
*/
|
||||||
|
public ConnectorNode() {
|
||||||
|
super(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addIncoming(IBasicBlock node) {
|
||||||
|
incoming.add(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @seeorg.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock#
|
||||||
|
* getIncomingIterator()
|
||||||
|
*/
|
||||||
|
public Iterator<IBasicBlock> getIncomingIterator() {
|
||||||
|
return incoming.iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see
|
||||||
|
* org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock#getIncomingSize
|
||||||
|
* ()
|
||||||
|
*/
|
||||||
|
public int getIncomingSize() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return incoming.size();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,99 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2009 Alena Laskavaia
|
||||||
|
* 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:
|
||||||
|
* Alena Laskavaia - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.codan.internal.core.cfg;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock;
|
||||||
|
import org.eclipse.cdt.codan.provisional.core.model.cfg.IConnectorNode;
|
||||||
|
import org.eclipse.cdt.codan.provisional.core.model.cfg.IControlFlowGraph;
|
||||||
|
import org.eclipse.cdt.codan.provisional.core.model.cfg.IDecisionArc;
|
||||||
|
import org.eclipse.cdt.codan.provisional.core.model.cfg.IDecisionNode;
|
||||||
|
import org.eclipse.cdt.codan.provisional.core.model.cfg.IExitNode;
|
||||||
|
import org.eclipse.cdt.codan.provisional.core.model.cfg.ISingleOutgoing;
|
||||||
|
import org.eclipse.cdt.codan.provisional.core.model.cfg.IStartNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: add description
|
||||||
|
*/
|
||||||
|
public class ControlFlowGraph implements IControlFlowGraph {
|
||||||
|
private List<IExitNode> exitNodes;
|
||||||
|
private IStartNode start;
|
||||||
|
|
||||||
|
public ControlFlowGraph(IStartNode start, Collection<IExitNode> exitNodes) {
|
||||||
|
setExitNodes(exitNodes);
|
||||||
|
this.start = start;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Iterator<IExitNode> getExitNodeIterator() {
|
||||||
|
return exitNodes.iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getExitNodeSize() {
|
||||||
|
return exitNodes.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExitNodes(Collection<IExitNode> exitNodes) {
|
||||||
|
if (this.exitNodes != null)
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Cannot modify already exiting connector"); //$NON-NLS-1$
|
||||||
|
this.exitNodes = Collections.unmodifiableList(new ArrayList<IExitNode>(
|
||||||
|
exitNodes));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @seeorg.eclipse.cdt.codan.provisional.core.model.cfg.IControlFlowGraph#
|
||||||
|
* getStartNode()
|
||||||
|
*/
|
||||||
|
public IStartNode getStartNode() {
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setStartNode(IStartNode start) {
|
||||||
|
this.start = start;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void print(IBasicBlock node) {
|
||||||
|
System.out.println(node.toString());
|
||||||
|
if (node instanceof IConnectorNode)
|
||||||
|
return;
|
||||||
|
if (node instanceof IDecisionNode) {
|
||||||
|
// todo
|
||||||
|
Iterator<IDecisionArc> decisionArcs = ((IDecisionNode) node)
|
||||||
|
.getDecisionArcs();
|
||||||
|
for (; decisionArcs.hasNext();) {
|
||||||
|
IDecisionArc arc = decisionArcs.next();
|
||||||
|
System.out.println("{" + arc.getIndex() + ":");
|
||||||
|
print(arc.getOutgoing());
|
||||||
|
System.out.println("}");
|
||||||
|
}
|
||||||
|
print(((IDecisionNode) node).getConnectionNode());
|
||||||
|
} else if (node instanceof ISingleOutgoing) {
|
||||||
|
print(((ISingleOutgoing) node).getOutgoing());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @seeorg.eclipse.cdt.codan.provisional.core.model.cfg.IControlFlowGraph#
|
||||||
|
* getUnconnectedNodeIterator()
|
||||||
|
*/
|
||||||
|
public Iterator<IBasicBlock> getUnconnectedNodeIterator() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,153 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2009 Alena Laskavaia
|
||||||
|
* 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:
|
||||||
|
* Alena Laskavaia - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.codan.internal.core.cfg;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock;
|
||||||
|
import org.eclipse.cdt.codan.provisional.core.model.cfg.IConnectorNode;
|
||||||
|
import org.eclipse.cdt.codan.provisional.core.model.cfg.IDecisionArc;
|
||||||
|
import org.eclipse.cdt.codan.provisional.core.model.cfg.IDecisionNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see {@link IDecisionNode}
|
||||||
|
*/
|
||||||
|
public class DecisionNode extends AbstractSingleIncomingNode implements
|
||||||
|
IDecisionNode {
|
||||||
|
private List<IDecisionArc> next = new ArrayList<IDecisionArc>(2);
|
||||||
|
private IConnectorNode conn;
|
||||||
|
|
||||||
|
class DecisionArc implements IDecisionArc {
|
||||||
|
int index;
|
||||||
|
IBasicBlock node;
|
||||||
|
|
||||||
|
DecisionArc(int i, IBasicBlock node) {
|
||||||
|
this.index = i;
|
||||||
|
this.node = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIndex() {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IBasicBlock getOutgoing() {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IDecisionNode getDecisionNode() {
|
||||||
|
return DecisionNode.this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see java.lang.Object#toString()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return index + "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param prev
|
||||||
|
*/
|
||||||
|
public DecisionNode(IBasicBlock prev) {
|
||||||
|
super(prev);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDecisionArcs(Collection<IDecisionArc> next) {
|
||||||
|
this.next = Collections.unmodifiableList(new ArrayList<IDecisionArc>(
|
||||||
|
next));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addOutgoing(IBasicBlock node) {
|
||||||
|
DecisionArc arc = new DecisionArc(getDecisionArcSize(), node);
|
||||||
|
next.add(arc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @seeorg.eclipse.cdt.codan.provisional.core.model.cfg.IDecisionNode#
|
||||||
|
* getDecisionArcs()
|
||||||
|
*/
|
||||||
|
public Iterator<IDecisionArc> getDecisionArcs() {
|
||||||
|
return next.iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @seeorg.eclipse.cdt.codan.provisional.core.model.cfg.IDecisionNode#
|
||||||
|
* getDecisionArcSize()
|
||||||
|
*/
|
||||||
|
public int getDecisionArcSize() {
|
||||||
|
return next.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @seeorg.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock#
|
||||||
|
* getOutgoingIterator()
|
||||||
|
*/
|
||||||
|
public Iterator<IBasicBlock> getOutgoingIterator() {
|
||||||
|
return new Iterator<IBasicBlock>() {
|
||||||
|
private Iterator<IDecisionArc> it;
|
||||||
|
{
|
||||||
|
it = next.iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasNext() {
|
||||||
|
return it.hasNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IBasicBlock next() {
|
||||||
|
IDecisionArc arc = it.next();
|
||||||
|
return arc.getOutgoing();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see
|
||||||
|
* org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock#getOutgoingSize
|
||||||
|
* ()
|
||||||
|
*/
|
||||||
|
public int getOutgoingSize() {
|
||||||
|
return next.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @seeorg.eclipse.cdt.codan.provisional.core.model.cfg.IDecisionNode#
|
||||||
|
* getConnectionNode()
|
||||||
|
*/
|
||||||
|
public IConnectorNode getConnectionNode() {
|
||||||
|
return conn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConnectorNode(IConnectorNode conn) {
|
||||||
|
this.conn = conn;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
package org.eclipse.cdt.codan.internal.core.cfg;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock;
|
||||||
|
import org.eclipse.cdt.codan.provisional.core.model.cfg.IExitNode;
|
||||||
|
import org.eclipse.cdt.codan.provisional.core.model.cfg.IStartNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plain node has one prev one jump
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ExitNode extends AbstractBasicBlock implements IExitNode {
|
||||||
|
private IBasicBlock prev;
|
||||||
|
private IStartNode start;
|
||||||
|
|
||||||
|
public ExitNode(IBasicBlock prev, IStartNode start) {
|
||||||
|
super();
|
||||||
|
this.prev = prev;
|
||||||
|
this.start = start;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Iterator<IBasicBlock> getIncomingIterator() {
|
||||||
|
return new OneElementIterator<IBasicBlock>(prev);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public Iterator<IBasicBlock> getOutgoingIterator() {
|
||||||
|
return Collections.EMPTY_LIST.iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIncomingSize() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getOutgoingSize() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IBasicBlock getIncoming() {
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IStartNode getStartNode() {
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIncoming(IBasicBlock prev) {
|
||||||
|
this.prev = prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStartNode(IStartNode start) {
|
||||||
|
this.start = start;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addOutgoing(IBasicBlock node) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,47 +1,33 @@
|
||||||
package org.eclipse.cdt.codan.internal.core.cfg;
|
package org.eclipse.cdt.codan.internal.core.cfg;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock;
|
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock;
|
||||||
import org.eclipse.cdt.codan.provisional.core.model.cfg.IConnectorNode;
|
import org.eclipse.cdt.codan.provisional.core.model.cfg.IConnectorNode;
|
||||||
import org.eclipse.cdt.codan.provisional.core.model.cfg.IJumpNode;
|
import org.eclipse.cdt.codan.provisional.core.model.cfg.IJumpNode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Plain node has one prev one jump
|
* Jump node is node that connects unusual control pass, such as goto, break and
|
||||||
*
|
* continue
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
public class JumpNode extends AbstarctBasicBlock implements IJumpNode {
|
public class JumpNode extends AbstractSingleIncomingNode implements IJumpNode {
|
||||||
final private IBasicBlock entry;
|
private IConnectorNode jump;
|
||||||
private IBasicBlock jump;
|
|
||||||
private boolean backward;
|
private boolean backward;
|
||||||
|
|
||||||
public JumpNode(IBasicBlock entry, IBasicBlock jump, boolean backward) {
|
public JumpNode(IBasicBlock entry, IConnectorNode jump, boolean backward) {
|
||||||
super();
|
super(entry);
|
||||||
this.entry = entry;
|
|
||||||
this.jump = jump;
|
this.jump = jump;
|
||||||
this.backward = backward;
|
this.backward = backward;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterator<IBasicBlock> getIncomingIterator() {
|
|
||||||
return new OneElementIterator<IBasicBlock>(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Iterator<IBasicBlock> getOutgoingIterator() {
|
public Iterator<IBasicBlock> getOutgoingIterator() {
|
||||||
return new OneElementIterator<IBasicBlock>(jump);
|
return new OneElementIterator<IBasicBlock>(jump);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getIncomingSize() {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getOutgoingSize() {
|
public int getOutgoingSize() {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IBasicBlock getIncoming() {
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IBasicBlock getOutgoing() {
|
public IBasicBlock getOutgoing() {
|
||||||
return jump;
|
return jump;
|
||||||
}
|
}
|
||||||
|
@ -50,9 +36,10 @@ public class JumpNode extends AbstarctBasicBlock implements IJumpNode {
|
||||||
return backward;
|
return backward;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setJump(IBasicBlock jump) {
|
public void setJump(IConnectorNode jump) {
|
||||||
if (!(jump instanceof IConnectorNode))
|
if (this.jump != null)
|
||||||
throw new IllegalArgumentException("Jump target must be a connection node"); //$NON-NLS-1$
|
throw new IllegalArgumentException(
|
||||||
|
"Cannot modify exiting connector"); //$NON-NLS-1$
|
||||||
this.jump = jump;
|
this.jump = jump;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,4 +47,8 @@ public class JumpNode extends AbstarctBasicBlock implements IJumpNode {
|
||||||
this.backward = backward;
|
this.backward = backward;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addOutgoing(IBasicBlock node) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,45 +6,45 @@ import org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock;
|
||||||
import org.eclipse.cdt.codan.provisional.core.model.cfg.IPlainNode;
|
import org.eclipse.cdt.codan.provisional.core.model.cfg.IPlainNode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Plain node has one prev one jump
|
* Plain node has one incoming arc and one outgoing arc
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class PlainNode extends AbstarctBasicBlock implements IPlainNode {
|
public class PlainNode extends AbstractSingleIncomingNode implements IPlainNode {
|
||||||
final IBasicBlock prev;
|
|
||||||
IBasicBlock next;
|
IBasicBlock next;
|
||||||
|
|
||||||
public PlainNode(IBasicBlock entry, IBasicBlock exit) {
|
public PlainNode(IBasicBlock prev, IBasicBlock next) {
|
||||||
super();
|
super(prev);
|
||||||
this.prev = entry;
|
this.next = next;
|
||||||
this.next = exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Iterator<IBasicBlock> getIncomingIterator() {
|
|
||||||
return new OneElementIterator<IBasicBlock>(prev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterator<IBasicBlock> getOutgoingIterator() {
|
public Iterator<IBasicBlock> getOutgoingIterator() {
|
||||||
return new OneElementIterator<IBasicBlock>(next);
|
return new OneElementIterator<IBasicBlock>(next);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getIncomingSize() {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getOutgoingSize() {
|
public int getOutgoingSize() {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IBasicBlock getIncoming() {
|
|
||||||
return prev;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IBasicBlock getOutgoing() {
|
public IBasicBlock getOutgoing() {
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOutgoing(IBasicBlock exit) {
|
public void setOutgoing(IBasicBlock exit) {
|
||||||
if (this.next != null) throw new IllegalArgumentException("Cannot modify already exiting connector"); //$NON-NLS-1$
|
if (this.next != null)
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Cannot modify already exiting connector"); //$NON-NLS-1$
|
||||||
this.next = exit;
|
this.next = exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see
|
||||||
|
* org.eclipse.cdt.codan.internal.core.cfg.AbstractBasicBlock#addOutgoing
|
||||||
|
* (org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void addOutgoing(IBasicBlock node) {
|
||||||
|
setOutgoing(node);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,27 +1,17 @@
|
||||||
package org.eclipse.cdt.codan.internal.core.cfg;
|
package org.eclipse.cdt.codan.internal.core.cfg;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock;
|
import org.eclipse.cdt.codan.provisional.core.model.cfg.IBasicBlock;
|
||||||
import org.eclipse.cdt.codan.provisional.core.model.cfg.IStartNode;
|
import org.eclipse.cdt.codan.provisional.core.model.cfg.IStartNode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start node has no prev, one jump and it is connect to function exits
|
* Start node has no incoming, one outgoing and it is connect to function exits
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class StartNode extends AbstarctBasicBlock implements IStartNode {
|
public class StartNode extends AbstractSingleOutgoingNode implements IStartNode {
|
||||||
private IBasicBlock next;
|
public StartNode(IBasicBlock next) {
|
||||||
private List<IBasicBlock> exitNodes;
|
super(next);
|
||||||
|
|
||||||
public StartNode(IBasicBlock next, Collection<IBasicBlock> exitNodes) {
|
|
||||||
super();
|
|
||||||
this.next = next;
|
|
||||||
if (exitNodes != null) this.exitNodes = Collections.unmodifiableList(new ArrayList<IBasicBlock>(exitNodes));
|
|
||||||
else this.exitNodes = null; // incomplete node
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
@ -29,37 +19,12 @@ public class StartNode extends AbstarctBasicBlock implements IStartNode {
|
||||||
return Collections.EMPTY_LIST.iterator();
|
return Collections.EMPTY_LIST.iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterator<IBasicBlock> getOutgoingIterator() {
|
|
||||||
return new OneElementIterator<IBasicBlock>(next);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getIncomingSize() {
|
public int getIncomingSize() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getOutgoingSize() {
|
@Override
|
||||||
return 1;
|
public void addOutgoing(IBasicBlock node) {
|
||||||
}
|
setOutgoing(node);
|
||||||
|
|
||||||
public IBasicBlock getOutgoing() {
|
|
||||||
return next;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Iterator<IBasicBlock> getExitNodeIterator() {
|
|
||||||
return exitNodes.iterator();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getExitNodeSize() {
|
|
||||||
return exitNodes.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOutgoing(IBasicBlock next) {
|
|
||||||
if (this.next != null) throw new IllegalArgumentException("Cannot modify already exiting connector"); //$NON-NLS-1$
|
|
||||||
this.next = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setExitNodes(Collection<IBasicBlock> exitNodes) {
|
|
||||||
if (this.exitNodes != null) throw new IllegalArgumentException("Cannot modify already exiting connector"); //$NON-NLS-1$
|
|
||||||
this.exitNodes = Collections.unmodifiableList(new ArrayList<IBasicBlock>(exitNodes));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,15 @@ package org.eclipse.cdt.codan.provisional.core.model.cfg;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Control flow graph basic block node - superinterface of all nodes. Each node
|
||||||
|
* has iterator and size over incoming and outgoing arc
|
||||||
|
* <p/>
|
||||||
|
* The following are speciazed versions of the nodes:
|
||||||
|
* <li>{@link IStartNode} - start node of the graph
|
||||||
|
* <li>{@link I}
|
||||||
|
*/
|
||||||
public interface IBasicBlock {
|
public interface IBasicBlock {
|
||||||
Iterator<IBasicBlock> getIncomingIterator();
|
Iterator<IBasicBlock> getIncomingIterator();
|
||||||
|
|
||||||
|
@ -10,5 +19,4 @@ public interface IBasicBlock {
|
||||||
int getIncomingSize();
|
int getIncomingSize();
|
||||||
|
|
||||||
int getOutgoingSize();
|
int getOutgoingSize();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
package org.eclipse.cdt.codan.provisional.core.model.cfg;
|
package org.eclipse.cdt.codan.provisional.core.model.cfg;
|
||||||
|
|
||||||
public interface IConnectorNode extends IBasicBlock {
|
|
||||||
|
|
||||||
|
public interface IConnectorNode extends IBasicBlock, ISingleOutgoing {
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2009 Alena Laskavaia
|
||||||
|
* 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:
|
||||||
|
* Alena Laskavaia - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.codan.provisional.core.model.cfg;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: add description
|
||||||
|
*/
|
||||||
|
public interface IControlFlowGraph {
|
||||||
|
IStartNode getStartNode();
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Iterator<IExitNode> getExitNodeIterator();
|
||||||
|
|
||||||
|
int getExitNodeSize();
|
||||||
|
|
||||||
|
Iterator<IBasicBlock> getUnconnectedNodeIterator();
|
||||||
|
}
|
|
@ -1,5 +1,31 @@
|
||||||
package org.eclipse.cdt.codan.provisional.core.model.cfg;
|
package org.eclipse.cdt.codan.provisional.core.model.cfg;
|
||||||
|
|
||||||
public interface IDecisionArc {
|
/**
|
||||||
|
* Arc that has a condition upon it, for example if branches have true/false
|
||||||
|
* condition, and switch branches have case condition
|
||||||
|
*/
|
||||||
|
public interface IDecisionArc extends ISingleOutgoing {
|
||||||
|
/**
|
||||||
|
* Index represent branch index in decision node, as well semantics: <br>
|
||||||
|
* 0 - always a false (else) branch of if, and default branch for switch,
|
||||||
|
* even if no code exists <br>
|
||||||
|
* 1 - is true (then) branch for if
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
int getIndex();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basic block that is at the end of the arc
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
IBasicBlock getOutgoing();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return parent node (decision node) or the decision arc
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
IDecisionNode getDecisionNode();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,17 @@
|
||||||
package org.eclipse.cdt.codan.provisional.core.model.cfg;
|
package org.eclipse.cdt.codan.provisional.core.model.cfg;
|
||||||
|
|
||||||
public interface IDecisionNode extends IBasicBlock {
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Interface for decision node. This node represent condition node in the graph,
|
||||||
|
* it has one incoming arc and many outgoing, each of them has a value of
|
||||||
|
* condition associated with it.
|
||||||
|
*/
|
||||||
|
public interface IDecisionNode extends IBasicBlock, ISingleIncoming {
|
||||||
|
Iterator<IDecisionArc> getDecisionArcs();
|
||||||
|
|
||||||
|
int getDecisionArcSize();
|
||||||
|
|
||||||
|
IConnectorNode getConnectionNode();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2009 Alena Laskavaia
|
||||||
|
* 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:
|
||||||
|
* Alena Laskavaia - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.codan.provisional.core.model.cfg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exit node of the graph. Usually return from the function, can also be throw
|
||||||
|
* or abort, such at exit(0) call.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface IExitNode extends IBasicBlock, ISingleIncoming {
|
||||||
|
IStartNode getStartNode();
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
package org.eclipse.cdt.codan.provisional.core.model.cfg;
|
package org.eclipse.cdt.codan.provisional.core.model.cfg;
|
||||||
|
|
||||||
public interface IPlainNode extends IBasicBlock, ISingleOutgoing, ISingleIncoming {
|
public interface IPlainNode extends IBasicBlock, ISingleOutgoing,
|
||||||
|
ISingleIncoming {
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
package org.eclipse.cdt.codan.provisional.core.model.cfg;
|
package org.eclipse.cdt.codan.provisional.core.model.cfg;
|
||||||
|
|
||||||
import java.util.Iterator;
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start node of the control flow graph. Each graph has only one start node. It
|
||||||
|
* has no incoming arcs and one outgoing arc. It also contains iterator for
|
||||||
|
* function exit nodes.
|
||||||
|
*/
|
||||||
public interface IStartNode extends IBasicBlock, ISingleOutgoing {
|
public interface IStartNode extends IBasicBlock, ISingleOutgoing {
|
||||||
Iterator<IBasicBlock> getExitNodeIterator();
|
|
||||||
|
|
||||||
int getExitNodeSize();
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue