Skip to content

Commit 1d79e8b

Browse files
committed
add code str macro for inline literals
1 parent a9ca67f commit 1d79e8b

1 file changed

Lines changed: 50 additions & 63 deletions

File tree

dioxus-code-macro/src/lib.rs

Lines changed: 50 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -277,101 +277,78 @@ fn language_variant_for_slug(slug: &str) -> Option<&'static str> {
277277
fn expand_code(input: CodeInput) -> syn::Result<TokenStream2> {
278278
let manifest_dir = env::var("CARGO_MANIFEST_DIR")
279279
.map_err(|error| syn::Error::new(Span::call_site(), error.to_string()))?;
280-
let manifest_dir = PathBuf::from(manifest_dir);
281-
let macro_path = input.path;
282-
let absolute_path = resolve_manifest_path(&manifest_dir, &macro_path);
283-
let crate_path = dioxus_code_crate_path()?;
284-
285-
let options_check = options_check_tokens(&crate_path, input.options.as_ref());
286-
280+
let absolute_path = resolve_manifest_path(&PathBuf::from(manifest_dir), &input.path);
287281
let source = fs::read_to_string(&absolute_path).map_err(|error| {
288282
syn::Error::new(
289283
Span::call_site(),
290284
format!("failed to read `{}`: {error}", absolute_path.display()),
291285
)
292286
})?;
293287

294-
let Some(language) = input
295-
.options
296-
.as_ref()
297-
.and_then(try_extract_language)
298-
.or_else(|| arborium::detect_language(&macro_path).map(str::to_string))
299-
else {
300-
let message = format!(
301-
"could not detect language for `{macro_path}`; pass `CodeOptions::builder().with_language(Language::Rust)`"
302-
);
303-
return Ok(quote! {{
304-
#options_check
305-
compile_error!(#message);
306-
}});
307-
};
308-
309-
let absolute_lit = LitStr::new(&absolute_path.to_string_lossy(), Span::call_site());
310-
let source_decl = quote! { const SOURCE: &str = include_str!(#absolute_lit); };
311-
312-
expand_highlighted_source(&crate_path, options_check, source_decl, &language, &source)
288+
expand_shared(input.options, source, Some(absolute_path))
313289
}
314290

315291
fn expand_code_str(input: CodeStrInput) -> syn::Result<TokenStream2> {
316-
let crate_path = dioxus_code_crate_path()?;
317-
let options_check = options_check_tokens(&crate_path, input.options.as_ref());
292+
expand_shared(input.options, input.source, None)
293+
}
318294

319-
let Some(language) = input.options.as_ref().and_then(try_extract_language) else {
320-
let message =
321-
"could not determine language for `code_str!`; pass `CodeOptions::builder().with_language(Language::Rust)`";
295+
fn expand_shared(
296+
options: Option<Expr>,
297+
source: String,
298+
origin_path: Option<PathBuf>,
299+
) -> syn::Result<TokenStream2> {
300+
let crate_path = dioxus_code_crate_path()?;
301+
let options_check = options_check_tokens(&crate_path, options.as_ref());
302+
303+
let Some(language) = options.as_ref().and_then(try_extract_language).or_else(|| {
304+
origin_path
305+
.as_ref()
306+
.and_then(|path| arborium::detect_language(&path.to_string_lossy()).map(str::to_string))
307+
}) else {
308+
let message = match origin_path.as_ref() {
309+
Some(path) => format!(
310+
"could not detect language for `{}`; pass `CodeOptions::builder().with_language(Language::Rust)`",
311+
path.display()
312+
),
313+
None => String::from(
314+
"could not determine language for `code_str!`; pass `CodeOptions::builder().with_language(Language::Rust)`",
315+
),
316+
};
322317
return Ok(quote! {{
323318
#options_check
324319
compile_error!(#message);
325320
}});
326321
};
327322

328-
let source_lit = LitStr::new(&input.source, Span::call_site());
329-
let source_decl = quote! { const SOURCE: &str = #source_lit; };
330-
331-
expand_highlighted_source(
332-
&crate_path,
333-
options_check,
334-
source_decl,
335-
&language,
336-
&input.source,
337-
)
338-
}
339-
340-
fn options_check_tokens(crate_path: &TokenStream2, options: Option<&Expr>) -> Option<TokenStream2> {
341-
options.map(|expr| {
342-
quote_spanned! { expr.span() =>
343-
const _: fn() = || {
344-
let _: #crate_path::CodeOptions = #expr;
345-
};
346-
}
347-
})
348-
}
349-
350-
fn expand_highlighted_source(
351-
crate_path: &TokenStream2,
352-
options_check: Option<TokenStream2>,
353-
source_decl: TokenStream2,
354-
language: &str,
355-
source: &str,
356-
) -> syn::Result<TokenStream2> {
357323
let mut highlighter = arborium::Highlighter::new();
358324
let spans = highlighter
359-
.highlight_spans(language, source)
325+
.highlight_spans(&language, &source)
360326
.map_err(|error| syn::Error::new(Span::call_site(), error.to_string()))?;
361327

362-
let Some(variant) = language_variant_for_slug(language) else {
328+
let Some(variant) = language_variant_for_slug(&language) else {
363329
let message = format!("language `{language}` has no `Language` variant");
364330
return Ok(quote! {{
365331
#options_check
366332
compile_error!(#message);
367333
}});
368334
};
369335
let variant_ident = Ident::new(variant, Span::call_site());
336+
337+
let source_decl = match origin_path {
338+
Some(path) => {
339+
let path_lit = LitStr::new(&path.to_string_lossy(), Span::call_site());
340+
quote! { const SOURCE: &str = include_str!(#path_lit); }
341+
}
342+
None => {
343+
let source_lit = LitStr::new(&source, Span::call_site());
344+
quote! { const SOURCE: &str = #source_lit; }
345+
}
346+
};
347+
370348
let span_tokens = normalize_spans(spans).into_iter().map(|span| {
371349
let start = span.start;
372350
let end = span.end;
373351
let tag = LitStr::new(span.tag, Span::call_site());
374-
375352
quote! {
376353
#crate_path::advanced::HighlightSpan::new(#start..#end, #tag)
377354
}
@@ -389,6 +366,16 @@ fn expand_highlighted_source(
389366
}})
390367
}
391368

369+
fn options_check_tokens(crate_path: &TokenStream2, options: Option<&Expr>) -> Option<TokenStream2> {
370+
options.map(|expr| {
371+
quote_spanned! { expr.span() =>
372+
const _: fn() = || {
373+
let _: #crate_path::CodeOptions = #expr;
374+
};
375+
}
376+
})
377+
}
378+
392379
struct NormalizedSpan {
393380
start: u32,
394381
end: u32,

0 commit comments

Comments
 (0)