All Downloads are FREE. Search and download functionalities are using the official Maven repository.

tool.designpatterns.verifiers.multiclassverifiers.compositeverifier.LoopVisitor Maven / Gradle / Ivy

The newest version!
package tool.designpatterns.verifiers.multiclassverifiers.compositeverifier;

import java.util.ArrayList;
import java.util.List;

import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.expr.MethodCallExpr;
import com.github.javaparser.ast.expr.MethodReferenceExpr;
import com.github.javaparser.ast.stmt.DoStmt;
import com.github.javaparser.ast.stmt.ForEachStmt;
import com.github.javaparser.ast.stmt.ForStmt;
import com.github.javaparser.ast.stmt.WhileStmt;
import com.github.javaparser.ast.visitor.GenericVisitorAdapter;
import com.github.javaparser.ast.visitor.Visitable;
import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
import com.github.javaparser.resolution.UnsolvedSymbolException;
import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserMethodDeclaration;

import tool.designpatterns.verifiers.VerifierUtils;
import tool.feedback.Feedback;
import tool.feedback.FeedbackTrace;

/**
 * This Visitor finds all loops and then accepts the Visitor {@link ComponentMethodVisitor}.
 */
final class LoopVisitor extends GenericVisitorAdapter {

    private int nbrInteratingBlocks;

    /* default */ LoopVisitor() {
        super();
        nbrInteratingBlocks = 0;
    }

    @Override
    public Feedback visit(
        ForStmt loopStmt, MethodDeclaration parentMethod) {
        super.visit(loopStmt, parentMethod);
        nbrInteratingBlocks++;
        return verifyLoop(loopStmt.getBody(), parentMethod);
    }

    @Override
    public Feedback visit(
        WhileStmt loopStmt, MethodDeclaration parentMethod) {
        super.visit(loopStmt, parentMethod);
        nbrInteratingBlocks++;
        return verifyLoop(loopStmt.getBody(), parentMethod);
    }

    @Override
    public Feedback visit(
        DoStmt loopStmt, MethodDeclaration parentMethod) {
        super.visit(loopStmt, parentMethod);
        nbrInteratingBlocks++;
        return verifyLoop(loopStmt.getBody(), parentMethod);
    }

    @Override
    public Feedback visit(
        ForEachStmt loopStmt, MethodDeclaration parentMethod) {
        super.visit(loopStmt, parentMethod);
        nbrInteratingBlocks++;
        return verifyLoop(loopStmt.getBody(), parentMethod);
    }

    @Override
    public Feedback visit(
        MethodCallExpr loopFunc, MethodDeclaration parentMethod) {
        super.visit(loopFunc, parentMethod);
        if (loopFunc.getNameAsString().equalsIgnoreCase("forEach")) {
            nbrInteratingBlocks++;
            return verifyLoop(loopFunc.getArgument(0), parentMethod);
        }
        return Feedback.getSuccessfulFeedback();
    }

    public void resetIteratingBlocks() {
        nbrInteratingBlocks = 0;
    }

    @SuppressWarnings("PMD.LinguisticNaming")
    public Feedback hasIteratingBlock(MethodDeclaration methodInContainer) {
        if (nbrInteratingBlocks == 0) {
            return Feedback.getNoChildFeedback("The method has no iterating block",
                                               new FeedbackTrace(methodInContainer));
        } else {
            return Feedback.getSuccessfulFeedback();
        }

    }

    private Feedback verifyLoop(Visitable loop, MethodDeclaration parentMethod) {
        ComponentMethodVisitor visitor = new ComponentMethodVisitor();
        loop.accept(visitor, parentMethod);
        if (visitor.getDoesDelegate().stream().anyMatch(e -> e)) {
            return Feedback.getSuccessfulFeedback();
        } else {
            return Feedback.getNoChildFeedback("Container method does not delegate method call",
                                               new FeedbackTrace(parentMethod));
        }
    }

    /**
     * This visitor is used in The Class LoopVisitor and checks the method passed is ever called.
     */
    private static class ComponentMethodVisitor extends VoidVisitorAdapter {

        private final List doesDelegate;

        private ComponentMethodVisitor() {
            super();
            this.doesDelegate = new ArrayList<>();
        }

        private List getDoesDelegate() {
            return doesDelegate;
        }

        @Override
        public void visit(
            MethodCallExpr methodCall, MethodDeclaration parentMethod) {
            super.visit(methodCall, parentMethod);
            try {
                JavaParserMethodDeclaration methodDeclaration =
                    (JavaParserMethodDeclaration) methodCall.resolve();
                doesDelegate.add(VerifierUtils
                                     .hasSameMethodHeader(methodDeclaration.getWrappedNode(),
                                                          parentMethod));
                // Standard library methods like List.get(index) or System.out.println throws
                // ClassCastException as their declaration is outside the scope of this project.
            } catch (ClassCastException exception) {
                doesDelegate.add(Boolean.FALSE);
            }
        }

        @Override
        public void visit(
            MethodReferenceExpr methodReference, MethodDeclaration parentMethod) {
            super.visit(methodReference, parentMethod);
            try {
                JavaParserMethodDeclaration methodDeclaration =
                    (JavaParserMethodDeclaration) methodReference.resolve();
                doesDelegate.add(VerifierUtils
                                     .hasSameMethodHeader(methodDeclaration.getWrappedNode(),
                                                          parentMethod));
                // TypeSolver can't seem to handle MethodReferenceExpr:s when their declaration
                // is outside of the project. This then throws UnsolvedSymbolException. The only
                // mentioned solution we found was to use Spoon...
            } catch (UnsolvedSymbolException exception) {
                doesDelegate.add(Boolean.FALSE);
            }
        }

    }

}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy