/*
 * Copyright (C) 2012 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 static com.android.SdkConstants.CONSTRUCTOR_NAME;
import static org.objectweb.asm.Opcodes.ACC_PRIVATE;
import static org.objectweb.asm.Opcodes.ACC_PROTECTED;
import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
import static org.objectweb.asm.Opcodes.ACC_STATIC;

import com.android.annotations.NonNull;
import com.android.tools.lint.client.api.LintDriver;
import com.android.tools.lint.detector.api.Category;
import com.android.tools.lint.detector.api.ClassContext;
import com.android.tools.lint.detector.api.ClassScanner;
import com.android.tools.lint.detector.api.Context;
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.Location;
import com.android.tools.lint.detector.api.Scope;
import com.android.tools.lint.detector.api.Severity;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.collect.Sets.SetView;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode;

/** Checks for accidental overrides */
public class OverrideDetector extends Detector implements ClassScanner {
    /** Accidental overrides */
    public static final Issue ISSUE =
            Issue.create(
                            "DalvikOverride",
                            "Method considered overridden by Dalvik",
                            "The Dalvik virtual machine will treat a package private method in one "
                                    + "class as overriding a package private method in its super class, even if "
                                    + "they are in separate packages.\n"
                                    + "\n"
                                    + "If you really did intend for this method to override the other, make the "
                                    + "method `protected` instead.\n"
                                    + "\n"
                                    + "If you did **not** intend the override, consider making the method private, or "
                                    + "changing its name or signature.\n"
                                    + "\n"
                                    + "Note that this check is disabled be default, because ART (the successor "
                                    + "to Dalvik) no longer has this behavior.",
                            Category.CORRECTNESS,
                            7,
                            Severity.ERROR,
                            new Implementation(
                                    OverrideDetector.class, EnumSet.of(Scope.ALL_CLASS_FILES)))
                    .setEnabledByDefault(false)
                    .setAndroidSpecific(true);

    /** map from owner class name to JVM signatures for its package private methods */
    private final Map<String, Set<String>> mPackagePrivateMethods = Maps.newHashMap();

    /** Map from owner to signature to super class being overridden */
    private Map<String, Map<String, String>> mErrors;

    /**
     * Map from owner to signature to corresponding location. When there are errors a single error
     * can have locations for both the overriding and overridden methods.
     */
    private Map<String, Map<String, Location>> mLocations;

    /** Constructs a new {@link OverrideDetector} */
    public OverrideDetector() {}

