Home | History | Annotate | Download | only in apilint

Lines Matching refs:clazz

66     def __init__(self, clazz, line, raw, blame):
67 self.clazz = clazz
94 def __init__(self, clazz, line, raw, blame):
95 self.clazz = clazz
184 clazz = None
203 if clazz and clazz_cb:
204 clazz_cb(clazz)
205 clazz = Class(pkg, line, raw, blame)
207 api[clazz.fullname] = clazz
209 clazz.ctors.append(Method(clazz, line, raw, blame))
211 clazz.methods.append(Method(clazz, line, raw, blame))
213 clazz.fields.append(Field(clazz, line, raw, blame))
216 if clazz and clazz_cb:
217 clazz_cb(clazz)
223 def __init__(self, sig, clazz, detail, error, rule, msg):
236 self.line = clazz.line
237 blame = clazz.blame
242 dump += "\n in " + repr(clazz)
243 dump += "\n in " + repr(clazz.pkg)
256 def _fail(clazz, detail, error, rule, msg):
260 sig = "%s-%s-%s" % (clazz.fullname, repr(detail), msg)
263 failures[sig] = Failure(sig, clazz, detail, error, rule, msg)
266 def warn(clazz, detail, rule, msg):
267 _fail(clazz, detail, False, rule, msg)
269 def error(clazz, detail, rule, msg):
270 _fail(clazz, detail, True, rule, msg)
275 def notice(clazz):
278 noticed[clazz.fullname] = hash(clazz)
281 def verify_constants(clazz):
283 if re.match("android\.R\.[a-z]+", clazz.fullname): return
284 if clazz.fullname.startswith("android.os.Build"): return
285 if clazz.fullname == "android.system.OsConstants": return
288 for f in clazz.fields:
291 error(clazz, f, "C2", "Constant field names must be FOO_NAME")
294 warn(clazz, f, "C8", "If min/max could change in future, make them dynamic methods")
296 error(clazz, f, None, "All constants must be defined at compile time")
299 def verify_enums(clazz):
301 if "extends java.lang.Enum" in clazz.raw:
302 error(clazz, None, "F5", "Enums are not allowed")
305 def verify_class_names(clazz):
307 if clazz.fullname.startswith("android.opengl"): return
308 if clazz.fullname.startswith("android.renderscript"): return
309 if re.match("android\.R\.[a-z]+", clazz.fullname): return
311 if re.search("[A-Z]{2,}", clazz.name) is not None:
312 warn(clazz, None, "S1", "Class names with acronyms should be Mtp not MTP")
313 if re.match("[^A-Z]", clazz.name):
314 error(clazz, None, "S1", "Class must start with uppercase char")
315 if clazz.name.endswith("Impl"):
316 error(clazz, None, None, "Don't expose your implementation details")
319 def verify_method_names(clazz):
321 if clazz.fullname.startswith("android.opengl"): return
322 if clazz.fullname.startswith("android.renderscript"): return
323 if clazz.fullname == "android.system.OsConstants": return
325 for m in clazz.methods:
327 warn(clazz, m, "S1", "Method names with acronyms should be getMtu() instead of getMTU()")
329 error(clazz, m, "S1", "Method name must start with lowercase char")
332 def verify_callbacks(clazz):
336 if clazz.fullname == "android.speech.tts.SynthesisCallback": return
338 if clazz.name.endswith("Callbacks"):
339 error(clazz, None, "L1", "Callback class names should be singular")
340 if clazz.name.endswith("Observer"):
341 warn(clazz, None, "L1", "Class should be named FooCallback")
343 if clazz.name.endswith("Callback"):
344 if "interface" in clazz.split:
345 error(clazz, None, "CL3", "Callbacks must be abstract class to enable extension in future API levels")
347 for m in clazz.methods:
349 error(clazz, m, "L1", "Callback method names must be onFoo() style")
352 def verify_listeners(clazz):
359 if clazz.name.endswith("Listener"):
360 if " abstract class " in clazz.raw:
361 error(clazz, None, "L1", "Listeners should be an interface, or otherwise renamed Callback")
363 for m in clazz.methods:
365 error(clazz, m, "L1", "Listener method names must be onFoo() style")
367 if len(clazz.methods) == 1 and clazz.name.startswith("On"):
368 m = clazz.methods[0]
369 if (m.name + "Listener").lower() != clazz.name.lower():
370 error(clazz, m, "L1", "Single listener method name must match class name")
373 def verify_actions(clazz):
380 for f in clazz.fields:
389 error(clazz, f, "C3", "Intent action constant name must be ACTION_FOO")
391 if clazz.fullname == "android.content.Intent":
393 elif clazz.fullname == "android.provider.Settings":
395 elif clazz.fullname == "android.app.admin.DevicePolicyManager" or clazz.fullname == "android.app.admin.DeviceAdminReceiver":
398 prefix = clazz.pkg.name + ".action"
401 error(clazz, f, "C4", "Inconsistent action value; expected '%s'" % (expected))
404 def verify_extras(clazz):
411 if clazz.fullname == "android.app.Notification": return
412 if clazz.fullname == "android.appwidget.AppWidgetManager": return
414 for f in clazz.fields:
421 error(clazz, f, "C3", "Intent extra must be EXTRA_FOO")
423 if clazz.pkg.name == "android.content" and clazz.name == "Intent":
425 elif clazz.pkg.name == "android.app.admin":
428 prefix = clazz.pkg.name + ".extra"
431 error(clazz, f, "C4", "Inconsistent extra value; expected '%s'" % (expected))
434 def verify_equals(clazz):
438 for m in clazz.methods:
443 error(clazz, None, "M8", "Must override both equals and hashCode; missing one")
446 def verify_parcelable(clazz):
448 if "implements android.os.Parcelable" in clazz.raw:
449 creator = [ i for i in clazz.fields if i.name == "CREATOR" ]
450 write = [ i for i in clazz.methods if i.name == "writeToParcel" ]
451 describe = [ i for i in clazz.methods if i.name == "describeContents" ]
454 error(clazz, None, "FW3", "Parcelable requires CREATOR, writeToParcel, and describeContents; missing one")
456 if ((" final class " not in clazz.raw) and
457 (" final deprecated class " not in clazz.raw)):
458 error(clazz
460 for c in clazz.ctors:
462 error(clazz, c, "FW3", "Parcelable inflation is exposed through CREATOR, not raw constructors")
465 def verify_protected(clazz):
467 for m in clazz.methods:
469 error(clazz, m, "M7", "Protected methods not allowed; must be public")
470 for f in clazz.fields:
472 error(clazz, f, "M7", "Protected fields not allowed; must be public")
475 def verify_fields(clazz):
497 for f in clazz.fields:
499 if clazz.fullname in IGNORE_BARE_FIELDS:
501 elif clazz.fullname.endswith("LayoutParams"):
503 elif clazz.fullname.startswith("android.util.Mutable"):
506 error(clazz, f, "F2", "Bare fields must be marked final, or add accessors if mutable")
510 error(clazz, f, "S1", "Non-static fields must be named using myField style")
513 error(clazz, f, "F1", "Internal objects must not be exposed")
517 error(clazz, f, "C2", "Constants must be marked static final")
520 def verify_register(clazz):
524 methods = [ m.name for m in clazz.methods ]
525 for m in clazz.methods:
530 error(clazz, m, "L2", "Missing unregister method")
534 error(clazz, m, "L2", "Missing register method")
537 error(clazz, m, "L3", "Callback methods should be named register/unregister")
543 error(clazz, m, "L2", "Missing remove method")
547 error(clazz, m, "L2", "Missing add method")
550 error(clazz, m, "L3", "Listener methods should be named add/remove")
553 def verify_sync(clazz):
555 for m in clazz.methods:
557 error(clazz, m, "M5", "Internal locks must not be exposed")
560 def verify_intent_builder(clazz):
562 if clazz.name == "Intent": return
564 for m in clazz.methods:
569 warn(clazz, m, "FW1", "Methods creating an Intent should be named createFooIntent()")
572 def verify_helper_classes(clazz):
576 if "extends android.app.Service" in clazz.raw:
578 if not clazz.name.endswith("Service"):
579 error(clazz, None, "CL4", "Inconsistent class name; should be FooService")
582 for f in clazz.fields:
585 if f.value != clazz.fullname:
586 error(clazz, f, "C4", "Inconsistent interface constant; expected '%s'" % (clazz.fullname))
588 if "extends android.content.ContentProvider" in clazz.raw:
590 if not clazz.name.endswith("Provider"):
591 error(clazz, None, "CL4", "Inconsistent class name; should be FooProvider")
594 for f in clazz.fields:
597 if f.value != clazz.fullname:
598 error(clazz, f, "C4", "Inconsistent interface constant; expected '%s'" % (clazz.fullname))
600 if "extends android.content.BroadcastReceiver" in clazz.raw:
602 if not clazz.name.endswith("Receiver"):
603 error(clazz, None, "CL4", "Inconsistent class name; should be FooReceiver")
605 if "extends android.app.Activity" in clazz.raw:
607 if not clazz.name.endswith("Activity"):
608 error(clazz, None, "CL4", "Inconsistent class name; should be FooActivity")
611 for m in clazz.methods:
615 warn(clazz, m, None, "Methods implemented by developers should be named onFoo()")
617 warn(clazz, m, None, "If implemented by developer, should be named onFoo(); otherwise consider marking final")
620 def verify_builder(clazz):
623 if " extends " in clazz.raw: return
624 if not clazz.name.endswith("Builder"): return
626 if clazz.name != "Builder":
627 warn(clazz, None, None, "Builder should be defined as inner class")
630 for m in clazz.methods:
639 warn(clazz, m, None, "Builder methods names should use setFoo() style")
642 if not m.typ.endswith(clazz.fullname):
643 warn(clazz, m, "M4", "Methods must return the builder object")
646 warn(clazz, None, None, "Missing build() method")
649 def verify_aidl(clazz):
651 if "extends android.os.Binder" in clazz.raw or "implements android.os.IInterface" in clazz.raw:
652 error(clazz, None, None, "Raw AIDL interfaces must not be exposed")
655 def verify_internal(clazz):
657 if clazz.pkg.name.startswith("com.android"):
658 error(clazz, None, None, "Internal classes must not be exposed")
661 def verify_layering(clazz):
687 cr = rank(clazz.pkg.name)
690 for f in clazz.fields:
693 warn(clazz, f, "FW6", "Field type violates package layering")
695 for m in clazz.methods:
698 warn(clazz, m, "FW6", "Method return type violates package layering")
702 warn(clazz, m, "FW6", "Method argument type violates package layering")
705 def verify_boolean(clazz):
712 gets = [ m for m in clazz.methods if is_get(m) ]
713 sets = [ m for m in clazz.methods if is_set(m) ]
718 error(clazz, m, "M6", "Symmetric method for %s must be named %s" % (trigger, expected))
720 for m in clazz.methods:
745 def verify_collections(clazz):
747 if clazz.fullname == "android.os.Bundle": return
751 for m in clazz.methods:
753 error(clazz, m, "CL2", "Return type is concrete collection; must be higher-level interface")
756 error(clazz, m, "CL2", "Argument is concrete collection; must be higher-level interface")
759 def verify_flags(clazz):
762 for f in clazz.fields:
771 warn(clazz, f, "C1", "Found overlapping flag constant value")
775 def verify_exception(clazz):
777 for m in clazz.methods:
780 error(clazz, m, "S1", "Methods must not throw generic exceptions")
783 if clazz.name == "android.content.ContentProviderClient": continue
784 if clazz.name == "android.os.Binder": continue
785 if clazz.name == "android.os.IBinder": continue
787 error(clazz, m, "FW9", "Methods calling into system server should rethrow RemoteException as RuntimeException")
790 warn(clazz, m, "S1", "Methods taking no arguments should throw IllegalStateException")
793 def verify_google(clazz):
796 if re.search("google", clazz.raw, re.IGNORECASE):
797 error(clazz, None, None, "Must never reference Google")
800 test.extend(clazz.ctors)
801 test.extend(clazz.fields)
802 test.extend(clazz.methods)
806 error(clazz, t, None, "Must never reference Google")
809 def verify_bitset(clazz):
812 for f in clazz.fields:
814 error(clazz, f, None, "Field type must not be heavy BitSet")
816 for m in clazz.methods:
818 error(clazz, m, None, "Return type must not be heavy BitSet")
821 error(clazz, m, None, "Argument type must not be heavy BitSet")
824 def verify_manager(clazz):
827 if not clazz.name.endswith("Manager"): return
829 for c in clazz.ctors:
830 error(clazz, c, None, "Managers must always be obtained from Context; no direct constructors")
832 for m in clazz.methods:
833 if m.typ == clazz.fullname:
834 error(clazz, m, None, "Managers must always be obtained from Context")
837 def verify_boxed(clazz):
842 for c in clazz.ctors:
845 error(clazz, c, "M11", "Must avoid boxed primitives")
847 for f in clazz.fields:
849 error(clazz, f, "M11", "Must avoid boxed primitives")
851 for m in clazz.methods:
853 error(clazz, m, "M11", "Must avoid boxed primitives")
856 error(clazz, m, "M11", "Must avoid boxed primitives")
859 def verify_static_utils(clazz):
861 if clazz.fullname.startswith("android.opengl"): return
862 if clazz.fullname.startswith("android.R"): return
865 if len(clazz.ctors) == 1 and len(clazz.ctors[0].args) == 0:
867 test.extend(clazz.fields)
868 test.extend(clazz.methods)
875 error(clazz, None, None, "Fully-static utility classes must not have constructor")
878 def verify_overload_args(clazz):
880 if clazz.fullname.startswith("android.opengl"): return
883 for m in clazz.methods:
911 warn(clazz, m, "M2", "Expected common arguments [%s] at beginning of overloaded method" % (", ".join(common_args)))
915 error(clazz, m, "M2", "Expected consistent argument ordering between overloads: %s..." % (", ".join(locked_sig)))
918 def verify_callback_handlers(clazz):
932 if s in clazz.pkg.name_path: return
933 if s in clazz.extends_path: return
936 if "app" in clazz.pkg.name_path or "app" in clazz.extends_path:
938 if s in clazz.fullname: return
939 if "content" in clazz.pkg.name_path or "content" in clazz.extends_path:
941 if s in clazz.fullname: return
945 examine = clazz.ctors + clazz.methods
966 warn(clazz, f, "L1", "Registration methods should have overload that accepts delivery Executor")
969 def verify_context_first(clazz):
971 examine = clazz.ctors + clazz.methods
975 error(clazz, m, "M3", "Context is distinct, so it must be the first argument")
978 error(clazz, m, "M3", "ContentResolver is distinct, so it must be the first argument")
981 def verify_listener_last(clazz):
983 examine = clazz.ctors + clazz.methods
991 warn(clazz, m, "M3", "Listeners should always be at end of argument list")
994 def verify_resource_names(clazz):
996 if not re.match("android\.R\.[a-z]+", clazz.fullname): return
999 if clazz.name in ["anim","animator","color","dimen","drawable","interpolator","layout","transition","menu","mipmap","string","plurals","raw","xml"]:
1000 for f in clazz.fields:
1002 error(clazz, f, None, "Expected resource name in this class to be foo_bar_baz style")
1005 if clazz.name in ["array","attr","id","bool","fraction","integer"]:
1006 for f in clazz.fields:
1012 error(clazz, f, "C7", "Expected resource name in this class to be fooBarBaz style")
1015 if clazz.name in ["style"]:
1016 for f in clazz.fields:
1018 error(clazz, f, "C7", "Expected resource name in this class to be FooBar_Baz style")
1021 def verify_files(clazz):
1028 test.extend(clazz.ctors)
1029 test.extend(clazz.methods)
1039 warn(clazz, m, "M10", "Methods accepting File should also accept FileDescriptor or streams")
1042 def verify_manager_list(clazz):
1045 if not clazz.name.endswith("Manager"): return
1047 for m in clazz.methods:
1049 warn(clazz, m, None, "Methods should return List<? extends Parcelable> instead of Parcelable[] to support ParceledListSlice under the hood")
1052 def verify_abstract_inner(clazz):
1055 if re.match(".+?\.[A-Z][^\.]+\.[A-Z]", clazz.fullname):
1056 if " abstract " in clazz.raw and " static " not in clazz.raw:
1057 warn(clazz, None, None, "Abstract inner classes should be static to improve testability")
1060 def verify_runtime_exceptions(clazz):
1097 examine = clazz.ctors + clazz.methods
1101 error(clazz, m, None, "Methods must not mention RuntimeException subclasses in throws clauses")
1104 def verify_error(clazz):
1106 if not clazz.extends: return
1107 if clazz.extends.endswith("Error"):
1108 error(clazz, None, None, "Trouble must be reported through an Exception, not Error")
1109 if clazz.extends.endswith("Exception") and not clazz.name.endswith("Exception"):
1110 error(clazz, None, None, "Exceptions must be named FooException")
1113 def verify_units(clazz):
1127 for m in clazz.methods:
1131 error(clazz, m, None, "Expected method name units to be " + v)
1133 warn(clazz, m, None, "Returned time values are strongly encouraged to be in milliseconds unless you need the extra precision")
1135 error(clazz, m, None, "Returned time values must be in milliseconds")
1137 for m in clazz.methods:
1144 error(clazz, m, None, "Fractions must use floats")
1146 error(clazz, m, None, "Percentage must use ints")
1149 def verify_closable(clazz):
1151 if "implements java.lang.AutoCloseable" in clazz.raw: return
1152 if "implements java.io.Closeable" in clazz.raw: return
1154 for m in clazz.methods:
1157 warn(clazz, m, None, "Classes that release resources should implement AutoClosable and CloseGuard")
1161 def verify_member_name_not_kotlin_keyword(clazz):
1178 for m in clazz.methods:
1180 error(clazz, m, None, "Method name must not be a Kotlin keyword")
1181 for f in clazz.fields:
1183 error(clazz, f, None, "Field name must not be a Kotlin keyword")
1186 def verify_method_name_not_kotlin_operator(clazz):
1193 error(clazz, m, None, "Only one of '{0}' and '{0}Assign' methods should be present for Kotlin".format(op))
1196 for m in clazz.methods:
1202 warn(clazz, m, None, "Method can be invoked as a unary operator from Kotlin")
1208 warn(clazz, m, None, "Method can be invoked as a pre/postfix inc/decrement operator from Kotlin")
1212 warn(clazz, m, None, "Method can be invoked as a binary operator from Kotlin")
1217 warn(clazz, m, None, "Method can be invoked as a 'in' operator from Kotlin")
1221 warn(clazz, m, None, "Method can be invoked with an indexing operator from Kotlin")
1225 warn(clazz, m, None, "Method can be invoked with function call syntax from Kotlin")
1231 warn(clazz, m, None, "Method can be invoked as a compound assignment operator from Kotlin")
1235 def verify_collections_over_arrays(clazz):
1239 for m in clazz.methods:
1241 warn(clazz, m, None, "Method should return Collection<> (or subclass) instead of raw array")
1244 warn(clazz, m, None, "Method argument should be Collection<> (or subclass) instead of raw array")
1247 def verify_user_handle(clazz):
1249 if clazz.name.endswith("Listener") or clazz.name.endswith("Callback") or clazz.name.endswith("Callbacks"): return
1250 if clazz.fullname == "android.app.admin.DeviceAdminReceiver": return
1251 if clazz.fullname == "android.content.pm.LauncherApps": return
1252 if clazz.fullname == "android.os.UserHandle": return
1253 if clazz.fullname == "android.os.UserManager": return
1255 for m in clazz.methods:
1259 warn(clazz, m, None, "Method taking UserHandle should be named 'doFooAsUser' or 'queryFooForUser'")
1262 def verify_params(clazz):
1264 if clazz.name.endswith("Params"): return
1265 if clazz.fullname == "android.app.ActivityOptions": return
1266 if clazz.fullname == "android.app.BroadcastOptions": return
1267 if clazz.fullname == "android.os.Bundle": return
1268 if clazz.fullname == "android.os.BaseBundle": return
1269 if clazz.fullname == "android.os.PersistableBundle": return
1273 if clazz.name.endswith(b):
1274 error(clazz, None, None, "Classes holding a set of parameters should be called 'FooParams'")
1277 def verify_services(clazz):
1279 if clazz.fullname != "android.content.Context": return
1281 for f in clazz.fields:
1287 error(clazz, f, "C4", "Inconsistent service value; expected '%s'" % (expected))
1290 def verify_tense(clazz):
1292 if clazz.fullname.startswith("android.opengl"): return
1294 for m in clazz.methods:
1296 warn(clazz, m, None, "Unexpected tense; probably meant 'enabled'")
1299 def verify_icu(clazz):
1321 for m in clazz.ctors + clazz.methods:
1327 warn(clazz, m, None, "Type %s should be replaced with richer ICU type %s" % (arg, better[arg]))
1330 def verify_clone(clazz):
1332 for m in clazz.methods:
1334 error(clazz, m, None, "Provide an explicit copy constructor instead of implementing clone()")
1337 def examine_clazz(clazz):
1340 notice(clazz)
1342 if clazz.pkg.name.startswith("java"): return
1343 if clazz.pkg.name.startswith("junit"): return
1344 if clazz.pkg.name.startswith("org.apache"): return
1345 if clazz.pkg.name.startswith("org.xml"): return
1346 if clazz.pkg.name.startswith("org.json"): return
1347 if clazz.pkg.name.startswith("org.w3c"): return
1348 if clazz.pkg.name.startswith("android.icu."): return
1350 verify_constants(clazz)
1351 verify_enums(clazz)
1352 verify_class_names(clazz)
1353 verify_method_names(clazz)
1354 verify_callbacks(clazz)
1355 verify_listeners(clazz)
1356 verify_actions(clazz)
1357 verify_extras(clazz)
1358 verify_equals(clazz)
1359 verify_parcelable(clazz)
1360 verify_protected(clazz)
1361 verify_fields(clazz)
1362 verify_register(clazz)
1363 verify_sync(clazz)
1364 verify_intent_builder(clazz)
1365 verify_helper_classes(clazz)
1366 verify_builder(clazz)
1367 verify_aidl(clazz)
1368 verify_internal(clazz)
1369 verify_layering(clazz)
1370 verify_boolean(clazz)
1371 verify_collections(clazz)
1372 verify_flags(clazz)
1373 verify_exception(clazz)
1374 if not ALLOW_GOOGLE: verify_google(clazz)
1375 verify_bitset(clazz)
1376 verify_manager(clazz)
1377 verify_boxed(clazz)
1378 verify_static_utils(clazz)
1379 # verify_overload_args(clazz)
1380 verify_callback_handlers(clazz)
1381 verify_context_first(clazz)
1382 verify_listener_last(clazz)
1383 verify_resource_names(clazz)
1384 verify_files(clazz)
1385 verify_manager_list(clazz)
1386 verify_abstract_inner(clazz)
1387 verify_runtime_exceptions(clazz)
1388 verify_error(clazz)
1389 verify_units(clazz)
1390 verify_closable(clazz)
1391 verify_member_name_not_kotlin_keyword(clazz)
1392 verify_method_name_not_kotlin_operator(clazz)
1393 verify_collections_over_arrays(clazz)
1394 verify_user_handle(clazz)
1395 verify_params(clazz)
1396 verify_services(clazz)
1397 verify_tense(clazz)
1398 verify_icu(clazz)
1399 verify_clone(clazz)
1427 def ctor_exists(api, clazz, test):
1428 for m in clazz.ctors:
1432 def all_methods(api, clazz):
1433 methods = list(clazz.methods)
1434 if clazz.extends is not None:
1435 methods.extend(all_methods(api, api[clazz.extends]))
1438 def method_exists(api, clazz, test):
1439 methods = all_methods(api, clazz)
1444 def field_exists(api, clazz, test):
1445 for f in clazz.fields:
1494 for clazz in cur.values():
1495 if " deprecated " in clazz.raw and not clazz.fullname in prev:
1496 error(clazz, None, None, "Found API deprecation at birth")
1498 for i in clazz.ctors + clazz.methods + clazz.fields:
1500 error(clazz, i, None, "Found API deprecation at birth")