Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Building a Better Codebase with Lint - Droidcon Americas

Building a Better Codebase with Lint - Droidcon Americas

Subhrajyoti Sen

November 17, 2020
Tweet

More Decks by Subhrajyoti Sen

Other Decks in Programming

Transcript

  1. KeepTruckin
    Subhrajyoti Sen Droidcon Americas 2020
    Building a Better Codebase
    with Lint

    View Slide

  2. What is Lint?
    < / >

    View Slide

  3. What is Lint?
    • Static analysis tool

    View Slide

  4. What is Lint?
    • Static analysis tool
    • Open Source

    View Slide

  5. What is Lint?
    • Static analysis tool
    • Open Source
    • Works on .java, .kt, .gradle and a lot more

    View Slide

  6. What is Lint?
    • Static analysis tool
    • Open Source
    • Works on .java, .kt, .gradle and a lot more
    • Can be used outside Android as well

    View Slide

  7. What is Lint?
    • Static analysis tool
    • Open Source
    • Works on .java, .kt, .gradle and a lot more
    • Can be used outside Android as well
    • Can be extended to write custom rules

    View Slide

  8. What is Lint?
    • Static analysis tool
    • Open Source
    • Works on .java, .kt, .gradle and a lot more
    • Can be used outside Android as well
    • Can be extended to write custom rules
    • Can be run from both Android Studio and CLI

    View Slide

  9. What does Lint look like?
    < / >

    View Slide

  10. Internationalization

    View Slide

  11. Security

    View Slide

  12. Performance

    View Slide

  13. Accessibility

    View Slide

  14. Why consider Lint?
    < / >

    View Slide

  15. Why consider Lint?
    • Opinionated codebase

    View Slide

  16. Why consider Lint?
    • Opinionated codebase
    • Simpler code reviews

    View Slide

  17. Why consider Lint?
    • Opinionated codebase
    • Simpler code reviews
    • Adherence to style guide

    View Slide

  18. Setup
    < / >

    View Slide

  19. Create a new module

    View Slide

  20. Dependencies
    dependencies {
    compileOnly "org.jetbrains.kotlin:kotlin stdlib:$kotlin_version"
    compileOnly 'com.android.tools.lint:lint api:27.1.1'
    compileOnly 'com.android.tools.lint:lint checks:27.1.1'
    }

    View Slide

  21. Issue Registry
    class Registry : IssueRegistry() {
    override val api: Int = CURRENT_API
    @get:NotNull
    override val issues: List
    get() = listOf()
    }

    View Slide

  22. Register Issue Registry
    jar {
    manifest {
    attributes 'Lint-Registry-V2': 'me.subhrajyoti.lint.Registry'
    }
    }

    View Slide

  23. Register Issue Registry
    dependencies {
    lintChecks project(':lint')
    }

    View Slide

  24. The Basic Elements
    Scope
    The kind of files the lint rule applies to
    • JAVA_FILE_SCOPE
    • GRADLE_SCOPE
    • MANIFEST_SCOPE
    • PROGUARD_SCOPE
    • RESOURCE_FILE_SCOPE

    View Slide

  25. The Basic Elements
    Severity
    How severe is the issue
    • INFORMATIONAL
    • WARNING
    • ERROR
    • FATAL

    View Slide

  26. The Basic Elements
    Category
    The category the issue falls in, from a pre-defined list of categories
    • SECURITY
    • PERFORMANCE
    • L18N
    • A11Y

    View Slide

  27. Use case - TextView

    View Slide

  28. Custom Rule Structure
    val ISSUE: Issue = Issue.create(
    "MissingStyleAttribute",
    "style attribute is missing",
    "We should use style to style a TextView " +
    "in order to provide consistent design",
    Category.CORRECTNESS,
    5,
    Severity.ERROR,
    Implementation(
    MissingStyleAttributeDetector::class.java,
    Scope.RESOURCE_FILE_SCOPE
    )
    )

    View Slide

  29. Custom Rule Structure
    class MissingStyleAttributeDetector : ResourceXmlDetector() {
    }

    View Slide

  30. Custom Rule Structure
    class MissingStyleAttributeDetector : ResourceXmlDetector() {
    @Nullable
    override fun getApplicableElements(): Collection? {
    return listOf("TextView")
    }
    }

    View Slide

  31. Custom Rule Structure
    class MissingStyleAttributeDetector : ResourceXmlDetector() {
    @Nullable
    override fun getApplicableElements(): Collection? {
    return listOf(SdkConstants.TEXT_VIEW)
    }
    }

    View Slide

  32. Custom Rule Structure
    class MissingStyleAttributeDetector : ResourceXmlDetector() {
    //..
    override fun appliesTo(folderType: ResourceFolderType): Boolean {
    return folderType == ResourceFolderType.LAYOUT
    }
    }

    View Slide

  33. Custom Rule Structure
    class MissingStyleAttributeDetector : ResourceXmlDetector() {
    //..
    override fun visitElement(context: XmlContext, element: Element) {
    if (!element.hasAttribute(SdkConstants.ATTR_STYLE)) {
    context.report(
    ISSUE,
    element,
    context.getLocation(element),
    "Add style to TextView in order to provide consistent design"
    )
    }
    }
    }

    View Slide

  34. Remember this?
    class MissingStyleAttributeDetector : ResourceXmlDetector() {
    @Nullable
    override fun getApplicableElements(): Collection? {
    return listOf(SdkConstants.TEXT_VIEW)
    }
    }

    View Slide

  35. A small bug

    View Slide

  36. Integration

    View Slide

  37. Integration
    • Incremental fixes

    View Slide

  38. Integration
    • Incremental fixes
    • Using a baseline

    View Slide

  39. Baseline
    android {
    lintOptions {
    baseline file("lint baseline.xml")
    }
    }

    View Slide

  40. Baseline - Pass 1

    View Slide

  41. Baseline - Pass 2

    View Slide

  42. lint-baseline.xml

    id="MissingStyleAttribute"
    message="Add style to TextView in order to provide consistent design"
    errorLine1=" <TextView"
    errorLine2=" ^">
    file="src/main/res/layout/activity_main.xml"
    line="10"
    column="5"/>


    View Slide

  43. Performance

    View Slide

  44. Performance
    • Single pass
    • Missing attribute
    • Fast
    • Enable in IDE

    View Slide

  45. Performance
    • Single pass
    • Missing attribute
    • Fast
    • Enable in IDE
    • Multiple pass
    • Unused resources
    • Slow
    • Disable in IDE

    View Slide

  46. Kotlin Considerations?

    View Slide

  47. Kotlin Considerations?
    • No explicit return statements

    View Slide

  48. Kotlin Considerations?
    • No explicit return statements
    • No explicit type declarations

    View Slide

  49. Kotlin Considerations?
    • No explicit return statements
    • No explicit type declarations
    • Write one test case for Kotlin usage

    View Slide

  50. References
    • https://groups.google.com/g/lint-dev
    • https://github.com/SubhrajyotiSen/LintTalk
    • https://github.com/vanniktech/lint-rules
    • https://www.youtube.com/watch?v=p8yX5-lPS6o

    View Slide

  51. @iamsubhrajyoti

    View Slide