private static SourceSpec methodFromString(String str) {
        str = str.trim();
        int len = str.length();
        int i = 0;
        while (Character.isWhitespace(str.charAt(i))) i++;

        int start = i;
        while (i < len && !Character.isWhitespace(str.charAt(i))) i++;

        String returnStatement;
        if (i == len) {
            i = 0;
            returnStatement = "";
        } else {
            returnStatement = str.substring(start, i);
        }
        Type returnTy;
        Type declaringTy;
        String[] paramTypeNames;
        String name;

        returnTy = Type.forName(returnStatement);
        start = i;
        i = str.indexOf('(', i);
        i = str.lastIndexOf('.', i);
        declaringTy = Type.forName(str.substring(start, i).trim());

        start = ++i;
        i = str.indexOf('(', i);
        name = str.substring(start, i).trim();
        start = ++i;
        i = str.indexOf(')', i);

        paramTypeNames = parseParamTypeNames(str.substring(start, i).trim());

        Type[] paramTys = Type.forNames(paramTypeNames);
        return new SourceSpec(
                name.equals("<init>") ? Kind.CONSTRUCTOR : Kind.METHOD,
                returnTy,
                declaringTy,
                name,
                paramTys);
    }
This is a parser for custom aop pointcut expression.
<p>
Such as <pre>int android.util.Log.d(java.lang.String,java.lang.String)</pre>
plugin/src/main/groovy/com/didichuxing/tools/droidassist/spec/SourceSpec.java