/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.tools.lint.checks

import com.android.SdkConstants.CLASS_APPLICATION
import com.android.SdkConstants.CLASS_CONTEXT
import com.android.SdkConstants.CLASS_FRAGMENT
import com.android.SdkConstants.CLASS_VIEW
import com.android.tools.lint.client.api.JavaEvaluator
import com.android.tools.lint.client.api.UElementHandler
import com.android.tools.lint.detector.api.Category
import com.android.tools.lint.detector.api.Detector
import com.android.tools.lint.detector.api.Implementation
import com.android.tools.lint.detector.api.Issue
import com.android.tools.lint.detector.api.JavaContext
import com.android.tools.lint.detector.api.Location
import com.android.tools.lint.detector.api.Scope
import com.android.tools.lint.detector.api.Severity
import com.android.tools.lint.detector.api.SourceCodeScanner
import com.android.tools.lint.detector.api.getMethodName
import com.intellij.openapi.util.Ref
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiClassType
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiField
import com.intellij.psi.PsiKeyword
import com.intellij.psi.PsiModifier
import com.intellij.psi.PsiModifierList
import org.jetbrains.uast.UAnonymousClass
import org.jetbrains.uast.UBinaryExpression
import org.jetbrains.uast.UCallExpression
import org.jetbrains.uast.UClass
import org.jetbrains.uast.UElement
import org.jetbrains.uast.UField
import org.jetbrains.uast.UMethod
import org.jetbrains.uast.UObjectLiteralExpression
import org.jetbrains.uast.UQualifiedReferenceExpression
import org.jetbrains.uast.UResolvable
import org.jetbrains.uast.getContainingUClass
import org.jetbrains.uast.getParentOfType
import org.jetbrains.uast.toUElement
import org.jetbrains.uast.util.isAssignment
import org.jetbrains.uast.visitor.AbstractUastVisitor
import java.util.Locale

/** Looks for leaks via static fields */
class LeakDetector : Detector(), SourceCodeScanner {

    override fun applicableSuperClasses(): List<String>? {
        return SUPER_CLASSES
    }

    /** Warn about inner classes that aren't static: these end up retaining the outer class */
    override fun visitClass(context: JavaContext, declaration: UClass) {
        val containingClass = declaration.getContainingUClass()
        val isAnonymous = declaration is UAnonymousClass

        // Only consider static inner classes
        val evaluator = context.evaluator
        val isStatic = evaluator.isStatic(declaration) || containingClass == null
        if (isStatic || isAnonymous) { // containingClass == null: implicitly static
            // But look for fields that store contexts
            for (field in declaration.fields) {
                checkInstanceField(context, field)
            }

            if (!isAnonymous) {
                return
            }
        }

        var superClass: String? = null
        for (cls in SUPER_CLASSES) {
            if (evaluator.inheritsFrom(declaration, cls, false)) {
                superClass = cls
                break
            }
        }
        superClass ?: return

        val uastParent = declaration.uastParent
        if (uastParent != null) {

            val method = uastParent.getParentOfType<UMethod>(
                UMethod::class.java,
                true,
                UClass::class.java,
                UObjectLiteralExpression::class.java
            )
            if (method != null && evaluator.isStatic(method)) {
                return
            }
        }

        val invocation = declaration.getParentOfType<UCallExpression>(
            UObjectLiteralExpression::class.java,
            true,
            UMethod::class.java
        )

        val location: Location
        location = if (isAnonymous && invocation != null) {
            context.getCallLocation(invocation, false, false)
        } else {
            context.getNameLocation(declaration)
        }
        var name: String?
        if (isAnonymous) {
            name = "anonymous " + (declaration as UAnonymousClass)
                .baseClassReference
                .qualifiedName
        } else {
            name = declaration.qualifiedName
            if (name == null) {
                name = declaration.name
            }
        }

        val superClassName = superClass.substring(superClass.lastIndexOf('.') + 1)
        context.report(
            ISSUE,
            declaration,
            location,
            "This `$superClassName` class should be static or leaks might occur ($name)"
        )
    }

