Annotation based Android lint check generation

Overview

Intervention

License Bintray Android Arsenal

Annotation based Android lint check generation

Generate custom Android lint checks and have lint warn you about code you may be dealing with using Kotlin extensions or your own coding conventions.

How is this useful?

We create and annotate the following simple extension functions:

@Intervene(name = "ContentView", warnAgainst = "setContentView")
fun Activity.layout(@LayoutRes layoutRes: Int) {
    this.setContentView(layoutRes)
}

@Intervene(name = "ToastIntervention", warnAgainst = "Toast.makeText")
fun Activity.toast(message: String, length: Int = Toast.LENGTH_SHORT) {
    Toast.makeText(this, message, length).show()
}

Having the following sample Activity:

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContentView(R.layout.activity_main)

        Toast.makeText(this, "Awesome", Toast.LENGTH_SHORT).show()

        toast("Even more Awesome")
    }
}

Running lint would generate the following report: Intervention report printscreen

The report is detailed and also includes the annotated code that would fix the issue.

How to use?

1. Preparation

a. Lint Module

Custom lint checks in Android need to be created in a Java Module, so go ahead and create one.

File -> New -> New Module... -> Java Library

Intervention generates kotlin code, so you need to apply the Kotlin plugin in the newly created module and instruct the module to use Kotlin generated files. Also, the module must declate the Registry class for the lint checks it contains; the Registry is generated by Intervention. Finally it should have a dependency on Android Lint and the main Intervention project. All in all, the Java module's gradle script should look like this:

apply plugin: 'java-library'
apply plugin: 'kotlin'

/* Sets the JAVA compatibility */
sourceCompatibility = '1.8'
targetCompatibility = '1.8'

/* Uses kotlin generated code in the project */
sourceSets {
    main {
        java {
            srcDir "${buildDir.absolutePath}/generated/source/kaptKotlin/"
        }
    }
}

/* Declares the lint Registry class */
jar {
    manifest {
        attributes("Lint-Registry-v2": "com.izikode.izilib.interventions.InterventionRegistry")
    }
}

/* All dependencies must be compileOnly as per lint regulations */
dependencies {
    compileOnly "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.11"
    compileOnly "com.android.tools.lint:lint-api:26.2.1"
    compileOnly "com.izikode.izilib:intervention:0.4"
}

b. Android module

Intervention uses Kotlin code generation, so you must apply the Kapt plugin on your Android module. Also, you must provide the annotation processor with the path to your Java lint module created above. To do this modify your Android gradle script and add the following:

apply plugin: 'kotlin-kapt'

kapt {
    arguments {
        arg('interventionsModuleDir', project(':appinterventions').projectDir.absolutePath)
    }
}
Replace appinterventions with the name of your Java lint module.

You must also add the Intervention dependencies in your Android module, as well as the Java lint module:

dependencies {
    ...
    implementation "com.izikode.izilib:intervention:0.4"
    kapt "com.izikode.izilib:interventioncompiler:0.4"

    lintChecks project(":appinterventions")
}
Again replace appinterventions with the name of your Java lint module.

2. Usage

a. Annotate

Use the Intervene annotation to decorate extension or any other functions for which you want to have lint checks. A simple example is the ToastIntervention from the sample project.

@Intervene(name = "ToastIntervention", warnAgainst = "Toast.makeText")
fun Activity.toast(message: String, length: Int = Toast.LENGTH_SHORT) {
    Toast.makeText(this, message, length).show()
}

Another example is the Fragment factory function from the sample project.

class MainFragment : Fragment() {
    companion object {
        @Intervene(name = "MainFragmentInitialization", warnAgainst = "MainFragment()", useInstead = "MainFragment.newInstance()")
        fun newInstance() = MainFragment()
    }
}
  • name is the lint check's name and ID.
  • warnAgainst is the piece of code that when matched will trigger the warning.
  • useInstead is the code that replaces the above. When left empty (default) the compiler will provide the function signature in the report.
  • priority can be either Priority.LOW, Priority.NORMAL (default) or Priority.HIGH.
  • type can be either Type.WARNING (default) or Type.ERROR. Error stops the build.

b. Build and run lint

For a full example, see the sample app.

Licence

Copyright 2018 Fanis Veizis

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
You might also like...
A simple, classic Kotlin MVI implementation based on coroutines with Android support, clean DSL and easy to understand logic

A simple, classic Kotlin MVI implementation based on coroutines with Android support, clean DSL and easy to understand logic

A native android app that shows how much calories one must consume based on their profile
A native android app that shows how much calories one must consume based on their profile

Healtify is a native android app which allows the user to track the amout of Calories they are consuming. It not only tracks the calories but also shows how much of fat, protein and carbs they have consumed and how much they should be doing.

