Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Start of linting Android embedding #8023

Merged
merged 7 commits into from
Mar 4, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion shell/platform/android/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="io.flutter.app" android:versionCode="1" android:versionName="0.0.1">

<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="21" />
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="21" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.sensor.accelerometer" android:required="true" />
Expand Down
1 change: 1 addition & 0 deletions tools/android_lint/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
lint_report/
148 changes: 148 additions & 0 deletions tools/android_lint/bin/main.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2019?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm worried the license checker won't be smart enough to figure out this doesn't impact licensing :(

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI @gspencergoog @dnfield my understanding is that 2013 should be the year used on all licenses within the embedding.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nevermind, this file lives somewhere else.

// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:io';

import 'package:args/args.dart';
import 'package:path/path.dart' as path;
import 'package:process/process.dart';

const LocalProcessManager processManager = LocalProcessManager();

/// Runs the Android SDK Lint tool on flutter/shell/platform/android.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When will this run? And what will be the impact on the fact that most files will not conform to our desired styles?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right now it would be run by hand. Longer term we want to run it as part of CI.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we determine that the linter is suggesting things that violate our desired styles we can turn them off. For now we want to just try to catch as much as we can.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But these aren't being run on PRs are they? What I want to avoid is being forced to make changes to existing files just because I had to alter a constructor argument, etc.

///
/// This script scans the flutter/shell/platform/android directory for Java
/// files to build a `project.xml` file. This file is then passed to the lint
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where are the lint rules that are being applied?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right now all of the default ones and all warnings, which are all getting elevated to errors.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But the linter includes style doesn't it? If so, which of the many flavors of java/Android style is it applying?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm also curious where these are actually defined. I don't know any default lint rules off the top of my head.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the public doc for it: https://developer.android.com/studio/write/lint

I don't know that it actually checks what we'd be calling style - or certainly not everything in the Java style guide.

/// tool and HTML output is reqeusted in the directory for the `--out`
/// parameter, which defaults to `lint_report`.
///
/// The `--in` parameter may be specified to force this script to scan a
/// specific location for the engine repository, and expects to be given the
/// `src` directory that contains both `third_party` and `flutter`.
///
/// At the time of this writing, the Android Lint tool doesn't work well with
/// Java > 1.8. This script will print a warning if you are not running
/// Java 1.8.
Future<void> main(List<String> args) async {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we break this function down? Something like:

request = parseArgs(args);
writeProjectFile(request);
result = runLint();
return result;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More or less done - I could definitely get fancier with this, but right now I just want something that works.

final ArgParser argParser = setupOptions();
await checkJava1_8();
final int exitCode = await runLint(argParser, argParser.parse(args));
exit(exitCode);
}

Future<int> runLint(ArgParser argParser, ArgResults argResults) async {
final Directory androidDir = Directory(path.join(
argResults['in'],
'flutter',
'shell',
'platform',
'android',
));
if (!androidDir.existsSync()) {
print('This command must be run from the engine/src directory, '
'or be passed that directory as the --in parameter.\n');
print(argParser.usage);
return -1;
}

final Directory androidSdkDir = Directory(
path.join(argResults['in'], 'third_party', 'android_tools', 'sdk'),
);

if (!androidSdkDir.existsSync()) {
print('The Android SDK for this engine is missing from the '
'third_party/android_tools directory. Have you run gclient sync?\n');
print(argParser.usage);
return -1;
}

final IOSink projectXml = File('./project.xml').openWrite();
projectXml.write(
'''<!-- THIS FILE IS GENERATED. PLEASE USE THE INCLUDED DART PROGRAM WHICH -->
<!-- WILL AUTOMATICALLY FIND ALL .java FILES AND INCLUDE THEM HERE -->
<project>
<sdk dir="${androidSdkDir.path}" />
<module name="FlutterEngine" android="true" library="true" compile-sdk-version="android-P">
<manifest file="${path.join(androidDir.path, 'AndroidManifest.xml')}" />
''');
for (final FileSystemEntity entity in androidDir.listSync(recursive: true)) {
if (!entity.path.endsWith('.java')) {
continue;
}
projectXml.writeln(' <src file="${entity.path}" />');
}

projectXml.write(''' </module>
</project>
''');
await projectXml.close();

print('Wrote project.xml, starting lint...');
final ProcessResult result = await processManager.run(
<String>[
path.join(androidSdkDir.path, 'tools', 'bin', 'lint'),
'--project',
'./project.xml',
'--html',
argResults['out'],
'--showall',
'--exitcode', // Set non-zero exit code on errors
'-Wall',
'-Werror',
],
);
if (result.stderr != null) {
print('Lint tool had internal errors:');
print(result.stderr);
}
print(result.stdout);
return result.exitCode;
}

ArgParser setupOptions() {
final ArgParser argParser = ArgParser();
argParser.addOption(
'in',
help: 'The path to `engine/src`.',
defaultsTo: path.relative(
path.join(
path.dirname(
path.dirname(path.dirname(path.fromUri(Platform.script))),
),
'..',
'..',
),
),
);
argParser.addOption(
'out',
help: 'The path to write the generated the HTML report to.',
defaultsTo: 'lint_report',
);
argParser.addFlag(
'help',
help: 'Print usage of the command.',
negatable: false,
defaultsTo: false,
);

return argParser;
}

Future<void> checkJava1_8() async {
print('Checking Java version...');
final ProcessResult javaResult = await processManager.run(
<String>['java', '-version'],
);
if (javaResult.exitCode != 0) {
print('Could not run "java -version". '
'Ensure Java is installed and available on your path.');
print(javaResult.stderr);
}
final String javaVersionStdout = javaResult.stdout;
if (javaVersionStdout.contains('"1.8')) {
print('The Android SDK tools may not work properly with your Java version. '
'If this process fails, please retry using Java 1.8.');
}
}
81 changes: 81 additions & 0 deletions tools/android_lint/project.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<!-- THIS FILE IS GENERATED. PLEASE USE THE INCLUDED DART PROGRAM WHICH -->
<!-- WILL AUTOMATICALLY FIND ALL .java FILES AND INCLUDE THEM HERE -->
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should you find all Java files, or only the Java files listed in BUILD.gn?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could use BUILD.gn - in which case we could probably write this as a build rule. I don't really have a strong opinion on that - would we want unlinted files in the repo that aren't part of the build though?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess the question is, why would a Java file exist without being a part of BUILD.gn....and if no such situation can occur, then why not just yank the Java file paths out of BUILD.gn?

<project>
<sdk dir="../../../third_party/android_tools/sdk" />
<module name="FlutterEngine" android="true" library="true" compile-sdk-version="android-P">
<manifest file="../../../flutter/shell/platform/android/AndroidManifest.xml" />
<src file="../../../flutter/shell/platform/android/io/flutter/app/FlutterPluginRegistry.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/app/FlutterFragmentActivity.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/app/FlutterActivity.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/app/FlutterActivityEvents.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/app/FlutterApplication.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/app/FlutterActivityDelegate.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/util/Preconditions.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/util/Predicate.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/util/PathUtils.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/engine/renderer/FlutterRenderer.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/engine/renderer/OnFirstFrameRenderedListener.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/engine/dart/DartExecutor.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/engine/dart/PlatformMessageHandler.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/engine/dart/DartMessenger.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/engine/FlutterShellArgs.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/SettingsChannel.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/NavigationChannel.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/LocalizationChannel.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/TextInputChannel.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/AccessibilityChannel.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/KeyEventChannel.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/SystemChannel.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/LifecycleChannel.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/engine/android/AndroidTouchProcessor.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/engine/android/FlutterActivity.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/engine/android/FlutterView.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/engine/android/FlutterTextureView.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/engine/android/FlutterFragment.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/engine/android/FlutterSurfaceView.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/engine/android/AndroidKeyProcessor.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/plugin/platform/PlatformViewRegistry.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/plugin/platform/VirtualDisplayController.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/plugin/platform/PlatformViewRegistryImpl.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/plugin/platform/SingleViewPresentation.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/plugin/platform/PlatformViewFactory.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/plugin/platform/PlatformView.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/plugin/common/BasicMessageChannel.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/plugin/common/JSONMethodCodec.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/plugin/common/JSONUtil.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/plugin/common/PluginRegistry.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/plugin/common/MessageCodec.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/plugin/common/ErrorLogResult.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/plugin/common/JSONMessageCodec.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/plugin/common/ActivityLifecycleListener.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/plugin/common/BinaryCodec.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/plugin/common/FlutterException.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/plugin/common/StringCodec.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/plugin/common/StandardMessageCodec.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/plugin/common/StandardMethodCodec.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/plugin/common/MethodCodec.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/plugin/common/BinaryMessenger.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/plugin/common/MethodCall.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/plugin/common/EventChannel.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/plugin/common/MethodChannel.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/plugin/editing/TextInputPlugin.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/plugin/editing/InputConnectionAdaptor.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/view/FlutterNativeView.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/view/ResourceUpdater.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/view/FlutterCallbackInformation.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/view/VsyncWaiter.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/view/FlutterView.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/view/FlutterMain.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/view/ResourceExtractor.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/view/TextureRegistry.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/view/ResourcePaths.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/view/ResourceCleaner.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/view/FlutterRunArguments.java" />
<src file="../../../flutter/shell/platform/android/io/flutter/view/AccessibilityBridge.java" />
</module>
</project>
5 changes: 5 additions & 0 deletions tools/android_lint/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
name: android_lint
dependencies:
args: 1.5.0
path: ^1.6.2
process: ^3.0.9