Package org.adoptopenjdk.jitwatch.util

Source Code of org.adoptopenjdk.jitwatch.util.ParseUtil

/*
* Copyright (c) 2013, 2014 Chris Newland.
* Licensed under https://github.com/AdoptOpenJDK/jitwatch/blob/master/LICENSE-BSD
* Instructions: https://github.com/AdoptOpenJDK/jitwatch/wiki
*/
package org.adoptopenjdk.jitwatch.util;

import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.ATTR_ARGUMENTS;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.ATTR_HOLDER;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.ATTR_NAME;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.ATTR_RETURN;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.C_COLON;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.C_DOT;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.C_OBJECT_REF;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.C_OPEN_SQUARE_BRACKET;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.C_QUOTE;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.C_SEMICOLON;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.C_SLASH;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.C_SPACE;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.DEBUG_LOGGING_SIG_MATCH;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_ARRAY_BRACKET_PAIR;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_CLASS;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_CLOSE_PARENTHESES;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_DOT;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_DOUBLE_QUOTE;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_EMPTY;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_ENTITY_APOS;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_NEWLINE;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_OBJECT_ARRAY_DEF;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_OPEN_ANGLE;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_OPEN_PARENTHESES;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_PACKAGE;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_QUOTE;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_SEMICOLON;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_SLASH;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_SPACE;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_VARARGS_DOTS;