🪐 Modern Android development with Hilt, Coroutines, Flow, JetPack(ViewModel) based on MVVM architecture.

Ceres 🪐 Modern Android development with Hilt, Coroutines, Flow, JetPack(ViewModel) based on MVVM architecture. Download Gradle Add the dependency bel

Kotlin-based modern RecyclerView rendering weapon
Kotlin-based modern RecyclerView rendering weapon

Read this in other languages: 中文, English, Changelog Yasha Item introduction: Kotlin-based modern RecyclerView rendering weapon Item Features: No Adap

An Easy-to-use Kotlin based Customizable Modules Collection with Material Layouts by BlackBeared.
An Easy-to-use Kotlin based Customizable Modules Collection with Material Layouts by BlackBeared.

Fusion By BlackBeared An Easy-to-use Kotlin based Customizable Library with Material Layouts by @blackbeared. Features Custom Floating Action Buttons

Download tool based on kotlin and coroutine.
Download tool based on kotlin and coroutine.

DownloadX A multi-threaded download tool written with Coroutine and Kotlin Read this in other languages: 中文, English, Changelog Prepare Add jitpack re

:octocat: A demo project based on MVVM architecture and material design & animations.
:octocat: A demo project based on MVVM architecture and material design & animations.

GithubFollows A simple demo project based on MVVM clean architecture and material design & animations. Architecture Specs & Open-source libraries Mini

🎬 A demo project for The Movie DB based on Kotlin MVVM architecture and material design & animations.
🎬 A demo project for The Movie DB based on Kotlin MVVM architecture and material design & animations.

TheMovies A simple project for The Movie DB based on Kotlin MVVM clean architecture and material design & animations. How to build on your environment

A kotlin implementation of commutative encryption based on ECC ElGamal encryption over Curve25519

komuta A commutative encryption implementation. This is a naive implementation of commutative encryption using the ElGamal scheme applied over Curve25

Comments
  • Release 0.1

    Release 0.1

    Includes the initial concept implementation and provides:

    • The intervention dependency with the Intervene annotation
    • The interventioncompiler dependency
    • A sample project
    opened by iFanie 0
Releases(v0.4)
Owner
Fanis Veizis
Fanis Veizis
An annotation and Kotlin compiler plugin for enforcing a when statement is exhaustive

An annotation and Kotlin compiler plugin for enforcing a when statement is exhaustive

Cash App 468 Jan 4, 2023
API-Annotate - Single annotation to mark API elements

API-Annotate A single annotation for annotating externally-consumed elements in

null 0 Feb 5, 2022
An amazing expense tracker app, with great features and beautiful UI. Check it out!

My Expense Tracker Expense tracker app to keep your finances in order. Built entirely in Kotlin using modern architecture components. Build ??️ My Exp

Ken Ali 7 Oct 26, 2022
Stepper Touch for Android based on MaterialUp submission

Stepper-Touch For more updates on this and other open-source projects, follow me on twitter ?? here Stepper Touch for Android based on a Material Up s

Dion Segijn 666 Dec 27, 2022
Extension functions over Android's callback-based APIs which allows writing them in a sequential way within coroutines or observe multiple callbacks through kotlin flow.

callback-ktx A lightweight Android library that wraps Android's callback-based APIs into suspending extension functions which allow writing them in a

Sagar Viradiya 171 Oct 31, 2022
Beautifully designed Pokémon Database app for Android based on PokéAPI and powered by Kotlin.

PokéFacts PokéFacts is an open-source Pokémon Database app for Android based on PokéAPI and powered by Kotlin. The app allows users to view Pokémons,

Arjun Mehta 9 Oct 22, 2022
Delish, a Food Recipes App in Jetpack Compose and Hilt based on modern Android tech-stacks and MVVM clean architecture.

Delish Screens Tech stack & Open-source libraries 100% Kotlin based + Coroutines + Flow for asynchronous. Dagger Hilt 2.37 Accompanist JetPack Jetpack

Mohamed Elbehiry 305 Dec 12, 2022
Android app with minimal UI to run snowflake pluggable transports proxy, based on library IPtProxy

Simple Kotlin app for testing IPtProxy's snowflake proxy on Android Essentially a button for starting and stopping a Snowflake Proxy with the default

null 2 Jun 26, 2022
Android sample application based on Andorid architecture

Gitgle Gitgle(Github + Google) is simple github user search application, using G

WonJoong 3 Jan 22, 2022
A markdown-based note-taking app for Android

Noteless A markdown-based note-taking app for Android Compatible with notes saved in Notable Features Markdown-optimized editor with syntax highlighti

null 459 Dec 29, 2022