Merge "Add a helper script to apply lint fixes"

This commit is contained in:
Matt Gilbride
2022-08-23 18:04:07 +00:00
committed by Android (Google) Code Review
4 changed files with 132 additions and 0 deletions

View File

@@ -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"],
}

View File

@@ -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
tools/lint/fix/README.md Normal file
View File

@@ -0,0 +1,46 @@
# 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
)
```

View File

@@ -0,0 +1,76 @@
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)")