├── app
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── values
│ │ │ │ ├── strings.xml
│ │ │ │ ├── colors.xml
│ │ │ │ ├── dimens.xml
│ │ │ │ └── styles.xml
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ ├── fuck.png
│ │ │ │ ├── deleteme.jpg
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-hdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── values-w820dp
│ │ │ │ └── dimens.xml
│ │ │ └── layout
│ │ │ │ ├── activity_lfbase.xml
│ │ │ │ ├── activity_lint_check_right.xml
│ │ │ │ └── activity_main.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── qjoy
│ │ │ │ ├── testsupport
│ │ │ │ ├── json
│ │ │ │ │ ├── HunmanInfoError.java
│ │ │ │ │ ├── HunmanInfo.java
│ │ │ │ │ ├── PeopleInfo.java
│ │ │ │ │ └── FastJsonTools.java
│ │ │ │ ├── log
│ │ │ │ │ └── MyLog.java
│ │ │ │ ├── activity
│ │ │ │ │ ├── LFBaseActivity.java
│ │ │ │ │ ├── LintCheckRightActivity.java
│ │ │ │ │ ├── LintCheckRightAppAcompatActivity.java
│ │ │ │ │ └── LFBaseAppCompatActivity.java
│ │ │ │ └── debug
│ │ │ │ │ └── DebugHelp.java
│ │ │ │ └── MainActivity.java
│ │ └── AndroidManifest.xml
│ ├── test
│ │ └── java
│ │ │ └── qjoy
│ │ │ └── com
│ │ │ └── myapplication
│ │ │ └── ExampleUnitTest.java
│ └── androidTest
│ │ └── java
│ │ └── qjoy
│ │ └── com
│ │ └── myapplication
│ │ └── ExampleInstrumentedTest.java
├── proguard-rules.pro
└── build.gradle
├── liblflintrules
├── .gitignore
├── Readme.md
├── build.gradle
├── src
│ └── main
│ │ └── java
│ │ └── com
│ │ └── qjoy
│ │ ├── LFIssueRegistry.java
│ │ ├── ClassDetector
│ │ ├── FastJsonUsageDetector.java
│ │ └── LoggerUsageDetector.java
│ │ ├── BinaryResource
│ │ └── ImageFileSizeDetector.java
│ │ ├── JavaDetector
│ │ ├── BaseActivityDetector.java
│ │ ├── FastJsonDetector.java
│ │ └── ChineseStringDetector.java
│ │ └── XmlDetector
│ │ └── ViewIdNameDetector.java
└── liblflintrules.iml
├── liblflintrules_aarwrap
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ └── values
│ │ │ │ └── strings.xml
│ │ └── AndroidManifest.xml
│ └── androidTest
│ │ └── java
│ │ └── qjoy
│ │ └── com
│ │ └── liblflintrules_aarwrap
│ │ └── ExampleInstrumentedTest.java
├── proguard-rules.pro
├── build.gradle
└── liblflintrules_aarwrap.iml
├── settings.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── AndrLintWatchDog.iml
├── lintrulescheckdemo.iml
├── README.md
├── gradlew.bat
└── gradlew
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/liblflintrules/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/liblflintrules_aarwrap/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':liblflintrules', ':liblflintrules_aarwrap'
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | lintrulescheckdemo
3 |
4 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qjoy/AndroidLintWatchDog/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/fuck.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qjoy/AndroidLintWatchDog/HEAD/app/src/main/res/mipmap-xxxhdpi/fuck.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qjoy/AndroidLintWatchDog/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qjoy/AndroidLintWatchDog/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/deleteme.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qjoy/AndroidLintWatchDog/HEAD/app/src/main/res/mipmap-xxxhdpi/deleteme.jpg
--------------------------------------------------------------------------------
/liblflintrules_aarwrap/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | liblflintrules_aarwrap
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qjoy/AndroidLintWatchDog/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qjoy/AndroidLintWatchDog/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qjoy/AndroidLintWatchDog/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/java/com/qjoy/testsupport/json/HunmanInfoError.java:
--------------------------------------------------------------------------------
1 | package com.qjoy.testsupport.json;
2 |
3 | /**
4 | * @author AleXQ
5 | * @Date 16/9/23
6 | * @Description: 测试基类
7 | */
8 |
9 | public class HunmanInfoError{
10 | }
11 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Sep 26 10:47:40 CST 2016
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip
7 |
--------------------------------------------------------------------------------
/app/src/main/java/com/qjoy/testsupport/json/HunmanInfo.java:
--------------------------------------------------------------------------------
1 | package com.qjoy.testsupport.json;
2 |
3 | import java.io.Serializable;
4 |
5 | /**
6 | * @author AleXQ
7 | * @Date 16/9/23
8 | * @Description: 测试基类
9 | */
10 |
11 | public class HunmanInfo implements Serializable {
12 | }
13 |
--------------------------------------------------------------------------------
/liblflintrules_aarwrap/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/java/com/qjoy/testsupport/json/PeopleInfo.java:
--------------------------------------------------------------------------------
1 | package com.qjoy.testsupport.json;
2 |
3 | /**
4 | * @author AleXQ
5 | * @Date 16/9/22
6 | * @Description: 用户信息
7 | */
8 |
9 | /**
10 | * lint检查提示
11 | * 应该继承自HunmanInfo,而不是HunmanInfoError
12 | */
13 | public class PeopleInfo extends HunmanInfoError{
14 | public String name;
15 | public String school;
16 | public String birthday;
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/java/com/qjoy/testsupport/log/MyLog.java:
--------------------------------------------------------------------------------
1 | package com.qjoy.testsupport.log;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.util.Log;
5 |
6 | /**
7 | * @author AleXQ
8 | * @Date 16/9/22
9 | * @Description: 测试log
10 | */
11 |
12 | @SuppressLint("All")
13 | public class MyLog {
14 | public static void d(String Tag, String content){
15 | Log.d(Tag, content);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/java/com/qjoy/testsupport/activity/LFBaseActivity.java:
--------------------------------------------------------------------------------
1 | package com.qjoy.testsupport.activity;
2 |
3 | import android.app.Activity;
4 | import android.os.Bundle;
5 |
6 | import qjoy.com.myapplication.R;
7 |
8 | public class LFBaseActivity extends Activity {
9 |
10 | @Override
11 | protected void onCreate(Bundle savedInstanceState) {
12 | super.onCreate(savedInstanceState);
13 | setContentView(R.layout.activity_lfbase);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/java/com/qjoy/testsupport/activity/LintCheckRightActivity.java:
--------------------------------------------------------------------------------
1 | package com.qjoy.testsupport.activity;
2 |
3 | import android.os.Bundle;
4 |
5 | import qjoy.com.myapplication.R;
6 |
7 | public class LintCheckRightActivity extends LFBaseActivity {
8 |
9 | @Override
10 | protected void onCreate(Bundle savedInstanceState) {
11 | super.onCreate(savedInstanceState);
12 | setContentView(R.layout.activity_lint_check_right);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/app/src/main/java/com/qjoy/testsupport/activity/LintCheckRightAppAcompatActivity.java:
--------------------------------------------------------------------------------
1 | package com.qjoy.testsupport.activity;
2 |
3 | import android.os.Bundle;
4 |
5 | import qjoy.com.myapplication.R;
6 |
7 | public class LintCheckRightAppAcompatActivity extends LFBaseAppCompatActivity {
8 |
9 | @Override
10 | protected void onCreate(Bundle savedInstanceState) {
11 | super.onCreate(savedInstanceState);
12 | setContentView(R.layout.activity_lint_check_right);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/app/src/main/java/com/qjoy/testsupport/activity/LFBaseAppCompatActivity.java:
--------------------------------------------------------------------------------
1 | package com.qjoy.testsupport.activity;
2 |
3 | import android.os.Bundle;
4 | import android.support.v7.app.AppCompatActivity;
5 |
6 | import qjoy.com.myapplication.R;
7 |
8 | public class LFBaseAppCompatActivity extends AppCompatActivity {
9 |
10 | @Override
11 | protected void onCreate(Bundle savedInstanceState) {
12 | super.onCreate(savedInstanceState);
13 | setContentView(R.layout.activity_lfbase);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/test/java/qjoy/com/myapplication/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package qjoy.com.myapplication;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/liblflintrules/Readme.md:
--------------------------------------------------------------------------------
1 | ##Error类型错误
2 | 1. ChineseStringDetector
3 | 检查java代码中的中文硬编码
4 | 2. LoggerUsageDetector
5 | 由于系统默认Log在release下依然会打印日志,造成泄露信息的风险
6 | 3. FastJsonDetector
7 | 检查fastJson格式化类对象是否实现了Serializable或者Parcelable
8 | 4. BaseActivityDetector
9 | 检查工程所有Activity是否继承自LFBaseActivity或者LFBaseAppCompatActivity
10 | 5. ViewIdNameDetector
11 | 检查layout文件中的id是否符合《Android-Code-Style》中"布局文件中的id命名"这个部分的规定
12 | 6. ImageFileSizeDetector
13 | 检查图片文件尺寸是否超过某个限定的大小
14 | ##Warning类型错误
15 |
--------------------------------------------------------------------------------
/liblflintrules/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'java'
2 |
3 | dependencies {
4 | compile fileTree(dir: 'libs', include: ['*.jar'])
5 | compile 'com.android.tools.lint:lint-api:25.2.0'
6 | compile 'com.android.tools.lint:lint-checks:25.2.0'
7 | }
8 |
9 | jar {
10 | manifest {
11 | attributes('Lint-Registry': 'com.qjoy.LFIssueRegistry')
12 | }
13 | }
14 |
15 | configurations {
16 | lintJarOutput
17 | }
18 |
19 | dependencies {
20 | lintJarOutput files(jar)
21 | }
22 |
23 | defaultTasks 'assemble'
24 |
25 | sourceCompatibility = "1.7"
26 | targetCompatibility = "1.7"
27 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_lfbase.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_lint_check_right.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/alex_xq/Library/Android/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/liblflintrules_aarwrap/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/alex_xq/Library/Android/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/qjoy/com/myapplication/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package qjoy.com.myapplication;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumentation test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("qjoy.com.myapplication", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 |
13 | org.gradle.jvmargs=-Xmx1536m
14 |
15 | #调试lint代码
16 | #org.gradle.jvmargs='-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005'
17 |
18 | # When configured, Gradle will run in incubating parallel mode.
19 | # This option should only be used with decoupled projects. More details, visit
20 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
21 | # org.gradle.parallel=true
22 |
23 |
--------------------------------------------------------------------------------
/AndrLintWatchDog.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/liblflintrules_aarwrap/src/androidTest/java/qjoy/com/liblflintrules_aarwrap/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package qjoy.com.liblflintrules_aarwrap;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumentation test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("qjoy.com.liblflintrules_aarwrap.test", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/lintrulescheckdemo.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
19 |
20 |
21 |
26 |
27 |
--------------------------------------------------------------------------------
/liblflintrules/src/main/java/com/qjoy/LFIssueRegistry.java:
--------------------------------------------------------------------------------
1 | package com.qjoy;
2 |
3 | import com.android.tools.lint.detector.api.Issue;
4 | import com.qjoy.BinaryResource.ImageFileSizeDetector;
5 | import com.qjoy.ClassDetector.LoggerUsageDetector;
6 | import com.qjoy.JavaDetector.BaseActivityDetector;
7 | import com.qjoy.JavaDetector.ChineseStringDetector;
8 | import com.qjoy.JavaDetector.FastJsonDetector;
9 | import com.qjoy.XmlDetector.ViewIdNameDetector;
10 |
11 | import java.util.Arrays;
12 | import java.util.List;
13 |
14 | /**
15 | * @author AleXQ
16 | * @Date 16/9/19
17 | * @Description: 用来注册我们自己定义了哪些issue,这样lint在检查代码时才知道要针对哪些issue进行检查
18 | */
19 |
20 | public class LFIssueRegistry extends com.android.tools.lint.client.api.IssueRegistry {
21 | @Override
22 | public List getIssues() {
23 | System.out.println("###### LFIssueRegistry lint rules works ######");
24 | return Arrays.asList(
25 | FastJsonDetector.ISSUE
26 | , ViewIdNameDetector.ISSUE
27 | , ChineseStringDetector.ISSUE
28 | , LoggerUsageDetector.ISSUE
29 | , BaseActivityDetector.ISSUE
30 | , ImageFileSizeDetector.ISSUE
31 | );
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/app/src/main/java/com/qjoy/testsupport/json/FastJsonTools.java:
--------------------------------------------------------------------------------
1 | package com.qjoy.testsupport.json;
2 |
3 | import android.annotation.SuppressLint;
4 |
5 | import com.alibaba.fastjson.JSON;
6 |
7 | import java.util.List;
8 |
9 | /**
10 | * Created by guxiuzhong on 2015/5/12.
11 | * 开源项目FastJson json解析和生成的工具类
12 | */
13 | @SuppressLint("QjoyJavaFastJson")
14 | public class FastJsonTools {
15 |
16 | /**
17 | * 将java类型的对象转换为JSON格式的字符串
18 | *
19 | * @param object java类型的对象
20 | * @return JSON格式的字符串
21 | */
22 | public static String serialize(T object) {
23 | return JSON.toJSONString(object);
24 | }
25 |
26 | /**
27 | * 将JSON格式的字符串转换为java类型的对象或者java数组类型的对象,不包括java集合类型
28 | *
29 | * @param json JSON格式的字符串
30 | * @param clz java类型或者java数组类型,不包括java集合类型
31 | * @return java类型的对象或者java数组类型的对象,不包括java集合类型的对象
32 | */
33 | public static T deserialize(String json, Class clz) {
34 |
35 | return JSON.parseObject(json, clz);
36 | }
37 |
38 |
39 | /**
40 | * 将JSON格式的字符串转换为List类型的对象
41 | *
42 | * @param json JSON格式的字符串
43 | * @param clz 指定泛型集合里面的T类型
44 | * @return List类型的对象
45 | */
46 | public static List deserializeList(String json, Class clz) {
47 |
48 | if(json == null || !json.startsWith("[")) {
49 | return null;
50 | }
51 | return JSON.parseArray(json, clz);
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 24
5 | buildToolsVersion "24.0.0"
6 | defaultConfig {
7 | applicationId "qjoy.com.myapplication"
8 | minSdkVersion 11
9 | targetSdkVersion 24
10 | versionCode 1
11 | versionName "1.0"
12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 |
21 |
22 | lintOptions {
23 | // if true, stop the gradle build if errors are found
24 | abortOnError false
25 | // if true, only report errors
26 | ignoreWarnings true
27 | }
28 |
29 | }
30 |
31 | configurations {
32 | lintChecks
33 | }
34 |
35 | dependencies {
36 | compile fileTree(dir: 'libs', include: ['*.jar'])
37 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
38 | exclude group: 'com.android.support', module: 'support-annotations'
39 | })
40 | compile 'com.android.support:appcompat-v7:24.1.1'
41 | testCompile 'junit:junit:4.12'
42 | compile 'com.alibaba:fastjson:1.1.45.android'
43 |
44 | // 使用开发中的可调式版本进行lint-check
45 | debugCompile project(':liblflintrules_aarwrap')
46 |
47 | // 使用发布版本进行lint-check
48 | // debugCompile 'com.qjoy:liblflintrules_aarwrap:1.0.3'
49 | }
50 |
--------------------------------------------------------------------------------
/app/src/main/java/com/qjoy/testsupport/debug/DebugHelp.java:
--------------------------------------------------------------------------------
1 | package com.qjoy.testsupport.debug;
2 |
3 | /**
4 | * Copyright (c) 2015 by laifeng
5 | *
6 | * @author xueqing
7 | * @Date 15/9/1
8 | * @Description: $gradle打包libraray造成BuildConfig.Debug判断有问题
9 | */
10 |
11 | import java.lang.reflect.Field;
12 | import java.lang.reflect.Method;
13 |
14 | import qjoy.com.myapplication.BuildConfig;
15 |
16 | /**
17 | * User: xueqing(xueqing@youku.com)
18 | * Date: 2015-09-01
19 | * Time: 16:14
20 | * FIXME
21 | */
22 | public class DebugHelp {
23 |
24 | public static Boolean sDebug = null;
25 |
26 | public static boolean isDebugBuild() {
27 | if (sDebug == null) {
28 | try {
29 | final Class> activityThread = Class.forName("android.app.ActivityThread");
30 | final Method currentPackage = activityThread.getMethod("currentPackageName");
31 | final String packageName = (String) currentPackage.invoke(null, (Object[]) null);
32 | final Class> buildConfig = Class.forName(packageName + ".BuildConfig");
33 | final Field DEBUG = buildConfig.getField("DEBUG");
34 | DEBUG.setAccessible(true);
35 | sDebug = DEBUG.getBoolean(null);
36 | } catch (final Throwable t) {
37 | final String message = t.getMessage();
38 | if (message != null && message.contains("BuildConfig")) {
39 | // Proguard obfuscated build. Most likely a production build.
40 | sDebug = false;
41 | } else {
42 | sDebug = BuildConfig.DEBUG;
43 | }
44 | }
45 | }
46 | return sDebug;
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/app/src/main/java/com/qjoy/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.qjoy;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.os.Bundle;
5 | import android.util.Log;
6 |
7 | import com.qjoy.testsupport.activity.LintCheckRightAppAcompatActivity;
8 | import com.qjoy.testsupport.json.FastJsonTools;
9 | import com.qjoy.testsupport.json.PeopleInfo;
10 | import com.qjoy.testsupport.log.MyLog;
11 |
12 | import java.util.ArrayList;
13 |
14 | import qjoy.com.myapplication.R;
15 |
16 |
17 | public class MainActivity extends LintCheckRightAppAcompatActivity {
18 |
19 | @SuppressWarnings("unused")
20 | private static final String TAG = "MainActivity";
21 |
22 | @Override
23 | protected void onCreate(Bundle savedInstanceState) {
24 | super.onCreate(savedInstanceState);
25 | setContentView(R.layout.activity_main);
26 |
27 | /*
28 | // QjoyClassLogUtilsNotUsed测试
29 | LogTest();
30 |
31 | // QjoyJavaFastJson测试
32 | JsonTest();
33 |
34 | // QjoyJavaFastJson测试
35 | JsonArrayTest();
36 | */
37 | }
38 |
39 | private void LogTest(){
40 | Log.d(TAG, "test");
41 | }
42 |
43 | // @SuppressLint("QjoyJavaChineseString")
44 | // private void JsonTest(){
45 | // PeopleInfo info = FastJsonTools.deserialize("{\"name\":\"Alex\",\"school\":\"Beira\",\"birthday\":\"1985年3月xx日\"}"
46 | // , PeopleInfo.class);
47 | // MyLog.d(TAG, info.name);
48 | // }
49 |
50 | // private void JsonTestOrg(){
51 | // PeopleInfo info = JSON.parseObject("{\"name\":\"Alex\",\"school\":\"Beira\",\"birthday\":\"1985年3月xx日\"}"
52 | // , PeopleInfo.class);
53 | // MyLog.d(TAG, info.name);
54 | // }
55 |
56 | @SuppressLint("QjoyJavaChineseString")
57 | private void JsonArrayTest(){
58 | ArrayList infos = (ArrayList)FastJsonTools.deserializeList("[{\"name\":\"Alex\",\"school\":\"Beida\",\"birthday\":\"1985年3月xx日\"},{\"name\":\"Brain\",\"school\":\"Qinghua\",\"birthday\":\"1988年5月xx日\"}]"
59 | , PeopleInfo.class);
60 | MyLog.d(TAG, "Array length:"+infos.size());
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/liblflintrules/src/main/java/com/qjoy/ClassDetector/FastJsonUsageDetector.java:
--------------------------------------------------------------------------------
1 | /*
2 | package com.qjoy.ClassDetector;
3 |
4 | import com.android.annotations.NonNull;
5 | import com.android.tools.lint.detector.api.Category;
6 | import com.android.tools.lint.detector.api.ClassContext;
7 | import com.android.tools.lint.detector.api.Detector;
8 | import com.android.tools.lint.detector.api.Implementation;
9 | import com.android.tools.lint.detector.api.Issue;
10 | import com.android.tools.lint.detector.api.Scope;
11 | import com.android.tools.lint.detector.api.Severity;
12 |
13 | import org.objectweb.asm.tree.ClassNode;
14 | import org.objectweb.asm.tree.MethodInsnNode;
15 | import org.objectweb.asm.tree.MethodNode;
16 |
17 | import java.util.Arrays;
18 | import java.util.List;
19 |
20 | public class FastJsonUsageDetector extends Detector implements Detector.ClassScanner {
21 | public static final Issue ISSUE = Issue.create("QjoyClassFastJsonCheck",
22 | "FastJson",
23 | "Check the class of use fastjson has implemented Serializable or Parcelable interface",
24 | Category.MESSAGES,
25 | 9,
26 | Severity.ERROR,
27 | new Implementation(FastJsonUsageDetector.class,
28 | Scope.CLASS_FILE_SCOPE));
29 |
30 | @Override
31 | public List getApplicableCallNames() {
32 | return Arrays.asList("deserialize", "deserializeAny", "deserializeList");
33 | }
34 |
35 | @Override
36 | public List getApplicableMethodNames() {
37 | return Arrays.asList("deserialize", "deserializeAny", "deserializeList");
38 | }
39 |
40 | @Override
41 | public void checkCall(@NonNull ClassContext context,
42 | @NonNull ClassNode classNode,
43 | @NonNull MethodNode method,
44 | @NonNull MethodInsnNode call) {
45 | String owner = call.owner;
46 | if (owner.startsWith("com/qjoy/testsupport/json/FastJsonTools")) {
47 |
48 | System.out.print(context.getClassNode() + "\n");
49 |
50 | context.report(ISSUE,
51 | method,
52 | call,
53 | context.getLocation(call),
54 | "fastjson需要实现 Serializable或Parcelable接口,否则混淆后执行会崩溃");
55 | }
56 | }
57 | }
58 | */
59 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | AndroidLintWatchDog
2 | =================
3 | **by QJoy ([email](alexq_andr@163.com) alexq_andr@163.com)**
4 |
5 | 
6 | 
7 | 
8 |
9 | **AndroidLintWatchDog is a collection of some typical Android-Custom-Lint-Check sample. some of them can be used directly, others you can make a little modification to adapt to your project.**
10 |
11 | ##Features
12 | - [x] ImageFileSizeDetector : 检查图片文件尺寸是否超过某个限定的大小;
13 | - [x] LoggerUsageDetector : 使用android.util.Log任何方法;
14 | - [x] FastJsonDetector : 检查fastJson格式化类对象是否实现了Serializable或者Parcelable;
15 | - [x] BaseActivityDetector : 检查工程所有Activity是否继承自LFBaseActivity或者LFBaseAppCompatActivity;
16 | - [x] ViewIdNameDetector : 检查layout文件中的id是否符合《Android-Code-Style》中"布局文件中的id命名"这个部分的规定;
17 |
18 | ## Requirements
19 | - AndroidStudio
20 |
21 | ## Installation
22 | ###Import library into project
23 |
24 | Here is two way to use yourself's custom-lint-check.
25 | 1. Basic Way : import library from local module.
26 | Like this:
27 | debugCompile project(':liblflintrules_aarwrap')
28 |
29 | 2. Advanced Way : push your library to maven/jcenter,import from remote.
30 | Like this:
31 | debugCompile 'com.qjoy:liblflintrules_aarwrap:1.0.3'
32 | ###Setting for lint
33 | Add lint setting in your module gradle file.
34 |
35 | ```
36 | android {
37 |
38 | ...
39 |
40 | lintOptions {
41 | // if true, stop the gradle build if errors are found
42 | abortOnError false
43 | // if true, only report errors
44 | ignoreWarnings true
45 | }
46 |
47 | }
48 | ```
49 |
50 | ## Use AndroidLintWatchDog
51 | Do these in AndroidStudio Terminal tab:
52 |
53 | 1. "cd" to the module that you want check your lint-rules;
54 | 例:cd app
55 | 2. "lint" command for it;
56 | 例:../gradlew lint
57 | 3. BUILD SUCCESSFUL,now here is a html file be maked.open it,read it.
58 | 例:Wrote HTML report to file:///省去了无用的路径/app/build/outputs/lint-results-debug.html
59 |
60 | ## More Details about AndroidLintWatchDog
61 | **[Detail-androidlintwatchdog](http://alexq.farbox.com/post/andrlintwatchdog-custom-lint-zi-ding-yi-lint-ti-gao-dai-ma-zhi-liang)**
62 | ## Release History
63 |
64 | ## License
65 | **AndroidLintWatchDog is released under the BSD license. See LICENSE for details.**
66 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/liblflintrules/src/main/java/com/qjoy/ClassDetector/LoggerUsageDetector.java:
--------------------------------------------------------------------------------
1 | package com.qjoy.ClassDetector;
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.Arrays;
17 | import java.util.EnumSet;
18 | import java.util.List;
19 |
20 | @SuppressWarnings("QjoyJavaChineseString")
21 | public class LoggerUsageDetector extends Detector implements Detector.ClassScanner {
22 |
23 | private static final Class extends Detector> DETECTOR_CLASS = LoggerUsageDetector.class;
24 | private static final EnumSet DETECTOR_SCOPE = Scope.CLASS_FILE_SCOPE;
25 | private static final Implementation IMPLEMENTATION = new Implementation(
26 | DETECTOR_CLASS,
27 | DETECTOR_SCOPE
28 | );
29 |
30 | private static final String ISSUE_ID = "QJoyLogUtilsNotUsed";
31 | private static final String ISSUE_DESCRIPTION = "QJoyLogUtilsNotUsed";
32 | private static final String ISSUE_EXPLANATION = "Logging should be avoided in production for security and performance reasons. Therefore, we created a LogUtils that wraps all our calls to Logger and disable them for release flavor.";
33 | private static final Category ISSUE_CATEGORY = Category.CORRECTNESS;
34 | private static final int ISSUE_PRIORITY = 9;
35 | private static final Severity ISSUE_SEVERITY = Severity.ERROR;
36 |
37 | public static final Issue ISSUE = Issue.create(
38 | ISSUE_ID,
39 | ISSUE_DESCRIPTION,
40 | ISSUE_EXPLANATION,
41 | ISSUE_CATEGORY,
42 | ISSUE_PRIORITY,
43 | ISSUE_SEVERITY,
44 | IMPLEMENTATION
45 | );
46 |
47 | @Override
48 | public List getApplicableCallNames() {
49 | return Arrays.asList("v", "d", "i", "w", "e", "wtf");
50 | }
51 |
52 | @Override
53 | public List getApplicableMethodNames() {
54 | return Arrays.asList("v", "d", "i", "w", "e", "wtf");
55 | }
56 |
57 | @Override
58 | public void checkCall(@NonNull ClassContext context,
59 | @NonNull ClassNode classNode,
60 | @NonNull MethodNode method,
61 | @NonNull MethodInsnNode call) {
62 | String owner = call.owner;
63 | if (owner.startsWith("android/util/Log")) {
64 | context.report(ISSUE,
65 | method,
66 | call,
67 | context.getLocation(call),
68 | "使用MyLog类日志, 避免使用Log");
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/liblflintrules/src/main/java/com/qjoy/BinaryResource/ImageFileSizeDetector.java:
--------------------------------------------------------------------------------
1 | package com.qjoy.BinaryResource;
2 |
3 | import com.android.resources.ResourceFolderType;
4 | import com.android.tools.lint.detector.api.Category;
5 | import com.android.tools.lint.detector.api.Detector;
6 | import com.android.tools.lint.detector.api.Implementation;
7 | import com.android.tools.lint.detector.api.Issue;
8 | import com.android.tools.lint.detector.api.Location;
9 | import com.android.tools.lint.detector.api.ResourceContext;
10 | import com.android.tools.lint.detector.api.Scope;
11 | import com.android.tools.lint.detector.api.Severity;
12 |
13 | import java.util.EnumSet;
14 |
15 | @SuppressWarnings("ALL")
16 | public class ImageFileSizeDetector extends Detector implements Detector.BinaryResourceScanner {
17 |
18 | private static final Class extends Detector> DETECTOR_CLASS = ImageFileSizeDetector.class;
19 | private static final EnumSet DETECTOR_SCOPE = Scope.BINARY_RESOURCE_FILE_SCOPE;
20 | private static final Implementation IMPLEMENTATION = new Implementation(
21 | DETECTOR_CLASS,
22 | DETECTOR_SCOPE
23 | );
24 |
25 | private static final String ISSUE_ID = "QJoyImageFileSizeInvalid";
26 | private static final String ISSUE_DESCRIPTION = "QJoyImageFileSizeInvalid";
27 | private static final String ISSUE_EXPLANATION = "Image File too large, Compress your one or more image files, Final Solution: https://github.com/qjoy/TinyPNGNodeJSBatcher";
28 | private static final Category ISSUE_CATEGORY = Category.CORRECTNESS;
29 | private static final int ISSUE_PRIORITY = 5;
30 | private static final Severity ISSUE_SEVERITY = Severity.ERROR;
31 |
32 | public static final Issue ISSUE = Issue.create(
33 | ISSUE_ID,
34 | ISSUE_DESCRIPTION,
35 | ISSUE_EXPLANATION,
36 | ISSUE_CATEGORY,
37 | ISSUE_PRIORITY,
38 | ISSUE_SEVERITY,
39 | IMPLEMENTATION
40 | ).addMoreInfo("https://github.com/qjoy/TinyPNGNodeJSBatcher");
41 |
42 |
43 | @SuppressWarnings({"WeakerAccess", "CanBeFinal"})
44 | String reportStr = "图片文件过大: %d" + "KB,超过了项目限制的:" + CHECK_IMAGE_KB_SIZE + "KB,请进行压缩或找设计重新出图.";
45 |
46 | private static final String CHECK_IMAGE_PNG = ".png";
47 | private static final String CHECK_IMAGE_JPEG = ".jpeg";
48 | private static final String CHECK_IMAGE_JPG = ".jpg";
49 | private static final long CHECK_IMAGE_KB_SIZE = 250;
50 |
51 | @Override
52 | public boolean appliesTo(ResourceFolderType var1) {
53 | return var1.getName().equalsIgnoreCase(String.valueOf(ResourceFolderType.MIPMAP)) || var1.getName().equalsIgnoreCase(String.valueOf(ResourceFolderType.DRAWABLE));
54 | }
55 |
56 | @Override
57 | public void checkBinaryResource(ResourceContext context) {
58 |
59 | String filename = context.file.getName();
60 |
61 | if ( filename.contains(CHECK_IMAGE_PNG)
62 | || filename.contains(CHECK_IMAGE_JPEG)
63 | || filename.contains(CHECK_IMAGE_JPG)
64 | ){
65 | long fileSize = context.file.length()/1024;
66 | if (fileSize > CHECK_IMAGE_KB_SIZE){
67 |
68 | String repS = String.format(reportStr, fileSize);
69 |
70 | Location fileLocation = Location.create(context.file);
71 | context.report(ISSUE,
72 | fileLocation,
73 | repS);
74 | }
75 | }
76 |
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/liblflintrules_aarwrap/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'com.github.dcendents.android-maven'
3 | apply plugin: 'com.jfrog.bintray'
4 |
5 | android {
6 | compileSdkVersion 24
7 | buildToolsVersion "24.0.0"
8 |
9 | defaultConfig {
10 | minSdkVersion 11
11 | targetSdkVersion 24
12 | versionCode 1
13 | versionName "1.0"
14 |
15 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
16 |
17 | }
18 | buildTypes {
19 | release {
20 | minifyEnabled false
21 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
22 | }
23 | }
24 | }
25 |
26 | dependencies {
27 | compile fileTree(dir: 'libs', include: ['*.jar'])
28 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
29 | exclude group: 'com.android.support', module: 'support-annotations'
30 | })
31 | }
32 |
33 | /*
34 | * rules for including "lint.jar" in aar
35 | */
36 | configurations {
37 | lintJarImport
38 | }
39 |
40 | dependencies {
41 | lintJarImport project(path: ":liblflintrules", configuration: "lintJarOutput")
42 | }
43 |
44 | task copyLintJar(type: Copy) {
45 | from (configurations.lintJarImport) {
46 | rename {
47 | String fileName ->
48 | 'lint.jar'
49 | }
50 | }
51 | into 'build/intermediates/lint/'
52 | }
53 |
54 | project.afterEvaluate {
55 | def compileLintTask = project.tasks.find { it.name == 'compileLint' }
56 | compileLintTask.dependsOn(copyLintJar)
57 | }
58 |
59 | /**
60 | * 上传&设置到bintray指令
61 | */
62 | // 提交到仓库中的版本号
63 |
64 | version = "1.0.6.1"
65 |
66 | def siteUrl = 'current null' // 项目的主页,换成自己的
67 | def gitUrl = 'current null' // Git仓库的url
68 | group = "com.qjoy" //这个地址是将来compile引用的地址
69 | install {
70 | repositories.mavenInstaller {
71 | pom {
72 | project {
73 | packaging 'aar'
74 | name 'qjoy lint rules checker' //项目描述
75 | url siteUrl
76 | licenses {
77 | license {
78 | name 'The Apache Software License, Version 2.0'
79 | url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
80 | }
81 | }
82 | developers {
83 | developer {//填写的一些开发者的基本信息
84 | id 'AlexQ' //填写开发者的id
85 | name 'AlexQ' //填写开发者的name
86 | email 'alexq_andr@163.com' //填写开发者的email
87 | }
88 | }
89 | scm {
90 | connection gitUrl
91 | developerConnection gitUrl
92 | url siteUrl
93 | }
94 | }
95 | }
96 | }
97 | }
98 | task sourcesJar(type: Jar) {
99 | from android.sourceSets.main.java.srcDirs
100 | classifier = 'sources'
101 | }
102 | task javadoc(type: Javadoc) {
103 | source = android.sourceSets.main.java.srcDirs
104 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
105 | }
106 | task javadocJar(type: Jar, dependsOn: javadoc) {
107 | classifier = 'javadoc'
108 | from javadoc.destinationDir
109 | }
110 | artifacts {
111 | archives javadocJar
112 | archives sourcesJar
113 | }
114 | Properties properties = new Properties()
115 | properties.load(project.rootProject.file('local.properties').newDataInputStream())
116 | bintray {
117 | user = properties.getProperty("bintray.user")
118 | key = properties.getProperty("bintray.apikey")
119 | configurations = ['archives']
120 | pkg {
121 | repo = "maven"
122 | name = "qjoy_lintrules" //发布到JCenter上的项目名字
123 | websiteUrl = siteUrl
124 | vcsUrl = gitUrl
125 | licenses = ["BSD"]
126 | publish = true
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/liblflintrules/liblflintrules.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/liblflintrules/src/main/java/com/qjoy/JavaDetector/BaseActivityDetector.java:
--------------------------------------------------------------------------------
1 | package com.qjoy.JavaDetector;
2 |
3 | import com.android.tools.lint.client.api.JavaParser;
4 | import com.android.tools.lint.detector.api.Category;
5 | import com.android.tools.lint.detector.api.Detector;
6 | import com.android.tools.lint.detector.api.Implementation;
7 | import com.android.tools.lint.detector.api.Issue;
8 | import com.android.tools.lint.detector.api.JavaContext;
9 | import com.android.tools.lint.detector.api.Scope;
10 | import com.android.tools.lint.detector.api.Severity;
11 |
12 | import java.util.EnumSet;
13 |
14 | import lombok.ast.AstVisitor;
15 | import lombok.ast.ClassDeclaration;
16 | import lombok.ast.ForwardingAstVisitor;
17 | import lombok.ast.Node;
18 |
19 | /**
20 | * @author QJOY
21 | * @Date 16/9/22
22 | * @Description: 检查工程所有Activity是否继承自LFBaseActivity或者LFBaseAppCompatActivity
23 | */
24 | @SuppressWarnings({"QjoyJavaChineseString", "deprecation"})
25 | public class BaseActivityDetector extends Detector implements Detector.JavaScanner {
26 |
27 | private static final Class extends Detector> DETECTOR_CLASS = BaseActivityDetector.class;
28 | private static final EnumSet DETECTOR_SCOPE = Scope.JAVA_FILE_SCOPE;
29 | private static final Implementation IMPLEMENTATION = new Implementation(
30 | DETECTOR_CLASS,
31 | DETECTOR_SCOPE
32 | );
33 |
34 | private static final String ISSUE_ID = "QJoyJavaBaseActivity";
35 | private static final String ISSUE_DESCRIPTION = "QJoyJavaBaseActivity";
36 | private static final String ISSUE_EXPLANATION = "Check whether your Activity inherited from LFBaseActivity";
37 | private static final Category ISSUE_CATEGORY = Category.CORRECTNESS;
38 | private static final int ISSUE_PRIORITY = 9;
39 | private static final Severity ISSUE_SEVERITY = Severity.ERROR;
40 |
41 | public static final Issue ISSUE = Issue.create(
42 | ISSUE_ID,
43 | ISSUE_DESCRIPTION,
44 | ISSUE_EXPLANATION,
45 | ISSUE_CATEGORY,
46 | ISSUE_PRIORITY,
47 | ISSUE_SEVERITY,
48 | IMPLEMENTATION
49 | );
50 |
51 | private JavaContext mContext;
52 |
53 | private static final String INTERFACE_JAVAOBJECT = "java.lang.Object";
54 | /**
55 | * 不可以直接继承的Activity类全信息
56 | */
57 | private static final String INVALIDE_ACTVITY_PARENTNAME_0 = "android.app.Activity";
58 | private static final String INVALIDE_ACTVITY_PARENTNAME_1 = "android.support.v7.app.AppCompatActivity";
59 |
60 | private static final String VALIDE_ACTVITY_PARENTNAME_0 = "LFBaseActivity";
61 | private static final String VALIDE_ACTVITY_PARENTNAME_1 = "LFBaseAppCompatActivity";
62 | /**
63 | * 报错信息
64 | */
65 | private static final String REPORTWORD = "需要继承自LFBaseActivity/LFBaseAppCompatActivity,不允许直接继承自Activity/AppCompatActivity";
66 |
67 | @SuppressWarnings("deprecation")
68 | @Override
69 | public AstVisitor createJavaVisitor(JavaContext context) {
70 |
71 | mContext = context;
72 |
73 | return new ForwardingAstVisitor() {
74 | @Override
75 | public boolean visitClassDeclaration(ClassDeclaration node) {
76 |
77 | @SuppressWarnings("deprecation") JavaParser.ResolvedNode resolve = mContext.resolve(node);
78 |
79 | if (resolve instanceof JavaParser.ResolvedClass) {
80 |
81 | if (resolve.getName().contains(VALIDE_ACTVITY_PARENTNAME_0) ||
82 | resolve.getName().contains(VALIDE_ACTVITY_PARENTNAME_1)
83 | ){
84 | return super.visitClassDeclaration(node);
85 | }
86 |
87 | JavaParser.ResolvedClass superclass = ((JavaParser.ResolvedClass) resolve).getSuperClass();
88 |
89 | recursiveSupperClass(superclass, node);
90 | }
91 |
92 |
93 | return super.visitClassDeclaration(node);
94 | }
95 |
96 | JavaParser.ResolvedClass recursiveSupperClass(JavaParser.ResolvedClass curClass, Node node){
97 |
98 | //是否已经找到跟节点Object上了
99 | if (curClass.getName().equals(INTERFACE_JAVAOBJECT)){
100 | return curClass;
101 | }
102 |
103 | //在当前节点查找是否
104 | if (checkActivityRules(curClass, node)) {
105 | return curClass;
106 | }
107 | else{
108 | return recursiveSupperClass(curClass.getSuperClass(), node);
109 | }
110 | }
111 |
112 | boolean checkActivityRules(JavaParser.ResolvedClass curClass, Node node){
113 | boolean res = false;
114 |
115 | if (curClass.getName().contains(VALIDE_ACTVITY_PARENTNAME_0) ||
116 | curClass.getName().contains(VALIDE_ACTVITY_PARENTNAME_1)){
117 | res = true;
118 | }
119 |
120 | if (curClass.matches(INVALIDE_ACTVITY_PARENTNAME_0) ||
121 | curClass.matches(INVALIDE_ACTVITY_PARENTNAME_1)){
122 | mContext.report(
123 | ISSUE,
124 | node, mContext.getLocation(node),
125 | REPORTWORD
126 | );
127 |
128 | res = true;
129 | }
130 |
131 | return res;
132 |
133 | }
134 |
135 | };
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/liblflintrules/src/main/java/com/qjoy/JavaDetector/FastJsonDetector.java:
--------------------------------------------------------------------------------
1 |
2 | package com.qjoy.JavaDetector;
3 |
4 | import com.android.annotations.NonNull;
5 | import com.android.tools.lint.client.api.JavaParser;
6 | import com.android.tools.lint.detector.api.Category;
7 | import com.android.tools.lint.detector.api.Detector;
8 | import com.android.tools.lint.detector.api.Implementation;
9 | import com.android.tools.lint.detector.api.Issue;
10 | import com.android.tools.lint.detector.api.JavaContext;
11 | import com.android.tools.lint.detector.api.Scope;
12 | import com.android.tools.lint.detector.api.Severity;
13 |
14 | import java.util.ArrayList;
15 | import java.util.EnumSet;
16 |
17 | import lombok.ast.AstVisitor;
18 | import lombok.ast.ForwardingAstVisitor;
19 | import lombok.ast.MethodInvocation;
20 | import lombok.ast.Node;
21 |
22 | @SuppressWarnings("All")
23 |
24 | /**
25 | * @author QJOY
26 | * @Date 16/9/22
27 | * @Description: 检查fastJson格式化类对象是否实现了Serializable或者Parcelable
28 | */
29 | public class FastJsonDetector extends Detector implements Detector.JavaScanner {
30 |
31 | private static final Class extends Detector> DETECTOR_CLASS = FastJsonDetector.class;
32 | private static final EnumSet DETECTOR_SCOPE = Scope.JAVA_FILE_SCOPE;
33 | private static final Implementation IMPLEMENTATION = new Implementation(
34 | DETECTOR_CLASS,
35 | DETECTOR_SCOPE
36 | );
37 |
38 | private static final String ISSUE_ID = "QjoyJavaFastJson";
39 | private static final String ISSUE_DESCRIPTION = "QjoyJavaFastJson";
40 | private static final String ISSUE_EXPLANATION = "Check the class of use fastjson has implemented Serializable or Parcelable interface";
41 | private static final Category ISSUE_CATEGORY = Category.LINT;
42 | private static final int ISSUE_PRIORITY = 9;
43 | private static final Severity ISSUE_SEVERITY = Severity.ERROR;
44 |
45 | public static final Issue ISSUE = Issue.create(
46 | ISSUE_ID,
47 | ISSUE_DESCRIPTION,
48 | ISSUE_EXPLANATION,
49 | ISSUE_CATEGORY,
50 | ISSUE_PRIORITY,
51 | ISSUE_SEVERITY,
52 | IMPLEMENTATION
53 | );
54 |
55 | private JavaContext mContext;
56 |
57 | private static final String FASTJSONTOOLS_NAME = "FastJsonTools";
58 |
59 | private static final String INTERFACE_JAVAOBJECT = "java.lang.Object";
60 | /**
61 | * 需要实现的接口名称
62 | */
63 | private static final String INTERFACE_SERIALIZABLE = "Serializable";
64 | private static final String INTERFACE_PARCELABLE = "Parcelable";
65 |
66 |
67 | private static final String FASTJSONORG_NAME = "JSON";
68 |
69 |
70 | /**
71 | * 报错信息
72 | */
73 | private static final String REPORTWORD = "被用到FastJson的JSON.parseXXX方法的类,必须实现Serializable或Parcelable接口,否则混淆后执行会崩溃";
74 | /**
75 | * 检测的接口名称
76 | */
77 | //public static String serialize(T object)
78 | // private static final String FASTJSONMETHOD_SERIALIZE = "serialize";
79 | //public static T deserialize(String json, Class clz)
80 | private static final String FASTJSONMETHOD_DESERIALIZE = "deserialize";
81 | // //public static List deserializeList(String json, Class clz)
82 | // private static final String FASTJSONMETHOD_DESERIALIZELIST = "deserializeList";
83 | private static final String FASTJSONMETHOD_PARSEOBJECT = "parseObject";
84 |
85 |
86 | @Override
87 | public AstVisitor createJavaVisitor(final @NonNull JavaContext context) {
88 |
89 | mContext = context;
90 |
91 | return new ForwardingAstVisitor() {
92 | @Override
93 | public boolean visitMethodInvocation(MethodInvocation node) {
94 |
95 | JavaParser.ResolvedNode resolve = context.resolve(node);
96 | if (resolve instanceof JavaParser.ResolvedMethod) {
97 | JavaParser.ResolvedMethod method = (JavaParser.ResolvedMethod) resolve;
98 | // 方法所在的类校验
99 | JavaParser.ResolvedClass containingClass = method.getContainingClass();
100 | if (containingClass.getName().contains(FASTJSONTOOLS_NAME) ||
101 | containingClass.getName().contains(FASTJSONORG_NAME)
102 | ) {
103 |
104 | if (method.getName().equals(FASTJSONMETHOD_DESERIALIZE) ||
105 | method.getName().equals(FASTJSONMETHOD_PARSEOBJECT)
106 | ) {
107 |
108 | JavaParser.TypeDescriptor classType = method.getReturnType();
109 | JavaParser.ResolvedClass resolvedClass = classType.getTypeClass();
110 |
111 | recursiveSupperClass(resolvedClass, node);
112 |
113 | return true;
114 | }
115 | // else if (method.getName().equals(FASTJSONMETHOD_SERIALIZE)
116 | // ){
117 | //
118 | // JavaParser.TypeDescriptor classType = method.getArgumentType(0);
119 | // JavaParser.ResolvedClass resolvedClass = classType.getTypeClass();
120 | //
121 | // recursiveSupperClass(resolvedClass, node);
122 | //
123 | // return true;
124 | // }
125 | }
126 | }
127 | return super.visitMethodInvocation(node);
128 | }
129 |
130 | boolean found = false;
131 |
132 | JavaParser.ResolvedClass recursiveSupperClass(JavaParser.ResolvedClass curClass, Node node){
133 |
134 | if (found)
135 | return null;
136 | //是否已经找到跟节点上了
137 | if (curClass.getName().equals(INTERFACE_JAVAOBJECT)){
138 | context.report(
139 | ISSUE,
140 | node,
141 | context.getLocation(node),
142 | REPORTWORD
143 | );
144 | found = true;
145 | return curClass;
146 | }
147 |
148 | //在当前节点查找是否
149 | if (checkFastJsonRules(curClass, node)) {
150 | return curClass;
151 | }
152 | else{
153 | return recursiveSupperClass(curClass.getSuperClass(), node);
154 | }
155 | }
156 |
157 | boolean checkFastJsonRules(JavaParser.ResolvedClass curClass, Node node){
158 | boolean res = false;
159 | try {
160 | ArrayList interfaces = (ArrayList) curClass.getInterfaces();
161 |
162 | boolean valid = false;
163 | for (int i = 0; i < interfaces.size(); i++) {
164 | JavaParser.ResolvedClass tmpInterface = interfaces.get(i);
165 | if (tmpInterface.getName().contains(INTERFACE_SERIALIZABLE) ||
166 | tmpInterface.getName().contains(INTERFACE_PARCELABLE)) {
167 | valid = true;
168 | found = true;
169 | }
170 | }
171 |
172 | if (!valid) {
173 | context.report(
174 | ISSUE,
175 | node, context.getLocation(node),
176 | REPORTWORD
177 | );
178 | res = true;
179 | found = true;
180 | }
181 | }
182 | catch (Exception e){
183 | res = false;
184 | }
185 |
186 | // System.out.print("\n method:" + des.getName() + "\n");
187 | return res;
188 |
189 | }
190 | };
191 |
192 |
193 | }
194 |
195 |
196 |
197 |
198 | }
199 |
--------------------------------------------------------------------------------
/liblflintrules/src/main/java/com/qjoy/XmlDetector/ViewIdNameDetector.java:
--------------------------------------------------------------------------------
1 | package com.qjoy.XmlDetector;
2 |
3 | import com.android.annotations.NonNull;
4 | import com.android.resources.ResourceFolderType;
5 | import com.android.tools.lint.detector.api.Category;
6 | import com.android.tools.lint.detector.api.Context;
7 | import com.android.tools.lint.detector.api.Detector;
8 | import com.android.tools.lint.detector.api.Implementation;
9 | import com.android.tools.lint.detector.api.Issue;
10 | import com.android.tools.lint.detector.api.ResourceXmlDetector;
11 | import com.android.tools.lint.detector.api.Scope;
12 | import com.android.tools.lint.detector.api.Severity;
13 | import com.android.tools.lint.detector.api.XmlContext;
14 |
15 | import org.w3c.dom.Attr;
16 |
17 | import java.util.Collection;
18 | import java.util.Collections;
19 | import java.util.EnumSet;
20 |
21 | import static com.android.SdkConstants.VALUE_ID;
22 |
23 | /**
24 | * @author QJOY
25 | * @Date 16/9/22
26 | * @Description: 检查layout文件中的id是否符合《Android-Code-Style》中"布局文件中的id命名"这个部分的规定
27 | */
28 | @SuppressWarnings("QjoyJavaChineseString")
29 | public class ViewIdNameDetector extends ResourceXmlDetector
30 | {
31 |
32 | private static final Class extends Detector> DETECTOR_CLASS = ViewIdNameDetector.class;
33 | private static final EnumSet DETECTOR_SCOPE = Scope.RESOURCE_FILE_SCOPE;
34 | private static final Implementation IMPLEMENTATION = new Implementation(
35 | DETECTOR_CLASS,
36 | DETECTOR_SCOPE
37 | );
38 |
39 | private static final String ISSUE_ID = "QjoyResourceXmlViewIdName";
40 | private static final String ISSUE_DESCRIPTION = "QjoyResourceXmlViewIdName";
41 | private static final String ISSUE_EXPLANATION = "Check whether the name is conform to the specifications";
42 | private static final Category ISSUE_CATEGORY = Category.LINT;
43 | private static final int ISSUE_PRIORITY = 9;
44 | private static final Severity ISSUE_SEVERITY = Severity.ERROR;
45 |
46 | public static final Issue ISSUE = Issue.create(
47 | ISSUE_ID,
48 | ISSUE_DESCRIPTION,
49 | ISSUE_EXPLANATION,
50 | ISSUE_CATEGORY,
51 | ISSUE_PRIORITY,
52 | ISSUE_SEVERITY,
53 | IMPLEMENTATION
54 | );
55 |
56 | String reportStrFormat = "Layout文件中id命名不符合规范: %s, 前缀必须是: %s";
57 |
58 |
59 | private static final String ANDROIDID = "android:id";
60 | /*
61 | id命名规范
62 | */
63 | /*layout*/
64 | private static final String IDHEADER_LAYOUT_ABBREVIATION = "layout";
65 | private static final String ID_LAYOUT_RELATIVELAYOUT = "RelativeLayout";
66 | private static final String ID_LAYOUT_LINEARLAYOUT = "LinearLayout";
67 | private static final String ID_LAYOUT_FRAMELAYOUT = "FrameLayout";
68 | /*button*/
69 | private static final String IDHEADER_BUTTON_ABBREVIATION = "button";
70 | private static final String ID_BUTTON_BUTTON = "Button";
71 | private static final String ID_BUTTON_RADIOBUTTON = "RadioButton";
72 | private static final String ID_BUTTON_IMAGEBUTTON = "ImageButton";
73 | /*text*/
74 | private static final String IDHEADER_TEXT_ABBREVIATION = "text";
75 | private static final String ID_TEXT_TEXTVIEW = "TextView";
76 | private static final String ID_TEXT_EDITTEXT = "EditText";
77 | /*imageView*/
78 | private static final String IDHEADER_IMAGEVIEW_ABBREVIATION = "imageView";
79 | private static final String ID_IMAGEVIEW = "ImageView";
80 | /*listView*/
81 | private static final String IDHEADER_LISTVIEW_ABBREVIATION = "listView";
82 | private static final String ID_LISTVIEW = "ListView";
83 | /*webView*/
84 | private static final String IDHEADER_WEBVIEW_ABBREVIATION = "webView";
85 | private static final String ID_WEBVIEW = "WebView";
86 | /*listView*/
87 | private static final String IDHEADER_CHECKBOX_ABBREVIATION = "checkBox";
88 | private static final String ID_CHECKBOX = "CheckBox";
89 | /*listView*/
90 | private static final String IDHEADER_PROGRESSBAR_ABBREVIATION = "progressBar";
91 | private static final String ID_PROGRESSBAR = "ProgressBar";
92 | /*listView*/
93 | private static final String IDHEADER_SEEKBAR_ABBREVIATION = "seekBar";
94 | private static final String ID_SEEKBAR = "SeekBar";
95 |
96 | @Override
97 | public void beforeCheckProject(Context context) {
98 | super.beforeCheckProject(context);
99 | }
100 |
101 | @Override
102 | public boolean appliesTo(ResourceFolderType folderType) {
103 | return ResourceFolderType.LAYOUT == folderType;
104 | }
105 |
106 | @Override
107 | public Collection getApplicableAttributes() {
108 | return Collections.singletonList(VALUE_ID);
109 | }
110 |
111 | @Override
112 | public void visitAttribute(@NonNull XmlContext context, @NonNull Attr attribute) {
113 | super.visitAttribute(context, attribute);
114 |
115 | String prnMain = context.getMainProject().getDir().getPath();
116 | String prnCur = context.getProject().getDir().getPath();
117 |
118 | //1.只关心id节点
119 | //2.只关心工程中的xml文件,build等等目录下的不关心
120 | if (attribute.getName().startsWith(ANDROIDID) && prnMain.equals(prnCur))
121 | checkNameRule(context, attribute);
122 | }
123 |
124 | private void checkNameRule(XmlContext context, Attr attribute) {
125 |
126 | String tagName = attribute.getOwnerElement().getTagName();//LineanLayout...
127 | //layout
128 | int startIndex = 0;
129 | String idName = attribute.getValue().substring(5);
130 | String attrRight = "";
131 | switch (tagName) {
132 | case ID_LAYOUT_LINEARLAYOUT:
133 | case ID_LAYOUT_RELATIVELAYOUT:
134 | case ID_LAYOUT_FRAMELAYOUT:
135 | attrRight = IDHEADER_LAYOUT_ABBREVIATION;
136 | startIndex = idName.indexOf(attrRight);
137 | break;
138 | case ID_BUTTON_BUTTON:
139 | case ID_BUTTON_IMAGEBUTTON:
140 | case ID_BUTTON_RADIOBUTTON:
141 | attrRight = IDHEADER_BUTTON_ABBREVIATION;
142 | startIndex = idName.indexOf(attrRight);
143 | break;
144 | case ID_TEXT_TEXTVIEW:
145 | case ID_TEXT_EDITTEXT:
146 | attrRight = IDHEADER_TEXT_ABBREVIATION;
147 | startIndex = idName.indexOf(attrRight);
148 | break;
149 | case ID_IMAGEVIEW:
150 | attrRight = IDHEADER_IMAGEVIEW_ABBREVIATION;
151 | startIndex = idName.indexOf(attrRight);
152 | break;
153 | case ID_LISTVIEW:
154 | attrRight = IDHEADER_LISTVIEW_ABBREVIATION;
155 | startIndex = idName.indexOf(attrRight);
156 | break;
157 | case ID_WEBVIEW:
158 | attrRight = IDHEADER_WEBVIEW_ABBREVIATION;
159 | startIndex = idName.indexOf(attrRight);
160 | break;
161 | case ID_CHECKBOX:
162 | attrRight = IDHEADER_CHECKBOX_ABBREVIATION;
163 | startIndex = idName.indexOf(attrRight);
164 | break;
165 | case ID_PROGRESSBAR:
166 | attrRight = IDHEADER_PROGRESSBAR_ABBREVIATION;
167 | startIndex = idName.indexOf(attrRight);
168 | break;
169 | case ID_SEEKBAR:
170 | attrRight = IDHEADER_SEEKBAR_ABBREVIATION;
171 | startIndex = idName.indexOf(attrRight);
172 | break;
173 | }
174 |
175 | if (startIndex != 0) {
176 |
177 | String reportStr = String.format(reportStrFormat, idName, attrRight);
178 |
179 | context.report(ISSUE,
180 | attribute,
181 | context.getLocation(attribute),
182 | reportStr);
183 | }
184 |
185 | }
186 |
187 | }
188 |
--------------------------------------------------------------------------------
/liblflintrules_aarwrap/liblflintrules_aarwrap.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | generateDebugSources
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
--------------------------------------------------------------------------------
/liblflintrules/src/main/java/com/qjoy/JavaDetector/ChineseStringDetector.java:
--------------------------------------------------------------------------------
1 | package com.qjoy.JavaDetector;
2 |
3 | import com.android.annotations.NonNull;
4 | import com.android.tools.lint.detector.api.Category;
5 | import com.android.tools.lint.detector.api.Detector;
6 | import com.android.tools.lint.detector.api.Implementation;
7 | import com.android.tools.lint.detector.api.Issue;
8 | import com.android.tools.lint.detector.api.JavaContext;
9 | import com.android.tools.lint.detector.api.Scope;
10 | import com.android.tools.lint.detector.api.Severity;
11 |
12 | import java.util.EnumSet;
13 | import java.util.regex.Matcher;
14 | import java.util.regex.Pattern;
15 |
16 | import lombok.ast.AlternateConstructorInvocation;
17 | import lombok.ast.Annotation;
18 | import lombok.ast.AnnotationDeclaration;
19 | import lombok.ast.AnnotationElement;
20 | import lombok.ast.AnnotationMethodDeclaration;
21 | import lombok.ast.AnnotationValueArray;
22 | import lombok.ast.ArrayAccess;
23 | import lombok.ast.ArrayCreation;
24 | import lombok.ast.ArrayDimension;
25 | import lombok.ast.ArrayInitializer;
26 | import lombok.ast.Assert;
27 | import lombok.ast.AstVisitor;
28 | import lombok.ast.BinaryExpression;
29 | import lombok.ast.Block;
30 | import lombok.ast.BooleanLiteral;
31 | import lombok.ast.Break;
32 | import lombok.ast.Case;
33 | import lombok.ast.Cast;
34 | import lombok.ast.Catch;
35 | import lombok.ast.CharLiteral;
36 | import lombok.ast.ClassDeclaration;
37 | import lombok.ast.ClassLiteral;
38 | import lombok.ast.Comment;
39 | import lombok.ast.CompilationUnit;
40 | import lombok.ast.ConstructorDeclaration;
41 | import lombok.ast.ConstructorInvocation;
42 | import lombok.ast.Continue;
43 | import lombok.ast.Default;
44 | import lombok.ast.DoWhile;
45 | import lombok.ast.EmptyDeclaration;
46 | import lombok.ast.EmptyStatement;
47 | import lombok.ast.EnumConstant;
48 | import lombok.ast.EnumDeclaration;
49 | import lombok.ast.EnumTypeBody;
50 | import lombok.ast.ExpressionStatement;
51 | import lombok.ast.FloatingPointLiteral;
52 | import lombok.ast.For;
53 | import lombok.ast.ForEach;
54 | import lombok.ast.Identifier;
55 | import lombok.ast.If;
56 | import lombok.ast.ImportDeclaration;
57 | import lombok.ast.InlineIfExpression;
58 | import lombok.ast.InstanceInitializer;
59 | import lombok.ast.InstanceOf;
60 | import lombok.ast.IntegralLiteral;
61 | import lombok.ast.InterfaceDeclaration;
62 | import lombok.ast.KeywordModifier;
63 | import lombok.ast.LabelledStatement;
64 | import lombok.ast.MethodDeclaration;
65 | import lombok.ast.MethodInvocation;
66 | import lombok.ast.Modifiers;
67 | import lombok.ast.Node;
68 | import lombok.ast.NormalTypeBody;
69 | import lombok.ast.NullLiteral;
70 | import lombok.ast.PackageDeclaration;
71 | import lombok.ast.Return;
72 | import lombok.ast.Select;
73 | import lombok.ast.StaticInitializer;
74 | import lombok.ast.StringLiteral;
75 | import lombok.ast.Super;
76 | import lombok.ast.SuperConstructorInvocation;
77 | import lombok.ast.Switch;
78 | import lombok.ast.Synchronized;
79 | import lombok.ast.This;
80 | import lombok.ast.Throw;
81 | import lombok.ast.Try;
82 | import lombok.ast.TypeReference;
83 | import lombok.ast.TypeReferencePart;
84 | import lombok.ast.TypeVariable;
85 | import lombok.ast.UnaryExpression;
86 | import lombok.ast.VariableDeclaration;
87 | import lombok.ast.VariableDefinition;
88 | import lombok.ast.VariableDefinitionEntry;
89 | import lombok.ast.VariableReference;
90 | import lombok.ast.While;
91 |
92 | public class ChineseStringDetector extends Detector implements Detector.JavaScanner {
93 |
94 | private static final Class extends Detector> DETECTOR_CLASS = ChineseStringDetector.class;
95 | private static final EnumSet DETECTOR_SCOPE = Scope.JAVA_FILE_SCOPE;
96 | private static final Implementation IMPLEMENTATION = new Implementation(
97 | DETECTOR_CLASS,
98 | DETECTOR_SCOPE
99 | );
100 |
101 | private static final String ISSUE_ID = "QjoyJavaChineseString";
102 | private static final String ISSUE_DESCRIPTION = "QjoyJavaChineseString";
103 | private static final String ISSUE_EXPLANATION = "Check chinese string hardcode in java file";
104 | private static final Category ISSUE_CATEGORY = Category.CORRECTNESS;
105 | private static final int ISSUE_PRIORITY = 5;
106 | private static final Severity ISSUE_SEVERITY = Severity.ERROR;
107 |
108 | public static final Issue ISSUE = Issue.create(
109 | ISSUE_ID,
110 | ISSUE_DESCRIPTION,
111 | ISSUE_EXPLANATION,
112 | ISSUE_CATEGORY,
113 | ISSUE_PRIORITY,
114 | ISSUE_SEVERITY,
115 | IMPLEMENTATION
116 | );
117 |
118 | public AstVisitor createJavaVisitor(@NonNull final JavaContext context) {
119 | return new AstVisitor() {
120 | @Override
121 | public boolean visitTypeReference(TypeReference typeReference) {
122 | return false;
123 | }
124 |
125 | @Override
126 | public boolean visitTypeReferencePart(TypeReferencePart typeReferencePart) {
127 | return false;
128 | }
129 |
130 | @Override
131 | public boolean visitVariableReference(VariableReference variableReference) {
132 | return false;
133 | }
134 |
135 | @Override
136 | public boolean visitIdentifier(Identifier identifier) {
137 | return false;
138 | }
139 |
140 | @Override
141 | public boolean visitIntegralLiteral(IntegralLiteral integralLiteral) {
142 | return false;
143 | }
144 |
145 | @Override
146 | public boolean visitFloatingPointLiteral(FloatingPointLiteral floatingPointLiteral) {
147 | return false;
148 | }
149 |
150 | @Override
151 | public boolean visitBooleanLiteral(BooleanLiteral booleanLiteral) {
152 | return false;
153 | }
154 |
155 | @Override
156 | public boolean visitCharLiteral(CharLiteral charLiteral) {
157 | return false;
158 | }
159 |
160 | @Override
161 | public boolean visitStringLiteral(StringLiteral stringLiteral) {
162 | String patternStr = "[\\u4e00-\\u9fa5]";
163 | Pattern pattern = Pattern.compile(patternStr);
164 | Matcher matcher = pattern.matcher(stringLiteral.astValue());
165 | if (matcher.find()) {
166 | context.report(
167 | ISSUE,
168 | stringLiteral, context.getLocation(stringLiteral),
169 | "chinese string:" + stringLiteral.astValue()
170 | );
171 | }
172 | return false;
173 | }
174 |
175 | @Override
176 | public boolean visitNullLiteral(NullLiteral nullLiteral) {
177 | return false;
178 | }
179 |
180 | @Override
181 | public boolean visitBinaryExpression(BinaryExpression binaryExpression) {
182 | return false;
183 | }
184 |
185 | @Override
186 | public boolean visitUnaryExpression(UnaryExpression unaryExpression) {
187 | return false;
188 | }
189 |
190 | @Override
191 | public boolean visitInlineIfExpression(InlineIfExpression inlineIfExpression) {
192 | return false;
193 | }
194 |
195 | @Override
196 | public boolean visitCast(Cast cast) {
197 | return false;
198 | }
199 |
200 | @Override
201 | public boolean visitInstanceOf(InstanceOf instanceOf) {
202 | return false;
203 | }
204 |
205 | @Override
206 | public boolean visitConstructorInvocation(ConstructorInvocation constructorInvocation) {
207 | return false;
208 | }
209 |
210 | @Override
211 | public boolean visitMethodInvocation(MethodInvocation methodInvocation) {
212 | return false;
213 | }
214 |
215 | @Override
216 | public boolean visitSelect(Select select) {
217 | return false;
218 | }
219 |
220 | @Override
221 | public boolean visitArrayAccess(ArrayAccess arrayAccess) {
222 | return false;
223 | }
224 |
225 | @Override
226 | public boolean visitArrayCreation(ArrayCreation arrayCreation) {
227 | return false;
228 | }
229 |
230 | @Override
231 | public boolean visitArrayInitializer(ArrayInitializer arrayInitializer) {
232 | return false;
233 | }
234 |
235 | @Override
236 | public boolean visitAnnotationValueArray(AnnotationValueArray annotationValueArray) {
237 | return false;
238 | }
239 |
240 | @Override
241 | public boolean visitArrayDimension(ArrayDimension arrayDimension) {
242 | return false;
243 | }
244 |
245 | @Override
246 | public boolean visitClassLiteral(ClassLiteral classLiteral) {
247 | return false;
248 | }
249 |
250 | @Override
251 | public boolean visitSuper(Super aSuper) {
252 | return false;
253 | }
254 |
255 | @Override
256 | public boolean visitThis(This aThis) {
257 | return false;
258 | }
259 |
260 | @Override
261 | public boolean visitLabelledStatement(LabelledStatement labelledStatement) {
262 | return false;
263 | }
264 |
265 | @Override
266 | public boolean visitExpressionStatement(ExpressionStatement expressionStatement) {
267 | return false;
268 | }
269 |
270 | @Override
271 | public boolean visitIf(If anIf) {
272 | return false;
273 | }
274 |
275 | @Override
276 | public boolean visitFor(For aFor) {
277 | return false;
278 | }
279 |
280 | @Override
281 | public boolean visitForEach(ForEach forEach) {
282 | return false;
283 | }
284 |
285 | @Override
286 | public boolean visitTry(Try aTry) {
287 | return false;
288 | }
289 |
290 | @Override
291 | public boolean visitCatch(Catch aCatch) {
292 | return false;
293 | }
294 |
295 | @Override
296 | public boolean visitWhile(While aWhile) {
297 | return false;
298 | }
299 |
300 | @Override
301 | public boolean visitDoWhile(DoWhile doWhile) {
302 | return false;
303 | }
304 |
305 | @Override
306 | public boolean visitSynchronized(Synchronized aSynchronized) {
307 | return false;
308 | }
309 |
310 | @Override
311 | public boolean visitBlock(Block block) {
312 | return false;
313 | }
314 |
315 | @Override
316 | public boolean visitAssert(Assert anAssert) {
317 | return false;
318 | }
319 |
320 | @Override
321 | public boolean visitEmptyStatement(EmptyStatement emptyStatement) {
322 | return false;
323 | }
324 |
325 | @Override
326 | public boolean visitSwitch(Switch aSwitch) {
327 | return false;
328 | }
329 |
330 | @Override
331 | public boolean visitCase(Case aCase) {
332 | return false;
333 | }
334 |
335 | @Override
336 | public boolean visitDefault(Default aDefault) {
337 | return false;
338 | }
339 |
340 | @Override
341 | public boolean visitBreak(Break aBreak) {
342 | return false;
343 | }
344 |
345 | @Override
346 | public boolean visitContinue(Continue aContinue) {
347 | return false;
348 | }
349 |
350 | @Override
351 | public boolean visitReturn(Return aReturn) {
352 | return false;
353 | }
354 |
355 | @Override
356 | public boolean visitThrow(Throw aThrow) {
357 | return false;
358 | }
359 |
360 | @Override
361 | public boolean visitVariableDeclaration(VariableDeclaration variableDeclaration) {
362 | return false;
363 | }
364 |
365 | @Override
366 | public boolean visitVariableDefinition(VariableDefinition variableDefinition) {
367 | return false;
368 | }
369 |
370 | @Override
371 | public boolean visitVariableDefinitionEntry(VariableDefinitionEntry variableDefinitionEntry) {
372 | return false;
373 | }
374 |
375 | @Override
376 | public boolean visitTypeVariable(TypeVariable typeVariable) {
377 | return false;
378 | }
379 |
380 | @Override
381 | public boolean visitKeywordModifier(KeywordModifier keywordModifier) {
382 | return false;
383 | }
384 |
385 | @Override
386 | public boolean visitModifiers(Modifiers modifiers) {
387 | return false;
388 | }
389 |
390 | @Override
391 | public boolean visitAnnotation(Annotation annotation) {
392 | return false;
393 | }
394 |
395 | @Override
396 | public boolean visitAnnotationElement(AnnotationElement annotationElement) {
397 | return false;
398 | }
399 |
400 | @Override
401 | public boolean visitNormalTypeBody(NormalTypeBody normalTypeBody) {
402 | return false;
403 | }
404 |
405 | @Override
406 | public boolean visitEnumTypeBody(EnumTypeBody enumTypeBody) {
407 | return false;
408 | }
409 |
410 | @Override
411 | public boolean visitEmptyDeclaration(EmptyDeclaration emptyDeclaration) {
412 | return false;
413 | }
414 |
415 | @Override
416 | public boolean visitMethodDeclaration(MethodDeclaration methodDeclaration) {
417 | return false;
418 | }
419 |
420 | @Override
421 | public boolean visitConstructorDeclaration(ConstructorDeclaration constructorDeclaration) {
422 | return false;
423 | }
424 |
425 | @Override
426 | public boolean visitSuperConstructorInvocation(SuperConstructorInvocation superConstructorInvocation) {
427 | return false;
428 | }
429 |
430 | @Override
431 | public boolean visitAlternateConstructorInvocation(AlternateConstructorInvocation alternateConstructorInvocation) {
432 | return false;
433 | }
434 |
435 | @Override
436 | public boolean visitInstanceInitializer(InstanceInitializer instanceInitializer) {
437 | return false;
438 | }
439 |
440 | @Override
441 | public boolean visitStaticInitializer(StaticInitializer staticInitializer) {
442 | return false;
443 | }
444 |
445 | @Override
446 | public boolean visitClassDeclaration(ClassDeclaration classDeclaration) {
447 | return false;
448 | }
449 |
450 | @Override
451 | public boolean visitInterfaceDeclaration(InterfaceDeclaration interfaceDeclaration) {
452 | return false;
453 | }
454 |
455 | @Override
456 | public boolean visitEnumDeclaration(EnumDeclaration enumDeclaration) {
457 | return false;
458 | }
459 |
460 | @Override
461 | public boolean visitEnumConstant(EnumConstant enumConstant) {
462 | return false;
463 | }
464 |
465 | @Override
466 | public boolean visitAnnotationDeclaration(AnnotationDeclaration annotationDeclaration) {
467 | return false;
468 | }
469 |
470 | @Override
471 | public boolean visitAnnotationMethodDeclaration(AnnotationMethodDeclaration annotationMethodDeclaration) {
472 | return false;
473 | }
474 |
475 | @Override
476 | public boolean visitCompilationUnit(CompilationUnit compilationUnit) {
477 | return false;
478 | }
479 |
480 | @Override
481 | public boolean visitPackageDeclaration(PackageDeclaration packageDeclaration) {
482 | return false;
483 | }
484 |
485 | @Override
486 | public boolean visitImportDeclaration(ImportDeclaration importDeclaration) {
487 | return false;
488 | }
489 |
490 | @Override
491 | public boolean visitParseArtefact(Node node) {
492 | return false;
493 | }
494 |
495 | @Override
496 | public boolean visitComment(Comment comment) {
497 | return false;
498 | }
499 |
500 | @Override
501 | public void endVisit(Node node) {
502 |
503 | }
504 |
505 | @Override
506 | public void afterVisitTypeReference(TypeReference typeReference) {
507 |
508 | }
509 |
510 | @Override
511 | public void afterVisitTypeReferencePart(TypeReferencePart typeReferencePart) {
512 |
513 | }
514 |
515 | @Override
516 | public void afterVisitVariableReference(VariableReference variableReference) {
517 |
518 | }
519 |
520 | @Override
521 | public void afterVisitIdentifier(Identifier identifier) {
522 |
523 | }
524 |
525 | @Override
526 | public void afterVisitIntegralLiteral(IntegralLiteral integralLiteral) {
527 |
528 | }
529 |
530 | @Override
531 | public void afterVisitFloatingPointLiteral(FloatingPointLiteral floatingPointLiteral) {
532 |
533 | }
534 |
535 | @Override
536 | public void afterVisitBooleanLiteral(BooleanLiteral booleanLiteral) {
537 |
538 | }
539 |
540 | @Override
541 | public void afterVisitCharLiteral(CharLiteral charLiteral) {
542 |
543 | }
544 |
545 | @Override
546 | public void afterVisitStringLiteral(StringLiteral stringLiteral) {
547 | }
548 |
549 | @Override
550 | public void afterVisitNullLiteral(NullLiteral nullLiteral) {
551 |
552 | }
553 |
554 | @Override
555 | public void afterVisitBinaryExpression(BinaryExpression binaryExpression) {
556 |
557 | }
558 |
559 | @Override
560 | public void afterVisitUnaryExpression(UnaryExpression unaryExpression) {
561 |
562 | }
563 |
564 | @Override
565 | public void afterVisitInlineIfExpression(InlineIfExpression inlineIfExpression) {
566 |
567 | }
568 |
569 | @Override
570 | public void afterVisitCast(Cast cast) {
571 |
572 | }
573 |
574 | @Override
575 | public void afterVisitInstanceOf(InstanceOf instanceOf) {
576 |
577 | }
578 |
579 | @Override
580 | public void afterVisitConstructorInvocation(ConstructorInvocation constructorInvocation) {
581 |
582 | }
583 |
584 | @Override
585 | public void afterVisitMethodInvocation(MethodInvocation methodInvocation) {
586 |
587 | }
588 |
589 | @Override
590 | public void afterVisitSelect(Select select) {
591 |
592 | }
593 |
594 | @Override
595 | public void afterVisitArrayAccess(ArrayAccess arrayAccess) {
596 |
597 | }
598 |
599 | @Override
600 | public void afterVisitArrayCreation(ArrayCreation arrayCreation) {
601 |
602 | }
603 |
604 | @Override
605 | public void afterVisitArrayInitializer(ArrayInitializer arrayInitializer) {
606 |
607 | }
608 |
609 | @Override
610 | public void afterVisitAnnotationValueArray(AnnotationValueArray annotationValueArray) {
611 |
612 | }
613 |
614 | @Override
615 | public void afterVisitArrayDimension(ArrayDimension arrayDimension) {
616 |
617 | }
618 |
619 | @Override
620 | public void afterVisitClassLiteral(ClassLiteral classLiteral) {
621 |
622 | }
623 |
624 | @Override
625 | public void afterVisitSuper(Super aSuper) {
626 |
627 | }
628 |
629 | @Override
630 | public void afterVisitThis(This aThis) {
631 |
632 | }
633 |
634 | @Override
635 | public void afterVisitLabelledStatement(LabelledStatement labelledStatement) {
636 |
637 | }
638 |
639 | @Override
640 | public void afterVisitExpressionStatement(ExpressionStatement expressionStatement) {
641 |
642 | }
643 |
644 | @Override
645 | public void afterVisitIf(If anIf) {
646 |
647 | }
648 |
649 | @Override
650 | public void afterVisitFor(For aFor) {
651 |
652 | }
653 |
654 | @Override
655 | public void afterVisitForEach(ForEach forEach) {
656 |
657 | }
658 |
659 | @Override
660 | public void afterVisitTry(Try aTry) {
661 |
662 | }
663 |
664 | @Override
665 | public void afterVisitCatch(Catch aCatch) {
666 |
667 | }
668 |
669 | @Override
670 | public void afterVisitWhile(While aWhile) {
671 |
672 | }
673 |
674 | @Override
675 | public void afterVisitDoWhile(DoWhile doWhile) {
676 |
677 | }
678 |
679 | @Override
680 | public void afterVisitSynchronized(Synchronized aSynchronized) {
681 |
682 | }
683 |
684 | @Override
685 | public void afterVisitBlock(Block block) {
686 |
687 | }
688 |
689 | @Override
690 | public void afterVisitAssert(Assert anAssert) {
691 |
692 | }
693 |
694 | @Override
695 | public void afterVisitEmptyStatement(EmptyStatement emptyStatement) {
696 |
697 | }
698 |
699 | @Override
700 | public void afterVisitSwitch(Switch aSwitch) {
701 |
702 | }
703 |
704 | @Override
705 | public void afterVisitCase(Case aCase) {
706 |
707 | }
708 |
709 | @Override
710 | public void afterVisitDefault(Default aDefault) {
711 |
712 | }
713 |
714 | @Override
715 | public void afterVisitBreak(Break aBreak) {
716 |
717 | }
718 |
719 | @Override
720 | public void afterVisitContinue(Continue aContinue) {
721 |
722 | }
723 |
724 | @Override
725 | public void afterVisitReturn(Return aReturn) {
726 |
727 | }
728 |
729 | @Override
730 | public void afterVisitThrow(Throw aThrow) {
731 |
732 | }
733 |
734 | @Override
735 | public void afterVisitVariableDeclaration(VariableDeclaration variableDeclaration) {
736 |
737 | }
738 |
739 | @Override
740 | public void afterVisitVariableDefinition(VariableDefinition variableDefinition) {
741 |
742 | }
743 |
744 | @Override
745 | public void afterVisitVariableDefinitionEntry(VariableDefinitionEntry variableDefinitionEntry) {
746 |
747 | }
748 |
749 | @Override
750 | public void afterVisitTypeVariable(TypeVariable typeVariable) {
751 |
752 | }
753 |
754 | @Override
755 | public void afterVisitKeywordModifier(KeywordModifier keywordModifier) {
756 |
757 | }
758 |
759 | @Override
760 | public void afterVisitModifiers(Modifiers modifiers) {
761 |
762 | }
763 |
764 | @Override
765 | public void afterVisitAnnotation(Annotation annotation) {
766 |
767 | }
768 |
769 | @Override
770 | public void afterVisitAnnotationElement(AnnotationElement annotationElement) {
771 |
772 | }
773 |
774 | @Override
775 | public void afterVisitNormalTypeBody(NormalTypeBody normalTypeBody) {
776 |
777 | }
778 |
779 | @Override
780 | public void afterVisitEnumTypeBody(EnumTypeBody enumTypeBody) {
781 |
782 | }
783 |
784 | @Override
785 | public void afterVisitEmptyDeclaration(EmptyDeclaration emptyDeclaration) {
786 |
787 | }
788 |
789 | @Override
790 | public void afterVisitMethodDeclaration(MethodDeclaration methodDeclaration) {
791 |
792 | }
793 |
794 | @Override
795 | public void afterVisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration) {
796 |
797 | }
798 |
799 | @Override
800 | public void afterVisitSuperConstructorInvocation(SuperConstructorInvocation superConstructorInvocation) {
801 |
802 | }
803 |
804 | @Override
805 | public void afterVisitAlternateConstructorInvocation(AlternateConstructorInvocation alternateConstructorInvocation) {
806 |
807 | }
808 |
809 | @Override
810 | public void afterVisitInstanceInitializer(InstanceInitializer instanceInitializer) {
811 |
812 | }
813 |
814 | @Override
815 | public void afterVisitStaticInitializer(StaticInitializer staticInitializer) {
816 |
817 | }
818 |
819 | @Override
820 | public void afterVisitClassDeclaration(ClassDeclaration classDeclaration) {
821 |
822 | }
823 |
824 | @Override
825 | public void afterVisitInterfaceDeclaration(InterfaceDeclaration interfaceDeclaration) {
826 |
827 | }
828 |
829 | @Override
830 | public void afterVisitEnumDeclaration(EnumDeclaration enumDeclaration) {
831 |
832 | }
833 |
834 | @Override
835 | public void afterVisitEnumConstant(EnumConstant enumConstant) {
836 |
837 | }
838 |
839 | @Override
840 | public void afterVisitAnnotationDeclaration(AnnotationDeclaration annotationDeclaration) {
841 |
842 | }
843 |
844 | @Override
845 | public void afterVisitAnnotationMethodDeclaration(AnnotationMethodDeclaration annotationMethodDeclaration) {
846 |
847 | }
848 |
849 | @Override
850 | public void afterVisitCompilationUnit(CompilationUnit compilationUnit) {
851 |
852 | }
853 |
854 | @Override
855 | public void afterVisitPackageDeclaration(PackageDeclaration packageDeclaration) {
856 |
857 | }
858 |
859 | @Override
860 | public void afterVisitImportDeclaration(ImportDeclaration importDeclaration) {
861 |
862 | }
863 |
864 | @Override
865 | public void afterVisitParseArtefact(Node node) {
866 |
867 | }
868 |
869 | @Override
870 | public void afterVisitComment(Comment comment) {
871 |
872 | }
873 | };
874 | }
875 |
876 |
877 | }
878 |
--------------------------------------------------------------------------------