<commit_before>package com.inaka.lewis.issues;

import com.android.annotations.NonNull;
import com.android.tools.lint.detector.api.Category;
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.LintUtils;
import com.android.tools.lint.detector.api.Location;
import com.android.tools.lint.detector.api.ResourceXmlDetector;
import com.android.tools.lint.detector.api.Scope;
import com.android.tools.lint.detector.api.Severity;
import com.android.tools.lint.detector.api.XmlContext;
import com.inaka.lewis.utils.Constants;

import org.w3c.dom.Element;
import org.w3c.dom.Node;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import static com.android.SdkConstants.ANDROID_MANIFEST_XML;
import static com.android.SdkConstants.ANDROID_URI;
import static com.android.SdkConstants.ATTR_NAME;
import static com.android.SdkConstants.TAG_ACTIVITY;
import static com.android.SdkConstants.TAG_APPLICATION;
import static com.android.SdkConstants.TAG_INTENT_FILTER;
import static com.android.xml.AndroidManifest.NODE_ACTION;
import static com.android.xml.AndroidManifest.NODE_CATEGORY;


public class LauncherActivityDetector extends ResourceXmlDetector implements Detector.XmlScanner {

    public static final Issue ISSUE_MISSING_LAUNCHER = Issue.create(
            "MissingLauncherDetector",
            "Missing Launcher Activity",
            "This app should have an activity with a launcher intent.",
            Category.CORRECTNESS,
            5,
            Severity.WARNING,
            new Implementation(LauncherActivityDetector.class, Scope.MANIFEST_SCOPE));

    public static final Issue ISSUE_MORE_THAN_ONE_LAUNCHER = Issue.create(
            "MoreThanOneLauncherDetector",
            "More than one Launcher Activity",
            "This app should have only one activity with a launcher intent.",
            Category.CORRECTNESS,
            5,
            Severity.WARNING,
            new Implementation(LauncherActivityDetector.class, Scope.MANIFEST_SCOPE));

    public static final Issue ISSUE_LAUNCHER_ACTIVITY_IN_LIBRARY = Issue.create(
            "LauncherActivityInLibrary",
            "Launcher Activity in library",
            "This library should not have activities with a launcher intent.",
            Category.CORRECTNESS,
            8,
            Severity.ERROR,
            new Implementation(LauncherActivityDetector.class, Scope.MANIFEST_SCOPE));

    /**
     * This will be true if the current file we're checking has at least one activity.
     */
    private boolean mHasActivity;

    /**
     * This will be true if there is a launcher activity
     */
    private boolean mHasLauncherActivity;

    /**
     * The lacation of the <application> tag
     */
    private Location mApplicationTagLocation;

    @Override
    public Collection<String> getApplicableElements() {
        List<String> elements = new ArrayList<String>();
        elements.add(TAG_ACTIVITY);
        elements.add(TAG_APPLICATION);
        return elements;
    }

    @Override
    public void beforeCheckProject(@NonNull Context context) {
        mHasActivity = false;
        mHasLauncherActivity = false;
        mApplicationTagLocation = null;
    }

