docspec
docspec copied to clipboard
Better Qualified Name (QNAME)
The current spec draft defines QNAME for the following:
- STRUCT: namespace + config.namespacedelimiter + name
- FUNCTION: namespace + '#' + name
- METHOD: namespace + config.namespacedelimiter + STRUCT.name + '#' + name
Two things I'm not 100% lucky with:
- The hash as delimiter: Often is that QNAME turns into uris that are also used in urls with html output and then the hash is a reserved keyword here. So it must be taken with care to use it for the good. Can some of the DocTools developers give good use cases?
- More QNAMEs: I'd like to see at least, that params are expressed by a unique identifier. What else?
similar to what I suggested on issue #2, I think the docspec should refrain from defining textual formats as much as possible. I think the choice of files as the top level container of all other objects is adding unnecessary complexity to the spec.
In the semantics of most languages/runtimes you address code by namespace and the file a piece of code comes from is really just metadata about that piece of code. I propose that in combination with my suggestion to nest namespaces, we make NAMESPACE the container for classes/interfaces/traits/functions/constants/variables and add a "filename" attribute into the COMMON part of the spec. The FILE objects would remain with their other properties (e.g. version is very useful)
Bringing this back on topic: this would make the QNAMEs redundant, except for referring to specific objects. I would then suggest that QNAMEs become a data structure made up of a list of namespaces, an object type, and optionally a list of parent objects (in the case of methods, you would have a list of one name that is the class the method is defined in). Here is an example:
QNAME
// A QNAME pointed at the "action" method of the "Widget" class in the foo.bar namespace
{
"namespace": ["foo", "bar"],
"type": "method",
"name": "action",
"parents": ["Widget"]
}
// QNAME pointed at the parameter named "$user" of the same method
{
"namespace": ["foo", "bar"],
"type": "parameter"
"name": "$user",
"parents": ["Widget", "action"],
}
As a lighter alternative, we could define QNAME's as simply a list of property names that walks through the json object starting at the root namespace:
["namespaces", "foo", "namespaces", "bar", "classes", "Widget", "methods", "action", "parameters", "$user"]
In either case it would up to the parsers to read a string like foo\bar\Widget::action($user) in a doc comment and transform it into the canonical form that all output formatters could understand. (That canonical form being the QNAME datastructure).
That went quite a bit longer than I expected... what do you think?
With that object it is more a QOBJECT instead of a QNAME. The benefit of the QNAME (and to have it as a key in the JSON format - which may look duplicated in the first view) is to uniquely identify a symbol with a string. With the QNAME as key it is possible that output generators can create an (internal) index. Lookups can be done in the key-value-map, anyway you need to traverse the docspec format for each lookup (well you can use cache internally, true). The second benefit is, that symbols are often used in urls (see above), which isn't possible with QOBJECT.
That's why I favor the QNAME format for now. Or do I miss something here?
The names are still unique, they are just organized into a hierarchy instead of a flat mapping. I don't think the speed difference in lookups is worth worrying about, and if it is, caching the paths is simple. I might be missing something, but I don't see how this precludes the building of an index by output generators...
Regarding URLs, they would surely be produced by the output formatter anyways, so it makes more sense to not have object name set as a string. E.g. an output formatter could more easily produce the following html if it didn't have to parse and re-format a string representation of the name.
<div id="foo-bar-classes-widget-methods-action">
<h2>\foo\bar#Widget::action($user)</h2>
<p id="foo-bar-classes-widget-methods-action__summary">...</p>
<dl class="parameters">
<dt class="parameter name" id="foo-bar-classes-widget-methods-action-parameters-_S_user">$user</dt>
<dd class="parameter desc">The user to perform the action with</dd>
</dl>
</div>
edit: had an incomplete sentence in there