xref: /aosp_15_r20/art/tools/method-to-descriptor.py (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker#!/usr/bin/python3
2*795d594fSAndroid Build Coastguard Worker#
3*795d594fSAndroid Build Coastguard Worker# Copyright 2020, The Android Open Source Project
4*795d594fSAndroid Build Coastguard Worker#
5*795d594fSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
6*795d594fSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
7*795d594fSAndroid Build Coastguard Worker# You may obtain a copy of the License at
8*795d594fSAndroid Build Coastguard Worker#
9*795d594fSAndroid Build Coastguard Worker#     http://www.apache.org/licenses/LICENSE-2.0
10*795d594fSAndroid Build Coastguard Worker#
11*795d594fSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
12*795d594fSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
13*795d594fSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*795d594fSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
15*795d594fSAndroid Build Coastguard Worker# limitations under the License.
16*795d594fSAndroid Build Coastguard Worker"""Converts a method to a descriptor or vice-versa.
17*795d594fSAndroid Build Coastguard Worker
18*795d594fSAndroid Build Coastguard Workereg:
19*795d594fSAndroid Build Coastguard Worker
20*795d594fSAndroid Build Coastguard Worker% echo 'void myclass.foobar(long, java.lang.Object)' | method-to-descriptor.py
21*795d594fSAndroid Build Coastguard WorkerLmyclass;->foobar(jLjaga/lang/Object;)V
22*795d594fSAndroid Build Coastguard Worker% echo 'Lmyclass;->foobar(j)V' | method2descriptor.py -r
23*795d594fSAndroid Build Coastguard Workervoid myclass.foobar(long)
24*795d594fSAndroid Build Coastguard Worker"""
25*795d594fSAndroid Build Coastguard Worker
26*795d594fSAndroid Build Coastguard Workerimport argparse
27*795d594fSAndroid Build Coastguard Workerimport sys
28*795d594fSAndroid Build Coastguard Worker
29*795d594fSAndroid Build Coastguard Worker
30*795d594fSAndroid Build Coastguard Workerdef GetStdinLineIter():
31*795d594fSAndroid Build Coastguard Worker  """reads from stdin"""
32*795d594fSAndroid Build Coastguard Worker  return map(str.strip, sys.stdin)
33*795d594fSAndroid Build Coastguard Worker
34*795d594fSAndroid Build Coastguard Worker
35*795d594fSAndroid Build Coastguard Workerdef readDescriptor(s):
36*795d594fSAndroid Build Coastguard Worker  """Reads a single descriptor and returns the string starting at the point after the descriptor"""
37*795d594fSAndroid Build Coastguard Worker  if s[0] == "[":
38*795d594fSAndroid Build Coastguard Worker    inner, rest = readDescriptor(s[1:])
39*795d594fSAndroid Build Coastguard Worker    return "[" + inner, rest
40*795d594fSAndroid Build Coastguard Worker  elif s[0] == "L":
41*795d594fSAndroid Build Coastguard Worker    type_end = s.index(";")
42*795d594fSAndroid Build Coastguard Worker    return s[:type_end + 1], s[type_end + 1:]
43*795d594fSAndroid Build Coastguard Worker  else:
44*795d594fSAndroid Build Coastguard Worker    assert s[0] in {"B", "C", "D", "F", "I", "J", "S", "Z", "V"}, s[0]
45*795d594fSAndroid Build Coastguard Worker    return s[0], s[1:]
46*795d594fSAndroid Build Coastguard Worker
47*795d594fSAndroid Build Coastguard Worker
48*795d594fSAndroid Build Coastguard Worker# Descriptor to name for basic types
49*795d594fSAndroid Build Coastguard WorkerTYPE_MAP = {
50*795d594fSAndroid Build Coastguard Worker    "V": "void",
51*795d594fSAndroid Build Coastguard Worker    "B": "byte",
52*795d594fSAndroid Build Coastguard Worker    "C": "char",
53*795d594fSAndroid Build Coastguard Worker    "D": "double",
54*795d594fSAndroid Build Coastguard Worker    "F": "float",
55*795d594fSAndroid Build Coastguard Worker    "I": "int",
56*795d594fSAndroid Build Coastguard Worker    "J": "long",
57*795d594fSAndroid Build Coastguard Worker    "S": "short",
58*795d594fSAndroid Build Coastguard Worker    "Z": "boolean"
59*795d594fSAndroid Build Coastguard Worker}
60*795d594fSAndroid Build Coastguard Worker
61*795d594fSAndroid Build Coastguard Worker# Name to descriptor
62*795d594fSAndroid Build Coastguard WorkerDESC_MAP = dict((y, x) for x, y in TYPE_MAP.items())
63*795d594fSAndroid Build Coastguard Worker
64*795d594fSAndroid Build Coastguard Workerdef TypeDescriptorToName(desc):
65*795d594fSAndroid Build Coastguard Worker  """Turn a single type descirptor into a name"""
66*795d594fSAndroid Build Coastguard Worker  if desc[0] == "[":
67*795d594fSAndroid Build Coastguard Worker    inner = TypeDescriptorToName(desc[1:])
68*795d594fSAndroid Build Coastguard Worker    return inner + "[]"
69*795d594fSAndroid Build Coastguard Worker  elif desc[0] == "L":
70*795d594fSAndroid Build Coastguard Worker    assert desc[-1] == ";", desc
71*795d594fSAndroid Build Coastguard Worker    return desc[1:-1].replace("/", ".")
72*795d594fSAndroid Build Coastguard Worker  else:
73*795d594fSAndroid Build Coastguard Worker    return TYPE_MAP[desc]
74*795d594fSAndroid Build Coastguard Worker
75*795d594fSAndroid Build Coastguard Workerdef DescriptorToName(desc):
76*795d594fSAndroid Build Coastguard Worker  """Turn a method descriptor into a name"""
77*795d594fSAndroid Build Coastguard Worker  class_name, rest = readDescriptor(desc)
78*795d594fSAndroid Build Coastguard Worker  assert rest[0:2] == "->", desc
79*795d594fSAndroid Build Coastguard Worker  rest = rest[2:]
80*795d594fSAndroid Build Coastguard Worker  args_start = rest.index("(")
81*795d594fSAndroid Build Coastguard Worker  func_name = rest[:args_start]
82*795d594fSAndroid Build Coastguard Worker  rest = rest[args_start + 1:]
83*795d594fSAndroid Build Coastguard Worker  args = []
84*795d594fSAndroid Build Coastguard Worker  while rest[0] != ")":
85*795d594fSAndroid Build Coastguard Worker    cur_arg, rest = readDescriptor(rest)
86*795d594fSAndroid Build Coastguard Worker    args.append(cur_arg)
87*795d594fSAndroid Build Coastguard Worker  rest = rest[1:]
88*795d594fSAndroid Build Coastguard Worker  return_type, rest = readDescriptor(rest)
89*795d594fSAndroid Build Coastguard Worker  assert rest.strip() == "", desc
90*795d594fSAndroid Build Coastguard Worker  return "{} {}.{}({})".format(
91*795d594fSAndroid Build Coastguard Worker      TypeDescriptorToName(return_type), TypeDescriptorToName(class_name),
92*795d594fSAndroid Build Coastguard Worker      func_name, ",".join(map(TypeDescriptorToName, args)))
93*795d594fSAndroid Build Coastguard Worker
94*795d594fSAndroid Build Coastguard Workerdef SingleNameToDescriptor(name):
95*795d594fSAndroid Build Coastguard Worker  if name in DESC_MAP:
96*795d594fSAndroid Build Coastguard Worker    return DESC_MAP[name]
97*795d594fSAndroid Build Coastguard Worker  elif name.endswith("[]"):
98*795d594fSAndroid Build Coastguard Worker    return "[" + SingleNameToDescriptor(name[:-2])
99*795d594fSAndroid Build Coastguard Worker  elif name == "":
100*795d594fSAndroid Build Coastguard Worker    return ""
101*795d594fSAndroid Build Coastguard Worker  else:
102*795d594fSAndroid Build Coastguard Worker    return "L" + name.replace(".", "/") + ";"
103*795d594fSAndroid Build Coastguard Worker
104*795d594fSAndroid Build Coastguard Worker
105*795d594fSAndroid Build Coastguard Workerdef NameToDescriptor(desc):
106*795d594fSAndroid Build Coastguard Worker  return_name = desc.split()[0]
107*795d594fSAndroid Build Coastguard Worker  name_and_args = desc.split()[1]
108*795d594fSAndroid Build Coastguard Worker  args_start = name_and_args.index("(")
109*795d594fSAndroid Build Coastguard Worker  names = name_and_args[0:args_start]
110*795d594fSAndroid Build Coastguard Worker  meth_split = names.rfind(".")
111*795d594fSAndroid Build Coastguard Worker  class_name = names[:meth_split]
112*795d594fSAndroid Build Coastguard Worker  meth_name = names[meth_split + 1:]
113*795d594fSAndroid Build Coastguard Worker  args = map(str.strip, name_and_args[args_start + 1:-1].split(","))
114*795d594fSAndroid Build Coastguard Worker  return "{}->{}({}){}".format(
115*795d594fSAndroid Build Coastguard Worker      SingleNameToDescriptor(class_name), meth_name,
116*795d594fSAndroid Build Coastguard Worker      "".join(map(SingleNameToDescriptor, args)),
117*795d594fSAndroid Build Coastguard Worker      SingleNameToDescriptor(return_name))
118*795d594fSAndroid Build Coastguard Worker
119*795d594fSAndroid Build Coastguard Worker
120*795d594fSAndroid Build Coastguard Workerdef main():
121*795d594fSAndroid Build Coastguard Worker  parser = argparse.ArgumentParser(
122*795d594fSAndroid Build Coastguard Worker      "method-to-descriptor.py",
123*795d594fSAndroid Build Coastguard Worker      description="Convert a java method-name/stream into it's descriptor or vice-versa."
124*795d594fSAndroid Build Coastguard Worker  )
125*795d594fSAndroid Build Coastguard Worker  parser.add_argument(
126*795d594fSAndroid Build Coastguard Worker      "-r",
127*795d594fSAndroid Build Coastguard Worker      "--reverse",
128*795d594fSAndroid Build Coastguard Worker      dest="reverse",
129*795d594fSAndroid Build Coastguard Worker      action="store_true",
130*795d594fSAndroid Build Coastguard Worker      default=False,
131*795d594fSAndroid Build Coastguard Worker      help="reverse. Go from descriptor to method-declaration")
132*795d594fSAndroid Build Coastguard Worker  parser.add_argument("method", help="what to change", nargs="*")
133*795d594fSAndroid Build Coastguard Worker  args = parser.parse_args()
134*795d594fSAndroid Build Coastguard Worker  if args.method != []:
135*795d594fSAndroid Build Coastguard Worker    inputs = iter(args.method)
136*795d594fSAndroid Build Coastguard Worker  else:
137*795d594fSAndroid Build Coastguard Worker    inputs = GetStdinLineIter()
138*795d594fSAndroid Build Coastguard Worker  for name in inputs:
139*795d594fSAndroid Build Coastguard Worker    if args.reverse:
140*795d594fSAndroid Build Coastguard Worker      print(DescriptorToName(name))
141*795d594fSAndroid Build Coastguard Worker    else:
142*795d594fSAndroid Build Coastguard Worker      print(NameToDescriptor(name))
143*795d594fSAndroid Build Coastguard Worker
144*795d594fSAndroid Build Coastguard Worker
145*795d594fSAndroid Build Coastguard Workerif __name__ == "__main__":
146*795d594fSAndroid Build Coastguard Worker  main()
147