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

jp.skypencil.findbugs.slf4j.parameter.ArrayDataHandler Maven / Gradle / Ivy

There is a newer version: 1.5.0
Show newest version
package jp.skypencil.findbugs.slf4j.parameter;


import org.apache.bcel.Constants;

import edu.umd.cs.findbugs.OpcodeStack;
import edu.umd.cs.findbugs.OpcodeStack.Item;

/**
 * This class is responsible to create/update ArrayData instance in userValue.
 */
public class ArrayDataHandler {
    private final Strategy strategy;

    ArrayDataHandler (Strategy strategy) {
        this.strategy = strategy;
    }

    void sawOpcode(OpcodeStack stack, int seen) {
        if (seen == Constants.AASTORE) {
            checkStoredInstance(stack);
        }
    }

    /**
     * Call this method before #afterOpcode of detector.
     * If this method returns new userValue, attach it to the head value of stack
     * after #afterOpcode of detector is called.
     *
     * @return non-null if seen == ANEWARRAY
     */
    ArrayData afterOpcode(OpcodeStack stack, int seen, String className, int pc) {
        if (seen != Constants.ANEWARRAY) {
            return null;
        } else if (stack.isTop()) {
            // see https://github.com/eller86/findbugs-slf4j/issues/29
            System.err.printf("ArrayDataHandler: stack is TOP, cannot be analyzed. %s:%d%n",
                    className, pc);
            return null;
        }
        return tryToDetectArraySize(stack);
    }

    private void checkStoredInstance(OpcodeStack stack) {
        Item storedValue = stack.getStackItem(0);
        Item arrayIndexItem = stack.getStackItem(1);
        Item targetArray = stack.getStackItem(2);
        Object arrayIndex = arrayIndexItem.getConstant();

        if (arrayIndex instanceof Number) {
            ArrayData data = (ArrayData) targetArray.getUserValue();
            Number index = (Number) arrayIndex;
            store(storedValue, data, index.intValue());
        }
    }

    private ArrayData tryToDetectArraySize(OpcodeStack stack) {
        Item arraySizeItem = stack.getStackItem(0);
        final int arraySize;

        if (arraySizeItem != null && arraySizeItem.getConstant() instanceof Number) {
            // save array size as "user value"
            arraySize = ((Number) arraySizeItem.getConstant()).intValue();
        } else {
            // currently we ignore array which gets variable as array size (like `new Object[a]`)
            arraySize = -1;
        }

        return new ArrayData(arraySize);
    }

    void store(Item storedItem, ArrayData arrayData, int index) {
        strategy.store(storedItem, arrayData, index);
    }

    public static interface Strategy {
        void store(Item storedItem, ArrayData arrayData, int index);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy