Commit 3860ac7e authored by Carlos Galindo's avatar Carlos Galindo
Browse files

MULTIPLE COMMITS 4 EXPERIMENTS

ObjectTree: make fields into arrays of Strings.

- The previous approach used a single string, with fields separated by dots.
- The inclusion of packages in class names thwarts the previous approach.
parent eb2d8253
Loading
Loading
Loading
Loading
+17 −22
Original line number Diff line number Diff line
package es.upv.mist.slicing.cli;

import com.github.javaparser.JavaParser;
import com.github.javaparser.ParseResult;
import com.github.javaparser.ParserConfiguration;
import com.github.javaparser.Problem;
import com.github.javaparser.StaticJavaParser;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.comments.BlockComment;
import com.github.javaparser.ast.nodeTypes.NodeWithName;
import com.github.javaparser.symbolsolver.JavaSymbolSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
import es.upv.mist.slicing.graphs.augmented.ASDG;
import es.upv.mist.slicing.graphs.augmented.PSDG;
import es.upv.mist.slicing.graphs.exceptionsensitive.ESSDG;
@@ -21,12 +16,15 @@ import es.upv.mist.slicing.slicing.FileLineSlicingCriterion;
import es.upv.mist.slicing.slicing.Slice;
import es.upv.mist.slicing.slicing.SlicingCriterion;
import es.upv.mist.slicing.utils.NodeHashSet;
import es.upv.mist.slicing.utils.StaticTypeSolver;
import org.apache.commons.cli.*;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;
@@ -175,24 +173,21 @@ public class Slicer {

    public void slice() throws ParseException {
        // Configure JavaParser
        ParserConfiguration parserConfig = new ParserConfiguration();
        parserConfig.setAttributeComments(false);
        CombinedTypeSolver cts = new CombinedTypeSolver();
        cts.add(new ReflectionTypeSolver(true));
        Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.INFO, "Configuring JavaParser");
        StaticTypeSolver.addTypeSolverJRE();
        for (File directory : dirIncludeSet)
            if (directory.isDirectory())
                cts.add(new JavaParserTypeSolver(directory));
        parserConfig.setSymbolResolver(new JavaSymbolSolver(cts));
        JavaParser parser = new JavaParser(parserConfig);
            StaticTypeSolver.addTypeSolver(new JavaParserTypeSolver(directory));
        StaticJavaParser.getConfiguration().setAttributeComments(false);

        // Build the SDG
        Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.INFO, "Parsing files");
        Set<CompilationUnit> units = new NodeHashSet<>();
        List<Problem> problems = new LinkedList<>();
        boolean scFileFound = false;
        for (File file : (Iterable<File>) findAllJavaFiles(dirIncludeSet)::iterator)
            scFileFound |= parse(parser, file, units, problems);
            scFileFound |= parse(file, units, problems);
        if (!scFileFound)
            parse(parser, scFile, units, problems);
            parse(scFile, units, problems);
        if (!problems.isEmpty()) {
            for (Problem p : problems)
                System.out.println(" * " + p.getVerboseMessage());
@@ -209,16 +204,20 @@ public class Slicer {
            default:
                throw new IllegalArgumentException("Unknown type of graph. Available graphs are SDG, ASDG, PSDG, ESSDG");
        }
        Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.INFO, "Building the SDG");
        sdg.build(new NodeList<>(units));

        // Slice the SDG
        Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.INFO, "Searching for criterion and slicing");
        SlicingCriterion sc = new FileLineSlicingCriterion(scFile, scLine, scVar);
        Slice slice = sdg.slice(sc);

        // Convert the slice to code and output the result to `outputDir`
        Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.INFO, "Printing slice to files");
        for (CompilationUnit cu : slice.toAst()) {
            if (cu.getStorage().isEmpty())
                throw new IllegalStateException("A synthetic CompilationUnit was discovered, with no file associated to it.");
            Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.INFO, "Printing slice for " + cu.getStorage().get().getFileName());
            String packagePath = cu.getPackageDeclaration().map(NodeWithName::getNameAsString).orElse("").replace(".", "/");
            File packageDir = new File(outputDir, packagePath);
            packageDir.mkdirs();
