Skip to content

Commit f1451c0

Browse files
feat: improve exception help messages (#12)
Fixes #5
1 parent 4b68423 commit f1451c0

5 files changed

Lines changed: 108 additions & 23 deletions

File tree

lib/src/crate_info_validator.dart

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ interface class CrateInfoValidator {
2929
const requiredTypes = ['staticlib', 'cdylib'];
3030
if (!requiredTypes.every(libCrateTypes.contains)) {
3131
throw RustValidationException([
32-
'Cargo.toml must specify $requiredTypes under lib.crate-types',
32+
'''
33+
Your Cargo.toml must specify $requiredTypes under `lib.crate-types`.
34+
For more information, see https://github.com/GregoryConrad/native_toolchain_rs?tab=readme-ov-file#cargotoml''',
3335
]);
3436
}
3537

@@ -45,15 +47,19 @@ interface class CrateInfoValidator {
4547
const deniedChannels = {'stable', 'beta', 'nightly'};
4648
if (deniedChannels.contains(channel)) {
4749
toolchainIssues.add(
48-
'Your current channel in rust-toolchain.toml is $channel; '
49-
'this is dangerous and consequently is not allowed! '
50-
'Please specify an exact version to fix this issue.',
50+
'''
51+
The rust-toolchain.toml is using the `$channel` channel, which is not allowed.
52+
Please specify an exact version (e.g., `1.90.0`) to ensure a reproducible build.
53+
For more information, see https://github.com/GregoryConrad/native_toolchain_rs?tab=readme-ov-file#rust-toolchaintoml''',
5154
);
5255
}
5356

5457
if (!targets.contains(targetTriple)) {
5558
toolchainIssues.add(
56-
'$targetTriple is not one of the supported targets: $targets',
59+
'''
60+
The rust-toolchain.toml does not include the target `$targetTriple`.
61+
If you wish to support this target, please add it to the `targets` array in the rust-toolchain.toml file.
62+
For more information, see https://github.com/GregoryConrad/native_toolchain_rs?tab=readme-ov-file#rust-toolchaintoml''',
5763
);
5864
}
5965

lib/src/crate_resolver.dart

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,11 @@ interface class CrateDirectoryResolver {
1919
.firstOrNull;
2020
if (crateDirectory == null) {
2121
throw RustValidationException([
22-
'No options for the crate path ($cratePathOptions) exist at $rootPath',
22+
'''
23+
Could not find the crate directory.
24+
The following paths were checked: $cratePathOptions at $rootPath.
25+
Please make sure that the crate is in one of these locations, or explicitly specify the `cratePath` in your `RustBuilder`.
26+
For more information, see https://github.com/GregoryConrad/native_toolchain_rs?tab=readme-ov-file#code-setup''',
2327
]);
2428
}
2529
return crateDirectory;

lib/src/exception.dart

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,10 @@ final class RustValidationException implements RustBuildException {
4444

4545
@override
4646
String toString() =>
47-
'RustValidationException(validationErrors: $validationErrors)';
47+
'''
48+
RustValidationException(
49+
${validationErrors.map((e) => ' - $e').join(Platform.lineTerminator)}
50+
)''';
4851
}
4952

5053
/// A [RustBuildException] that specifies there was an issue

lib/src/toml_parsing.dart

Lines changed: 76 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,12 @@ final class TomlDocumentWrapper {
3737
exception,
3838
stackTrace,
3939
);
40-
throw RustValidationException(['Could not find $path in $filePath']);
40+
throw RustValidationException([
41+
'''
42+
Could not find the field `$path` in the TOML file at $filePath.
43+
Please ensure the field exists and is correctly formatted.
44+
The following exception was thrown: $exception''',
45+
]);
4146
}
4247
}
4348
}
@@ -53,7 +58,11 @@ interface class CargoManifestParser {
5358
) {
5459
logger?.info('Looking for Cargo.toml');
5560
if (!File(manifestPath).existsSync()) {
56-
throw RustValidationException(['$manifestPath not found']);
61+
throw RustValidationException([
62+
'''
63+
The Cargo.toml file was not found at $manifestPath.
64+
For more information, see https://github.com/GregoryConrad/native_toolchain_rs?tab=readme-ov-file#cargotoml''',
65+
]);
5766
}
5867

5968
logger?.info('Parsing Cargo.toml');
@@ -62,15 +71,42 @@ interface class CargoManifestParser {
6271
manifest = tomlDocumentFactory.parseFile(manifestPath);
6372
} on Object catch (exception, stackTrace) {
6473
logger?.severe('Failed to parse Cargo.toml', exception, stackTrace);
65-
throw RustValidationException(['Failed to parse Cargo.toml: $exception']);
74+
throw RustValidationException([
75+
'''
76+
Failed to parse the Cargo.toml file at $manifestPath.
77+
Please check the file for syntax errors.
78+
For more information, see https://doc.rust-lang.org/cargo/reference/manifest.html
79+
The following exception was thrown: $exception''',
80+
]);
6681
}
6782

6883
final [
6984
String crateName,
7085
List<String> libCrateTypes,
7186
] = RustValidationException.compose<dynamic>([
72-
() => manifest.walk<String>('package.name'),
73-
() => manifest.walk<List<dynamic>>('lib.crate-type').cast<String>(),
87+
() {
88+
try {
89+
return manifest.walk<String>('package.name');
90+
} on RustValidationException {
91+
throw const RustValidationException([
92+
'''
93+
The Cargo.toml file must specify the `package.name` field.
94+
For more information, see https://doc.rust-lang.org/cargo/reference/manifest.html#the-name-field''',
95+
]);
96+
}
97+
},
98+
() {
99+
try {
100+
return manifest.walk<List<dynamic>>('lib.crate-type').cast<String>();
101+
} on RustValidationException {
102+
throw const RustValidationException([
103+
'''
104+
The Cargo.toml file must specify the `lib.crate-type` field.
105+
For more information, see https://github.com/GregoryConrad/native_toolchain_rs?tab=readme-ov-file#cargotoml
106+
and https://doc.rust-lang.org/cargo/reference/cargo-targets.html#the-crate-type-field''',
107+
]);
108+
}
109+
},
74110
]);
75111

76112
return (crateName: crateName, libCrateTypes: libCrateTypes);
@@ -88,7 +124,11 @@ interface class ToolchainTomlParser {
88124
) {
89125
logger?.info('Looking for rust-toolchain.toml');
90126
if (!File(toolchainTomlPath).existsSync()) {
91-
throw RustValidationException(['$toolchainTomlPath not found']);
127+
throw RustValidationException([
128+
'''
129+
The rust-toolchain.toml file was not found at $toolchainTomlPath.
130+
For more information, see https://github.com/GregoryConrad/native_toolchain_rs?tab=readme-ov-file#rust-toolchaintoml''',
131+
]);
92132
}
93133

94134
logger?.info('Parsing rust-toolchain.toml');
@@ -98,19 +138,43 @@ interface class ToolchainTomlParser {
98138
} on Object catch (e, stackTrace) {
99139
logger?.severe('Failed to parse rust-toolchain.toml', e, stackTrace);
100140
throw RustValidationException([
101-
'Failed to parse rust-toolchain.toml: $e',
141+
'''
142+
Failed to parse the rust-toolchain.toml file at $toolchainTomlPath.
143+
Please check the file for syntax errors.
144+
For more information, see https://github.com/GregoryConrad/native_toolchain_rs?tab=readme-ov-file#rust-toolchaintoml
145+
The following exception was thrown: $e''',
102146
]);
103147
}
104148

105149
final [
106150
String channel,
107151
Set<String> targets,
108152
] = RustValidationException.compose<dynamic>([
109-
() => toolchain.walk<String>('toolchain.channel'),
110-
() => toolchain
111-
.walk<List<dynamic>>('toolchain.targets')
112-
.cast<String>()
113-
.toSet(),
153+
() {
154+
try {
155+
return toolchain.walk<String>('toolchain.channel');
156+
} on RustValidationException {
157+
throw const RustValidationException([
158+
'''
159+
The rust-toolchain.toml file must specify the `toolchain.channel` field.
160+
For more information, see https://github.com/GregoryConrad/native_toolchain_rs?tab=readme-ov-file#rust-toolchaintoml''',
161+
]);
162+
}
163+
},
164+
() {
165+
try {
166+
return toolchain
167+
.walk<List<dynamic>>('toolchain.targets')
168+
.cast<String>()
169+
.toSet();
170+
} on RustValidationException {
171+
throw const RustValidationException([
172+
'''
173+
The rust-toolchain.toml file must specify the `toolchain.targets` field.
174+
For more information, see https://github.com/GregoryConrad/native_toolchain_rs?tab=readme-ov-file#rust-toolchaintoml''',
175+
]);
176+
}
177+
},
114178
]);
115179

116180
return (channel: channel, targets: targets);

test/crate_info_validator_test.dart

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,18 @@ void main() {
6363
isA<RustValidationException>().having(
6464
(e) => e.validationErrors,
6565
'validationErrors',
66-
containsAll([
67-
'''Cargo.toml must specify [staticlib, cdylib] under lib.crate-types''',
68-
'''Your current channel in rust-toolchain.toml is stable; this is dangerous and consequently is not allowed! Please specify an exact version to fix this issue.''',
69-
'''aarch64-linux-android is not one of the supported targets: {x86_64-linux-gnu}''',
66+
equals([
67+
'''
68+
Your Cargo.toml must specify [staticlib, cdylib] under `lib.crate-types`.
69+
For more information, see https://github.com/GregoryConrad/native_toolchain_rs?tab=readme-ov-file#cargotoml''',
70+
'''
71+
The rust-toolchain.toml is using the `stable` channel, which is not allowed.
72+
Please specify an exact version (e.g., `1.90.0`) to ensure a reproducible build.
73+
For more information, see https://github.com/GregoryConrad/native_toolchain_rs?tab=readme-ov-file#rust-toolchaintoml''',
74+
'''
75+
The rust-toolchain.toml does not include the target `aarch64-linux-android`.
76+
If you wish to support this target, please add it to the `targets` array in the rust-toolchain.toml file.
77+
For more information, see https://github.com/GregoryConrad/native_toolchain_rs?tab=readme-ov-file#rust-toolchaintoml''',
7078
]),
7179
),
7280
),

0 commit comments

Comments
 (0)