Open octogonz opened 6 years ago
@rbuckton has been working on a simplification of the declaration syntax that also makes it more consistent with JSDoc namepaths.
The initial work is committed here:
And a bunch of examples can be found by searching for "canonicalReference"
in PR microsoft/web-build-tools#1406 which updates API Extractor to generate this experimental notation in its .api.json output (without affecting the TSDoc input for now).
[...] How to handle this?
Just link to disambiguation page and the problem is solved.
export class A {
public b: string = 'hello';
}
export namespace A {
export let b: number = 123;
}
let a = new A();
// a.b is a string
// A.b is a number
[...] How to handle this?
Just link to disambiguation page and the problem is solved.
FYI @rbuckton's updated syntax uses different operators to disambiguate them:
A.b
is the static number
member.A#b
is the instance string
member.But where it is NOT ambiguous (for example because there is no static member), then we won't consider it an error to write A.b
instead of A#b
. This lenient policy should minimize the amount of migration work needed when we release the new syntax.
(Ron has made a lot of progress with overhauling the parser to integrate this new grammar, but it isn't a simple update. It will be a breaking change for the DocDeclarationReference
/ DocMemberReference
parser APIs.)
Will the upcoming private fields readily follow such syntax?
Container.#id
(private static)Container##id
(private instance)Per sec. 4 of the proposal:
This proposal allows both abbreviated references to private state (
#x
) which have an implicitthis
as the receiver, as well as explicit receivers (obj.#x
). The implicit receiver form is intended for better ergonomics for the common case, and the explicit receiver form allows the full generality of "class-private" (as opposed to "instance-private").
Will the upcoming private fields readily follow such syntax?
Do you really think it is necessary to reference hard private Members in documentation? I think code comments as developer documentation should suffice in this case, especially since the referenced target must be declared in the same class in the same source code file and thus should be easy to find.
The syntax to reference instance members by #
and static members by .
is much older than the invention of a #
prefix for private names in ECMAScript.
To me, the only important thing is that the parser must not get confused by the presence of private fields. It is perfectly valid to have a "normal" member and a private-name member of the same base name:
class Foo {
foo = "";
#foo = 123;
/**
* Updates the field {@link Foo#foo}, which is public and of type string.
*/
updateFoo() { ... }
}
Is the tsdoc project still being actively worked on? Seems like many items from the tsdoc website/spec reference things like this one that are not complete but have been open for several years now... for this one, five years! Does anyone know the status of the tsdoc project overall?
@GitMurf The TSDoc project is still actively supported, but for some time there has not been much progress on new features. TSDoc is maintained by Rush Stack, along with API Extractor which relies very heavily on the TSDoc system. Unfortunately we have not be able to prioritize development of TSDoc because the current implementation already meets the needs of API Extractor very well. Every time TSDoc comes up, I want so badly to come work on it, but unfortunately some other project always seems to have higher priority.
If someone from the community could get involved and help push TSDoc along, that would be really great. 🙏 TSDoc is a relatively complex project however, so what we need most isn't small PRs, but rather someone with time to learn about the parser and requirements, and maybe help get some of the already existing PRs merged. (If anyone's interested, feel free to contact me.)
Certain tags such as
{@inheritdoc}
contain references to other API items. AEDoc supports two notations for API item references:For internal references, we use:
Example:exportName.memberName
{@inheritdoc BaseWidget.draw}
The ".memberName
" is optional and included e.g. if the API item is a member of a class or interface.For external references, we use:
Example:@scopeName/packageName:exportName.memberName
{@inheritdoc @microsoft/widget-lib:BaseWidget.draw}
The "@scopeName/
" and ".memberName
" are optional. The "@scopeName/
" is used for scoped NPM packages.This might be a reasonable starting point. However, it doesn't consider nesting members such as namespaces (which has turned out to be surprisingly common for legacy SDKs, despite all the downsides and attempts to deprecate them).
Also, AEDoc today overlooks an [interesting edge case](http://www.typescriptlang.org/play/#src=export%20class%20A%20%7B%0D%0A%20%20%20%20public%20b%3A%20string%20%3D%20'hello'%3B%0D%0A%7D%0D%0A%0D%0Aexport%20namespace%20A%20%7B%0D%0A%20%20%20%20export%20let%20b%3A%20number%20%3D%20123%3B%0D%0A%7D%0D%0A%0D%0Alet%20a%20%3D%20new%20A()%3B%0D%0A%0D%0A%2F%2F%20a.b%20is%20a%20string%0D%0A%2F%2F%20A.b%20is%20a%20number):
In this example, an expression such as
{@link A.b}
would be ambiguous. Which declaration is it referring to? How to handle this?