Skip to content

Commit

Permalink
Account for removal of analysis_options_user.yaml from Flutter (#1329)
Browse files Browse the repository at this point in the history
  • Loading branch information
parlough committed Feb 7, 2024
1 parent 113f055 commit f41a55d
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 128 deletions.
85 changes: 18 additions & 67 deletions lib/src/analysis_options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,93 +8,44 @@ import 'dart:isolate';

import 'package:http/http.dart' as http;
import 'package:logging/logging.dart';
import 'package:path/path.dart' as p;
import 'package:retry/retry.dart';
import 'package:yaml/yaml.dart' as yaml;

final _logger = Logger('analysis_options');

String? _cachedFlutterOptionsOnGithub;
String? _cachedLintsCoreInResolvedReferences;
String? _cachedLintsCoreOptionsOnGithub;
String? _cachedCoreLints;

/// Returns the default analysis options (in yaml format).
Future<String> getDefaultAnalysisOptionsYaml({
required bool usesFlutter,
required String? flutterSdkDir,
}) async {
if (usesFlutter) {
return await _getFlutterAnalysisOptions(flutterSdkDir);
} else {
return await _getLintsCoreAnalysisOptions();
}
}

Future<String> _getFlutterAnalysisOptions(String? flutterSdkDir) async {
// try to load local file
flutterSdkDir ??= Platform.environment['FLUTTER_ROOT'];
if (flutterSdkDir != null &&
flutterSdkDir.isNotEmpty &&
await Directory(flutterSdkDir).exists()) {
final file = File(p.join(flutterSdkDir, 'packages', 'flutter', 'lib',
'analysis_options_user.yaml'));
if (await file.exists()) {
return await file.readAsString();
}
}

// try to load latest from github
if (_cachedFlutterOptionsOnGithub != null) {
return _cachedFlutterOptionsOnGithub!;
}
try {
final rs = await _httpGetWithRetry(Uri.parse(
'https://raw.githubusercontent.com/flutter/flutter/master/packages/flutter/lib/analysis_options_user.yaml'));
if (rs.statusCode == 200) {
_cachedFlutterOptionsOnGithub = rs.body;
return _cachedFlutterOptionsOnGithub!;
}
} catch (_) {
// no-op
}

// fallback empty options
_logger.warning('Unable to load default Flutter analysis options.');
return '';
}
/// The default analysis options configuration (in its raw yaml format).
Future<String> getDefaultAnalysisOptionsYaml() async =>
_cachedCoreLints ??= await _getLintsCoreAnalysisOptions();

Future<String> _getLintsCoreAnalysisOptions() async {
// try to load local lints from the resolved package references
if (_cachedLintsCoreInResolvedReferences != null) {
return _cachedLintsCoreInResolvedReferences!;
}
// Try to load local lints from the resolved package references.
try {
final resource =
await Isolate.resolvePackageUri(Uri.parse('package:lints/core.yaml'));
final file = File.fromUri(resource!);
_cachedLintsCoreInResolvedReferences = await file.readAsString();
return _cachedLintsCoreInResolvedReferences!;
final coreLintsUri = Uri(scheme: 'package', path: 'lints/core.yaml');
final resource = await Isolate.resolvePackageUri(coreLintsUri);
if (resource != null) {
final file = File.fromUri(resource);
return await file.readAsString();
}
} on Exception catch (_) {
// no-op
// Gracefully handle exception to fall back to an empty config.
}

// try to load latest from github
if (_cachedLintsCoreOptionsOnGithub != null) {
return _cachedLintsCoreOptionsOnGithub!;
}
// Try to load latest version of the core lints from GitHub.
try {
final rs = await _httpGetWithRetry(Uri.parse(
'https://raw.githubusercontent.com/dart-lang/lints/main/lib/core.yaml'));
if (rs.statusCode == 200 && rs.body.contains('rules:')) {
_cachedLintsCoreOptionsOnGithub = rs.body;
return _cachedLintsCoreOptionsOnGithub!;
return rs.body;
}
} on Exception catch (_) {
// no-op
// Gracefully handle exception to fall back to an empty config.
}

// fallback empty options
_logger.warning('Unable to load default analysis options.');
// If we couldn't load the core lints,
// log a warning and fall back to an empty analysis config.
_logger.warning('Unable to load the core set of analysis options.');
return '';
}

Expand Down
5 changes: 1 addition & 4 deletions lib/src/sdk_env.dart
Original file line number Diff line number Diff line change
Expand Up @@ -194,10 +194,7 @@ class ToolEnvironment {
if (await analysisOptionsFile.exists()) {
originalOptions = await analysisOptionsFile.readAsString();
}
final rawOptionsContent = await getDefaultAnalysisOptionsYaml(
usesFlutter: usesFlutter,
flutterSdkDir: _flutterSdk._config.rootPath,
);
final rawOptionsContent = await getDefaultAnalysisOptionsYaml();
final customOptionsContent = updatePassthroughOptions(
original: originalOptions, custom: rawOptionsContent);
try {
Expand Down
18 changes: 1 addition & 17 deletions test/analysis_options_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ import 'package:yaml/yaml.dart' as yaml;

void main() {
test('default options', () async {
final content = await getDefaultAnalysisOptionsYaml(
usesFlutter: false, flutterSdkDir: null);
final content = await getDefaultAnalysisOptionsYaml();
expect(content, contains('linter:'));
expect(content, contains('rules:'));
expect(content, contains('avoid_empty_else'));
Expand All @@ -23,21 +22,6 @@ void main() {
});
});

test('default Flutter options', () async {
final content = await getDefaultAnalysisOptionsYaml(
usesFlutter: true, flutterSdkDir: null);
expect(json.decode(json.encode(yaml.loadYaml(content))), {
'analyzer': {
'errors': {
'missing_required_param': 'warning',
},
},
'linter': {
'rules': hasLength(greaterThan(10)),
},
});
});

test('passthrough for empty options', () {
final content = updatePassthroughOptions(original: '', custom: '');
expect(json.decode(content), <String, Object?>{});
Expand Down
8 changes: 4 additions & 4 deletions test/goldens/end2end/audio_service-0.18.10.json
Original file line number Diff line number Diff line change
Expand Up @@ -159,10 +159,10 @@
{
"id": "analysis",
"title": "Pass static analysis",
"grantedPoints": 40,
"grantedPoints": 50,
"maxPoints": 50,
"status": "partial",
"summary": "### [~] 40/50 points: code has no errors, warnings, lints, or formatting issues\n\nFound 16 issues. Showing the first 2:\n\n<details>\n<summary>\nINFO: Unclosed instance of 'Sink'.\n</summary>\n\n`lib/audio_service.dart:1943:40`\n\n```\n ╷\n1943 │ final BehaviorSubject<PlaybackState> _playbackState = BehaviorSubject();\n │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n ╵\n```\n\nTo reproduce make sure you are using the [lints_core](https://pub.dev/packages/lints) and run `flutter analyze lib/audio_service.dart`\n</details>\n<details>\n<summary>\nINFO: Unclosed instance of 'Sink'.\n</summary>\n\n`lib/audio_service.dart:1944:42`\n\n```\n ╷\n1944 │ final BehaviorSubject<List<MediaItem>> _queue = BehaviorSubject();\n │ ^^^^^^^^^^^^^^^^^^^^^^^^^^\n ╵\n```\n\nTo reproduce make sure you are using the [lints_core](https://pub.dev/packages/lints) and run `flutter analyze lib/audio_service.dart`\n</details>"
"status": "passed",
"summary": "### [*] 50/50 points: code has no errors, warnings, lints, or formatting issues\n"
},
{
"id": "dependency",
Expand All @@ -186,7 +186,7 @@
"path": "audio_service"
},
"contributingUrl": "https://github.com/ryanheise/audio_service/blob/minor/CONTRIBUTING.md",
"grantedPoints": 120,
"grantedPoints": 130,
"maxPoints": 130
},
"urlProblems": []
Expand Down
38 changes: 2 additions & 36 deletions test/goldens/end2end/audio_service-0.18.10.json_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,44 +61,10 @@ Because:
* `package:path_provider/path_provider.dart` that declares support for platforms: `Android`, `iOS`, `Windows`, `Linux`, `macOS`.
</details>

## 40/50 Pass static analysis
## 50/50 Pass static analysis

### [~] 40/50 points: code has no errors, warnings, lints, or formatting issues
### [*] 50/50 points: code has no errors, warnings, lints, or formatting issues

Found 16 issues. Showing the first 2:

<details>
<summary>
INFO: Unclosed instance of 'Sink'.
</summary>

`lib/audio_service.dart:1943:40`

```
1943 │ final BehaviorSubject<PlaybackState> _playbackState = BehaviorSubject();
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
```

To reproduce make sure you are using the [lints_core](https://pub.dev/packages/lints) and run `flutter analyze lib/audio_service.dart`
</details>
<details>
<summary>
INFO: Unclosed instance of 'Sink'.
</summary>

`lib/audio_service.dart:1944:42`

```
1944 │ final BehaviorSubject<List<MediaItem>> _queue = BehaviorSubject();
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^
```

To reproduce make sure you are using the [lints_core](https://pub.dev/packages/lints) and run `flutter analyze lib/audio_service.dart`
</details>

## 20/20 Support up-to-date dependencies

Expand Down

0 comments on commit f41a55d

Please sign in to comment.