Handle new current.txt format.
We're starting to see "@interface" show up, so handle them like any
other interface. We're also seeing more details argument lists
with names and annotations; ignore them for now, since all our
existing lint checks work on the "real" data type.
Verified that it handles new support library current.txt files
without causing any regressions against existing framework
current.txt files.
Test: manual inspection
Bug: 111555356
Change-Id: Id11c3561edd317e4ba1a9b43993fd96d8243e00d
diff --git a/tools/apilint/apilint.py b/tools/apilint/apilint.py
index 9db3f02..018e9c9 100644
--- a/tools/apilint/apilint.py
+++ b/tools/apilint/apilint.py
@@ -69,12 +69,19 @@
self.raw = raw.strip(" {;")
self.blame = blame
+ # drop generics for now; may need multiple passes
+ raw = re.sub("<[^<]+?>", "", raw)
+ raw = re.sub("<[^<]+?>", "", raw)
+
raw = raw.split()
self.split = list(raw)
for r in ["field", "volatile", "transient", "public", "protected", "static", "final", "deprecated"]:
while r in raw: raw.remove(r)
+ # ignore annotations for now
+ raw = [ r for r in raw if not r.startswith("@") ]
+
self.typ = raw[0]
self.name = raw[1].strip(";")
if len(raw) >= 4 and raw[2] == "=":
@@ -97,25 +104,39 @@
self.raw = raw.strip(" {;")
self.blame = blame
- # drop generics for now
- raw = re.sub("<.+?>", "", raw)
+ # drop generics for now; may need multiple passes
+ raw = re.sub("<[^<]+?>", "", raw)
+ raw = re.sub("<[^<]+?>", "", raw)
- raw = re.split("[\s(),;]+", raw)
+ # handle each clause differently
+ raw_prefix, raw_args, _, raw_throws = re.match(r"(.*?)\((.*?)\)( throws )?(.*?);$", raw).groups()
+
+ # parse prefixes
+ raw = re.split("[\s]+", raw_prefix)
for r in ["", ";"]:
while r in raw: raw.remove(r)
self.split = list(raw)
- for r in ["method", "public", "protected", "static", "final", "deprecated", "abstract", "default"]:
+ for r in ["method", "public", "protected", "static", "final", "deprecated", "abstract", "default", "operator"]:
while r in raw: raw.remove(r)
self.typ = raw[0]
self.name = raw[1]
+
+ # parse args
self.args = []
+ for arg in re.split(",\s*", raw_args):
+ arg = re.split("\s", arg)
+ # ignore annotations for now
+ arg = [ a for a in arg if not a.startswith("@") ]
+ if len(arg[0]) > 0:
+ self.args.append(arg[0])
+
+ # parse throws
self.throws = []
- target = self.args
- for r in raw[2:]:
- if r == "throws": target = self.throws
- else: target.append(r)
+ for throw in re.split(",\s*", raw_throws):
+ self.throws.append(throw)
+
self.ident = ident(self.raw)
def __hash__(self):
@@ -135,12 +156,18 @@
self.fields = []
self.methods = []
+ # drop generics for now; may need multiple passes
+ raw = re.sub("<[^<]+?>", "", raw)
+ raw = re.sub("<[^<]+?>", "", raw)
+
raw = raw.split()
self.split = list(raw)
if "class" in raw:
self.fullname = raw[raw.index("class")+1]
elif "interface" in raw:
self.fullname = raw[raw.index("interface")+1]
+ elif "@interface" in raw:
+ self.fullname = raw[raw.index("@interface")+1]
else:
raise ValueError("Funky class type %s" % (self.raw))