Skip to content

Commit 19360e7

Browse files
committed
RUM-16478: UnsafeThirdPartyFunctionCall improvements
Add validateSortedWithinClasses to DetektConfigValidator so knownSafeCalls and knownThrowingCalls entries must be in alphabetical order within each class group; sort both YAML config files accordingly. Adds wildcard support and overlap detection to the rule, and splits it into focused modules. Wildcards: YAML entries in knownSafeCalls/knownThrowingCalls now accept per-parameter wildcards — * (any non-nullable type) and ? (any nullable type). Valid only at generic parameter positions; misuse throws IllegalStateException. Overlap detection: Rejects entries that are both safe and throwing, and catches duplicate/overlapping patterns within each list. Removed 17 pre-existing duplicates plus two genuine conflicts (Thread.interrupt(), Array.first(Function1)). Config cleanup: Collapsed repeated generic-parameter entries to wildcards across safe-calls and detekt configs. Refactor: RulesParser (YAML parsing), CodeParser (call-expression extraction), WildcardPattern (matching + validation); the rule now keeps only visitor wiring and the safe/throwing/unknown decision.
1 parent c6e8fe9 commit 19360e7

14 files changed

Lines changed: 1980 additions & 332 deletions

File tree

detekt_custom_safe_calls_android.yml

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ datadog:
2222
- "android.content.ComponentName.resolveViewUrl()"
2323
- "android.content.Context.createDeviceProtectedStorageContext()"
2424
- "android.content.Context.getSharedPreferences(kotlin.String?, kotlin.Int)"
25-
- "android.content.Context.getSystemService(kotlin.String)"
2625
- "android.content.Context.getSystemService(java.lang.Class)"
26+
- "android.content.Context.getSystemService(kotlin.String)"
2727
- "android.content.Context.registerComponentCallbacks(android.content.ComponentCallbacks?)"
2828
- "android.content.Context.registerReceiver(android.content.BroadcastReceiver?, android.content.IntentFilter?)"
2929
- "android.content.Context.registerReceiver(android.content.BroadcastReceiver?, android.content.IntentFilter?, kotlin.Int)"
@@ -40,7 +40,6 @@ datadog:
4040
- "android.content.IntentFilter.constructor(kotlin.String?)"
4141
- "android.content.pm.PackageManager.PackageInfoFlags.of(kotlin.Long)"
4242
- "android.content.pm.PackageManager.hasSystemFeature(kotlin.String)"
43-
- "android.content.res.AssetManager.open(kotlin.String, kotlin.Int)"
4443
- "android.content.res.ColorStateList.getColor(kotlin.IntArray)"
4544
- "android.content.res.ColorStateList.getColorForState(kotlin.IntArray?, kotlin.Int)"
4645
- "android.content.res.Resources.Theme.resolveAttribute(kotlin.Int, android.util.TypedValue?, kotlin.Boolean)"
@@ -156,12 +155,12 @@ datadog:
156155
- "android.view.Window.peekDecorView()"
157156
- "android.view.inspector.WindowInspector.getGlobalWindowViews()"
158157
- "androidx.collection.LruCache.evictAll()"
158+
- "androidx.collection.LruCache.hitCount()"
159159
- "androidx.collection.LruCache.maxSize()"
160+
- "androidx.collection.LruCache.missCount()"
160161
- "androidx.collection.LruCache.put(com.datadog.android.flags.internal.ExposureEventsProcessor.CacheKey, kotlin.Boolean)"
161162
- "androidx.collection.LruCache.put(com.datadog.android.sessionreplay.internal.recorder.resources.Alpha8CacheKey, kotlin.String)"
162163
- "androidx.collection.LruCache.size()"
163-
- "androidx.collection.LruCache.hitCount()"
164-
- "androidx.collection.LruCache.missCount()"
165164
- "androidx.collection.LruCache.trimToSize(kotlin.Int)"
166165
# endregion
167166
# region Android Webview APIs
@@ -235,9 +234,9 @@ datadog:
235234
- "android.graphics.Rect.height()"
236235
- "android.graphics.Rect.width()"
237236
- "android.graphics.RectF.constructor()"
238-
- "android.graphics.RectF.width()"
239237
- "android.graphics.RectF.height()"
240238
- "android.graphics.RectF.toRect()"
239+
- "android.graphics.RectF.width()"
241240
- "android.graphics.Typeface.create(android.graphics.Typeface?, kotlin.Int)"
242241
- "android.os.Handler.sendMessageAtFrontOfQueue(android.os.Message)"
243242
- "android.os.Message.obtain(android.os.Handler?, java.lang.Runnable?)"
@@ -251,9 +250,9 @@ datadog:
251250
- "androidx.compose.runtime.Composition.takeIf(kotlin.Function1)"
252251
- "androidx.compose.runtime.DisposableEffect(kotlin.Any?, kotlin.Any?, kotlin.Function1)"
253252
- "androidx.compose.runtime.DisposableEffectScope.onDispose(kotlin.Function0)"
254-
- "androidx.compose.runtime.LaunchedEffect(kotlin.Any?, kotlin.coroutines.SuspendFunction1)"
255-
- "androidx.compose.runtime.LaunchedEffect(kotlin.Any?, kotlin.Any?, kotlin.coroutines.SuspendFunction1)"
256253
- "androidx.compose.runtime.LaunchedEffect(kotlin.Any?, kotlin.Any?, kotlin.Any?, kotlin.coroutines.SuspendFunction1)"
254+
- "androidx.compose.runtime.LaunchedEffect(kotlin.Any?, kotlin.Any?, kotlin.coroutines.SuspendFunction1)"
255+
- "androidx.compose.runtime.LaunchedEffect(kotlin.Any?, kotlin.coroutines.SuspendFunction1)"
257256
- "androidx.compose.runtime.produceState(kotlin.Boolean, kotlin.Any?, kotlin.coroutines.SuspendFunction1)"
258257
- "androidx.compose.runtime.ProduceStateScope.awaitDispose(kotlin.Function0)"
259258
- "androidx.compose.runtime.remember(kotlin.Any?, kotlin.Any?, kotlin.Function0)"
@@ -289,18 +288,15 @@ datadog:
289288
- "android.content.ContentResolver.registerContentObserver(android.net.Uri, kotlin.Boolean, android.database.ContentObserver)"
290289
- "android.content.ContentResolver.unregisterContentObserver(android.database.ContentObserver)"
291290
- "android.content.SharedPreferences.edit(kotlin.Boolean, kotlin.Function1)"
292-
- "androidx.core.content.ContextCompat.getColor(android.content.Context, kotlin.Int)"
293291
- "androidx.core.content.ContextCompat.getColor(android.content.Context?, kotlin.Int)"
294292
- "androidx.core.os.requestProfiling(android.content.Context, androidx.core.os.ProfilingRequest, java.util.concurrent.Executor?, java.util.function.Consumer?)"
295293
- "androidx.core.os.StackSamplingRequestBuilder.build()"
296294
- "androidx.core.os.StackSamplingRequestBuilder.constructor()"
297295
- "androidx.core.os.StackSamplingRequestBuilder.setBufferSizeKb(kotlin.Int)"
298-
- "androidx.core.os.StackSamplingRequestBuilder.setDurationMs(kotlin.Int)"
299296
- "androidx.core.os.StackSamplingRequestBuilder.setCancellationSignal(android.os.CancellationSignal)"
297+
- "androidx.core.os.StackSamplingRequestBuilder.setDurationMs(kotlin.Int)"
300298
- "androidx.core.os.StackSamplingRequestBuilder.setSamplingFrequencyHz(kotlin.Int)"
301299
- "androidx.core.os.StackSamplingRequestBuilder.setTag(kotlin.String)"
302-
- "androidx.core.view.GestureDetectorCompat.constructor(android.content.Context, android.view.GestureDetector.OnGestureListener)"
303-
- "androidx.core.view.GestureDetectorCompat.onTouchEvent(android.view.MotionEvent)"
304300
- "androidx.core.view.GestureDetectorCompat.constructor(android.content.Context?, android.view.GestureDetector.OnGestureListener?)"
305301
- "androidx.core.view.GestureDetectorCompat.onTouchEvent(android.view.MotionEvent?)"
306302
- "androidx.fragment.app.FragmentManager.FragmentLifecycleCallbacks.onFragmentActivityCreated(androidx.fragment.app.FragmentManager, androidx.fragment.app.Fragment, android.os.Bundle?)"

0 commit comments

Comments
 (0)