package com.zulip.android.customlintrules.detectors; import com.android.annotations.NonNull; import com.android.tools.lint.detector.api.Category; import com.android.tools.lint.detector.api.ClassContext; 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.Scope; import com.android.tools.lint.detector.api.Severity; import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.MethodInsnNode; import org.objectweb.asm.tree.MethodNode; import java.util.Collections; import java.util.EnumSet; import java.util.List; /** * Custom lint rule to check e.printStackTrace() is used or not */ public class PrintStackTraceDetector extends Detector implements Detector.ClassScanner { private static final Class<? extends Detector> DETECTOR_CLASS = PrintStackTraceDetector.class; private static final EnumSet<Scope> DETECTOR_SCOPE = Scope.CLASS_FILE_SCOPE; private static final Implementation IMPLEMENTATION = new Implementation( DETECTOR_CLASS, DETECTOR_SCOPE ); private static final String ISSUE_ID = "ZLog"; private static final String ISSUE_DESCRIPTION = "Use `ZLog.logException(e);` instead of `e.printStackTrace();` "; private static final String ISSUE_EXPLANATION = "`ZLog.logException(e);` print stacktrace as well as report that to the Crashlytics. " + "It provides real-time crash reporting, down to the exact line of code that caused the crash and we can start work as soon as it is reported. " + "All logged exceptions are appeared as 'non-fatal' issue in the Fabric dashboard. It helps in knowing when app gone to unexpected state like" + " malformed network data, misunderstanding of requirements, a logic error etc. Whenever exception is caught it prevent app to crash and continue the app flow(as well as report to Dashboard)"; private static final Category ISSUE_CATEGORY = Category.USABILITY; private static final int ISSUE_PRIORITY = 9; private static final Severity ISSUE_SEVERITY = Severity.ERROR; public static final Issue ISSUE = Issue.create( ISSUE_ID, ISSUE_DESCRIPTION, ISSUE_EXPLANATION, ISSUE_CATEGORY, ISSUE_PRIORITY, ISSUE_SEVERITY, IMPLEMENTATION ); private static final String FUNCTION_NAME = "printStackTrace"; @Override public List<String> getApplicableCallNames() { return Collections.singletonList(FUNCTION_NAME); } @Override public List<String> getApplicableMethodNames() { return Collections.singletonList(FUNCTION_NAME); } @Override public void checkCall(@NonNull ClassContext context, @NonNull ClassNode classNode, @NonNull MethodNode method, @NonNull MethodInsnNode call) { context.report(ISSUE, method, call, context.getLocation(call), "You must use our `ZLog.logException(e);` "); } }