/*
 * Copyright (C) 2019 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.studio

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.Scope
import com.android.tools.lint.detector.api.Severity
import com.android.tools.lint.detector.api.SourceCodeScanner
import com.android.tools.lint.detector.api.UastLintUtils
import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiVariable
import org.jetbrains.uast.UCallExpression
import org.jetbrains.uast.UExpression
import org.jetbrains.uast.ULiteralExpression
import org.jetbrains.uast.UQualifiedReferenceExpression
import org.jetbrains.uast.UReferenceExpression
import org.jetbrains.uast.tryResolve

/**
 * Looks for places where you accidentally pass a path in as a regular expression;
 * this will fail on Windows where the path separator is \, an escape.
 */
class RegexpPathDetector : Detector(), SourceCodeScanner {

    companion object Issues {
        private val IMPLEMENTATION = Implementation(
            RegexpPathDetector::class.java,
            Scope.JAVA_FILE_SCOPE
        )

        @JvmField
        val ISSUE = Issue.create(
            id = "RegexPath",
            briefDescription = "Using Path as Regular Expression",
            explanation = """
                Be careful when passing in a path into a method which expects \
                a regular expression. Your code may work on Linux or OSX, but on \
                Windows the file separator is a back slash, which in a regular \
                expression is interpreted as an escape for the next character!

                For more info, see `go/files-howto`.
            """,
            category = CROSS_PLATFORM,
            priority = 6,
            severity = Severity.ERROR,
            platforms = STUDIO_PLATFORMS,
            implementation = IMPLEMENTATION
        )
    }

    override fun getApplicableMethodNames(): List<String>? =
        //  Common APIs which take regular expressions:
        //    Pattern.compile(regex, ...)
        //    String.split(regex, ...)
        //    String.replaceAll(regex, ...)
        //    String.replaceFirst(String regex, ...)
        // TODO: kotlin.text.Regex constructor!
        listOf("compile", "split", "replaceAll", "replaceFirst")

    override fun visitMethodCall(
        context: JavaContext,
        node: UCallExpression,
        method: PsiMethod
    ) {
        val evaluator = context.evaluator
        // Make sure it's the right methods
        when (method.name) {
            "compile" -> {
                if (!evaluator.isMemberInClass(method, "java.util.regex.Pattern")) {
                    return
                }
            }
            "split", "replaceAll", "replaceFirst" -> {
                if (!evaluator.isMemberInClass(method, "java.lang.String")) {
                    return
                }
            }
            else -> {
                error(method.name)
            }
        }

        // In all these methods, the argument is the first one
        val arg = node.valueArguments.firstOrNull() ?: return
        if (isPath(arg)) {
            context.report(
                ISSUE, node, context.getLocation(node),
                "Passing a path to a parameter which expects a regular expression " +
                        "is dangerous; on Windows path separators will look like escapes. " +
                        "Wrap path with `Pattern.quote`."
            )
        }
    }

    private fun isPath(arg: UExpression): Boolean {
        if (arg is ULiteralExpression) {
            // Common: it's a string literal; probably a deliberate regular expression; do nothing
            return false
        }

        if (arg is UReferenceExpression) {
            val name = arg.resolvedName
            if (name != null && (name == "path" || name.endsWith("Path"))) {
                return true
            }
        }

        // Two common scenarios:
        // (1) variable/parameter reference: String.split(path)
        // (2) nested method call, e.g. String.split(file.getPath())

        val resolved = arg.tryResolve() ?: return false
        if (resolved is PsiMethod) {
            // Method call
            // We generally can't reason about these, except File.getPath() is a common one
            if (resolved.name == "getPath") {
                return true
            }
        } else if (resolved is PsiVariable) {
            // TODO: See if it's initialized
            val lastAssignment = UastLintUtils.findLastAssignment(resolved, arg) ?: run {
                // TODO: look at initializer
                return false
            }

            if (lastAssignment is UCallExpression && lastAssignment.methodName == "getPath") {
                return true
            }
            if (lastAssignment is UQualifiedReferenceExpression &&
                    lastAssignment.selector is UCallExpression &&
                (lastAssignment.selector as UCallExpression).methodName == "getPath") {
                return true
            }
        }

        return false
    }
}
