@@ -868,7 +868,7 @@ impl<'tcx> ExtraInfo<'tcx> {
868868
869869#[ derive( Eq , PartialEq , Clone , Debug ) ]
870870pub ( crate ) struct LangString {
871- original : String ,
871+ pub ( crate ) original : String ,
872872 pub ( crate ) should_panic : bool ,
873873 pub ( crate ) no_run : bool ,
874874 pub ( crate ) ignore : Ignore ,
@@ -1158,6 +1158,29 @@ impl<'a, 'tcx> Iterator for TagIterator<'a, 'tcx> {
11581158 }
11591159}
11601160
1161+ fn tokens ( string : & str ) -> impl Iterator < Item = LangStringToken < ' _ > > {
1162+ // Pandoc, which Rust once used for generating documentation,
1163+ // expects lang strings to be surrounded by `{}` and for each token
1164+ // to be proceeded by a `.`. Since some of these lang strings are still
1165+ // loose in the wild, we strip a pair of surrounding `{}` from the lang
1166+ // string and a leading `.` from each token.
1167+
1168+ let string = string. trim ( ) ;
1169+
1170+ let first = string. chars ( ) . next ( ) ;
1171+ let last = string. chars ( ) . last ( ) ;
1172+
1173+ let string =
1174+ if first == Some ( '{' ) && last == Some ( '}' ) { & string[ 1 ..string. len ( ) - 1 ] } else { string } ;
1175+
1176+ string
1177+ . split ( |c| c == ',' || c == ' ' || c == '\t' )
1178+ . map ( str:: trim)
1179+ . map ( |token| token. strip_prefix ( '.' ) . unwrap_or ( token) )
1180+ . filter ( |token| !token. is_empty ( ) )
1181+ . map ( |token| LangStringToken :: LangToken ( token) )
1182+ }
1183+
11611184impl Default for LangString {
11621185 fn default ( ) -> Self {
11631186 Self {
@@ -1208,122 +1231,130 @@ impl LangString {
12081231
12091232 data. original = string. to_owned ( ) ;
12101233
1211- for token in TagIterator :: new ( string, extra) {
1212- match token {
1213- LangStringToken :: LangToken ( "should_panic" ) => {
1214- data. should_panic = true ;
1215- seen_rust_tags = !seen_other_tags;
1216- }
1217- LangStringToken :: LangToken ( "no_run" ) => {
1218- data. no_run = true ;
1219- seen_rust_tags = !seen_other_tags;
1220- }
1221- LangStringToken :: LangToken ( "ignore" ) => {
1222- data. ignore = Ignore :: All ;
1223- seen_rust_tags = !seen_other_tags;
1224- }
1225- LangStringToken :: LangToken ( x) if x. starts_with ( "ignore-" ) => {
1226- if enable_per_target_ignores {
1227- ignores. push ( x. trim_start_matches ( "ignore-" ) . to_owned ( ) ) ;
1234+ let mut call = |tokens : & mut dyn Iterator < Item = LangStringToken < ' _ > > | {
1235+ for token in tokens {
1236+ match token {
1237+ LangStringToken :: LangToken ( "should_panic" ) => {
1238+ data. should_panic = true ;
12281239 seen_rust_tags = !seen_other_tags;
12291240 }
1230- }
1231- LangStringToken :: LangToken ( "rust" ) => {
1232- data. rust = true ;
1233- seen_rust_tags = true ;
1234- }
1235- LangStringToken :: LangToken ( "custom" ) => {
1236- if custom_code_classes_in_docs {
1237- seen_custom_tag = true ;
1238- } else {
1239- seen_other_tags = true ;
1241+ LangStringToken :: LangToken ( "no_run" ) => {
1242+ data. no_run = true ;
1243+ seen_rust_tags = !seen_other_tags;
12401244 }
1241- }
1242- LangStringToken :: LangToken ( "test_harness" ) => {
1243- data. test_harness = true ;
1244- seen_rust_tags = !seen_other_tags || seen_rust_tags;
1245- }
1246- LangStringToken :: LangToken ( "compile_fail" ) => {
1247- data. compile_fail = true ;
1248- seen_rust_tags = !seen_other_tags || seen_rust_tags;
1249- data. no_run = true ;
1250- }
1251- LangStringToken :: LangToken ( x) if x. starts_with ( "edition" ) => {
1252- data. edition = x[ 7 ..] . parse :: < Edition > ( ) . ok ( ) ;
1253- }
1254- LangStringToken :: LangToken ( x)
1255- if allow_error_code_check && x. starts_with ( 'E' ) && x. len ( ) == 5 =>
1256- {
1257- if x[ 1 ..] . parse :: < u32 > ( ) . is_ok ( ) {
1258- data. error_codes . push ( x. to_owned ( ) ) ;
1245+ LangStringToken :: LangToken ( "ignore" ) => {
1246+ data. ignore = Ignore :: All ;
1247+ seen_rust_tags = !seen_other_tags;
1248+ }
1249+ LangStringToken :: LangToken ( x) if x. starts_with ( "ignore-" ) => {
1250+ if enable_per_target_ignores {
1251+ ignores. push ( x. trim_start_matches ( "ignore-" ) . to_owned ( ) ) ;
1252+ seen_rust_tags = !seen_other_tags;
1253+ }
1254+ }
1255+ LangStringToken :: LangToken ( "rust" ) => {
1256+ data. rust = true ;
1257+ seen_rust_tags = true ;
1258+ }
1259+ LangStringToken :: LangToken ( "custom" ) => {
1260+ if custom_code_classes_in_docs {
1261+ seen_custom_tag = true ;
1262+ } else {
1263+ seen_other_tags = true ;
1264+ }
1265+ }
1266+ LangStringToken :: LangToken ( "test_harness" ) => {
1267+ data. test_harness = true ;
12591268 seen_rust_tags = !seen_other_tags || seen_rust_tags;
1260- } else {
1261- seen_other_tags = true ;
12621269 }
1263- }
1264- LangStringToken :: LangToken ( x) if extra. is_some ( ) => {
1265- let s = x. to_lowercase ( ) ;
1266- if let Some ( ( flag, help) ) = if s == "compile-fail"
1267- || s == "compile_fail"
1268- || s == "compilefail"
1270+ LangStringToken :: LangToken ( "compile_fail" ) => {
1271+ data. compile_fail = true ;
1272+ seen_rust_tags = !seen_other_tags || seen_rust_tags;
1273+ data. no_run = true ;
1274+ }
1275+ LangStringToken :: LangToken ( x) if x. starts_with ( "edition" ) => {
1276+ data. edition = x[ 7 ..] . parse :: < Edition > ( ) . ok ( ) ;
1277+ }
1278+ LangStringToken :: LangToken ( x)
1279+ if allow_error_code_check && x. starts_with ( 'E' ) && x. len ( ) == 5 =>
12691280 {
1270- Some ( (
1271- "compile_fail" ,
1272- "the code block will either not be tested if not marked as a rust one \
1273- or won't fail if it compiles successfully",
1274- ) )
1275- } else if s == "should-panic" || s == "should_panic" || s == "shouldpanic" {
1276- Some ( (
1277- "should_panic" ,
1278- "the code block will either not be tested if not marked as a rust one \
1279- or won't fail if it doesn't panic when running",
1280- ) )
1281- } else if s == "no-run" || s == "no_run" || s == "norun" {
1282- Some ( (
1283- "no_run" ,
1284- "the code block will either not be tested if not marked as a rust one \
1285- or will be run (which you might not want)",
1286- ) )
1287- } else if s == "test-harness" || s == "test_harness" || s == "testharness" {
1288- Some ( (
1289- "test_harness" ,
1290- "the code block will either not be tested if not marked as a rust one \
1291- or the code will be wrapped inside a main function",
1292- ) )
1293- } else {
1294- None
1295- } {
1296- if let Some ( extra) = extra {
1297- extra. error_invalid_codeblock_attr_with_help (
1298- format ! ( "unknown attribute `{x}`. Did you mean `{flag}`?" ) ,
1299- help,
1300- ) ;
1281+ if x[ 1 ..] . parse :: < u32 > ( ) . is_ok ( ) {
1282+ data. error_codes . push ( x. to_owned ( ) ) ;
1283+ seen_rust_tags = !seen_other_tags || seen_rust_tags;
1284+ } else {
1285+ seen_other_tags = true ;
13011286 }
13021287 }
1303- seen_other_tags = true ;
1304- data. unknown . push ( x. to_owned ( ) ) ;
1305- }
1306- LangStringToken :: LangToken ( x) => {
1307- seen_other_tags = true ;
1308- data. unknown . push ( x. to_owned ( ) ) ;
1309- }
1310- LangStringToken :: KeyValueAttribute ( key, value) => {
1311- if custom_code_classes_in_docs {
1312- if key == "class" {
1313- data. added_classes . push ( value. to_owned ( ) ) ;
1314- } else if let Some ( extra) = extra {
1315- extra. error_invalid_codeblock_attr ( format ! (
1316- "unsupported attribute `{key}`"
1317- ) ) ;
1288+ LangStringToken :: LangToken ( x) if extra. is_some ( ) => {
1289+ let s = x. to_lowercase ( ) ;
1290+ if let Some ( ( flag, help) ) = if s == "compile-fail"
1291+ || s == "compile_fail"
1292+ || s == "compilefail"
1293+ {
1294+ Some ( (
1295+ "compile_fail" ,
1296+ "the code block will either not be tested if not marked as a rust one \
1297+ or won't fail if it compiles successfully",
1298+ ) )
1299+ } else if s == "should-panic" || s == "should_panic" || s == "shouldpanic" {
1300+ Some ( (
1301+ "should_panic" ,
1302+ "the code block will either not be tested if not marked as a rust one \
1303+ or won't fail if it doesn't panic when running",
1304+ ) )
1305+ } else if s == "no-run" || s == "no_run" || s == "norun" {
1306+ Some ( (
1307+ "no_run" ,
1308+ "the code block will either not be tested if not marked as a rust one \
1309+ or will be run (which you might not want)",
1310+ ) )
1311+ } else if s == "test-harness" || s == "test_harness" || s == "testharness" {
1312+ Some ( (
1313+ "test_harness" ,
1314+ "the code block will either not be tested if not marked as a rust one \
1315+ or the code will be wrapped inside a main function",
1316+ ) )
1317+ } else {
1318+ None
1319+ } {
1320+ if let Some ( extra) = extra {
1321+ extra. error_invalid_codeblock_attr_with_help (
1322+ format ! ( "unknown attribute `{x}`. Did you mean `{flag}`?" ) ,
1323+ help,
1324+ ) ;
1325+ }
13181326 }
1319- } else {
13201327 seen_other_tags = true ;
1328+ data. unknown . push ( x. to_owned ( ) ) ;
1329+ }
1330+ LangStringToken :: LangToken ( x) => {
1331+ seen_other_tags = true ;
1332+ data. unknown . push ( x. to_owned ( ) ) ;
1333+ }
1334+ LangStringToken :: KeyValueAttribute ( key, value) => {
1335+ if custom_code_classes_in_docs {
1336+ if key == "class" {
1337+ data. added_classes . push ( value. to_owned ( ) ) ;
1338+ } else if let Some ( extra) = extra {
1339+ extra. error_invalid_codeblock_attr ( format ! (
1340+ "unsupported attribute `{key}`"
1341+ ) ) ;
1342+ }
1343+ } else {
1344+ seen_other_tags = true ;
1345+ }
1346+ }
1347+ LangStringToken :: ClassAttribute ( class) => {
1348+ data. added_classes . push ( class. to_owned ( ) ) ;
13211349 }
1322- }
1323- LangStringToken :: ClassAttribute ( class) => {
1324- data. added_classes . push ( class. to_owned ( ) ) ;
13251350 }
13261351 }
1352+ } ;
1353+
1354+ if custom_code_classes_in_docs {
1355+ call ( & mut TagIterator :: new ( string, extra) . into_iter ( ) )
1356+ } else {
1357+ call ( & mut tokens ( string) )
13271358 }
13281359
13291360 // ignore-foo overrides ignore
0 commit comments