Slide 1

Slide 1 text

CUSTOM LINT RULES IMPROVE YOUR CODE QUALITY WITH DEDICATED CONVENTIONS

Slide 2

Slide 2 text

ANDRÉ DIERMANN Software Architect @ it-objects

Slide 3

Slide 3 text

OUR MOTIVATION FOR CUSTOM LINT RULES IN WORDS enterprise mobility solution (> 10.000 users in EU, Asia, USA) several developers working distributed in different countries complex business logic due to full offline mode custom application architecture huge code base

Slide 4

Slide 4 text

OUR MOTIVATION FOR CUSTOM LINT RULES IN NUMBERS 32 build variants >2.000 classes in ~100 packages (with ~150.000 lines of code) >200 screens with >1.500 widgets (>30.000 lines of XML) >3.500 string references (>35.000 translations) ...

Slide 5

Slide 5 text

AGENDA Introduction Lint API basics Hands-on: custom Lint rules Real world scenarios Q & A

Slide 6

Slide 6 text

INTRODUCTION Lint Custom rules Challenges

Slide 7

Slide 7 text

LINT tool for command-line and IDE scans all kind of development artifacts reports potential bugs, bad coding habits, broken conventions, ... features more than 200 built-in checks (January 2015)

Slide 8

Slide 8 text

EXAMPLE

Slide 9

Slide 9 text

EXAMPLE

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

CUSTOM RULES MOTIVATION work in large and distributed teams requires dedicated conventions huge code bases require automated checks need for 'Android specific' validations (vs. checkstyle, FindBugs, ...) ...

Slide 12

Slide 12 text

CHALLENGES WRITING CUSTOM LINT RULES poor documentation bad testability

Slide 13

Slide 13 text

LINT API BASICS Core principles of the Lint API I s s u e D e t e c t o r S c a n n e r I s s u e R e g i s t r y

Slide 14

Slide 14 text

ISSUE An I s s u e is a type of problem you want to find and show to the user.

Slide 15

Slide 15 text

ISSUE registered in an I s s u e R e g i s t r y reported by a D e t e c t o r final class created by static factory method has certain attributes, such as S e v e r i t y S c o p e ...

Slide 16

Slide 16 text

EXAMPLE p u b l i c s t a t i c f i n a l I s s u e I S S U E = I s s u e . c r e a t e ( " H e l l o W o r l d " , / / I D " U n e x p e c t e d a p p l i c a t i o n t i t l e " , / / b r i e f d e s c r i p t i o n " T h e a p p l i c a t i o n t i t l e s h o u l d " / / e x p l a n a t i o n + " s t a t e ' H e l l o w o r l d ' " , C a t e g o r y . C O R R E C T N E S S , / / c a t e g o r y 5 , / / p r i o r i t y S e v e r i t y . I N F O R M A T I O N A L , / / s e v e r i t y n e w I m p l e m e n t a t i o n ( / / i m p l e m e n t a t i o n H e l l o W o r l d D e t e c t o r . c l a s s , / / d e t e c t o r S c o p e . M A N I F E S T _ S C O P E / / s c o p e ) ) ;

Slide 17

Slide 17 text

DETECTOR A D e t e c t o r is responsible for scanning through code and finding I s s u e instances and reporting them.

Slide 18

Slide 18 text

DETECTOR implementation of a Lint rule analyzes development artifacts reports I s s u e s specialized by S c a n n e r s

Slide 19

Slide 19 text

EXAMPLE p u b l i c c l a s s H e l l o W o r l d D e t e c t o r e x t e n d s D e t e c t o r i m p l e m e n t s X m l S c a n n e r { p u b l i c s t a t i c f i n a l I s s u e I S S U E = I s s u e . c r e a t e ( . . . ) ; @ O v e r r i d e p u b l i c C o l l e c t i o n < S t r i n g > g e t A p p l i c a b l e E l e m e n t s ( ) { . . . } @ O v e r r i d e p u b l i c C o l l e c t i o n < S t r i n g > g e t A p p l i c a b l e A t t r i b u t e s ( ) { . . . } @ O v e r r i d e p u b l i c v o i d v i s i t E l e m e n t ( @ N o n N u l l X m l C o n t e x t c o n t e x t , @ N o n N u l l E l e m e n t e l e m e n t ) { . . . } @ O v e r r i d e p u b l i c v o i d v i s i t A t t r i b u t e ( @ N o n N u l l X m l C o n t e x t c o n t e x t , @ N o n N u l l A t t r a t t r i b u t e ) { . . . } }

