-
Notifications
You must be signed in to change notification settings - Fork 44
/
analysis_options.dart
122 lines (105 loc) · 3.85 KB
/
analysis_options.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:convert';
import 'dart:io';
import 'dart:isolate';
import 'package:http/http.dart' as http;
import 'package:logging/logging.dart';
import 'package:retry/retry.dart';
import 'package:yaml/yaml.dart' as yaml;
final _logger = Logger('analysis_options');
String? _cachedCoreLints;
/// 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.
try {
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 (_) {
// Gracefully handle exception to fall back to an empty config.
}
// 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:')) {
return rs.body;
}
} on Exception catch (_) {
// Gracefully handle exception to fall back to an empty config.
}
// 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 '';
}
Future<http.Response> _httpGetWithRetry(Uri uri) async {
return retry(
() async {
final rs = await http.get(uri);
if (rs.statusCode >= 500 && rs.statusCode < 600) {
throw http.ClientException(
'Server returned status code: ${rs.statusCode}');
}
return rs;
},
retryIf: (e) => e is SocketException || e is http.ClientException,
maxAttempts: 3,
delayFactor: const Duration(seconds: 2),
);
}
const _analyzerErrorKeys = <String>['uri_has_not_been_generated'];
String updatePassthroughOptions({
required String? original,
required String custom,
}) {
Map? origMap;
if (original != null) {
try {
origMap = yaml.loadYaml(original) as Map;
} catch (_) {}
}
origMap ??= {};
final customMap =
json.decode(json.encode(yaml.loadYaml(custom))) ?? <String, dynamic>{};
final origAnalyzer = origMap['analyzer'];
if (origAnalyzer is Map) {
final origErrors = origAnalyzer['errors'];
if (origErrors is Map) {
final customAnalyzer =
customMap.putIfAbsent('analyzer', () => <String, Object?>{}) as Map;
final customErrors = customAnalyzer.putIfAbsent(
'errors', () => <String, Object?>{}) as Map;
for (var key in _analyzerErrorKeys) {
if (origErrors.containsKey(key)) {
customErrors[key] = origErrors[key];
}
}
}
final origExperiments = origAnalyzer['enable-experiment'];
if (origExperiments is List && origExperiments.contains('macros')) {
final customAnalyzer =
customMap.putIfAbsent('analyzer', () => <String, Object?>{}) as Map;
final customExperiments = customAnalyzer.putIfAbsent(
'enable-experiment', () => <String>[]) as List;
customExperiments.add('macros');
}
}
final origFormatter = origMap['formatter'];
if (origFormatter is Map) {
final pageWidth = origFormatter['page_width'];
if (pageWidth is int) {
final customFormatter =
customMap.putIfAbsent('formatter', () => <String, Object?>{}) as Map;
customFormatter['page_width'] = pageWidth;
}
}
return json.encode(customMap);
}