ApiLint: Add Kotlin-style type support
Test: tools/apilint/apilint_sha.sh HEAD && python tools/apilint/apilint_test.py Change-Id: Iac1fdabcbeffe57c8288d73b2359e8ce0b2bc3eb
This commit is contained in:
@@ -223,7 +223,7 @@ class Package():
|
||||
class V2Tokenizer(object):
|
||||
__slots__ = ["raw"]
|
||||
|
||||
DELIMITER = re.compile(r'\s+|[()@<>;,={}/"]|\[\]')
|
||||
DELIMITER = re.compile(r'\s+|[()@<>;,={}/"!?]|\[\]|\.\.\.')
|
||||
STRING_SPECIAL = re.compile(r'["\\]')
|
||||
|
||||
def __init__(self, raw):
|
||||
@@ -435,19 +435,32 @@ class V2LineParser(object):
|
||||
ret.append(self.parse_token())
|
||||
return ret
|
||||
|
||||
def parse_kotlin_nullability(self):
|
||||
t = self.lookahead()
|
||||
if t == "?" or t == "!":
|
||||
return self.parse_token()
|
||||
return None
|
||||
|
||||
def parse_type(self):
|
||||
type = self.parse_token()
|
||||
if type in V2LineParser.JAVA_LANG_TYPES:
|
||||
type = "java.lang." + type
|
||||
self.parse_matching_paren("<", ">")
|
||||
while self.parse_if("[]"):
|
||||
type += "[]"
|
||||
while True:
|
||||
t = self.lookahead()
|
||||
if t == "[]":
|
||||
type += self.parse_token()
|
||||
elif self.parse_kotlin_nullability() is not None:
|
||||
pass # discard nullability for now
|
||||
else:
|
||||
break
|
||||
return type
|
||||
|
||||
def parse_arg_type(self):
|
||||
type = self.parse_type()
|
||||
if self.parse_if("..."):
|
||||
type += "..."
|
||||
self.parse_kotlin_nullability() # discard nullability for now
|
||||
return type
|
||||
|
||||
def parse_name(self):
|
||||
@@ -466,7 +479,15 @@ class V2LineParser(object):
|
||||
|
||||
def parse_arg(self):
|
||||
self.parse_annotations()
|
||||
return self.parse_arg_type()
|
||||
type = self.parse_arg_type()
|
||||
l = self.lookahead()
|
||||
if l != "," and l != ")":
|
||||
self.parse_token() # kotlin argument name
|
||||
if self.parse_if('='): # kotlin default value
|
||||
(self.parse_matching_paren('(', ')') or
|
||||
self.parse_matching_paren('{', '}') or
|
||||
self.parse_token() and self.parse_matching_paren('(', ')'))
|
||||
return type
|
||||
|
||||
def parse_throws(self):
|
||||
ret = []
|
||||
|
||||
@@ -154,6 +154,14 @@ class V2TokenizerTests(unittest.TestCase):
|
||||
self._test("class Some.Class extends SomeOther {",
|
||||
['class', 'Some.Class', 'extends', 'SomeOther', '{'])
|
||||
|
||||
def test_varargs(self):
|
||||
self._test("name(String...)",
|
||||
['name', '(', 'String', '...', ')'])
|
||||
|
||||
def test_kotlin(self):
|
||||
self._test("String? name(String!...)",
|
||||
['String', '?', 'name', '(', 'String', '!', '...', ')'])
|
||||
|
||||
def test_annotation(self):
|
||||
self._test("method @Nullable public void name();",
|
||||
['method', '@', 'Nullable', 'public', 'void', 'name', '(', ')', ';'])
|
||||
@@ -271,5 +279,12 @@ class V2ParserTests(unittest.TestCase):
|
||||
self.assertEquals('NAME', f.name)
|
||||
self.assertEquals('( 0.0 / 0.0 )', f.value)
|
||||
|
||||
def test_kotlin_types(self):
|
||||
self._field('field public List<Integer[]?[]!>?[]![]? NAME;')
|
||||
self._method("method <T?> Class<T!>?[]![][]? name(Type!, Type argname,"
|
||||
+ "Class<T?>[][]?[]!...!) throws Exception, T;")
|
||||
self._method("method <T> T name(T a = 1, T b = A(1), Lambda f = { false }, N? n = null, "
|
||||
+ """double c = (1/0), float d = 1.0f, String s = "heyo", char c = 'a');""")
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user