Slide 20

Slide 20 text

SCANNER A S c a n n e r is a specialized interface for D e t e c t o r s .

Slide 21

Slide 21 text

SCANNER TYPES J a v a S c a n n e r C l a s s S c a n n e r B i n a r y R e s o u r c e S c a n n e r R e s o u r c e F o l d e r S c a n n e r X m l S c a n n e r G r a d l e S c a n n e r O t h e r F i l e S c a n n e r

Slide 22

Slide 22 text

EXAMPLE JavaScanner XmlScanner a p p l i c a b l e S u p e r C l a s s e s ( ) g e t A p p l i c a b l e E l e m e n c h e c k C l a s s ( . . . ) v i s i t E l e m e n t ( . . . ) g e t A p p l i c a b l e M e t h o d N a m e s ( ) g e t A p p l i c a b l e A t t r i b v i s i t M e t h o d ( . . . ) v i s i t A t t r i b u t e ( . . . ) ... ...

Slide 23

Slide 23 text

ISSUEREGISTRY An I s s u e R e g i s t r y is a registry which provides a list of checks to be performed on an Android project.

Slide 24

Slide 24 text

ISSUEREGISTRY subclass I s s u e R e g i s t r y override g e t I s s u e s ( ) reference in M A N I F E S T j a r { m a n i f e s t { a t t r i b u t e s ' L i n t - R e g i s t r y ' : ' y o u r . p a c k a g e . n a m e . C u s t o m I s s u e R e g i s t r y ' } }

Slide 25

Slide 25 text

EXAMPLE p u b l i c c l a s s C u s t o m I s s u e R e g i s t r y e x t e n d s I s s u e R e g i s t r y { @ O v e r r i d e p u b l i c L i s t < I s s u e > g e t I s s u e s ( ) { r e t u r n A r r a y s . a s L i s t ( / / N o t e : M y C u s t o m C h e c k . I S S U E , / / A c h e c k a c t u a l l y i s a d e t e c t o r . M y A d v a n c e d C h e c k . A N _ I S S U E , / / O n e d e t e c t o r c a n r e p o r t M y A d v a n c e d C h e c k . A N O T H E R _ I S S U E / / m u l t i p l e t y p e s o f i s s u e s . ) ; } }

Slide 26

Slide 26 text

HANDS-ON Getting started Detectors Testing Application

Slide 27

Slide 27 text

GETTING STARTED github.com/a11n/CustomLintRulesWorkshop $ g i t c l o n e h t t p s : / / g i t h u b . c o m / a 1 1 n / C u s t o m L i n t R u l e s W o r k s h o p . g i t $ c d C u s t o m L i n t R u l e s W o r k s h o p $ g i t c h e c k o u t - f s e c t i o n - 1

Slide 28

Slide 28 text

PRO TIPS have a look at the use S d k C o n s t a n t s wherever possible utilize L i n t U t i l s when applicable default set of checks

Slide 29

Slide 29 text

DETECTORS Simple detectors Advanced detectors

Slide 30

Slide 30 text

SIMPLE DETECTORS scan isolated artifacts of one type (e.g. just code or just resources) perform scan and evaluation in one phase

Slide 31

Slide 31 text

ADVANCED DETECTORS scan related artifacts of different types perform scan and evaluation in two phases

Slide 32

Slide 32 text

TESTING

Slide 33

Slide 33 text

TESTING No official test support official test support since last week's Google I/O not working (see ) (still in beta) #175161 Lint JUnit rule

Slide 34

Slide 34 text

TESTING LintDetectorTest p u b l i c c l a s s H a r d c o d e d V a l u e s D e t e c t o r T e s t e x t e n d s A b s t r a c t C h e c k T e s t { @ O v e r r i d e p r o t e c t e d D e t e c t o r g e t D e t e c t o r ( ) { r e t u r n n e w H a r d c o d e d V a l u e s D e t e c t o r ( ) ; } p u b l i c v o i d t e s t S t r i n g s ( ) t h r o w s E x c e p t i o n { a s s e r t E q u a l s ( " r e s / l a y o u t / a c c e s s i b i l i t y . x m l : 3 : W a r n i n g : [ I 1 8 N ] H a r d c o d e d s t r i n g \ " B " < B u t t o n a n d r o i d : t e x t = \ " B u t t o n \ " a n d r o i d : i d = \ " @ + i d / b u t t o n 1 \ " a n d r " ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ \ n " + " r e s / l a y o u t / a c c e s s i b i l i t y . x m l : 6 : W a r n i n g : [ I 1 8 N ] H a r d c o d e d s t r i n g \ " B " < B u t t o n a n d r o i d : t e x t = \ " B u t t o n \ " a n d r o i d : i d = \ " @ + i d / b u t t o n 2 \ " a n d r " ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ \ n " + " 0 e r r o r s , 2 w a r n i n g s \ n " , l i n t F i l e s ( " r e s / l a y o u t / a c c e s s i b i l i t y . x m l " ) ) ; } }