    override fun getApplicableUastTypes(): List<Class<out UElement>>? {
        return listOf<Class<out UElement>>(UField::class.java)
    }

    override fun createUastHandler(context: JavaContext): UElementHandler? {
        return FieldChecker(context)
    }

    private class FieldChecker(private val context: JavaContext) : UElementHandler() {

        override fun visitField(node: UField) {
            val modifierList = node.modifierList
            if (modifierList == null || !modifierList.hasModifierProperty(PsiModifier.STATIC)) {
                return
            }

            val type = node.type as? PsiClassType ?: return
            val fqn = type.canonicalText
            if (fqn.startsWith("java.")) {
                return
            }
            val cls = type.resolve() ?: return
            if (fqn.startsWith("android.")) {
                if (isLeakCandidate(cls, context.evaluator) &&
                    !isAppContextName(cls, node) &&
                    !isInitializedToAppContext(node, cls)
                ) {
                    val message =
                        "Do not place Android context classes in static fields; " +
                                "this is a memory leak"
                    report(node, modifierList, message)
                }
            } else {
                // User application object -- look to see if that one itself has
                // static fields?
                // We only check *one* level of indirection here
                for ((count, referenced) in cls.allFields.withIndex()) {
                    // Only check a few; avoid getting bogged down on large classes
                    if (count == 20) {
                        break
                    }

                    val innerType = referenced.type as? PsiClassType ?: continue

                    val canonical = innerType.canonicalText
                    if (canonical.startsWith("java.")) {
                        continue
                    }
                    val innerCls = innerType.resolve() ?: continue

                    if (canonical.startsWith("android.")) {
                        if (isLeakCandidate(innerCls, context.evaluator) &&
                            !isAppContextName(innerCls, referenced) &&
                            !isInitializedToAppContext(context, referenced, innerCls)
                        ) {
                            val message = "Do not place Android context classes in static " +
                                    "fields (static reference to `${cls.name}` which has field " +
                                    "`${referenced.name}` pointing to `${innerCls.name}`); this " +
                                    "is a memory leak"
                            report(node, modifierList, message)
                            break
                        }
                    }
                }
            }
        }

        private fun isInitializedToAppContext(
            context: JavaContext,
            field: PsiField,
            typeClass: PsiClass
        ): Boolean {
            if (!context.evaluator.extendsClass(typeClass, CLASS_CONTEXT, false)) {
                return false
            }

            val uField = field.toUElement(UField::class.java) ?: return true
            return isInitializedToAppContext(uField, typeClass)
        }

        /**
         * If it's a static field see if it's initialized to an app context in one of the
         * constructors
         */
        private fun isInitializedToAppContext(field: UField, typeClass: PsiClass): Boolean {
            val containingClass = field.getContainingUClass() ?: return false

            // Only check for app context if we're dealing with a Context field -- there's
            // no chance Fragments, Views etc will be the app context.
            if (!context.evaluator.extendsClass(typeClass, CLASS_CONTEXT, false)) {
                return false
            }

            for (method in containingClass.uastDeclarations) {
                if (method !is UMethod || !method.isConstructor) {
                    continue
                }
                val methodBody = method.uastBody ?: continue
                val assignedToAppContext = Ref(false)

                methodBody.accept(
                    object : AbstractUastVisitor() {
                        override fun visitBinaryExpression(node: UBinaryExpression): Boolean {
                            if (node.isAssignment() &&
                                node.leftOperand is UResolvable &&
                                field.sourcePsi == (node.leftOperand as UResolvable)
                                    .resolve()
                            ) {
                                // Yes, assigning to this field
                                // See if the right hand side looks like an app context
                                var rhs: UElement = node.rightOperand
                                while (rhs is UQualifiedReferenceExpression) {
                                    rhs = rhs.selector
                                }
                                if (rhs is UCallExpression) {
                                    if ("getApplicationContext" == getMethodName(rhs)) {
                                        assignedToAppContext.set(true)
                                    }
                                }
                            }
                            return super.visitBinaryExpression(node)
                        }
                    })

                if (assignedToAppContext.get()) {
                    return true
                }
            }

            return false
        }

