/* * This is a prototype implementation of the concept of Feature-Sen * sitive Dataflow Analysis. More details in the AOSD'12 paper: * Dataflow Analysis for Software Product Lines * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package br.ufal.cideei.soot.instrument.asttounit; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.CompilationUnit; import soot.Body; import soot.Unit; import soot.tagkit.SourceLnPosTag; import soot.util.Chain; // TODO: Auto-generated Javadoc /** * The Class ASTNodeUnitBridge is a utility class used to map between ASTNodes * and Units. */ public class ASTNodeUnitBridge { /** * This is a utility class with only static methods. There's no need for a * constructor. */ private ASTNodeUnitBridge() { } /** * Gets the ASTNodes from a unit. This transition takes into consideration * the position of unit in the source code. The SourceLnPosTag must be * present in this unit or an {@link IllegalArgumentException} will be * thrown. * * @param unit * the unit * @param compilationUnit * the compilation unit * @return the aST nodes from unit */ public static Collection<ASTNode> getASTNodesFromUnit(Unit unit, CompilationUnit compilationUnit) { ASTNodesAtRangeFinder ASTNodeVisitor; try { ASTNodeVisitor = new ASTNodesAtRangeFinder(unit, compilationUnit); } catch (IllegalArgumentException ex) { // TODO: silently ignoring an error is a bad idea. return Collections.emptyList(); } compilationUnit.accept(ASTNodeVisitor); return ASTNodeVisitor.getNodes(); } /** * Gets the ASTNodes from units. This transition ONLY takes into * consideration the starting line of the Units. If more precision is * necessary, see * {@link ASTNodeUnitBridge#getASTNodesFromUnit(Unit, CompilationUnit)}. * * @param units * the units * @param compilationUnit * the compilation unit * @return the aST nodes from units * * @see */ public static Collection<ASTNode> getASTNodesFromUnits(Collection<Unit> units, CompilationUnit compilationUnit) { return ASTNodeUnitBridge.getASTNodesFromLines(ASTNodeUnitBridge.getLinesFromUnits(units), compilationUnit); } /** * Gets the ASTNodes from lines. * * @param lines * the lines * @param compilationUnit * the compilation unit * @return the aST nodes from lines */ public static Collection<ASTNode> getASTNodesFromLines(Collection<Integer> lines, CompilationUnit compilationUnit) { MultipleLineNumbersVisitor linesVisitor = new MultipleLineNumbersVisitor(lines, compilationUnit); compilationUnit.accept(linesVisitor); return linesVisitor.getNodes(); } /** * Gets the lines from the AST nodes. * * @param nodes * the nodes * @param compilationUnit * the compilation unit * @return the lines from ast nodes */ public static Collection<Integer> getLinesFromASTNodes(Collection<ASTNode> nodes, CompilationUnit compilationUnit) { Set<Integer> lineSet = new HashSet<Integer>(); for (ASTNode node : nodes) { lineSet.add(compilationUnit.getLineNumber(node.getStartPosition())); } return lineSet; } /** * Gets the line from unit. * * @param unit * the unit * @return the line from unit */ public static Integer getLineFromUnit(Unit unit) { if (unit.hasTag("SourceLnPosTag")) { SourceLnPosTag lineTag = (SourceLnPosTag) unit.getTag("SourceLnPosTag"); return lineTag.startLn(); } return null; } /** * Gets the lines from units. * * @param units * the units * @return the lines from units */ public static Collection<Integer> getLinesFromUnits(Collection<Unit> units) { Set<Integer> lines = new HashSet<Integer>(units.size()); Iterator<Unit> iterator = units.iterator(); while (iterator.hasNext()) { Unit unit = iterator.next(); if (unit.hasTag("SourceLnPosTag")) { SourceLnPosTag lineTag = (SourceLnPosTag) unit.getTag("SourceLnPosTag"); lines.add(lineTag.startLn()); } } return lines; } /** * Gets the units from lines. * * @param lines * the lines * @param body * the body * @return the units from lines */ public static Collection<Unit> getUnitsFromLines(Collection<Integer> lines, Body body) { Set<Unit> unitSet = new HashSet<Unit>(); for (Integer line : lines) { Chain<Unit> units = body.getUnits(); for (Unit unit : units) { if (unit.hasTag("SourceLnPosTag")) { SourceLnPosTag lineTag = (SourceLnPosTag) unit.getTag("SourceLnPosTag"); if (lineTag != null) { if (lineTag.startLn() == line.intValue()) { unitSet.add(unit); } } } } } return unitSet; } }