Slide 35

Slide 35 text

TESTING Lint JUnit rule @ R u l e p u b l i c L i n t l i n t = n e w L i n t ( ) ; @ T e s t p u b l i c v o i d t e s t ( ) t h r o w s E x c e p t i o n { l i n t . s e t F i l e s ( " A n d r o i d M a n i f e s t . x m l " , " r e s / v a l u e s / s t r i n g . x m l " ) ; l i n t . s e t I s s u e s ( M y C u s t o m R u l e . I S S U E ) ; l i n t . a n a l y z e ( ) ; L i s t < W a r n i n g > w a r n i n g s = l i n t . g e t W a r n i n g s ( ) ; a s s e r t T h a t ( w a r n i n g s ) . h a s S i z e ( 2 ) ; }

Slide 36

Slide 36 text

APPLICATION Basic approach Integrated approach

Slide 37

Slide 37 text

BASIC APPROACH utilizes basic Lint extension feature two steps setup 1. assemble custom Lint rules into JAR 2. copy JAR to ~ / . a n d r o i d / l i n t /

Slide 38

Slide 38 text

BASIC APPROACH # ! / b i n / s h # B u i l d . j a r . / g r a d l e w a s s e m b l e # I n s t a l l i f [ ! - d " ~ / . a n d r o i d / l i n t / " ] ; t h e n m k d i r ~ / . a n d r o i d / l i n t / f i c p b u i l d / l i b s / l i n t . j a r ~ / . a n d r o i d / l i n t /

Slide 39

Slide 39 text

BASIC APPROACH Pros Cons just assemble and copy no straightforward distribution and configuration one resulting JAR no project-specific rules no changes in the project to analyze inconvenient for multi developer teams applied for all analyzed projects inconvenient for CI environments

Slide 40

Slide 40 text

INTEGRATED APPROACH uses AAR bundle as wrapper two steps setup 1. wrap custom Lint rules into an AAR 2. make application project depend on that AAR

Slide 41

Slide 41 text

THREE OPTIONS FOR DEPENDENCIES Copy the AAR to the libs folder d e p e n d e n c i e s { c o m p i l e f i l e T r e e ( d i r : ' l i b s ' , i n c l u d e : ' * . j a r ' ) } Deploy the AAR to a repository d e p e n d e n c i e s { c o m p i l e ' y o u r . p a c k a g e . n a m e : c u s t o m - l i n t : 1 . 0 . 0 @ a a r ' }

Slide 42

Slide 42 text

THREE OPTIONS FOR DEPENDENCIES Have a Java module for the Lint rules and an Android library module as wrapper A n d r o i d a p p l i c a t i o n p r o j e c t - - a p p / / d e f a u l t A n d r o i d a p p l i c a t i o n m o d u l e - - l i n t / / A n d r o i d l i b r a r y , a c t s a s w r a p p e r f o r t h e L i n t r u l e s - - l i n t r u l e s / / J a v a m o d u l e w i t h y o u r c u s t o m L i n t r u l e s p r o j e c t . a f t e r E v a l u a t e { d e f c o m p i l e L i n t = p r o j e c t . t a s k s . g e t B y P a t h ( ' : l i n t : c o m p i l e L i n t ' ) c o m p i l e L i n t . d e p e n d s O n ' : l i n t r u l e s : j a r ' c o m p i l e L i n t < < { c o p y { f r o m ' . . / l i n t r u l e s / b u i l d / l i b s ' i n t o ' b u i l d / i n t e r m e d i a t e s / l i n t ' } } }

Slide 43

Slide 43 text

INTEGRATED APPROACH Pros Cons allows project specific rules changes in project required integrated within project not applied for all analyzed projects ideal for multi developer teams (no official documentation on how to wrap into AAR bundle available) perfect for CI environments

Slide 44

Slide 44 text

REAL WORLD SCENARIOS Placeholder Naming conventions Activity/Fragment class names Layout names String references ID prefixes

Slide 45

Slide 45 text

PLACEHOLDER used for layout purposes help to get a meaningful overview present applied styles show wrapping

Slide 46

Slide 46 text

