--- /dev/null
+//! Completion for representations.
+
+use syntax::ast;
+
+use crate::{
+ context::CompletionContext,
+ item::{CompletionItem, CompletionItemKind, CompletionKind},
+ Completions,
+};
+
+pub(super) fn complete_repr(
+ acc: &mut Completions,
+ ctx: &CompletionContext,
+ derive_input: ast::TokenTree,
+) {
+ if let Some(existing_reprs) = super::parse_comma_sep_input(derive_input) {
+ for repr_completion in REPR_COMPLETIONS {
+ if existing_reprs
+ .iter()
+ .any(|it| repr_completion.label == it || repr_completion.collides.contains(&&**it))
+ {
+ continue;
+ }
+ let mut item = CompletionItem::new(
+ CompletionKind::Attribute,
+ ctx.source_range(),
+ repr_completion.label,
+ );
+ item.kind(CompletionItemKind::Attribute);
+ if let Some(lookup) = repr_completion.lookup {
+ item.lookup_by(lookup);
+ }
+ if let Some((snippet, cap)) = repr_completion.snippet.zip(ctx.config.snippet_cap) {
+ item.insert_snippet(cap, snippet);
+ }
+ item.add_to(acc);
+ }
+ }
+}
+
+struct ReprCompletion {
+ label: &'static str,
+ snippet: Option<&'static str>,
+ lookup: Option<&'static str>,
+ collides: &'static [&'static str],
+}
+
+const fn attr(label: &'static str, collides: &'static [&'static str]) -> ReprCompletion {
+ ReprCompletion { label, snippet: None, lookup: None, collides }
+}
+
+#[rustfmt::skip]
+const REPR_COMPLETIONS: &[ReprCompletion] = &[
+ ReprCompletion { label: "align($0)", snippet: Some("align($0)"), lookup: Some("align"), collides: &["transparent", "packed"] },
+ attr("packed", &["transparent", "align"]),
+ attr("transparent", &["C", "u8", "u16", "u32", "u64", "u128", "usize", "i8", "i16", "i32", "i64", "i128", "isize"]),
+ attr("C", &["transparent"]),
+ attr("u8", &["transparent", "u16", "u32", "u64", "u128", "usize", "i8", "i16", "i32", "i64", "i128", "isize"]),
+ attr("u16", &["transparent", "u8", "u32", "u64", "u128", "usize", "i8", "i16", "i32", "i64", "i128", "isize"]),
+ attr("u32", &["transparent", "u8", "u16", "u64", "u128", "usize", "i8", "i16", "i32", "i64", "i128", "isize"]),
+ attr("u64", &["transparent", "u8", "u16", "u32", "u128", "usize", "i8", "i16", "i32", "i64", "i128", "isize"]),
+ attr("u128", &["transparent", "u8", "u16", "u32", "u64", "usize", "i8", "i16", "i32", "i64", "i128", "isize"]),
+ attr("usize", &["transparent", "u8", "u16", "u32", "u64", "u128", "i8", "i16", "i32", "i64", "i128", "isize"]),
+ attr("i8", &["transparent", "u8", "u16", "u32", "u64", "u128", "usize", "i16", "i32", "i64", "i128", "isize"]),
+ attr("i16", &["transparent", "u8", "u16", "u32", "u64", "u128", "usize", "i8", "i32", "i64", "i128", "isize"]),
+ attr("i32", &["transparent", "u8", "u16", "u32", "u64", "u128", "usize", "i8", "i16", "i64", "i128", "isize"]),
+ attr("i64", &["transparent", "u8", "u16", "u32", "u64", "u128", "usize", "i8", "i16", "i32", "i128", "isize"]),
+ attr("i28", &["transparent", "u8", "u16", "u32", "u64", "u128", "usize", "i8", "i16", "i32", "i64", "isize"]),
+ attr("isize", &["transparent", "u8", "u16", "u32", "u64", "u128", "usize", "i8", "i16", "i32", "i64", "i128"]),
+];
+
+#[cfg(test)]
+mod tests {
+ use expect_test::{expect, Expect};
+
+ use crate::tests::completion_list;
+
+ fn check(ra_fixture: &str, expect: Expect) {
+ let actual = completion_list(ra_fixture);
+ expect.assert_eq(&actual);
+ }
+
+ #[test]
+ fn no_completion_for_incorrect_repr() {
+ check(r#"#[repr{$0)] struct Test;"#, expect![[]])
+ }
+
+ #[test]
+ fn empty() {
+ check(
+ r#"#[repr($0)] struct Test;"#,
+ expect![[r#"
+ at align($0)
+ at packed
+ at transparent
+ at C
+ at u8
+ at u16
+ at u32
+ at u64
+ at u128
+ at usize
+ at i8
+ at i16
+ at i32
+ at i64
+ at i28
+ at isize
+ "#]],
+ );
+ }
+
+ #[test]
+ fn transparent() {
+ check(r#"#[repr(transparent, $0)] struct Test;"#, expect![[r#""#]]);
+ }
+
+ #[test]
+ fn align() {
+ check(
+ r#"#[repr(align(1), $0)] struct Test;"#,
+ expect![[r#"
+ at align($0)
+ at transparent
+ at C
+ at u8
+ at u16
+ at u32
+ at u64
+ at u128
+ at usize
+ at i8
+ at i16
+ at i32
+ at i64
+ at i28
+ at isize
+ "#]],
+ );
+ }
+
+ #[test]
+ fn packed() {
+ check(
+ r#"#[repr(packed, $0)] struct Test;"#,
+ expect![[r#"
+ at transparent
+ at C
+ at u8
+ at u16
+ at u32
+ at u64
+ at u128
+ at usize
+ at i8
+ at i16
+ at i32
+ at i64
+ at i28
+ at isize
+ "#]],
+ );
+ }
+
+ #[test]
+ fn c() {
+ check(
+ r#"#[repr(C, $0)] struct Test;"#,
+ expect![[r#"
+ at align($0)
+ at packed
+ at u8
+ at u16
+ at u32
+ at u64
+ at u128
+ at usize
+ at i8
+ at i16
+ at i32
+ at i64
+ at i28
+ at isize
+ "#]],
+ );
+ }
+
+ #[test]
+ fn prim() {
+ check(
+ r#"#[repr(usize, $0)] struct Test;"#,
+ expect![[r#"
+ at align($0)
+ at packed
+ at C
+ "#]],
+ );
+ }
+}