Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a6b1edc3 authored by Matt Gilbride's avatar Matt Gilbride Committed by Android (Google) Code Review
Browse files

Merge "Add a helper script to apply lint fixes"

parents b6d070d1 9d5d4ccf
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -51,3 +51,9 @@ java_test_host {
        unit_test: true,
    },
}

python_binary_host {
    name: "lint_fix",
    main: "fix/lint_fix.py",
    srcs: ["fix/lint_fix.py"],
}
+4 −0
Original line number Diff line number Diff line
@@ -44,6 +44,10 @@ m out/soong/.intermediates/frameworks/base/services/autofill/services.autofill/a
  environment variable with the id of the lint. For example:
  `ANDROID_LINT_CHECK=UnusedTokenOfOriginalCallingIdentity m out/[...]/lint-report.html`

## How to apply automatic fixes suggested by lint

See [lint_fix](fix/README.md)

## Create or update a baseline

Baseline files can be used to silence known errors (and warnings) that are deemed to be safe. When
+46 −0
Original line number Diff line number Diff line
# Refactoring the platform with lint
Inspiration: go/refactor-the-platform-with-lint\
**Special Thanks: brufino@, azharaa@, for the prior work that made this all possible**

## What is this?

It's a python script that runs the framework linter,
and then copies modified files back into the source tree.\
Why python, you ask?  Because python is cool ¯\_(ツ)_/¯.

## Why?

Lint is not allowed to modify source files directly via lint's `--apply-suggestions` flag.
As a compromise, soong zips up the (potentially) modified sources and leaves them in an intermediate
directory.  This script runs the lint, unpacks those files, and copies them back into the tree.

## How do I run it?
**WARNING: You probably want to commit/stash any changes to your working tree before doing this...**

From this directory, run `python lint_fix.py -h`.
The script's help output explains things that are omitted here.

Alternatively, there is a python binary target you can build to make this
available anywhere in your tree:
```
m lint_fix
lint_fix -h
```

**Gotcha**: You must have run `source build/envsetup.sh` and `lunch` first.

Example: `lint_fix frameworks/base/services/core/services.core.unboosted UseEnforcePermissionAnnotation --dry-run`
```shell
(
export ANDROID_LINT_CHECK=UseEnforcePermissionAnnotation;
cd $ANDROID_BUILD_TOP;
source build/envsetup.sh;
rm out/soong/.intermediates/frameworks/base/services/core/services.core.unboosted/android_common/lint/lint-report.html;
m out/soong/.intermediates/frameworks/base/services/core/services.core.unboosted/android_common/lint/lint-report.html;
cd out/soong/.intermediates/frameworks/base/services/core/services.core.unboosted/android_common/lint;
unzip suggested-fixes.zip -d suggested-fixes;
cd suggested-fixes;
find . -path ./out -prune -o -name '*.java' -print | xargs -n 1 sh -c 'cp $1 $ANDROID_BUILD_TOP/$1' --;
rm -rf suggested-fixes
)
```
+76 −0
Original line number Diff line number Diff line
import argparse
import os
import sys

ANDROID_BUILD_TOP = os.environ.get("ANDROID_BUILD_TOP")
PATH_PREFIX = "out/soong/.intermediates"
PATH_SUFFIX = "android_common/lint"
FIX_DIR = "suggested-fixes"

parser = argparse.ArgumentParser(description="""
This is a python script that applies lint fixes to the platform:
1. Set up the environment, etc.
2. Build the lint and run it.
3. Unpack soong's intermediate zip containing source files modified by lint.
4. Copy the modified files back into the tree.

**Gotcha**: You must have run `source build/envsetup.sh` and `lunch` \
so that the `ANDROID_BUILD_TOP` environment variable has been set.
Alternatively, set it manually in your shell.
""", formatter_class=argparse.RawTextHelpFormatter)

parser.add_argument('build_path', metavar='build_path', type=str,
                    help='The build module to run '
                         '(e.g. frameworks/base/framework-minus-apex or '
                         'frameworks/base/services/core/services.core.unboosted)')

parser.add_argument('--check', metavar='check', type=str,
                    help='Which lint to run. Passed to the ANDROID_LINT_CHECK environment variable.')

parser.add_argument('--dry-run', dest='dry_run', action='store_true',
                    help='Just print the resulting shell script instead of running it.')

parser.add_argument('--no-fix', dest='no_fix', action='store_true',
                    help='Just build and run the lint, do NOT apply the fixes.')

args = parser.parse_args()

path = f"{PATH_PREFIX}/{args.build_path}/{PATH_SUFFIX}"
target = f"{path}/lint-report.html"

commands = []

if not args.dry_run:
    commands += [f"export ANDROID_BUILD_TOP={ANDROID_BUILD_TOP}"]

if args.check:
    commands += [f"export ANDROID_LINT_CHECK={args.check}"]

commands += [
    "cd $ANDROID_BUILD_TOP",
    "source build/envsetup.sh",
    f"rm {target}",  # remove the file first so soong doesn't think there is no work to do
    f"m {target}",
]

if not args.no_fix:
    commands += [
        f"cd {path}",
        f"unzip {FIX_DIR}.zip -d {FIX_DIR}",
        f"cd {FIX_DIR}",
        # Find all the java files in the fix directory, excluding the ./out subdirectory,
        # and copy them back into the same path within the tree.
        f"find . -path ./out -prune -o -name '*.java' -print | xargs -n 1 sh -c 'cp $1 $ANDROID_BUILD_TOP/$1' --",
        f"rm -rf {FIX_DIR}"
    ]

if args.dry_run:
    print("(\n" + ";\n".join(commands) + "\n)")
    sys.exit(0)

with_echo = []
for c in commands:
    with_echo.append(f'echo "{c}"')
    with_echo.append(c)

os.system("(\n" + ";\n".join(with_echo) + "\n)")