EXAMPLE

Slide 47

Slide 47 text

EXAMPLE

Slide 48

Slide 48 text

NAMING CONVENTIONS

Slide 49

Slide 49 text

ACTIVITY/FRAGMENT CLASS NAMES Natural names Conventional names ... C o n s u m e d M a t e r i a l s A c t i v i t y C u s t o m e r S i g n a t u r e F r a g m e n t O r d e r C o n f i r m a t i o n F r a g m e n t O r d e r D a t a M o d e l O r d e r R e p o r t A c t i v i t y O r d e r R e p o r t V i e w M o d e l V a n S t o c k M a t e r i a l F r a g m e n t ... ... A c t i v i t y C o n s u m e d M a t e A c t i v i t y O r d e r R e p o r t F r a g m e n t C u s t o m e r S i g n F r a g m e n t O r d e r C o n f i r m F r a g m e n t V a n S t o c k M a t e M o d e l O r d e r D a t a V i e w M o d e l O r d e r R e p o r t ...

Slide 50

Slide 50 text

LAYOUT NAMES should express where they are going to be used Examples: a c t i v i t y _ o r d e r _ s t a t u s . x m l f r a g m e n t _ c u s t o m e r _ d e t a i l s . x m l l i s t _ i t e m _ p u r c h a s e _ o r d e r . x m l

Slide 51

Slide 51 text

STRING REFERENCES From experience, string references should be tied to a widget in a 1:1 relation!! reduces semantical incorrectness allows outsourcing of translation process may be refined by literals to avoid redundancy could be declared in distinct and dedicated files

Slide 52

Slide 52 text

EXAMPLE < ! - - f r a g m e n t _ c u s t o m e r _ s i g n a t u r e . x m l - - > < T e x t V i e w a n d r o i d : i d = " @ + i d / t v C u s t o m e r N a m e " a n d r o i d : t e x t = " @ s t r i n g / f r a g m e n t _ c u s t o m e r _ s i g n a t u r e _ t v C u s t o m e r N a m e _ t e x t " / > < E d i t T e x t a n d r o i d : i d = " @ + i d / e t C u s t o m e r N a m e " a n d r o i d : h i n t = " @ s t r i n g / f r a g m e n t _ c u s t o m e r _ s i g n a t u r e _ e t C u s t o m e r N a m e _ h i n t " / > < B u t t o n a n d r o i d : i d = " @ + i d / b t S u b m i t " a n d r o i d : t e x t = " @ s t r i n g / f r a g m e n t _ c u s t o m e r _ s i g n a t u r e _ b t S u b m i t _ t e x t " / > < ! - - s t r i n g . x m l - - > < s t r i n g n a m e = " f r a g m e n t _ c u s t o m e r _ s i g n a t u r e _ t v C u s t o m e r N a m e _ t e x t " > P l e a s e e n t e r t h e c u s t o m e r n a m e : < / s t r i n g > < s t r i n g n a m e = " f r a g m e n t _ c u s t o m e r _ s i g n a t u r e _ b t S u b m i t _ t e x t " > @ s t r i n g / l i t e r a l _ s u b m i t < / s t r i n g >

Slide 53

Slide 53 text

ID PREFIXES infer semantics on widget types on inter-widget relations speed up code completion < R e l a t i v e L a y o u t a n d r o i d : i d = " @ + i d / l l C u s t o m e r D e t a i l s " . . . > < I m a g e V i e w a n d r o i d : i d = " @ + i d / i v C u s t o m e r N a m e " . . . / > < T e x t V i e w a n d r o i d : i d = " @ + i d / t v C u s t o m e r N a m e " . . . / > < E d i t T e x t a n d r o i d : i d = " @ + i d / e t C u s t o m e r N a m e " . . . / > . . . < B u t t o n a n d r o i d : i d = " @ + i d / b t S u b m i t " . . . / > < / R e l a t i v e L a y o u t >

Slide 54

Slide 54 text

SUMMARY custom Lint rules are written by extending D e t e c t o r s and implementing S c a n n e r s complex rules have a scan and an evaluation phase Lint API provides convenient access to different types of development artifacts AAR format allows easy deployment and project-related rules

Slide 55

Slide 55 text

WHAT'S NEXT release of reference guide for creating custom Lint rules improving Lint JUnit rule extending API advanced L i n t U t i l s advanced B a s e D e t e c t o r s encourage for more exchange (e.g. on StackOverflow)

Slide 56

Slide 56 text

THANK YOU FOR YOUR ATTENTION. Q&A  q2ad  a11n