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

com.strobel.decompiler.ast.PatternMatching Maven / Gradle / Ivy

There is a newer version: 2.5.0.Final
Show newest version
/*
 * PatternMatching.java
 *
 * Copyright (c) 2013 Mike Strobel
 *
 * This source code is based on Mono.Cecil from Jb Evain, Copyright (c) Jb Evain;
 * and ILSpy/ICSharpCode from SharpDevelop, Copyright (c) AlphaSierraPapa.
 *
 * This source code is subject to terms and conditions of the Apache License, Version 2.0.
 * A copy of the license can be found in the License.html file at the root of this distribution.
 * By using this source code in any fashion, you are agreeing to be bound by the terms of the
 * Apache License, Version 2.0.
 *
 * You must not remove this notice, or any other, from this software.
 */

package com.strobel.decompiler.ast;

import com.strobel.core.Comparer;
import com.strobel.core.Predicate;
import com.strobel.core.StrongBox;
import com.strobel.core.VerifyArgument;
import com.strobel.util.ContractUtils;

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

import static com.strobel.core.CollectionUtilities.any;
import static com.strobel.core.CollectionUtilities.single;

public final class PatternMatching {
    private PatternMatching() {
        throw ContractUtils.unreachable();
    }

    public static boolean match(final Node node, final AstCode code) {
        return node instanceof Expression &&
               ((Expression) node).getCode() == code;
    }

    public static boolean matchLeaveHandler(final Node node) {
        return match(node, AstCode.Leave) ||
               match(node, AstCode.EndFinally);
    }

    public static  boolean matchGetOperand(final Node node, final AstCode code, final StrongBox operand) {
        if (node instanceof Expression) {
            final Expression expression = (Expression) node;

            if (expression.getCode() == code &&
                expression.getArguments().isEmpty()) {

                operand.set(expression.getOperand());
                return true;
            }
        }

        operand.set(null);
        return false;
    }

    public static  boolean matchGetOperand(final Node node, final AstCode code, final Class operandType, final StrongBox operand) {
        if (node instanceof Expression) {
            final Expression expression = (Expression) node;

            if (expression.getCode() == code &&
                expression.getArguments().isEmpty() &&
                operandType.isInstance(expression.getOperand())) {

                operand.set(expression.getOperand());
                return true;
            }
        }

        operand.set(null);
        return false;
    }

    public static boolean matchGetArguments(final Node node, final AstCode code, final List arguments) {
        if (node instanceof Expression) {
            final Expression expression = (Expression) node;

            if (expression.getCode() == code) {
                assert expression.getOperand() == null;
                arguments.clear();
                arguments.addAll(expression.getArguments());
                return true;
            }
        }

        arguments.clear();
        return false;
    }

    public static  boolean matchGetArguments(final Node node, final AstCode code, final StrongBox operand, final List arguments) {
        if (node instanceof Expression) {
            final Expression expression = (Expression) node;

            if (expression.getCode() == code) {
                operand.set(expression.getOperand());
                arguments.clear();
                arguments.addAll(expression.getArguments());
                return true;
            }
        }

        operand.set(null);
        arguments.clear();
        return false;
    }

    public static boolean matchGetArgument(final Node node, final AstCode code, final StrongBox argument) {
        final ArrayList arguments = new ArrayList<>(1);

        if (matchGetArguments(node, code, arguments) && arguments.size() == 1) {
            argument.set(arguments.get(0));
            return true;
        }

        argument.set(null);
        return false;
    }

    public static  boolean matchGetArgument(
        final Node node,
        final AstCode code,
        final StrongBox operand,
        final StrongBox argument) {

        final ArrayList arguments = new ArrayList<>(1);

        if (matchGetArguments(node, code, operand, arguments) && arguments.size() == 1) {
            argument.set(arguments.get(0));
            return true;
        }

        argument.set(null);
        return false;
    }

    public static  boolean matchGetArguments(
        final Node node,
        final AstCode code,
        final StrongBox operand,
        final StrongBox argument1,
        final StrongBox argument2) {

        final ArrayList arguments = new ArrayList<>(2);

        if (matchGetArguments(node, code, operand, arguments) && arguments.size() == 2) {
            argument1.set(arguments.get(0));
            argument2.set(arguments.get(1));
            return true;
        }

        argument1.set(null);
        argument2.set(null);
        return false;
    }

    public static  boolean matchSingle(
        final Block block,
        final AstCode code,
        final StrongBox operand) {

        final List body = block.getBody();

        if (body.size() == 1 &&
            matchGetOperand(body.get(0), code, operand)) {

            return true;
        }

        operand.set(null);
        return false;
    }

    public static  boolean matchSingle(
        final Block block,
        final AstCode code,
        final StrongBox operand,
        final StrongBox argument) {

        final List body = block.getBody();

        if (body.size() == 1 &&
            matchGetArgument(body.get(0), code, operand, argument)) {

            return true;
        }

        operand.set(null);
        argument.set(null);
        return false;
    }

    public static boolean matchNullOrEmpty(final Block block) {
        return block == null || block.getBody().size() == 0;
    }

    public static boolean matchEmptyReturn(final Node node) {
        Node target = node;

        if (node instanceof Block || node instanceof BasicBlock) {
            final List body = node instanceof Block ? ((Block) node).getBody()
                                                          : ((BasicBlock) node).getBody();

            if (body.size() != 1) {
                return false;
            }

            target = body.get(0);
        }

        if (target instanceof Expression) {
            final Expression e = (Expression) target;

            return e.getCode() == AstCode.Return &&
                   e.getArguments().isEmpty();
        }

        return false;
    }

    public static  boolean matchSingle(
        final BasicBlock block,
        final AstCode code,
        final StrongBox operand,
        final StrongBox argument) {

        final List body = block.getBody();

        if (body.size() == 2 &&
            body.get(0) instanceof Label &&
            matchGetArgument(body.get(1), code, operand, argument)) {

            return true;
        }

        operand.set(null);
        argument.set(null);
        return false;
    }

    public static  boolean matchSingleAndBreak(
        final BasicBlock block,
        final AstCode code,
        final StrongBox operand,
        final StrongBox argument,
        final StrongBox




© 2015 - 2024 Weber Informatics LLC | Privacy Policy