1 /*
2  * Copyright 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 @file:Suppress("UnstableApiUsage")
18 
19 package androidx.build.lint
20 
21 import com.android.tools.lint.detector.api.Category
22 import com.android.tools.lint.detector.api.Detector
23 import com.android.tools.lint.detector.api.Implementation
24 import com.android.tools.lint.detector.api.Incident
25 import com.android.tools.lint.detector.api.Issue
26 import com.android.tools.lint.detector.api.JavaContext
27 import com.android.tools.lint.detector.api.Scope
28 import com.android.tools.lint.detector.api.Severity
29 import com.android.tools.lint.detector.api.SourceCodeScanner
30 import com.intellij.psi.PsiMethod
31 import java.util.EnumSet
32 import org.jetbrains.uast.UCallExpression
33 
34 class BanThreadSleep : Detector(), SourceCodeScanner {
getApplicableMethodNamesnull35     override fun getApplicableMethodNames() = listOf("sleep")
36 
37     override fun visitMethodCall(context: JavaContext, node: UCallExpression, method: PsiMethod) {
38         if (context.evaluator.isMemberInClass(method, "java.lang.Thread")) {
39             val incident =
40                 Incident(context)
41                     .issue(ISSUE)
42                     .location(context.getNameLocation(node))
43                     .message("Uses Thread.sleep()")
44                     .scope(node)
45             context.report(incident)
46         }
47     }
48 
49     companion object {
50         val ISSUE =
51             Issue.create(
52                 "BanThreadSleep",
53                 "Uses Thread.sleep() method",
54                 "Use of Thread.sleep() is not allowed, please use a callback " +
55                     "or another way to make more reliable code. See more details at " +
56                     "go/androidx/testability#calling-threadsleep-as-a-synchronization-barrier",
57                 Category.CORRECTNESS,
58                 5,
59                 Severity.ERROR,
60                 Implementation(
61                     BanThreadSleep::class.java,
62                     EnumSet.of(Scope.JAVA_FILE, Scope.TEST_SOURCES),
63                 )
64             )
65     }
66 }
67