From: Markus Armbruster <armbru@redhat.com>
To: John Snow <jsnow@redhat.com>
Cc: qemu-devel@nongnu.org, Konstantin Kostiuk <kkostiuk@redhat.com>,
Peter Maydell <peter.maydell@linaro.org>,
Eric Blake <eblake@redhat.com>,
qemu-block@nongnu.org, Michael Roth <michael.roth@amd.com>,
Kevin Wolf <kwolf@redhat.com>
Subject: Re: [PATCH 07/11] docs/qapi_domain: add namespace support to cross-references
Date: Thu, 13 Mar 2025 16:57:32 +0100 [thread overview]
Message-ID: <87o6y43our.fsf@pond.sub.org> (raw)
In-Reply-To: <CAFn=p-b8xsWJw4kROKFUDbBNuJU32_oyktUMB+F5gsE=M9S72w@mail.gmail.com> (John Snow's message of "Thu, 13 Mar 2025 11:10:33 -0400")
John Snow <jsnow@redhat.com> writes:
> On Thu, Mar 13, 2025 at 10:41 AM Markus Armbruster <armbru@redhat.com>
> wrote:
>
>> John Snow <jsnow@redhat.com> writes:
>>
>> > On Thu, Mar 13, 2025 at 2:47 AM Markus Armbruster <armbru@redhat.com> wrote:
>> >
>> >> John Snow <jsnow@redhat.com> writes:
>> >>
>> >> > This patch does three things:
>> >> >
>> >> > 1. Record the current namespace context in pending_xrefs so it can be
>> >> > used for link resolution later,
>> >> > 2. Pass that recorded namespace context to find_obj() when resolving a
>> >> > reference, and
>> >> > 3. Wildly and completely rewrite find_obj().
>> >> >
>> >> > cross-reference support is expanded to tolerate the presence or absence
>> >> > of either namespace or module, and to cope with the presence or absence
>> >> > of contextual information for either.
>> >> >
>> >> > References now work like this:
>> >> >
>> >> > 1. If the explicit reference target is recorded in the domain's object
>> >> > registry, we link to that target and stop looking. We do this lookup
>> >> > regardless of how fully qualified the target is, which allows direct
>> >> > references to modules (which don't have a module component to their
>> >> > names) or direct references to definitions that may or may not belong
>> >> > to a namespace or module.
>> >> >
>> >> > 2. If contextual information is available from qapi:namespace or
>> >> > qapi:module directives, try using those components to find a direct
>> >> > match to the implied target name.
>> >> >
>> >> > 3. If both prior lookups fail, generate a series of regular expressions
>> >> > looking for wildcard matches in order from most to least
>> >> > specific. Any explicitly provided components (namespace, module)
>> >> > *must* match exactly, but both contextual and entirely omitted
>> >> > components are allowed to differ from the search result. Note that if
>> >> > more than one result is found, Sphinx will emit a warning (a build
>> >> > error for QEMU) and list all of the candidate references.
>> >> >
>> >> > The practical upshot is that in the large majority of cases, namespace
>> >> > and module information is not required when creating simple `references`
>> >> > to definitions from within the same context -- even when identical
>> >> > definitions exist in other contexts.
>> >>
>> >> Can you illustrate this this examples?
>> >>
>> >
>> > do wha?
>>
>> Sorry, I went into the curve too fast.
>>
>> The stuff under "References now work like this" confuses me. I guess it
>> describes a series of lookups to try one after the other.
>>
>> I understand a cross-reference consists of namespace (optional), module
>> (optional), name, and role.
>>
>> Let's assume role is "any" for simplicity's sake.
>>
>> Regarding "1. If the explicit ...":
>>
>> What is a reference's "explicit reference target"? Examples might
>> help me understand.
>>
>
> explicit lookup: `QMP:block-core:block-dirty-bitmap-add`
>
> If that explicit target matches an object in the object database
> *directly*, we match immediately and don't consider other potential
> targets. This also applies to things like modules, e.g. `QMP:block-core`
> even though the "module" is absent (it IS the module)
>
> We always search for the explicit target no matter how un/fully qualified
> it is.
>
>
>>
>> What is "recorded in the domain's object registry"?
>>
>
> domain.objects{} - essentially a record of every ObjectDefinition's
> "fullname" - the return value from QAPIDefinition._get_fqn().
>
>
>>
>> Can you show me a reference where this lookup succeeds?
>>
>
> `QMP:block-core`
> `QMP:block-core.block-dirty-bitmap-add`
So, for this lookup to work, the reference must either be of the form
NAMESPACE:MODULE and resolve to that module in that namespace, or of the
form NAMESPACE:MODULE:DEFN and resolve to that definition in that module
in that namespace. Correct?
These a "fully qualified names (FQN)" in your parlance, right?
Note that the first form is syntactically indistinguishable from
NAMESPACE:DEFN, i.e. a reference to a definition that specifies the
namespace, but not the module.
If the NAMESPACE:MODULE interpretation resolves, we never try the
NAMESPACE:DEFN interpretation, because that happens in later steps.
Correct?
The first form is fully qualified only if it resolves as FQN. So,
whether such a reference is fully qualified is not syntactically
decidable. Hmm.
>> Regarding "2. If contextual information ...":
>>
>> I guess "contextual information" is the context established by
>> qapi:namespace and qapi:module directives, i.e. the current
>> namespace and module, if any.
>>
>
> Yep!
>
>
>>
>> If the cross reference lacks a namespace, we substitute the current
>> namespace. Same for module.
>>
>> We then use that "to find a direct match to the implied target
>> name". Sounds greek to me. Example(s) might help.
>>
>
> If namespace or module is missing from the link target, we try to fill in
> the blanks with the contextual information if present.
>
> Example, we are in the block-core section of the QEMU QMP reference manual
> document and we reference `block-dirty-bitmap-add`. With context, we are
> able to assemble a fully qualified name:
> "QMP:block-core.block-dirty-bitmap-add`. This matches an item in the
> registry directly, so it matches and no further search is performed.
We try this lookup only when the reference lacks a namespace and we are
"in" a namespace, or when it lacks a module and we are "in" a module.
Correct?
We then subsitute current namespace / module for the lacking one(s), and
try the same lookup as in 1. Correct?
If we have a reference of the form MYSTERY, it could either be a
reference to module MYSTERY in the current namespace, or to definition
MYSTERY in the current namespace and module. How do we decide?
>> Regarding "3. If both prior lookups fail ...":
>>
>> I guess we get here when namespace or module are absent, and
>> substituting the current namespace or module doesn't resolve. We
>> then substitute a wildcard, so to speak, i.e. look in all namespaces
>> / modules, and succeed if we find exactly one resolution. Fair?
>>
>
> More or less, though the mechanics are quite a bit more complex than your
> overview (and what I wrote in qapi-domain.rst.) We can get here for a few
> reasons:
>
> (1) We didn't provide a fully qualified target, and we don't have full
> context to construct one. For example, we are not "in" a namespace and/or
> not "in" a module. This is quite likely to happen when writing simple
> references to a definition name from outside of the transmogfrified QAPI
> documentation, e.g. from qapi-domain.rst itself, or dirty-bitmaps.rst, etc.
>
> (2) We didn't provide a fully qualified target, and we are referencing
> something from outside of the local context. For example, we are "in" a
> module but we are trying to link to a different module's definition. e.g.
> we are in QMP:transaction and we reference `block-dirty-bitmap-add`. The
> implied FQN will be QMP:transaction.block-dirty-bitmap.add, which will not
> resolve.
>
> The fuzzy search portion has an order of precedence for how it searches -
> and not all searches are tried universally, they are conditional to what
> was provided in the reference target and what context is available.
>
> 1. match against the explicitly provided namespace (module was not
> explicitly provided)
Look for the name in all of the namespace's modules?
> 2. match against the explicitly provided module (namespace was not
> explicitly provided)
Look for the name in all modules so named in all namespaces?
> 3. match against the implied namespace (neither namespace/module was
> explicitly provided)
?
> 4. match against the implied module (neither namespace/module was
> explicitly provided)
?
> 5. match against the definition name only, from anywhere (neither
> namespace/module was explicitly provided)
Look for the name anywhere?
I need examples :)
> The searches are performed in order: if a search returns zero results, the
> next search is tried. If any search returns one or more results, those
> results are returned and we stop searching down the list. The priority
> order ensures that any explicitly provided information is *always* used to
> find a match, but contextually provided information is merely a "hint" and
> can be ignored for the sake of a match.
>
> If find_obj() as a whole returns zero results, Sphinx emits a warning for a
> dangling reference. if find_obj() as a whole returns multiple results,
> Sphinx emits a warning for the ambiguous cross-reference.
>
> QEMU errors out on any such warnings under our normal build settings.
>
> Clear as mud?
Clearer, but not quite mud, yet.
> --js
>
>
>> [...]
>>
>>
next prev parent reply other threads:[~2025-03-13 15:58 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-03-13 4:43 [PATCH 00/11] docs/qapi: enable new guest-agent and storage-daemon docs John Snow
2025-03-13 4:43 ` [PATCH 01/11] docs/qapi_domain: isolate TYPE_CHECKING imports John Snow
2025-03-13 4:43 ` [PATCH 02/11] docs/qapi-domain: always store fully qualified name in signode John Snow
2025-03-13 4:43 ` [PATCH 03/11] docs/qapi_domain: add namespace support to FQN John Snow
2025-03-13 4:43 ` [PATCH 04/11] docs/qapi-domain: add :namespace: override option John Snow
2025-03-13 6:39 ` Markus Armbruster
2025-03-13 13:55 ` John Snow
2025-03-13 4:43 ` [PATCH 05/11] docs/qapi-domain: add qapi:namespace directive John Snow
2025-03-13 4:43 ` [PATCH 06/11] docs/qapidoc: add :namespace: option to qapi-doc directive John Snow
2025-03-13 4:43 ` [PATCH 07/11] docs/qapi_domain: add namespace support to cross-references John Snow
2025-03-13 6:47 ` Markus Armbruster
2025-03-13 13:58 ` John Snow
2025-03-13 14:40 ` Markus Armbruster
2025-03-13 15:10 ` John Snow
2025-03-13 15:57 ` Markus Armbruster [this message]
2025-03-13 16:57 ` John Snow
2025-03-13 18:30 ` Markus Armbruster
2025-03-13 18:59 ` John Snow
2025-03-14 7:08 ` Markus Armbruster
2025-03-14 7:20 ` Markus Armbruster
2025-03-13 4:43 ` [PATCH 08/11] docs/qapi-domain: add namespaced index support John Snow
2025-03-14 8:06 ` Markus Armbruster
2025-03-13 4:43 ` [PATCH 09/11] docs: add QAPI namespace "QMP" to qemu-qmp-ref John Snow
2025-03-14 7:27 ` Markus Armbruster
2025-03-13 4:43 ` [PATCH 10/11] docs: disambiguate references in qapi-domain.rst John Snow
2025-03-13 4:43 ` [PATCH 11/11] docs: enable transmogrifier for QSD and QGA John Snow
2025-03-13 6:54 ` Markus Armbruster
2025-03-13 14:02 ` John Snow
2025-03-13 15:27 ` Markus Armbruster
2025-03-14 9:21 ` [PATCH 00/11] docs/qapi: enable new guest-agent and storage-daemon docs Markus Armbruster
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87o6y43our.fsf@pond.sub.org \
--to=armbru@redhat.com \
--cc=eblake@redhat.com \
--cc=jsnow@redhat.com \
--cc=kkostiuk@redhat.com \
--cc=kwolf@redhat.com \
--cc=michael.roth@amd.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.