├── 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 | 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 | 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 | ![platform-android](https://img.shields.io/badge/platform-android-green.svg)  6 | ![license-bsd](https://img.shields.io/badge/license-BSD-red.svg)  7 | ![author-qjoy](https://img.shields.io/badge/author-QJoy-orange.svg)  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 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 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 | 8 | 9 | 10 | 11 | 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 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 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 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 | 8 | 9 | 10 | 11 | 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 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 | --------------------------------------------------------------------------------