/**
* Copyright 2008 Anders Hessellund
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* $Id: ReachingDefinitionAnalysis.java,v 1.1 2008/01/17 18:48:18 hessellund Exp $
*/
package org.ofbiz.plugin.analysis;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.Assignment;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.ExpressionStatement;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.Statement;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
//inspired by source code from a compiler course by Robby
class ReachingDefinitionAnalysis extends
MonotonicDataFlowFramework<Pair<String, ASTNode>> {
/**
* computes reaching definitions for each statement in a single method
* Lattice element: (variable x defining node)
* @param cfg The control flow graph of the method
*/
ReachingDefinitionAnalysis(ControlFlowGraph cfg) {
super(cfg, true, true);
}
@Override void computeFixPoint() {
Set<Pair<String, ASTNode>> init = new HashSet<Pair<String, ASTNode>>();
for (Object o : cfg.method.parameters()) {
SingleVariableDeclaration svd = (SingleVariableDeclaration) o;
init.add(new Pair<String, ASTNode>(svd.getName().getIdentifier(),
svd));
}
computeFixPoint(init);
}
@Override String getAnalysisName() {
return "Reaching Definition";
}
@Override String toString(Pair<String, ASTNode> e) {
return e.first + " <"+Util.getFirstLine(e.second)+">";
}
@SuppressWarnings("unchecked")
@Override protected Set<Pair<String, ASTNode>> gen(Set<Pair<String, ASTNode>> set, Statement stmt) {
Set<Pair<String, ASTNode>> result = new HashSet<Pair<String, ASTNode>>();
// assignments generate a def
if (stmt instanceof ExpressionStatement) {
ExpressionStatement es = (ExpressionStatement) stmt;
Expression e = es.getExpression();
if (e instanceof Assignment) {
Assignment a = (Assignment) e;
Expression lhs = a.getLeftHandSide();
// special case, lhs is an ArrayAccess node
if (!(lhs instanceof SimpleName)) return result;
SimpleName sn = (SimpleName) lhs;
String lhsLocalName = sn.getIdentifier();
if (lhsLocalName != null) {
result.add(new Pair<String, ASTNode>(lhsLocalName, stmt));
}
}
// variable declarations generate a def
} else if (stmt instanceof VariableDeclarationStatement) {
VariableDeclarationStatement vds = (VariableDeclarationStatement) stmt;
List<VariableDeclarationFragment> fragments = vds.fragments();
for (VariableDeclarationFragment vdf : fragments) {
if (vdf.getName().getIdentifier() != null) {
result.add(new Pair<String, ASTNode>(vdf.getName().getIdentifier(), stmt));
}
}
}
return result;
}
@SuppressWarnings("unchecked")
@Override protected Set<Pair<String, ASTNode>> kill(Set<Pair<String, ASTNode>> set, Statement stmt) {
Set<Pair<String, ASTNode>> result = new HashSet<Pair<String, ASTNode>>();
// expressions kill a def
if (stmt instanceof ExpressionStatement) {
ExpressionStatement es = (ExpressionStatement) stmt;
Expression e = es.getExpression();
if (e instanceof Assignment) {
Assignment a = (Assignment) e;
Expression lhs = a.getLeftHandSide();
// special case, lhs is an ArrayAccess node
if (!(lhs instanceof SimpleName)) return result;
SimpleName sn = (SimpleName) lhs;
String lhsLocalName = sn.getIdentifier();
if (lhsLocalName != null) {
for (Pair<String, ASTNode> pair : set) {
if (pair.first.equals(lhsLocalName)) {
result.add(pair);
}
}
}
}
// variable declarations kill a def
} else if (stmt instanceof VariableDeclarationStatement) {
VariableDeclarationStatement vds = (VariableDeclarationStatement) stmt;
List<VariableDeclarationFragment> fragments = vds.fragments();
for (VariableDeclarationFragment vdf : fragments) {
if (vdf.getName().getIdentifier() != null) {
for (Pair<String, ASTNode> pair : set) {
if (pair.first.equals(vdf.getName().getIdentifier())) {
result.add(pair);
}
}
}
}
}
return result;
}
}