MCPcopy Create free account
hub / github.com/clockworklabs/SpacetimeDB / parse

Method parse

crates/bindings-macro/src/table.rs:78–192  ·  view source on GitHub ↗
(input: TokenStream, struct_ident: &Ident)

Source from the content-addressed store, hash-verified

76
77impl TableArgs {
78 pub(crate) fn parse(input: TokenStream, struct_ident: &Ident) -> syn::Result<Self> {
79 let mut access = None;
80 let mut scheduled = None;
81 let mut accessor = None;
82 let mut name: Option<LitStr> = None;
83 let mut indices = Vec::new();
84 let mut event = None;
85 syn::meta::parser(|meta| {
86 match_meta!(match meta {
87 sym::public => {
88 check_duplicate_msg(&access, &meta, "already specified access level")?;
89 access = Some(TableAccess::Public(meta.path.span()));
90 }
91 sym::private => {
92 check_duplicate_msg(&access, &meta, "already specified access level")?;
93 access = Some(TableAccess::Private(meta.path.span()));
94 }
95 sym::accessor => {
96 check_duplicate(&accessor, &meta)?;
97 let value = meta.value()?;
98 accessor = Some(value.parse()?);
99 }
100 sym::name => {
101 check_duplicate(&name, &meta)?;
102 let value = meta.value()?;
103 // `fork` as a way to do lookahead `peek`, so that below when we parse as the `LitStr` we actually want,
104 // it works.
105 if let Ok(sym) = value.fork().parse::<Ident>() {
106 // The update from SpacetimeDB 1.* to 2.* changes `name =` to `accessor =`,
107 // and uses `name =` for a different thing. Now, only `accessor =` is mandatory,
108 // and `name =` accepts a string literal rather than an identifier.
109 // Detect the specific case where the user specifies a 1.*-style `name = ident`,
110 // and offer a diagnostic with a simple migration path.
111 // Unfortunately, we can't hook in to rustc's system for providing quick fixes in compiler errors,
112 // until [this ancient issue](https://github.com/rust-lang/rust/issues/54140) gets stabilized.
113 return Err(
114 if accessor.is_some() {
115 // If we've already encountered an `accessor`,
116 // then probably the user is actually trying to overwrite the `name`,
117 // so tell them to use a string literal instead of an ident.
118 // This is a best-effort check, and we won't hit it if the user specifies `name` first,
119 // but we're prioritizing the migration UX here.
120 meta.error(format_args!(
121 "Expected a string literal for `name`, but found an identifier.
122
123To overwrite the canonical name of the table, replace `name = {sym}` with `name = \"{sym}\"`."
124 ))
125 } else {
126 // FIXME: Ideally, this error span would point to the full pair `name = my_table`,
127 // but I (pgoldman 2026-02-18) can only figure out how to get it at either `name` or `my_table`.
128 // This version points at `name`, which, :shrug:.
129 // Note that, if the user specifies `name = {ident}` followed by `accessor = {ident}`,
130 // we'll hit this branch, even though the diagnostic doesn't apply and we'd prefer not to.
131 // I (pgoldman 2026-02-18) don't see a good way to distinguish this case
132 // without making our parsing dramatically more complicated,
133 // and it seems unlikely to occur.
134 meta.error(format_args!(
135 "Expected a string literal for `name`, but found an identifier. Did you mean to specify an `accessor`?

Callers 15

parse_schemeFunction · 0.45
make_uri_implFunction · 0.45
defaultRouteFromFileFunction · 0.45
mainFunction · 0.45
deserializeMethod · 0.45
pid_fileMethod · 0.45
dateMethod · 0.45
read_tokenMethod · 0.45
api_call_internalMethod · 0.45

Calls 10

UniqueFunction · 0.85
PrimaryKeyInterface · 0.85
parse_default_attrFunction · 0.85
spanMethod · 0.80
newFunction · 0.50
OkFunction · 0.50
IndexClass · 0.50
valueMethod · 0.45
to_stringMethod · 0.45
pathMethod · 0.45