Skip to content
This repository was archived by the owner on Jul 25, 2024. It is now read-only.

Commit e9f4e9e

Browse files
jainkuniyatimabbott
authored andcommitted
lint: Add a new lint rule to check for use of printStackTrace.
1 parent 091e113 commit e9f4e9e

File tree

11 files changed

+187
-3
lines changed

11 files changed

+187
-3
lines changed

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,4 @@ Please make sure these boxes are checked before submitting your pull request - t
1313

1414
- [ ] If new feature is implemeted then it is compatible with Night theme too.
1515

16-
- [ ] Used `Zlog.logException(e)` instead of `e.printStackTrace()`
17-
1816
- [ ] Commit messages are well-written.

app/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ dependencies {
107107
}
108108

109109
testCompile 'junit:junit:4.12'
110+
compile project(':customLintAAR')
110111

111112
}
112113

customLintAAR/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/build

customLintAAR/build.gradle

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
apply plugin: 'com.android.library'
2+
apply plugin: 'maven'
3+
4+
5+
android {
6+
compileSdkVersion 24
7+
buildToolsVersion "23.0.2"
8+
9+
defaultConfig {
10+
minSdkVersion 13
11+
targetSdkVersion 23
12+
versionCode 1
13+
versionName "1.0"
14+
}
15+
buildTypes {
16+
release {
17+
minifyEnabled false
18+
}
19+
}
20+
}
21+
22+
dependencies {
23+
compile fileTree(dir: 'libs', include: ['*.jar'])
24+
testCompile 'junit:junit:4.12'
25+
}
26+
27+
28+
/*
29+
* rules for including "lint.jar" in aar
30+
*/
31+
configurations {
32+
lintJarImport
33+
}
34+
35+
dependencies {
36+
lintJarImport project(path: ':customlintjar', configuration: "lintJarOutput")
37+
}
38+
39+
task copyLintJar(type: Copy) {
40+
from (configurations.lintJarImport) {
41+
rename {
42+
String fileName ->
43+
'lint.jar'
44+
}
45+
}
46+
into 'build/intermediates/lint/'
47+
}
48+
49+
project.afterEvaluate {
50+
def compileLintTask = project.tasks.find { it.name == 'compileLint' }
51+
compileLintTask.dependsOn(copyLintJar)
52+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
2+
package="com.zulip.android.customlintarr">
3+
4+
<application android:label="@string/app_name"/>
5+
6+
</manifest>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<resources>
2+
<string name="app_name">Custom Lint</string>
3+
</resources>

customlintjar/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/build

customlintjar/build.gradle

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
apply plugin: 'java'
2+
3+
dependencies {
4+
compile fileTree(include: ['*.jar'], dir: 'libs')
5+
compile 'com.android.tools.lint:lint:25.0.0'
6+
compile 'com.android.tools.lint:lint-api:25.0.0'
7+
compile 'com.android.tools.lint:lint-checks:25.0.0'
8+
testCompile 'com.android.tools.lint:lint-tests:24.5.0'
9+
}
10+
11+
jar {
12+
manifest {
13+
attributes('Lint-Registry': 'com.zulip.android.customlintrules.MyIssueRegistry')
14+
}
15+
}
16+
17+
configurations {
18+
lintJarOutput
19+
}
20+
21+
dependencies {
22+
lintJarOutput files(jar)
23+
}
24+
25+
defaultTasks 'assemble'
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.zulip.android.customlintrules;
2+
3+
import com.android.tools.lint.client.api.IssueRegistry;
4+
import com.android.tools.lint.detector.api.Issue;
5+
import com.zulip.android.customlintrules.detectors.PrintStackTraceDetector;
6+
7+
import java.util.Arrays;
8+
import java.util.List;
9+
10+
@SuppressWarnings("unused")
11+
public class MyIssueRegistry extends IssueRegistry {
12+
@Override
13+
public List<Issue> getIssues() {
14+
System.out.println("********Working on custom lint check!!!********");
15+
return Arrays.asList(
16+
PrintStackTraceDetector.ISSUE);
17+
18+
}
19+
}
20+
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package com.zulip.android.customlintrules.detectors;
2+
3+
import com.android.annotations.NonNull;
4+
import com.android.tools.lint.detector.api.Category;
5+
import com.android.tools.lint.detector.api.ClassContext;
6+
import com.android.tools.lint.detector.api.Detector;
7+
import com.android.tools.lint.detector.api.Implementation;
8+
import com.android.tools.lint.detector.api.Issue;
9+
import com.android.tools.lint.detector.api.Scope;
10+
import com.android.tools.lint.detector.api.Severity;
11+
12+
import org.objectweb.asm.tree.ClassNode;
13+
import org.objectweb.asm.tree.MethodInsnNode;
14+
import org.objectweb.asm.tree.MethodNode;
15+
16+
import java.util.Collections;
17+
import java.util.EnumSet;
18+
import java.util.List;
19+
20+
/**
21+
* Custom lint rule to check e.printStackTrace() is used or not
22+
*/
23+
public class PrintStackTraceDetector extends Detector
24+
implements Detector.ClassScanner {
25+
26+
private static final Class<? extends Detector> DETECTOR_CLASS = PrintStackTraceDetector.class;
27+
private static final EnumSet<Scope> DETECTOR_SCOPE = Scope.CLASS_FILE_SCOPE;
28+
29+
private static final Implementation IMPLEMENTATION = new Implementation(
30+
DETECTOR_CLASS,
31+
DETECTOR_SCOPE
32+
);
33+
34+
private static final String ISSUE_ID = "ZLog";
35+
private static final String ISSUE_DESCRIPTION = "Use `ZLog.logException(e);` instead of `e.printStackTrace();` ";
36+
private static final String ISSUE_EXPLANATION = "`ZLog.logException(e);` print stacktrace as well as report that to the Crashlytics. " +
37+
"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. "+
38+
"All logged exceptions are appeared as 'non-fatal' issue in the Fabric dashboard. It helps in knowing when app gone to unexpected state like" +
39+
" 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)";
40+
private static final Category ISSUE_CATEGORY = Category.USABILITY;
41+
private static final int ISSUE_PRIORITY = 9;
42+
private static final Severity ISSUE_SEVERITY = Severity.ERROR;
43+
44+
public static final Issue ISSUE = Issue.create(
45+
ISSUE_ID,
46+
ISSUE_DESCRIPTION,
47+
ISSUE_EXPLANATION,
48+
ISSUE_CATEGORY,
49+
ISSUE_PRIORITY,
50+
ISSUE_SEVERITY,
51+
IMPLEMENTATION
52+
);
53+
private static final String FUNCTION_NAME = "printStackTrace";
54+
55+
@Override
56+
public List<String> getApplicableCallNames() {
57+
return Collections.singletonList(FUNCTION_NAME);
58+
}
59+
60+
@Override
61+
public List<String> getApplicableMethodNames() {
62+
return Collections.singletonList(FUNCTION_NAME);
63+
}
64+
65+
@Override
66+
public void checkCall(@NonNull ClassContext context,
67+
@NonNull ClassNode classNode,
68+
@NonNull MethodNode method,
69+
@NonNull MethodInsnNode call) {
70+
context.report(ISSUE,
71+
method,
72+
call,
73+
context.getLocation(call),
74+
"You must use our `ZLog.logException(e);` ");
75+
76+
}
77+
}

0 commit comments

Comments
 (0)