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

mockit.internal.util.MethodFormatter Maven / Gradle / Ivy

Go to download

JMockit is a Java toolkit for automated developer testing. It contains mocking/faking APIs and a code coverage tool, supporting both JUnit and TestNG. The mocking APIs allow all kinds of Java code, without testability restrictions, to be tested in isolation from selected dependencies.

There is a newer version: 1.49
Show newest version
/*
 * Copyright (c) 2006 JMockit developers
 * This file is subject to the terms of the MIT license (see LICENSE.txt).
 */
package mockit.internal.util;

import java.util.*;
import javax.annotation.*;

import mockit.internal.state.*;

public final class MethodFormatter
{
   @Nonnull private final StringBuilder out;
   @Nonnull private final List parameterTypes;
   @Nonnull private final String classDesc;
   @Nonnull private String methodDesc;

   // Auxiliary fields for handling method parameters:
   private int parameterIndex;
   private int typeDescPos;
   private char typeCode;
   private int arrayDimensions;

   public MethodFormatter(@Nonnull String classDesc, @Nonnull String methodNameAndDesc) {
      this(classDesc, methodNameAndDesc, true);
   }

   public MethodFormatter(@Nonnull String classDesc, @Nonnull String methodNameAndDesc, boolean withParametersAppended) {
      out = new StringBuilder();
      parameterTypes = new ArrayList(5);
      this.classDesc = classDesc;
      methodDesc = "";
      methodDesc = methodNameAndDesc;
      appendFriendlyMethodSignature(withParametersAppended);
   }

   @Override
   public String toString() { return out.toString(); }

   @Nonnull public List getParameterTypes() { return parameterTypes; }

   private void appendFriendlyMethodSignature(boolean withParametersAppended) {
      String className = classDesc.replace('/', '.');
      out.append(className).append('#');

      String constructorName = getConstructorName(className);
      String friendlyDesc = methodDesc.replace("", constructorName);

      int leftParenNextPos = friendlyDesc.indexOf('(') + 1;
      int rightParenPos = friendlyDesc.indexOf(')');

      if (leftParenNextPos < rightParenPos) {
         out.append(friendlyDesc.substring(0, leftParenNextPos));

         String concatenatedParameterTypes = friendlyDesc.substring(leftParenNextPos, rightParenPos);

         if (withParametersAppended) {
            parameterIndex = 0;
            appendParameterTypesAndNames(concatenatedParameterTypes);
            out.append(')');
         }
         else {
            addParameterTypes(concatenatedParameterTypes);
         }
      }
      else {
         out.append(friendlyDesc.substring(0, rightParenPos + 1));
      }
   }

   @Nonnull
   private static String getConstructorName(@Nonnull String className) {
      int p = className.lastIndexOf('.');
      String constructorName = p < 0 ? className : className.substring(p + 1);

      //noinspection ReuseOfLocalVariable
      p = constructorName.lastIndexOf('$');

      if (p > 0) {
         constructorName = constructorName.substring(p + 1);
      }

      return constructorName;
   }

   private void appendParameterTypesAndNames(@Nonnull String typeDescs) {
      String sep = "";

      for (String typeDesc : typeDescs.split(";")) {
         out.append(sep);

         if (typeDesc.charAt(0) == 'L') {
            appendParameterType(friendlyReferenceType(typeDesc));
            appendParameterName();
         }
         else {
            appendPrimitiveParameterTypesAndNames(typeDesc);
         }

         sep = ", ";
      }
   }

   @Nonnull
   private static String friendlyReferenceType(@Nonnull String typeDesc) {
      return typeDesc.substring(1).replace("java/lang/", "").replace('/', '.');
   }

   private void appendParameterType(@Nonnull String friendlyTypeDesc) {
      out.append(friendlyTypeDesc);
      parameterTypes.add(friendlyTypeDesc);
   }

   private void appendParameterName() {
      String name = ParameterNames.getName(classDesc, methodDesc, parameterIndex);

      if (name != null) {
         out.append(' ').append(name);
      }

      parameterIndex++;
   }

   private void appendPrimitiveParameterTypesAndNames(@Nonnull String typeDesc) {
      String sep = "";

      for (typeDescPos = 0; typeDescPos < typeDesc.length(); typeDescPos++) {
         typeCode = typeDesc.charAt(typeDescPos);
         advancePastArrayDimensionsIfAny(typeDesc);

         out.append(sep);

         String paramType = getTypeNameForTypeDesc(typeDesc) + getArrayBrackets();
         appendParameterType(paramType);
         appendParameterName();

         sep = ", ";
      }
   }

   private void addParameterTypes(@Nonnull String typeDescs) {
      for (String typeDesc : typeDescs.split(";")) {
         if (typeDesc.charAt(0) == 'L') {
            parameterTypes.add(friendlyReferenceType(typeDesc));
         }
         else {
            addPrimitiveParameterTypes(typeDesc);
         }
      }
   }

   private void addPrimitiveParameterTypes(@Nonnull String typeDesc) {
      for (typeDescPos = 0; typeDescPos < typeDesc.length(); typeDescPos++) {
         typeCode = typeDesc.charAt(typeDescPos);
         advancePastArrayDimensionsIfAny(typeDesc);

         String paramType = getTypeNameForTypeDesc(typeDesc) + getArrayBrackets();
         parameterTypes.add(paramType);
      }
   }

   @Nonnull @SuppressWarnings("OverlyComplexMethod")
   private String getTypeNameForTypeDesc(@Nonnull String typeDesc) {
      String paramType;

      switch (typeCode) {
         case 'B': return "byte";
         case 'C': return "char";
         case 'D': return "double";
         case 'F': return "float";
         case 'I': return "int";
         case 'J': return "long";
         case 'S': return "short";
         case 'V': return "void";
         case 'Z': return "boolean";
         case 'L':
            paramType = friendlyReferenceType(typeDesc.substring(typeDescPos));
            typeDescPos = typeDesc.length();
            break;
         default:
            paramType = typeDesc.substring(typeDescPos);
            typeDescPos = typeDesc.length();
      }

      return paramType;
   }

   private void advancePastArrayDimensionsIfAny(@Nonnull String param) {
      arrayDimensions = 0;

      while (typeCode == '[') {
         typeDescPos++;
         typeCode = param.charAt(typeDescPos);
         arrayDimensions++;
      }
   }

   @Nonnull
   private String getArrayBrackets() {
      @SuppressWarnings("NonConstantStringShouldBeStringBuffer")
      String result = "";

      for (int i = 0; i < arrayDimensions; i++) {
         //noinspection StringContatenationInLoop
         result += "[]";
      }

      return result;
   }

   public void append(@Nonnull String text) { out.append(text); }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy