What lints?

Current actively developed lints are Detekt and ktlint. klint have a don't overengineer philosophy while detekt is more configurable.

How to set up Detekt?

https://github.com/detekt/detekt

Download binary from here https://github.com/detekt/detekt/releases Config file can be auto generated from command line or simple download mine default-detekt-config.yml

How to set up ktlint?

https://github.com/pinterest/ktlint Download binary from here https://github.com/pinterest/ktlint/releases Ktlint can be configured with standard .editorconfig file. You can find one anywhere in github or get mine: .editorconfig

How to make it check each commit?

Copy and configure script from here: pre-commit

#!/bin/bash
# Setting up guide http://dmitrysamoylenko.com/2020/12/06/configure_lints.html
# https://github.com/checkstyle/checkstyle
# https://github.com/pinterest/ktlint
# https://github.com/detekt/detekt

# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ]; then
  if [ -x "$JAVA_HOME/jre/sh/java" ]; then
    # IBM's JDK on AIX uses strange locations for the executables
    JAVACMD="$JAVA_HOME/jre/sh/java"
  else
    JAVACMD="$JAVA_HOME/bin/java"
  fi
  if [ ! -x "$JAVACMD" ]; then
    die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
  fi
else
  JAVACMD="java"
  which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi

GIT_ROOT_DIR=$(git rev-parse --show-toplevel)

cd ${GIT_ROOT_DIR}
#echo ${GIT_ROOT_DIR}
f=()
while read line; do
  if [ -n "$line" ]; then
    if [[ "$line" =~ .*"/build/".* ]]; then
      true #skip generated code
    else
      f+=("$line")
    fi
  fi
done <<<"$(git diff --diff-filter=d --staged --name-only)"

filesJava=""
filesKt=""
countJava=0
countKt=0
for i in "${!f[@]}"; do
  if [[ "${f[i]}" == *.java ]]; then
    filesJava+=" ${f[i]}"
    countJava=$((countJava + 1))
  fi
  if [[ "${f[i]}" == *.kt ]]; then
    filesKt+=" ${f[i]}"
    countKt=$((countKt + 1))
  fi
done

for i in "${!f[@]}"; do
  if [[ "${f[i]}" =~ .*.(java|kt)$ ]]; then
    lineNum=0
    while IFS= read line; do
      if [ -n "$line" ]; then
        lineNum=$((lineNum+1))
        if [[ "$line" =~ ^\ +[^\*].* ]]; then
          echo "Line starts with spaces. Please apply project code style. File: ${f[i]}:$lineNum, line: $line"
          exit 1
        elif [[ "$line" =~ .*oleg.*|.*xoxoxo.* ]]; then
          echo "forbidden word in line. File: ${f[i]}:$lineNum, line: $line"
          exit 1
        else
          true #skip good code
        fi
      fi
    done < "${f[i]}"
  fi
done

if [ ${#filesJava} -eq 0 ]; then
  echo "No *.java files to check."
else
  configloc=-Dconfig_loc=${GIT_ROOT_DIR}/ivi/config/checkstyle
  config=${GIT_ROOT_DIR}/ivi/config/checkstyle/checkstyle.xml
  params="${configloc} -jar ${GIT_ROOT_DIR}/githooks/checkstyle-8.38-all.jar -c ${config}${filesJava}"

  ${JAVACMD} $params
  result=$?
  if [ $result -ne 0 ]; then
    echo "Please fix the checkstyle problems before submit the commit!"
    exit $result
  else
    echo "#java files: $countJava"
  fi
fi

if [ ${#filesKt} -eq 0 ]; then
  echo "No *.kt files to check."
  exit 0
fi

# ktlint check
git diff --diff-filter=d --staged --name-only | grep '\.kt[s"]\?$' | xargs ./ktlint .
result=$?
if [ $result -ne 0 ]; then
  echo "Please fix the ktlint problems before submit the commit!"
  exit $result
fi

#detekt check

check_by_detekt() {
  arg=$1
  files=${arg%?}
  if [ ${#files} -eq 0 ]; then
    true #skip
  else
    params="--fail-fast --config default-detekt-config.yml --input ${files}"
    ./detekt ${params}
    result=$?
    if [ $result -ne 0 ]; then
      echo "Please fix the detekt problems before submit the commit!"
      exit $result
    fi
  fi
}
count=0
filesd=""
for i in "${!f[@]}"; do
  if [[ "${f[i]}" == *.kt ]]; then
    filesd+="${f[i]},"
    count=$((count + 1))
    # split into batches
    if [ $count -gt 1000 ]; then
      check_by_detekt $filesd
      count=0
      filesd=""
    fi
  fi
done

check_by_detekt $filesd
echo "# kt files: $count"
exit 0

How to make it work for all team members?

Make folder githooks/ in the root git project directory and put all downloaded files into it. Then in top of the project build.gradle insert:

exec {
	executable './../enable_lints.sh'
}

This will execute the script enable_lints.sh that will apply git path to the githooks/ directory and make git execute the script pre-commit before each commit. Contents of the script:

enable_lints.sh

#!/bin/bash
git config --global core.hooksPath githooks

Remember to make each script executable

chmod +x ./ktlint
chmod +x ./detekt
chmod +x ./githooks/pre-commit

Now add the githook/ directory and all new files to git and push it to server. All team should just open project again so AndroidStudio will run build.gradle script. Notice that script support only unix os and should be specially edited to support windows.