@@ -232,13 +231,9 @@ public class Slicer {
        }
    }

    private boolean parse(JavaParser parser, File file, Set<CompilationUnit> units, List<Problem> problems) {
    private boolean parse(File file, Set<CompilationUnit> units, List<Problem> problems) {
        try {
            ParseResult<CompilationUnit> result = parser.parse(file);
            if (result.isSuccessful())
                result.ifSuccessful(units::add);
            else
                problems.addAll(result.getProblems());
            units.add(StaticJavaParser.parse(file));
        } catch (FileNotFoundException e) {
            problems.add(new Problem(e.getLocalizedMessage(), null, e));
        }
+5 −0
Original line number Diff line number Diff line
package es.upv.mist.slicing.arcs.pdg;

import es.upv.mist.slicing.arcs.Arc;
import es.upv.mist.slicing.utils.Utils;

/** Represents a data dependency in an object-oriented SDG or PDG. */
public class FlowDependencyArc extends Arc {
@@ -12,4 +13,8 @@ public class FlowDependencyArc extends Arc {
        super(variable);
    }

    public FlowDependencyArc(String[] member) {
        super(Utils.arrayJoin(member, "."));
    }

}
+1 −1
Original line number Diff line number Diff line
@@ -271,7 +271,7 @@ public class CallGraph extends DirectedPseudograph<CallGraph.Vertex, CallGraph.E

        @Override
        public int hashCode() {
            return Objects.hash(declaration, declaration.getRange());
            return Objects.hash(declaration.getSignature(), declaration.getRange());
        }

        @Override
+18 −7
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@ package es.upv.mist.slicing.graphs;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.body.*;
import com.github.javaparser.ast.nodeTypes.NodeWithName;
import com.github.javaparser.ast.type.TypeParameter;
import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
import com.github.javaparser.resolution.UnsolvedSymbolException;
@@ -19,6 +20,8 @@ import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static es.upv.mist.slicing.nodes.ObjectTree.ROOT_NODE;

public class ClassGraph extends DirectedPseudograph<ClassGraph.Vertex<?>, ClassGraph.ClassArc> implements Buildable<NodeList<CompilationUnit>> {
    private static ClassGraph instance = null;

@@ -191,10 +194,10 @@ public class ClassGraph extends DirectedPseudograph<ClassGraph.Vertex<?>, ClassG
    protected ObjectTree generateObjectTreeFor(Vertex<? extends TypeDeclaration<?>> classVertex) {
        if (classVertex == null)
            return new ObjectTree();
        return generatePolyObjectTreeFor(classVertex, new ObjectTree(), ObjectTree.ROOT_NAME, 0);
        return generatePolyObjectTreeFor(classVertex, new ObjectTree(), ROOT_NODE, 0);
    }

    protected ObjectTree generatePolyObjectTreeFor(Vertex<? extends TypeDeclaration<?>> classVertex, ObjectTree tree, String level, int depth) {
    protected ObjectTree generatePolyObjectTreeFor(Vertex<? extends TypeDeclaration<?>> classVertex, ObjectTree tree, String[] level, int depth) {
        if (depth >= StaticConfig.K_LIMIT)
            return tree;
        Set<? extends TypeDeclaration<?>> types = subclassesOf(classVertex);
@@ -205,19 +208,25 @@ public class ClassGraph extends DirectedPseudograph<ClassGraph.Vertex<?>, ClassG
                Vertex<? extends TypeDeclaration<?>> subclassVertex = classDeclarationMap.get(mapKey(type));
                if (!findAllFieldsOf(subclassVertex).isEmpty()) {
                    ObjectTree newType = tree.addType(ASTUtils.resolvedTypeDeclarationToResolvedType(type.resolve()), level);
                    generateObjectTreeFor(subclassVertex, tree, level + '.' + newType.getMemberNode().getLabel(), depth + 1);
                    String[] newLevel = new String[level.length + 1];
                    System.arraycopy(level, 0, newLevel, 0, level.length);
                    newLevel[level.length] = newType.getMemberNode().getLabel();
                    generateObjectTreeFor(subclassVertex, tree, newLevel, depth + 1);
                }
            }
        }
        return tree;
    }

    protected void generateObjectTreeFor(Vertex<? extends TypeDeclaration<?>> classVertex, ObjectTree tree, String level, int depth) {
    protected void generateObjectTreeFor(Vertex<? extends TypeDeclaration<?>> classVertex, ObjectTree tree, String[] level, int depth) {
        Map<String, Vertex<? extends TypeDeclaration<?>>> classFields = findAllFieldsOf(classVertex);
        for (var entry : classFields.entrySet()) {
            tree.addField(level + '.' + entry.getKey());
            String[] newLevel = new String[level.length + 1];
            System.arraycopy(level, 0, newLevel, 0, level.length);
            newLevel[level.length] = entry.getKey();
            tree.addField(newLevel);
            if (entry.getValue() != null)
                generatePolyObjectTreeFor(entry.getValue(), tree, level + '.' + entry.getKey(), depth);
                generatePolyObjectTreeFor(entry.getValue(), tree, newLevel, depth);
        }
    }

@@ -441,7 +450,9 @@ public class ClassGraph extends DirectedPseudograph<ClassGraph.Vertex<?>, ClassG

        @Override
        public int hashCode() {
            return Objects.hash(declaration, declaration.getRange());
            if (declaration instanceof NodeWithName<?>)
                return Objects.hash(((NodeWithName<?>) declaration).getNameAsString(), declaration.getRange());
            return Objects.hash(String.valueOf(declaration), declaration.getRange());
        }

        @Override
+2 −5
Original line number Diff line number Diff line
@@ -98,15 +98,12 @@ public class CFG extends GraphWithRootNode<CallableDeclaration<?>> {
            stream = stream.takeWhile(va -> va != var);
        List<VariableAction> list = stream.filter(var::matches).filter(filter).collect(Collectors.toList());
        if (!list.isEmpty()) {
            boolean found = false;
            for (int i = list.size() - 1; i >= 0 && !found; i--) {
            for (int i = list.size() - 1; i >= 0; i--) {
                result.add(list.get(i));
                if (!list.get(i).isOptional())
                    found = true;
            }
            if (found)
                    return true;
            }
        }

        // Not found: traverse backwards!
        boolean allBranches = !incomingEdgesOf(currentNode).isEmpty();
Loading