        private fun report(
            field: PsiField,
            modifierList: PsiModifierList,
            message: String
        ) {
            var locationNode: PsiElement = field
            // Try to find the static modifier itself
            if (modifierList.hasExplicitModifier(PsiModifier.STATIC)) {
                var child: PsiElement? = modifierList.firstChild
                while (child != null) {
                    if (child is PsiKeyword && PsiKeyword.STATIC == child.text) {
                        locationNode = child
                        break
                    }
                    child = child.nextSibling
                }
            }
            val location = context.getLocation(locationNode)
            context.report(ISSUE, field, location, message)
        }
    }

    private fun checkInstanceField(context: JavaContext, field: UField) {
        val type = field.type as? PsiClassType ?: return
        val fqn = type.canonicalText
        if (fqn.startsWith("java.")) {
            return
        }
        val cls = type.resolve() ?: return

        if (isLeakCandidate(cls, context.evaluator)) {
            context.report(
                LeakDetector.ISSUE,
                field,
                context.getLocation(field),
                "This field leaks a context object"
            )
        }
    }

    companion object {
        /** Leaking data via static fields */
        @JvmField
        val ISSUE = Issue.create(
            id = "StaticFieldLeak",
            briefDescription = "Static Field Leaks",
            explanation = """
                A static field will leak contexts.

                Non-static inner classes have an implicit reference to their outer class. \
                If that outer class is for example a `Fragment` or `Activity`, then this \
                reference means that the long-running handler/loader/task will hold a \
                reference to the activity which prevents it from getting garbage collected.

                Similarly, direct field references to activities and fragments from these \
                longer running instances can cause leaks.

                ViewModel classes should never point to Views or non-application Contexts.
                """,
            category = Category.PERFORMANCE,
            androidSpecific = true,
            priority = 6,
            severity = Severity.WARNING,
            implementation = Implementation(LeakDetector::class.java, Scope.JAVA_FILE_SCOPE)
        )

        private val SUPER_CLASSES = listOf(
            "android.content.Loader",
            "android.support.v4.content.Loader",
            "android.os.AsyncTask",
            "android.arch.lifecycle.ViewModel",
            "androidx.lifecycle.ViewModel"
        )

        private const val CLASS_LIFECYCLE = "androidx.lifecycle.Lifecycle"
        private const val CLASS_LIFECYCLE_OLD = "android.arch.lifecycle.Lifecycle"

        private fun isAppContextName(cls: PsiClass, field: PsiField): Boolean {
            // Don't flag names like "sAppContext" or "applicationContext".
            val name = field.name
            val lower = name.toLowerCase(Locale.US)
            if (lower.contains("appcontext") || lower.contains("application")) {
                if (CLASS_CONTEXT == cls.qualifiedName) {
                    return true
                }
            }

            return false
        }

        private fun isLeakCandidate(cls: PsiClass, evaluator: JavaEvaluator): Boolean {
            return (evaluator.extendsClass(cls, CLASS_CONTEXT, false) &&
                    !evaluator.extendsClass(cls, CLASS_APPLICATION, false)) ||
                    evaluator.extendsClass(cls, CLASS_VIEW, false) ||
                    evaluator.extendsClass(cls, CLASS_FRAGMENT, false) ||
                    // From https://developer.android.com/topic/libraries/architecture/viewmodel:
                    // Caution: A ViewModel must never reference a view, Lifecycle, or any
                    // class that may hold a reference to the activity context
                    evaluator.extendsClass(cls, CLASS_LIFECYCLE, false) ||
                    evaluator.extendsClass(cls, CLASS_LIFECYCLE_OLD, false)
        }
    }
}
