1 /* 2 * Copyright (C) 2018 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.intellij.psi.PsiModifier 30 import java.util.Collections 31 import org.jetbrains.uast.UAnonymousClass 32 import org.jetbrains.uast.UClass 33 34 const val PARCELABLE_INTERFACE_CANONICAL_NAME = "android.os.Parcelable" 35 36 class BanParcelableUsage : Detector(), Detector.UastScanner { 37 applicableSuperClassesnull38 override fun applicableSuperClasses(): List<String>? { 39 return Collections.singletonList(PARCELABLE_INTERFACE_CANONICAL_NAME) 40 } 41 visitClassnull42 override fun visitClass(context: JavaContext, declaration: UClass) { 43 if ( 44 declaration.isInterface || 45 declaration.hasModifierProperty(PsiModifier.ABSTRACT) || 46 declaration is UAnonymousClass 47 ) { 48 return 49 } 50 // For now only find classes that directly implement Parcelable, because 51 // lint will also examine the entire inheritance and implementation chain. 52 for (superclass in declaration.uastSuperTypes) { 53 if (superclass.type.canonicalText == PARCELABLE_INTERFACE_CANONICAL_NAME) { 54 val incident = 55 Incident(context) 56 .issue(ISSUE) 57 .location(context.getNameLocation(declaration)) 58 .message("Class implements android.os.Parcelable") 59 .scope(declaration) 60 context.report(incident) 61 } 62 } 63 } 64 65 companion object { 66 val ISSUE = 67 Issue.create( 68 "BanParcelableUsage", 69 "Class implements android.os.Parcelable", 70 "Use of Parcelable is no longer recommended," + 71 " please use VersionedParcelable instead.", 72 Category.CORRECTNESS, 73 5, 74 Severity.ERROR, 75 Implementation(BanParcelableUsage::class.java, Scope.JAVA_FILE_SCOPE) 76 ) 77 } 78 } 79