    @Override
    public void afterCheckRootProject(@NonNull Context context) {
        // Process the check in two passes:
        //
        // In the first pass, gather the full set of package private methods for
        // each class.
        // When all classes have been processed at the end of the first pass,
        // find out whether any of the methods are potentially overriding those
        // in its super classes.
        //
        // If so, request a second pass. In the second pass, we gather full locations
        // for both the base and overridden method calls, and store these.
        // If the location is found to be in a suppressed context, remove that error
        // entry.
        //
        // At the end of the second pass, we generate the errors, combining locations
        // from both the overridden and overriding methods.
        if (context.getPhase() == 1) {
            Set<String> classes = mPackagePrivateMethods.keySet();
            LintDriver driver = context.getDriver();
            for (String owner : classes) {
                Set<String> methods = mPackagePrivateMethods.get(owner);
                String superClass = driver.getSuperClass(owner);
                int packageIndex = owner.lastIndexOf('/');
                while (superClass != null) {
                    int superPackageIndex = superClass.lastIndexOf('/');

                    // Only compare methods that differ in packages
                    if (packageIndex == -1
                            || superPackageIndex != packageIndex
                            || !owner.regionMatches(0, superClass, 0, packageIndex)) {
                        Set<String> superMethods = mPackagePrivateMethods.get(superClass);
                        if (superMethods != null) {
                            SetView<String> intersection = Sets.intersection(methods, superMethods);
                            if (!intersection.isEmpty()) {
                                if (mLocations == null) {
                                    mLocations = Maps.newHashMap();
                                }
                                // We need a separate data structure to keep track of which
                                // signatures are in error,
                                if (mErrors == null) {
                                    mErrors = Maps.newHashMap();
                                }

                                for (String signature : intersection) {
                                    Map<String, Location> locations = mLocations.get(owner);
                                    if (locations == null) {
                                        locations = Maps.newHashMap();
                                        mLocations.put(owner, locations);
                                    }
                                    locations.put(signature, null);

                                    locations = mLocations.get(superClass);
                                    if (locations == null) {
                                        locations = Maps.newHashMap();
                                        mLocations.put(superClass, locations);
                                    }
                                    locations.put(signature, null);

                                    Map<String, String> errors = mErrors.get(owner);
                                    if (errors == null) {
                                        errors = Maps.newHashMap();
                                        mErrors.put(owner, errors);
                                    }
                                    errors.put(signature, superClass);
                                }
                            }
                        }
                    }
                    superClass = driver.getSuperClass(superClass);
                }
            }

            //noinspection VariableNotUsedInsideIf
            if (mErrors != null) {
                context.requestRepeat(this, ISSUE.getImplementation().getScope());
            }
        } else {
            assert context.getPhase() == 2;

            for (Entry<String, Map<String, String>> ownerEntry : mErrors.entrySet()) {
                String owner = ownerEntry.getKey();
                Map<String, String> methodToSuper = ownerEntry.getValue();
                for (Entry<String, String> entry : methodToSuper.entrySet()) {
                    String signature = entry.getKey();
                    String superClass = entry.getValue();

                    Map<String, Location> ownerLocations = mLocations.get(owner);
                    if (ownerLocations != null) {
                        Location location = ownerLocations.get(signature);
                        if (location != null) {
                            Map<String, Location> superLocations = mLocations.get(superClass);
                            if (superLocations != null) {
                                Location superLocation = superLocations.get(signature);
                                if (superLocation != null) {
                                    location.setSecondary(superLocation);
                                    superLocation.setMessage(
                                            "This method is treated as overridden");
                                }
                            }
                            String methodName = signature;
                            int index = methodName.indexOf('(');
                            if (index != -1) {
                                methodName = methodName.substring(0, index);
                            }
                            String message =
                                    String.format(
                                            "This package private method may be unintentionally "
                                                    + "overriding `%1$s` in `%2$s`",
                                            methodName, ClassContext.getFqcn(superClass));
                            context.report(ISSUE, location, message);
                        }
                    }
                }
            }
        }
    }

    @SuppressWarnings("rawtypes") // ASM5 API
    @Override
    public void checkClass(@NonNull ClassContext context, @NonNull ClassNode classNode) {
        if (!context.getProject().getReportIssues()) {
            // If this is a library project not being analyzed, ignore it
            return;
        }

        List methodList = classNode.methods;
        if (context.getPhase() == 1) {
            for (Object m : methodList) {
                MethodNode method = (MethodNode) m;
                int access = method.access;
                // Only record non-static package private methods
                if ((access & (ACC_STATIC | ACC_PRIVATE | ACC_PROTECTED | ACC_PUBLIC)) != 0) {
                    continue;
                }

                // Ignore constructors too
                if (CONSTRUCTOR_NAME.equals(method.name)) {
                    continue;
                }

                String owner = classNode.name;
                Set<String> methods = mPackagePrivateMethods.get(owner);
                if (methods == null) {
                    methods = Sets.newHashSetWithExpectedSize(methodList.size());
                    mPackagePrivateMethods.put(owner, methods);
                }
                methods.add(method.name + method.desc);
            }
        } else {
            assert context.getPhase() == 2;
            Map<String, Location> methods = mLocations.get(classNode.name);
            if (methods == null) {
                // No locations needed from this class
                return;
            }

            for (Object m : methodList) {
                MethodNode method = (MethodNode) m;

                String signature = method.name + method.desc;
                if (methods.containsKey(signature)) {
                    if (context.getDriver().isSuppressed(ISSUE, classNode, method, null)) {
                        Map<String, String> errors = mErrors.get(classNode.name);
                        if (errors != null) {
                            errors.remove(signature);
                        }
                        continue;
                    }

                    Location location = context.getLocation(method, classNode);
                    methods.put(signature, location);
                    String description =
                            ClassContext.createSignature(classNode.name, method.name, method.desc);
                    location.setData(description);
                }
            }
        }
    }
}
