• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package android.signature.cts;
17 
18 import java.util.ArrayList;
19 import java.util.List;
20 import java.util.regex.Matcher;
21 import java.util.regex.Pattern;
22 import java.util.stream.Collectors;
23 
24 public class DexMethod extends DexMember {
25   private final List<String> mParamTypeList;
26 
DexMethod(String className, String name, String signature, String[] flags)27   public DexMethod(String className, String name, String signature, String[] flags) {
28       super(className, name, parseDexReturnType(signature), flags);
29       mParamTypeList = parseDexTypeList(signature);
30   }
31 
getDexSignature()32   public String getDexSignature() {
33       return "(" + String.join("", mParamTypeList) + ")" + getDexType();
34   }
35 
getJavaParameterTypes()36   public List<String> getJavaParameterTypes() {
37       return mParamTypeList.stream().map(DexMember::dexToJavaType).collect(Collectors.toList());
38   }
39 
isConstructor()40   public boolean isConstructor() {
41       return "<init>".equals(getName()) && "V".equals(getDexType());
42   }
43 
isStaticConstructor()44   public boolean isStaticConstructor() {
45       return "<clinit>".equals(getName()) && "V".equals(getDexType());
46   }
47 
48   @Override
toString()49   public String toString() {
50       return getJavaType() + " " + getJavaClassName() + "." + getName()
51               + "(" + String.join(", ", getJavaParameterTypes()) + ")";
52   }
53 
matchSignature(String signature)54   private static Matcher matchSignature(String signature) {
55       Matcher m = Pattern.compile("^\\((.*)\\)(.*)$").matcher(signature);
56       if (!m.matches()) {
57           throw new RuntimeException("Could not parse method signature: " + signature);
58       }
59       return m;
60   }
61 
parseDexReturnType(String signature)62   private static String parseDexReturnType(String signature) {
63       return matchSignature(signature).group(2);
64   }
65 
parseDexTypeList(String signature)66   private static List<String> parseDexTypeList(String signature) {
67       String typeSequence = matchSignature(signature).group(1);
68       List<String> list = new ArrayList<String>();
69       while (!typeSequence.isEmpty()) {
70           String type = firstDexTypeFromList(typeSequence);
71           list.add(type);
72           typeSequence = typeSequence.substring(type.length());
73       }
74       return list;
75   }
76 
77   /**
78    * Returns the first dex type in `typeList` or throws a ParserException
79    * if a dex type is not recognized. The input is not changed.
80    */
firstDexTypeFromList(String typeList)81   private static String firstDexTypeFromList(String typeList) {
82       String dexDimension = "";
83       while (typeList.startsWith("[")) {
84           dexDimension += "[";
85           typeList = typeList.substring(1);
86       }
87 
88       String type = null;
89       if (typeList.startsWith("V")
90               || typeList.startsWith("Z")
91               || typeList.startsWith("B")
92               || typeList.startsWith("C")
93               || typeList.startsWith("S")
94               || typeList.startsWith("I")
95               || typeList.startsWith("J")
96               || typeList.startsWith("F")
97               || typeList.startsWith("D")) {
98           type = typeList.substring(0, 1);
99       } else if (typeList.startsWith("L") && typeList.indexOf(";") > 0) {
100           type = typeList.substring(0, typeList.indexOf(";") + 1);
101       } else {
102           throw new RuntimeException("Unexpected dex type in \"" + typeList + "\"");
103       }
104 
105       return dexDimension + type;
106   }
107 }
108