    @Override
    public void afterCheckProject(@NonNull Context context) {

        // if it is a library
        if (context.getProject() == context.getMainProject() && context.getMainProject().isLibrary()){
            if (mHasLauncherActivity) {
                context.report(ISSUE_LAUNCHER_ACTIVITY_IN_LIBRARY, mApplicationTagLocation,
                        "Expecting " + ANDROID_MANIFEST_XML + " not to have an activity with a launcher intent.");
            }
        }
        
        // if it's not a library, it's an application
        if (context.getProject() == context.getMainProject() && !context.getMainProject().isLibrary() && mApplicationTagLocation != null) {

            if (!mHasActivity) {
                context.report(ISSUE_MISSING_LAUNCHER, mApplicationTagLocation,
                        "Expecting " + ANDROID_MANIFEST_XML + " to have an <" + TAG_ACTIVITY + "> tag.");
            } else if (!mHasLauncherActivity) {<commit_msg>#9 begin rule launcher activity in library<commit_after>package com.inaka.lewis.issues;

import com.android.annotations.NonNull;
import com.android.tools.lint.detector.api.Category;
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.LintUtils;
import com.android.tools.lint.detector.api.Location;
import com.android.tools.lint.detector.api.ResourceXmlDetector;
import com.android.tools.lint.detector.api.Scope;
import com.android.tools.lint.detector.api.Severity;
import com.android.tools.lint.detector.api.XmlContext;
import com.inaka.lewis.utils.Constants;

import org.w3c.dom.Element;
import org.w3c.dom.Node;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import static com.android.SdkConstants.ANDROID_MANIFEST_XML;
import static com.android.SdkConstants.ANDROID_URI;
import static com.android.SdkConstants.ATTR_NAME;
import static com.android.SdkConstants.TAG_ACTIVITY;
import static com.android.SdkConstants.TAG_APPLICATION;
import static com.android.SdkConstants.TAG_INTENT_FILTER;
import static com.android.xml.AndroidManifest.NODE_ACTION;
import static com.android.xml.AndroidManifest.NODE_CATEGORY;


public class LauncherActivityDetector extends ResourceXmlDetector implements Detector.XmlScanner {

    public static final Issue ISSUE_MISSING_LAUNCHER = Issue.create(
            "MissingLauncherDetector",
            "Missing Launcher Activity",
            "This app should have an activity with a launcher intent.",
            Category.CORRECTNESS,
            5,
            Severity.WARNING,
            new Implementation(LauncherActivityDetector.class, Scope.MANIFEST_SCOPE));

    public static final Issue ISSUE_MORE_THAN_ONE_LAUNCHER = Issue.create(
            "MoreThanOneLauncherDetector",
            "More than one Launcher Activity",
            "This app should have only one activity with a launcher intent.",
            Category.CORRECTNESS,
            5,
            Severity.WARNING,
            new Implementation(LauncherActivityDetector.class, Scope.MANIFEST_SCOPE));

    public static final Issue ISSUE_LAUNCHER_ACTIVITY_IN_LIBRARY = Issue.create(
            "LauncherActivityInLibrary",
            "Launcher Activity in library",
            "This library should not have activities with a launcher intent.",
            Category.CORRECTNESS,
            8,
            Severity.ERROR,
            new Implementation(LauncherActivityDetector.class, Scope.MANIFEST_SCOPE));

    /**
     * This will be true if the current file we're checking has at least one activity.
     */
    private boolean mHasActivity;

    /**
     * This will be true if there is a launcher activity
     */
    private boolean mHasLauncherActivity;

    /**
     * The lacation of the <application> tag
     */
    private Location mApplicationTagLocation;

    @Override
    public Collection<String> getApplicableElements() {
        List<String> elements = new ArrayList<String>();
        elements.add(TAG_ACTIVITY);
        elements.add(TAG_APPLICATION);
        return elements;
    }

    @Override
    public void beforeCheckProject(@NonNull Context context) {
        mHasActivity = false;
        mHasLauncherActivity = false;
        mApplicationTagLocation = null;
    }

    @Override
    public void afterCheckProject(@NonNull Context context) {

        // if it is a library
        if (context.getProject() == context.getMainProject() && context.getMainProject().isLibrary()){
            if (mHasLauncherActivity) {
                context.report(ISSUE_LAUNCHER_ACTIVITY_IN_LIBRARY, mApplicationTagLocation,
                        "Expecting " + ANDROID_MANIFEST_XML + " not to have an activity with a launcher intent.");
            }
        }

        // if it's not a library, it's an application
        if (context.getProject() == context.getMainProject() && !context.getMainProject().isLibrary() && mApplicationTagLocation != null) {

            if (!mHasActivity) {
                context.report(ISSUE_MISSING_LAUNCHER, mApplicationTagLocation,
                        "Expecting " + ANDROID_MANIFEST_XML + " to have an <" + TAG_ACTIVITY + "> tag.");
            } else if (!mHasLauncherActivity) {
{'fraction_non_alphanumeric': 0.08752710259043707, 'fraction_numerical': 0.0012552778728745864, 'mean_word_length': 3.0630505331478908, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 4}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4333221', 'n_tokens_mistral': 2522, 'n_tokens_neox': 2440, 'n_words': 552}