Skip to content

Commit dbdc1d4

Browse files
author
Illia Aihistov
committed
refactor: improve analysis options parsing robustness with type standardization and fix path resolution logic
1 parent ed46119 commit dbdc1d4

4 files changed

Lines changed: 54 additions & 35 deletions

File tree

lib/src/common/parameter_parser/analysis_options_loader.dart

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ class AnalysisOptionsLoader {
1010
final ResourceProvider _resourceProvider;
1111
final Map<String, CachedPackageRules> _rulesCache = {};
1212

13-
// Caches directory path -> nearest analysis_options.yaml file path
14-
final Map<String, String?> _nearestYamlCache = {};
13+
1514

1615
late final AnalysisOptionsParser _parser;
1716

@@ -101,29 +100,27 @@ class AnalysisOptionsLoader {
101100
}
102101

103102
String? _findNearestAnalysisOptionsFilePath(String startDirectoryPath) {
104-
return _nearestYamlCache.putIfAbsent(startDirectoryPath, () {
105-
final pathContext = _resourceProvider.pathContext;
106-
var currentDirectoryPath = startDirectoryPath;
107-
108-
while (currentDirectoryPath.isNotEmpty) {
109-
final candidatePath = pathContext.join(
110-
currentDirectoryPath,
111-
'analysis_options.yaml',
112-
);
113-
final candidateFile = _resourceProvider.getFile(candidatePath);
103+
final pathContext = _resourceProvider.pathContext;
104+
var currentDirectoryPath = startDirectoryPath;
105+
106+
while (currentDirectoryPath.isNotEmpty) {
107+
final candidatePath = pathContext.join(
108+
currentDirectoryPath,
109+
'analysis_options.yaml',
110+
);
111+
final candidateFile = _resourceProvider.getFile(candidatePath);
114112

115-
if (candidateFile.exists) {
116-
return candidatePath;
117-
}
113+
if (candidateFile.exists) {
114+
return candidatePath;
115+
}
118116

119-
final parentDir = pathContext.dirname(currentDirectoryPath);
120-
if (parentDir == currentDirectoryPath) {
121-
break;
122-
}
123-
currentDirectoryPath = parentDir;
117+
final parentDir = pathContext.dirname(currentDirectoryPath);
118+
if (parentDir == currentDirectoryPath) {
119+
break;
124120
}
121+
currentDirectoryPath = parentDir;
122+
}
125123

126-
return null;
127-
});
124+
return null;
128125
}
129126
}

lib/src/common/parameter_parser/analysis_options_parser.dart

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ class AnalysisOptionsParser {
2727
if (seenPaths.contains(path)) {
2828
return const RulesData.empty();
2929
}
30-
seenPaths.add(path);
3130

3231
final yaml = _parseYaml(analysisOptionsFile);
3332
if (yaml == null) {
@@ -37,10 +36,11 @@ class AnalysisOptionsParser {
3736
final mergedRules = <String, Map<String, Object?>>{};
3837
final disabledRules = <String>{};
3938

39+
final nextSeenPaths = {...seenPaths, path};
4040
_resolveAndMergeIncludes(
4141
analysisOptionsFile,
4242
yaml,
43-
seenPaths,
43+
nextSeenPaths,
4444
mergedRules,
4545
disabledRules,
4646
);
@@ -50,19 +50,34 @@ class AnalysisOptionsParser {
5050
return RulesData(rules: mergedRules, disabledRules: disabledRules);
5151
}
5252

53-
Map<dynamic, dynamic>? _parseYaml(File file) {
53+
Map<String, Object?>? _parseYaml(File file) {
5454
try {
5555
final optionsString = file.readAsStringSync();
5656
final parsed = loadYaml(optionsString);
57-
return parsed is Map ? parsed : null;
57+
if (parsed is! Map) return null;
58+
return _toStandardMap(parsed);
5859
} catch (_) {
5960
return null;
6061
}
6162
}
6263

64+
Map<String, Object?> _toStandardMap(Map<dynamic, dynamic> map) {
65+
return {
66+
for (final entry in map.entries)
67+
if (entry.key is String)
68+
entry.key as String: _toStandardType(entry.value),
69+
};
70+
}
71+
72+
Object? _toStandardType(Object? value) => switch (value) {
73+
Map() => _toStandardMap(value),
74+
Iterable() => value.map(_toStandardType).toList(),
75+
_ => value,
76+
};
77+
6378
void _resolveAndMergeIncludes(
6479
File baseFile,
65-
Map<dynamic, dynamic> yaml,
80+
Map<String, Object?> yaml,
6681
Set<String> seenPaths,
6782
Map<String, Map<String, Object?>> mergedRules,
6883
Set<String> disabledRules,
@@ -97,7 +112,7 @@ class AnalysisOptionsParser {
97112
}
98113

99114
void _parseRuleOptions(
100-
Map<dynamic, dynamic> yaml,
115+
Map<String, Object?> yaml,
101116
Map<String, Map<String, Object?>> mergedRules,
102117
Set<String> disabledRules,
103118
) {
@@ -131,7 +146,7 @@ class AnalysisOptionsParser {
131146
}
132147
}
133148

134-
Object? _extractDiagnostics(Map<dynamic, dynamic> yaml) {
149+
Object? _extractDiagnostics(Map<String, Object?> yaml) {
135150
final pluginConfig = yaml[kPluginName];
136151
if (pluginConfig is Map) {
137152
return pluginConfig['diagnostics'];
@@ -164,7 +179,7 @@ class AnalysisOptionsParser {
164179
/// from running, we parse this section and add suppressed rules
165180
/// to [disabledRules].
166181
void _parseSuppressedErrors(
167-
Map<dynamic, dynamic> yaml,
182+
Map<String, Object?> yaml,
168183
Map<String, Map<String, Object?>> mergedRules,
169184
Set<String> disabledRules,
170185
) {

lib/src/common/parameter_parser/package_config_resolver.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,13 @@ class PackageConfigResolver {
114114
final rootUri = Uri.parse(rootUriString);
115115
final resolvedRootUri = rootUri.isAbsolute
116116
? rootUri
117-
: Uri.file(packageConfigPath).resolveUri(rootUri);
117+
: _resourceProvider.pathContext
118+
.toUri(packageConfigPath)
119+
.resolveUri(rootUri);
118120

119121
if (resolvedRootUri.isScheme('file')) {
120122
result[name] = _resourceProvider.pathContext.join(
121-
resolvedRootUri.toFilePath(),
123+
_resourceProvider.pathContext.fromUri(resolvedRootUri),
122124
packageUriString,
123125
);
124126
}

lib/src/lints/avoid_using_api/models/avoid_using_api_parameters.dart

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,14 @@ class AvoidUsingApiParameters {
4848
return AvoidUsingApiParameters(
4949
entries: List<AvoidUsingApiEntryParameters>.from(
5050
(json['entries'] as Iterable?)?.map(
51-
(e) => AvoidUsingApiEntryParameters.fromJson(
52-
(e as YamlMap).toMap(),
53-
),
51+
(e) {
52+
if (e is YamlMap) {
53+
return AvoidUsingApiEntryParameters.fromJson(e.toMap());
54+
}
55+
return AvoidUsingApiEntryParameters.fromJson(
56+
Map<String, Object?>.from(e as Map),
57+
);
58+
},
5459
) ??
5560
[],
5661
),

0 commit comments

Comments
 (0)