import java.text.NumberFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.adoptopenjdk.jitwatch.model.IMetaMember;
import org.adoptopenjdk.jitwatch.model.IParseDictionary;
import org.adoptopenjdk.jitwatch.model.IReadOnlyJITDataModel;
import org.adoptopenjdk.jitwatch.model.LogParseException;
import org.adoptopenjdk.jitwatch.model.MemberSignatureParts;
import org.adoptopenjdk.jitwatch.model.MetaClass;
import org.adoptopenjdk.jitwatch.model.PackageManager;
import org.adoptopenjdk.jitwatch.model.Tag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public final class ParseUtil
{
  private static final Logger logger = LoggerFactory.getLogger(ParseUtil.class);

  // class<SPACE>METHOD<SPACE>(PARAMS)RETURN

  public static String METHOD_NAME_REGEX_GROUP = "([\\p{L}0-9_<>\\.\\$]+)";

  private static final Pattern PATTERN_LOG_SIGNATURE = Pattern.compile("^([0-9\\p{L}\\.\\$_]+) " + METHOD_NAME_REGEX_GROUP
      + " (\\(.*\\))(.*)");

  private static final Pattern PATTERN_ASSEMBLY_SIGNATURE = Pattern.compile("^(.*)\\s'(.*)'\\s'(.*)'\\sin\\s'(.*)'");

  public static final String SQUARE_BRACKET_PAIR = "[]";
  public static final String CONSTRUCTOR_INIT = "<init>";
  public static final String STATIC_INIT = "<clinit>";
  public static final String STATIC_BYTECODE_SIGNATURE = "static {}";

  public static final String NAME_SHORT = "short";
  public static final String NAME_CHARACTER = "char";
  public static final String NAME_BYTE = "byte";
  public static final String NAME_LONG = "long";
  public static final String NAME_DOUBLE = "double";
  public static final String NAME_BOOLEAN = "boolean";
  public static final String NAME_INTEGER = "int";
  public static final String NAME_FLOAT = "float";
  public static final String NAME_VOID = "void";

  public static final char TYPE_SHORT = 'S';
  public static final char TYPE_CHARACTER = 'C';
  public static final char TYPE_BYTE = 'B';
  public static final char TYPE_VOID = 'V';
  public static final char TYPE_LONG = 'J';
  public static final char TYPE_DOUBLE = 'D';
  public static final char TYPE_BOOLEAN = 'Z';
  public static final char TYPE_INTEGER = 'I';
  public static final char TYPE_FLOAT = 'F';

  private ParseUtil()
  {
  }

  public static long parseStamp(String stamp)
  {
    long result = 0;

    if (stamp != null)
    {
      double number = parseLocaleSafeDouble(stamp);

      result = (long) (number * 1000);
    }
    else
    {
      logger.warn("Could not parse null stamp");
    }

    return result;
  }

  public static double parseLocaleSafeDouble(String str)
  {
    NumberFormat nf = NumberFormat.getInstance(Locale.getDefault());

    double result = 0;

    try
    {
      result = nf.parse(str).doubleValue();
    }
    catch (ParseException pe)
    {
      logger.error("", pe);
    }

    return result;
  }

  public static Class<?> getPrimitiveClass(char c)
  {
    switch (c)
    {
    case TYPE_SHORT:
      return Short.TYPE;
    case TYPE_CHARACTER:
      return Character.TYPE;
    case TYPE_BYTE:
      return Byte.TYPE;
    case TYPE_VOID:
      return Void.TYPE;
    case TYPE_LONG:
      return Long.TYPE;
    case TYPE_DOUBLE:
      return Double.TYPE;
    case TYPE_BOOLEAN:
      return Boolean.TYPE;
    case TYPE_INTEGER:
      return Integer.TYPE;
    case TYPE_FLOAT:
      return Float.TYPE;
    }

    throw new RuntimeException("Unknown class for " + c);
  }

  /*
   * [C => char[] [[I => int[][] [Ljava.lang.Object; => java.lang.Object[]
   */
  public static String expandParameterType(String name)
  {
    StringBuilder builder = new StringBuilder();

    int arrayDepth = 0;
    int pos = 0;

    outerloop: while (pos < name.length())
    {
      char c = name.charAt(pos);

      switch (c)
      {
      case C_OPEN_SQUARE_BRACKET:
        arrayDepth++;
        break;
      case TYPE_SHORT:
        builder.append(NAME_SHORT);
        break;
      case TYPE_CHARACTER:
        builder.append(NAME_CHARACTER);
        break;
      case TYPE_BYTE:
        builder.append(NAME_BYTE);
        break;
      case TYPE_LONG:
        builder.append(NAME_LONG);
        break;
      case TYPE_DOUBLE:
        builder.append(NAME_DOUBLE);
        break;
      case TYPE_BOOLEAN:
        builder.append(NAME_BOOLEAN);
        break;
      case TYPE_INTEGER:
        builder.append(NAME_INTEGER);
        break;
      case TYPE_FLOAT:
        builder.append(NAME_FLOAT);
        break;
      case C_SEMICOLON:
        break;
      default:
        if (name.charAt(pos) == C_OBJECT_REF && name.endsWith(S_SEMICOLON))
        {
          builder.append(name.substring(pos + 1, name.length() - 1));
        }
        else
        {
          builder.append(name.substring(pos));
        }
        break outerloop;
      }

      pos++;
    }

    for (int i = 0; i < arrayDepth; i++)
    {
      builder.append(SQUARE_BRACKET_PAIR);
    }

    return builder.toString();
  }

  public static String[] splitLogSignatureWithRegex(String logSignature) throws LogParseException
  {
    Matcher matcher = PATTERN_LOG_SIGNATURE.matcher(logSignature);

    if (matcher.find())
    {
      String className = matcher.group(1);
      String methodName = matcher.group(2);
      String paramTypes = matcher.group(3).replace(S_OPEN_PARENTHESES, S_EMPTY).replace(S_CLOSE_PARENTHESES, S_EMPTY);
      String returnType = matcher.group(4);

      return new String[] { className, methodName, paramTypes, returnType };
    }

    throw new LogParseException("Could not split signature with regex: " + logSignature);
  }

  public static IMetaMember findMemberWithSignature(IReadOnlyJITDataModel model, String logSignature) throws LogParseException
  {
    IMetaMember metaMember = null;

    if (logSignature != null)
    {
      MemberSignatureParts msp = MemberSignatureParts.fromLogCompilationSignature(logSignature);

      metaMember = model.findMetaMember(msp);

      if (metaMember == null)
      {
        throw new LogParseException("MetaMember not found for " + logSignature);
      }
    }

    return metaMember;
  }

  public static Class<?>[] getClassTypes(String typesString) throws LogParseException
  {
    List<Class<?>> classes = new ArrayList<Class<?>>();

    if (typesString.length() > 0)
    {
      try
      {
        findClassesForTypeString(typesString, classes);
      }
      catch (Throwable t)
      {
        throw new LogParseException("Could not parse types: " + typesString, t);
      }

    } // end if empty

    return classes.toArray(new Class<?>[classes.size()]);
  }

  public static Class<?> findClassForLogCompilationParameter(String param) throws ClassNotFoundException
  {
    StringBuilder builder = new StringBuilder();

    if (isPrimitive(param))
    {
      return classForPrimitive(param);
    }
    else
    {
      int arrayBracketCount = getArrayBracketCount(param);

      if (arrayBracketCount == 0)
      {
        if (param.endsWith(S_VARARGS_DOTS))
        {
          String partBeforeDots = param.substring(0, param.length() - S_VARARGS_DOTS.length());

          if (isPrimitive(partBeforeDots))
          {
            builder.append(S_OPEN_ANGLE).append(classForPrimitive(partBeforeDots));
          }
          else
          {
            builder.append(S_OBJECT_ARRAY_DEF).append(partBeforeDots);
            builder.append(C_SEMICOLON);
          }
        }
        else
        {
          builder.append(param);
        }
      }
      else
      {
        int arrayBracketChars = 2 * arrayBracketCount;

        String partBeforeArrayBrackets = param.substring(0, param.length() - arrayBracketChars);

        for (int i = 0; i < arrayBracketCount - 1; i++)
        {
          builder.append(C_OPEN_SQUARE_BRACKET);
        }

        if (isPrimitive(partBeforeArrayBrackets))
        {
          builder.append(C_OPEN_SQUARE_BRACKET);

          builder.append(getClassTypeCharForPrimitiveTypeString(partBeforeArrayBrackets));
        }
        else
        {
          builder.append(S_OBJECT_ARRAY_DEF);

          builder.append(param);

          builder.delete(builder.length() - arrayBracketChars, builder.length());

          builder.append(C_SEMICOLON);
        }
      }

      return ClassUtil.loadClassWithoutInitialising(builder.toString());
    }
  }

  public static boolean paramClassesMatch(boolean memberHasVarArgs, List<Class<?>> memberParamClasses,
      List<Class<?>> signatureParamClasses)
  {
    boolean result = true;

    final int memberParamCount = memberParamClasses.size();
    final int signatureParamCount = signatureParamClasses.size();

    if (DEBUG_LOGGING_SIG_MATCH)
    {
      logger.debug("M Count: {} S Count: {}", memberParamCount, signatureParamCount);
    }

    if (memberParamCount > 0 && signatureParamCount > 0)
    {
      int memPos = memberParamCount - 1;

      for (int sigPos = signatureParamCount - 1; sigPos >= 0; sigPos--)
      {
        Class<?> sigParamClass = signatureParamClasses.get(sigPos);

        Class<?> memParamClass = memberParamClasses.get(memPos);

        boolean memberParamCouldBeVarArgs = false;

        boolean isLastParameter = (memPos == memberParamCount - 1);

        if (memberHasVarArgs && isLastParameter)
        {
          memberParamCouldBeVarArgs = true;
        }

        if (memParamClass.isAssignableFrom(sigParamClass))
        {
          if (DEBUG_LOGGING_SIG_MATCH)
          {
            logger.debug("{} isAssignableFrom {}", memParamClass, sigParamClass);
          }

          if (memPos > 0)
          {
            // move to previous member parameter
            memPos--;
          }
          else if (sigPos > 0)
          {
            if (DEBUG_LOGGING_SIG_MATCH)
            {
              logger.debug("More signature params but no more member params to try");
            }

            result = false;
            break;
          }
        }
        else
        {
          if (memberParamCouldBeVarArgs)
          {
            // check assignable
            Class<?> componentType = memParamClass.getComponentType();

            if (!componentType.isAssignableFrom(sigParamClass))
            {
              result = false;
              break;
            }
          }
          else
          {
            result = false;
            break;
          }
        }
      }

      boolean unusedMemberParams = (memPos > 0);

      if (unusedMemberParams)
      {
        result = false;
      }
    }

    return result;
  }

  public static boolean typeIsVarArgs(String type)
  {
    return type != null && type.endsWith(S_VARARGS_DOTS);
  }

  public static char getClassTypeCharForPrimitiveTypeString(String type)
  {
    switch (type)
    {
    case NAME_INTEGER:
      return TYPE_INTEGER;
    case NAME_BOOLEAN:
      return TYPE_BOOLEAN;
    case NAME_LONG:
      return TYPE_LONG;
    case NAME_DOUBLE:
      return TYPE_DOUBLE;
    case NAME_FLOAT:
      return TYPE_FLOAT;
    case NAME_SHORT:
      return TYPE_SHORT;
    case NAME_BYTE:
      return TYPE_BYTE;
    case NAME_CHARACTER:
      return TYPE_CHARACTER;
    case NAME_VOID:
      return TYPE_VOID;
    }

    throw new RuntimeException(type + " is not a primitive type");
  }

  public static boolean isPrimitive(String type)
  {
    boolean result = false;

    if (type != null)
    {
      switch (type)
      {
      case NAME_INTEGER:
      case NAME_BOOLEAN:
      case NAME_LONG:
      case NAME_DOUBLE:
      case NAME_FLOAT:
      case NAME_SHORT:
      case NAME_BYTE:
      case NAME_CHARACTER:
      case NAME_VOID:
        result = true;
      }
    }

    return result;
  }

  public static Class<?> classForPrimitive(String primitiveType)
  {
    if (primitiveType != null)
    {
      switch (primitiveType)
      {
      case NAME_INTEGER:
        return int.class;
      case NAME_BOOLEAN:
        return boolean.class;
      case NAME_LONG:
        return long.class;
      case NAME_DOUBLE:
        return double.class;
      case NAME_FLOAT:
        return float.class;
      case NAME_SHORT:
        return short.class;
      case NAME_BYTE:
        return byte.class;
      case NAME_CHARACTER:
        return char.class;
      case NAME_VOID:
        return void.class;
      }
    }

    throw new RuntimeException(primitiveType + " is not a primitive type");
  }

  public static int getArrayBracketCount(String param)
  {
    int count = 0;

    if (param != null)
    {
      int index = param.indexOf(S_ARRAY_BRACKET_PAIR, 0);

      while (index != -1)
      {
        count++;

        index = param.indexOf(S_ARRAY_BRACKET_PAIR, index + 2);
      }
    }

    return count;
  }

  /*
   * Converts (III[Ljava.lang.String;) into a list of Class<?>
   */
  private static void findClassesForTypeString(String typesString, List<Class<?>> classes) throws ClassNotFoundException
  {

    int pos = 0;

    StringBuilder builder = new StringBuilder();

    final int stringLen = typesString.length();

    while (pos < stringLen)
    {
      char c = typesString.charAt(pos);

      switch (c)
      {
      case C_OPEN_SQUARE_BRACKET:
        // Could be
        // [Ljava.lang.String; Object array
        // [I primitive array
        // [..[I multidimensional primitive array
        // [..[Ljava.lang.String multidimensional Object array
        builder.delete(0, builder.length());
        builder.append(c);
        pos++;
        c = typesString.charAt(pos);

        while (c == C_OPEN_SQUARE_BRACKET)
        {
          builder.append(c);
          pos++;
          c = typesString.charAt(pos);
        }

        if (c == C_OBJECT_REF)
        {
          // array of ref type
          while (pos < stringLen)
          {
            c = typesString.charAt(pos++);
            builder.append(c);

            if (c == C_SEMICOLON)
            {
              break;
            }
          }
        }
        else
        {
          // array of primitive
          builder.append(c);
          pos++;
        }

        Class<?> arrayClass = ClassUtil.loadClassWithoutInitialising(builder.toString());
        classes.add(arrayClass);
        builder.delete(0, builder.length());
        break;
      case C_OBJECT_REF:
        // ref type
        while (pos < stringLen - 1)
        {
          pos++;
          c = typesString.charAt(pos);

          if (c == C_SEMICOLON)
          {
            pos++;
            break;
          }

          builder.append(c);
        }
        Class<?> refClass = ClassUtil.loadClassWithoutInitialising(builder.toString());
        classes.add(refClass);
        builder.delete(0, builder.length());
        break;
      default:
        // primitive
        Class<?> primitiveClass = ParseUtil.getPrimitiveClass(c);
        classes.add(primitiveClass);
        pos++;

      } // end switch

    } // end while
  }

  public static String findBestMatchForMemberSignature(IMetaMember member, List<String> lines)
  {
    String match = null;

    if (lines != null)
    {
      int index = findBestLineMatchForMemberSignature(member, lines);

      if (index > 0 && index < lines.size())
      {
        match = lines.get(index);
      }
    }

    return match;
  }

  public static int findBestLineMatchForMemberSignature(IMetaMember member, List<String> lines)
  {
    int bestScoreLine = 0;

    if (lines != null)
    {
      String memberName = member.getMemberName();
      int modifier = member.getModifier();
      String returnTypeName = member.getReturnTypeName();
      String[] paramTypeNames = member.getParamTypeNames();

      int bestScore = 0;

      for (int i = 0; i < lines.size(); i++)
      {
        String line = lines.get(i);

        int score = 0;

        if (line.contains(memberName))
        {
          MemberSignatureParts msp = MemberSignatureParts.fromBytecodeSignature(member.getMetaClass()
              .getFullyQualifiedName(), line);

          if (!memberName.equals(msp.getMemberName()))
          {
            continue;
          }

          // modifiers matched
          if (msp.getModifier() != modifier)
          {
            continue;
          }

          List<String> mspParamTypes = msp.getParamTypes();

          if (mspParamTypes.size() != paramTypeNames.length)
          {
            continue;
          }

          int pos = 0;

          for (String memberParamType : paramTypeNames)
          {
            String mspParamType = msp.getParamTypes().get(pos++);

            if (compareTypeEquality(memberParamType, mspParamType, msp.getGenerics()))
            {
              score++;
            }
          }

          // return type matched
          if (compareTypeEquality(returnTypeName, msp.getReturnType(), msp.getGenerics()))
          {
            score++;
          }

          if (score > bestScore)
          {
            bestScoreLine = i;
            bestScore = score;
          }
        }
      }
    }

    return bestScoreLine;
  }

  private static boolean compareTypeEquality(String memberTypeName, String inMspTypeName, Map<String, String> genericsMap)
  {
    String mspTypeName = inMspTypeName;
    if (memberTypeName != null && memberTypeName.equals(mspTypeName))
    {
      return true;
    }
    else if (mspTypeName != null)
    {
      // Substitute generics to match with non-generic signature
      // public static <T extends java.lang.Object, U extends
      // java.lang.Object> T[] copyOf(U[], int, java.lang.Class<? extends
      // T[]>)";
      // U[] -> java.lang.Object[]
      String mspTypeNameWithoutArray = getParamTypeWithoutArrayBrackets(mspTypeName);
      String genericSubstitution = genericsMap.get(mspTypeNameWithoutArray);

      if (genericSubstitution != null)
      {
        mspTypeName = mspTypeName.replace(mspTypeNameWithoutArray, genericSubstitution);

        if (memberTypeName != null && memberTypeName.equals(mspTypeName))
        {
          return true;
        }
      }
    }

    return false;
  }

  public static String getParamTypeWithoutArrayBrackets(String paramType)
  {
    int bracketsIndex = paramType.indexOf(SQUARE_BRACKET_PAIR);

    if (bracketsIndex != -1)
    {
      return paramType.substring(0, bracketsIndex);
    }
    else
    {
      return paramType;
    }
  }

  public static IMetaMember lookupMember(String methodId, IParseDictionary parseDictionary, IReadOnlyJITDataModel model)
  {
    IMetaMember result = null;

    Tag methodTag = parseDictionary.getMethod(methodId);

    if (methodTag != null)
    {
      String methodName = methodTag.getAttribute(ATTR_NAME);

      String klassId = methodTag.getAttribute(ATTR_HOLDER);

      Tag klassTag = parseDictionary.getKlass(klassId);

      String metaClassName = klassTag.getAttribute(ATTR_NAME);

      metaClassName = metaClassName.replace(S_SLASH, S_DOT);

      String returnTypeId = methodTag.getAttribute(ATTR_RETURN);

      String argumentsTypeId = methodTag.getAttribute(ATTR_ARGUMENTS);

      String returnType = lookupType(returnTypeId, parseDictionary);

      String[] argumentTypes = new String[0];

      if (argumentsTypeId != null)
      {
        String[] typeIDs = argumentsTypeId.split(S_SPACE);

        argumentTypes = new String[typeIDs.length];

        int pos = 0;

        for (String typeID : typeIDs)
        {
          argumentTypes[pos++] = lookupType(typeID, parseDictionary);
        }
      }

      PackageManager pm = model.getPackageManager();

      MetaClass metaClass = pm.getMetaClass(metaClassName);

      if (metaClass == null)
      {
        logger.debug("metaClass not found: {}. Attempting classload", metaClassName);

        // Possible that TraceClassLoading did not log this class
        // try to classload and add to model

        Class<?> clazz = null;

        try
        {
          clazz = ClassUtil.loadClassWithoutInitialising(metaClassName);

          if (clazz != null)
          {
            metaClass = model.buildAndGetMetaClass(clazz);
          }
        }
        catch (ClassNotFoundException cnf)
        {
          logger.error("ClassNotFoundException: '" + metaClassName + C_QUOTE);
        }
        catch (NoClassDefFoundError ncdf)
        {
          logger.error("NoClassDefFoundError: '" + metaClassName + C_SPACE + ncdf.getMessage() + C_QUOTE);
        }
      }

      if (metaClass != null)
      {
        MemberSignatureParts msp = MemberSignatureParts.fromParts(metaClass.getFullyQualifiedName(), methodName,
            returnType, argumentTypes);
        result = metaClass.getMemberFromSignature(msp);
      }
      else
      {
        logger.error("metaClass not found: {}", metaClassName);
      }
    }

    return result;
  }

  public static String lookupType(String typeOrKlassID, IParseDictionary parseDictionary)
  {
    String result = null;

    if (typeOrKlassID != null)
    {
      Tag typeTag = parseDictionary.getType(typeOrKlassID);

      if (typeTag == null)
      {
        typeTag = parseDictionary.getKlass(typeOrKlassID);
      }

      if (typeTag != null)
      {
        result = typeTag.getAttribute(ATTR_NAME).replace(S_SLASH, S_DOT);

        result = ParseUtil.expandParameterType(result);
      }
    }

    return result;
  }

  public static String convertNativeCodeMethodName(String inLine)
  {
    String line = inLine.replace(S_ENTITY_APOS, S_QUOTE);

    Matcher matcher = PATTERN_ASSEMBLY_SIGNATURE.matcher(line);

    String result = null;

    if (matcher.find())
    {
      String memberName = matcher.group(2);
      String params = matcher.group(3).replace(S_SLASH, S_DOT);
      String className = matcher.group(4).replace(S_SLASH, S_DOT);

      StringBuilder builder = new StringBuilder();
      builder.append(className).append(C_SPACE);
      builder.append(memberName).append(C_SPACE);
      builder.append(params);

      result = builder.toString();
    }

    return result;
  }

  public static String getPackageFromSource(String source)
  {
    String result = null;

    String[] lines = source.split(S_NEWLINE);

    for (String line : lines)
    {
      line = line.trim();

      if (line.startsWith(S_PACKAGE) && line.endsWith(S_SEMICOLON))
      {
        result = line.substring(S_PACKAGE.length(), line.length() - 1).trim();
      }
    }

    if (result == null)
    {
      result = S_EMPTY;
    }

    return result;
  }

  public static String getClassFromSource(String source)
  {
    String result = null;

    String[] lines = source.split(S_NEWLINE);

    String classToken = S_SPACE + S_CLASS + S_SPACE;

    for (String line : lines)
    {
      line = line.trim();

      int classTokenPos = line.indexOf(classToken);

      if (classTokenPos != -1)
      {
        result = line.substring(classTokenPos + classToken.length());
      }
    }

    if (result == null)
    {
      result = "";
    }

    return result;
  }

  public static IMetaMember getMemberFromComment(IReadOnlyJITDataModel model, final String comment) throws LogParseException
  {
    // java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;

    String replace1 = comment.replace(C_DOT, C_SPACE);
    String replace2 = replace1.replace(C_COLON, C_SPACE);
    String replace3 = replace2.replace(C_SLASH, C_DOT);
    String replace4 = replace3.replace(S_DOUBLE_QUOTE, S_EMPTY);

    return ParseUtil.findMemberWithSignature(model, replace4);
  }
}
TOP

Related Classes of org.adoptopenjdk.jitwatch.util.ParseUtil

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.