package org.mutabilitydetector.checkers.settermethod; /* * #%L * MutabilityDetector * %% * Copyright (C) 2008 - 2014 Graham Allan * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * #L% */ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import java.lang.String; import java.util.ArrayList; import java.util.List; import javax.annotation.concurrent.NotThreadSafe; import org.objectweb.asm.Type; import org.objectweb.asm.commons.Method; import org.objectweb.asm.tree.*; /** * @author Juergen Fickel (jufickel@htwg-konstanz.de) * @version 17.02.2013 */ @NotThreadSafe final class EnhancedClassNode { private final ClassNode classNode; private final ControlFlowBlockCache cfbCache; private EnhancedClassNode(final ClassNode theClassNode) { classNode = theClassNode; cfbCache = ControlFlowBlockCache.newInstance(theClassNode.name); } public static EnhancedClassNode newInstance(final ClassNode classNode) { return new EnhancedClassNode(checkNotNull(classNode)); } public String getName() { return classNode.name; } public List<FieldNode> getFields() { return classNode.fields; } public List<MethodNode> getMethods() { return classNode.methods; } FieldNode findVariableWithName(final String variableName) { checkArgument(!variableName.isEmpty()); for (final FieldNode variable : getFields()) { if (variableName.equals(variable.name)) { return variable; } } return null; } List<MethodNode> findMethodByName(final String methodName) { checkArgument(!methodName.isEmpty()); final ArrayList<MethodNode> result = new ArrayList<MethodNode>(); for (final MethodNode method : getMethods()) { if (methodName.equals(method.name)) { result.add(method); } } result.trimToSize(); return result; } MethodNode findMethodByDescriptor(final String methodName, final Type returnType, final Type... argumentTypes) { checkArgument(!methodName.isEmpty(), "Parameter 'methodName' must neither be null nor empty!"); checkNotNull(returnType, "Parameter 'returnType' must not be null!"); final String desc = createDescriptorFor(methodName, returnType, argumentTypes); return findMethodByDescriptor(methodName, desc); } MethodNode findMethodByDescriptor(final String methodName, final String descriptor) { checkArgument(!methodName.isEmpty(), "Parameter 'methodName' must neither be null nor empty!"); checkArgument(!descriptor.isEmpty(), "Parameter 'descriptor' must neither be null nor empty!"); for (final MethodNode method : getMethods()) { if (method.name.equals(methodName) && method.desc.equals(descriptor)) { return method; } } return null; } private static String createDescriptorFor(final String methodName, final Type returnType, final Type[] argumentTypes) { final Method method = new Method(methodName, returnType, argumentTypes); return method.getDescriptor(); } /** * Delivers all {@link ControlFlowBlock}s of the given * {@link MethodNode}. * * @param method * the method. Must not be {@code null}. * @return a {@link List} containing all {@link ControlFlowBlock}s * of {@code method}. Is never {@code null}. * @see #findMethodByDescriptor(String, Type, Type...) * @see #findMethodByName(String) * @see #getControlFlowBlocksForMethod(String, Type, Type...) */ public List<ControlFlowBlock> getControlFlowBlocksForMethod(final MethodNode method) { return cfbCache.getControlFlowBlocksForMethod(method); } /** * Delivers all {@link ControlFlowBlock}s of a method which is * described by its name, its return type as well as its * argumentTypes. * * @param methodName * name of the method. Must neither be {@code null} nor * empty. * @param returnType * the {@link Type} of the return value of the * described method. Must not be {@code null}. * @param argumentTypes * (optional) the types of the method's arguments. * @return a {@link List} containing all {@link ControlFlowBlock}s * of the method which is described by {@code methodName}, * {@code returnType} and {@code argumentTypes}. Is never * {@code null}. * @see #getControlFlowBlocksForMethod(MethodNode) */ List<ControlFlowBlock> getControlFlowBlocksForMethod(final String methodName, final Type returnType, final Type... argumentTypes) { final MethodNode method = findMethodByDescriptor(methodName, returnType, argumentTypes); return getControlFlowBlocksForMethod(method); } @Override public String toString() { final StringBuilder builder = new StringBuilder(); builder.append(getClass().getSimpleName()).append(" [").append("classNode=").append(classNode); builder.append(", cfbCache=").append(cfbCache).append(']'); return builder.toString(); } }