-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introduce a syntax for importing elements just for doc comment references #50702
Comments
We obviously can, but I'd prefer not to. We generally try to avoid having tool-specific annotations (or annotations at all, since all annotations are tool specific to some extent) in the platform libraries. Changes to the annotations are driven by the tools, not the library maintainers, which splits the responsibility for maintaining platform libraries into multiple teams. Because platform libraries are hard to change, it also locks the tools into the current implementation. Changing almost anything becomes a breaking change, which can dampen the velocity of tool development. The tool would be locked to SDK minor-version releases for adding any new features, and major versions (or the breaking-change process) for removing or breaking anything. A tool can easily support multiple versions of their own metadata at the same time, but the platform libraries We have (Using a package import to support I would recommend using If enough people think the annotation will be highly valuable to many users, expected to be stable enough to not require frequent updates, and otherwise generally worth it, it's definitely technically possible to add it to We have added other things that are tool-related (like |
I imagine it being used almost never. It's really just for the flutter/engine and flutter/flutter repos. And some users here and there will use it, but I think an order of magnitude less than That leaves us with:
|
Less than |
This doesn't feel like an API that will change much (it mirrors the import mechanism, which is pretty mature syntax), so I don't have a lot of concern about the API needing to wait for major releases to make changes. It's also given meaning by the tools, since it's mostly just metadata, so the tools can evolve around this basic definition without needing the definition itself to change. And, since it's basically the same information as in an import statement, it's not really tool specific: someone could write another documentation system, and they'd still need, and be able to use, this doc import information.
I'd prefer it to be in |
As a counter-point to my other opinion, the one reason to put annotations into platform libraries is that the libraries themselves use those annotations ( Do we expect that platform libraries will want to use the feature? Platform libraries may want to refer to, say I still think making documentation depend on code-level declarations is breaking out of the documentation. Needing a dependency to write comments (and not just on the thing you want to link to) feels like overkill, |
|
My gut feeling is that the most appropriate approach is to put the links inside comments (maybe even require it to be a doc-comment, so If it's an annotation, then it's visible to everybody, whether they need it or not. I'm not particularly worried about parsing. If we can piggy-back on the Dart parser, it's better, but even without it, it's a fairly restricted grammar. If we want full IDE integration, then the analyzer should be able to understand the imports too (and therefore parse them), so that it can correctly link external doc-references in an IDE. I'd prefer to have that no matter what syntax we choose. |
To me, dartdoc is only half, maybe less than half of the story here (this proposal hardly references dartdoc). The main client, in my mind, is analyzer, such that these references inside doc comments are resolved correctly inside the IDE (meaning lots of things: navigation, hover, participation in renames, etc), in static analysis, in code search (GitHub, Kythe, etc) That being said, the singular use is, as you point out, to handle comments, which is not something typical annotation-customers handle. I don't know if the language spec or any other document says what annotations are for, or if their use is encouraged for this purpose or that purpose, but today most annotation use is for code generation (via analyzer APIs) or the analyzer (as its own tool). |
The intended use of annotations is to attach metadata to something. The spec doesn't say any more, because it cannot know. The design of annotations, however, was guided by being used by mirrors. That's why it's important that the value can be created using actual code imported into the current program, because otherwise the value couldn't exist in the program when DartDoc is a little special in this regard in that it's a kind of metadata attached to declarations, intended for a tool to process, that predates annotations. Even if we did have annotations back then, documentation is special, because it's more like text than like structured data. It wouldn't be as convenient if you had to do So, annotations are not amazing, because they impose source dependencies that the production code doesn't need. Putting the dependency into |
I do wish that Dart source files were able to integrate foreign data containers more easily into the language. For instance, it would be nice to have the ability to segregate portions of the file (without needing to prefix every line) to enable things like building the equivalent of a Jupyter notebook or CoLab, where the code is effectively embedded in the documentation instead of the other way around. Or being able to have multiple compilation units in one file, so that you can have unit tests, API documentation example code, and application/framework code co-mingled in the same file in different namespaces, and have the analyzer (and thus IDEs) understand all of them and check them in their respective namespaces/containers. Although, really, that isn't necessarily the purview of the language to define: you could build those things on top of the Dart language as-is with tools (as we've done with dartdoc), and that probably allows better subdivision of responsibility and allows more powerful aggregation of fine grained tools. But it is helpful to be able to attach extra-language metadata in the file to serve as data sources, which is kept in sync with the code, for the tools operate on. The This extra dependency information seems a little different than the comments themselves, however, and more in the analyzer's wheelhouse to resolve. If you want to aggregate small tools or plugins instead of making the analyzer a monolith, it seems reasonable to provide the different symbol lookup namespaces to a documentation-formatting analyzer plugin as input rather than letting the plugin figure it out for itself from its own metadata. Maybe a solution that would keep documentation parsing separate from the main analyzer while not involving the |
Yeah this actually would be all implemented in the parser, just as doc comment references are parsed in the parser. The CFE (I imagine) just drops that stuff on the floor, but it does tokenize it, and we'd apply the same functionality to a doc import directive inside a comment.
I think would be very complicated. We don't provide any APIs for resolving elements. |
Thinking and playing in the parser, I have some notes on the doc comment (
|
If we're using the It makes me wonder just how critical it is for doc imports to be able to extend across multiple lines (or have combinators, prefixes, or configurations, for that matter; I assume we won't support
We probably can, we'd just need to remove the leading |
@yjbanov: I was thinking about this with @gspencergoog, and our latest idea is writing an annotation class in Analyzer can recognize both of the locations of @docImport('package:flutter/foundation.dart', show: ['Widget', 'Elemet']) can have IDE support:
etc. |
Perhaps a can of worms, but sometimes when I use annotations the server recognises, they remind me of some things in .NET where it didn't matter where an I've often wondered if the same could work in Dart. For example if I made my own Each time I see Flutter special cased somewhere, I wonder if someone wanted to make a "Flutter-like" framework, how many places they'd find they can't get the same functionality because of this. Are the reasons that Flutter can't use Btw, I'm curious if just using normal |
Yeah that's nearly what I'm proposing, haha. I think in analyzer we only validate, for example, a
I'm not sure the technicalities behind it, but basically any I'm not even sure why the flutter engine is shipped as
I think the general reason is that IDE support is not good enough to make something a language feature. If it's not even good enough a reason to add to |
Yeah, that's probably fair. I can't remember examples where I'd used this in .NET, but I think they were probably much more specific names than things like Thanks for the extra info! |
I'm coming into this conversation a little late, but the idea of using the @pragma('dartdoc:import', 'package:flutter/material.dart')
import 'dart:convert';
import 'dart:io';
import 'package:path/path.dart' as p;
...
|
If possible, would you want to use class DocImport extends pragma {
const DocImport(String import) : super('dartdoc:import', import);
} (If so, I'll have to remove the |
Wouldn't the pattern above be useful even if not used for DartDoc? I didn't know about |
I'm not sure it's actually useful. I've thought about it some more, and I think it's better to keep Using a It gives you an implementation approach, which is to detect whether the annotation extends In the same code, you could probably just as easily check for whether the annotation was an instance of one of two So, all in all, I don't think subclassing |
FWIW, I was expecting checks to be on the name and thought the subclass was nice just for convenience of the user adding the annotation. If I create a tool @fooTool('xyz') than: @pragma('FooTool', 'xyz') Both should work ( (Note: I don't have any current use cases for pragma so is just me thinking out loud - this idea might be flawed in other ways :-) ) |
As I mentioned before (#50702 (comment)), scanning across multiple single-line comments isn't a problem. We trim the source of the comments to rescan only the portion between square brackets when dealing with doc references, and this wouldn't be any harder. |
I did not change the content of the functions, except the following: * modernized some variable declarations with `var`. * added periods to the end of comments. * privatized most methods. Work towards #50702 Change-Id: I4d63d3ee847316b58fa76c12558767c0825027a9 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/315243 Reviewed-by: Paul Berry <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]> Commit-Queue: Samuel Rawlins <[email protected]>
I suspect we ought to just remove many/all of the remaining simpler parser tests. I glanced at a few, and they do not seem specific to analyzer, so their covered features should be covered by parser tests in _fe_analyzer_shared. #50702 Change-Id: I0e524562f6584145db5e80a154e72ea66090d924 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/316042 Reviewed-by: Konstantin Shcheglov <[email protected]> Commit-Queue: Samuel Rawlins <[email protected]>
Now that comment reference parsing is done entirely in ast_builder, we can simplify the implementation. Work towards #50702 Change-Id: I0650706dfe31542454c7bc9832ec6104c141bd5d Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/316643 Commit-Queue: Samuel Rawlins <[email protected]> Reviewed-by: Paul Berry <[email protected]>
This simplifies comment reference-parsing in this refactor. Basically when a comment reference is discovered, we immediately parse it into a CommentReferenceImpl, instead of passing around the offset from place to place. Additionally we store fenced code block data on each Comment, for highlighting purposes. More data will be parsed in this code in the future. In particular, doc imports. Work towards #50702 Change-Id: Idb2dcae3fb54af567b1a7f43896c3226644bf6cc Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/317446 Commit-Queue: Samuel Rawlins <[email protected]> Reviewed-by: Konstantin Shcheglov <[email protected]>
As suggested in https://dart-review.googlesource.com/c/sdk/+/317446. This introduces a new class CharacterSequence, an abstraction over the two different doc comment types, and the two remarkably different ways they need to be walked. One good example of the complexities is that a line starting with `// ` must be completely ignored when processing a single-line doc comment, but must not be ignored when processing the lines of a multi-line doc comment. Implementing the logic of the two styles in one body was too ugly and complex. This also fixes a bug in offsets, as can be seen in the ast_builder_test. Work towards #50702 Change-Id: Ife5f17a88268e5cda1ac89d4c14fa1f1cad1333f Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/321360 Commit-Queue: Samuel Rawlins <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]>
Work towards #50702 * This adds a `docImport` field to the `Comment` class. * Doc imports are parsed with the standard Fasta parser and AstBuilder. * We add one static check that `deferred` isn't used. Other checks are needed. * Many tests. * We need to add support for line splits in a doc comment. * I think doc comment imports need to be visted by AST visitors, but maybe I am wrong... Change-Id: I06e2b6fe42ef5ce916d46d9a9db35334726677d0 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/322591 Commit-Queue: Samuel Rawlins <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]>
Work towards #50702 Change-Id: If9c3d702f16e609e0d1f2c2bf09ec02a73cd5a54 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/323427 Commit-Queue: Samuel Rawlins <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]>
Here's an update on what's been implemented, as it's not quite what's specified at top, CC @kallentu:
Otherwise, I think the resolution steps specified up top, and the new errors that should be reported, are unchanged. |
To clarify, are you talking about having the doc namespace available from the I haven't compared closely, but are the rules for doc imports the same as for normal imports (modulo the namespace being computed), or are there some interesting differences?
I believe that the rules for normal imports is that it's only an error if the conflicting name is actually referenced. I assume the same is true here. |
Yes I think they're exactly the same.
Ah yes, fair. True here as well. |
@lrhn To complete this work, I think it would be consistent, simple and straightforward for the analyzer will start reporting "compile time errors" on doc-imports, the same that are reported for regular imports. WDYT of that? For example, |
I'd be fine with reporting an invalid import as an error. I'd also make it an error to have a (I'm a little iffy about calling it a "compile-time error" for a tool that doesn't actually compile, but that's probably just idle pedantry. It's really a "doc-time error", where the analyzer is reporting that that the DartDoc tool will have an error here, just like a compile-time error is the analyzer reporting that a compiler will have an error. Or it's just "an error" because someone wanted to make something not be accepted, aka. lints). |
…ors. This CL adds doc import information to UnlinkedLibraryDirective and reports any static errors such as `URI_DOES_NOT_EXIST` from the doc imports. The doc imports should be treated similarly to actual imports so it uses a lot of the same logic. Based largely on Sam's WIP work in this CL: https://dart-review.googlesource.com/c/sdk/+/344340 Bug: #50702 Change-Id: Ic001fd6d4077eea04905288be0424e7b11b2b56c Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/345361 Reviewed-by: Samuel Rawlins <[email protected]> Reviewed-by: Konstantin Shcheglov <[email protected]> Commit-Queue: Kallen Tu <[email protected]>
Work towards supporting #50702 in google3. Related to the work attempted in flutter/flutter#150798. Change-Id: I36fb1c47c94d5b965529db910fbd0e347bfba645 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/373442 Reviewed-by: Konstantin Shcheglov <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]> Commit-Queue: Sam Rawlins <[email protected]>
Superceded by #56186, which includes the new syntax, a directive in doc comments, as implemented in the analyzer. |
This is an alternative proposal to #49073. This proposal improves upon the readability and perhaps the simplicity of that proposal. It is based on @lrhn 's brief comment on that proposal.
BACKGROUND
Audience
Anyone writing documented Dart code.
Glossary
///
), and which is placed just before a library element (class, top-level function, top-level constant, etc.) or a class/mixin/enum/extension element (method, field, etc.). A doc comment is parsed (by various tools) as Markdown text.[List]
or[Future.wait]
.show
andhide
combinators).OVERVIEW
The basic design is to add a new annotation, perhaps to the meta package,
@docImport
which looks similar to animport
directive. When a library is annotated with this annotation, the analyzer will add elements to one of a library's top-level namespace, just like animport
directive. Doc comment references can then resolve to elements provided by such "doc imports". Quick examples:DETAILED DESIGN/DISCUSSION
A class is introduced which can be used as an annotation:
Each
docImport
annotating alibrary
directive introduces a doc import which contributes to a new doc namespace.A library currently has one or more top-level namespaces: the un-prefixed namespace and zero or more prefixed namespaces, which result from import directive(s) with prefixes.
Each identifier in a library (both in code and in doc comment references) is resolved according to various scoping rules, which may resolve to a non-top-level identifier, or a top-level identifier from one of the top-level namespaces. (This is a simplification since a prefix itself is an identifier which needs resolution, and which can also be shadowed by a non-top-level identifier.)
This change introduces a second set of namespaces used only for the resolution of doc comments: the "doc namespaces." The doc namespaces are a superset of the regular namespaces, and each doc namespace is a superset of the corresponding regular namespace (with the same prefix).
For a given library, the doc namespace with prefix
p
is computed via the following steps:p
:@docImport
annotation specified with prefixp
:(The "regular" namespaces are computed in the exact same way, excluding step 3.)
Each doc comment reference is then resolved using the standard scoping rules, and using the doc namespaces as the set of top-level namespaces.
New static warnings are reported in the following situations:
ACCESSIBILITY
I am not aware of any accessibility considerations.
INTERNATIONALIZATION
I am not aware of any internationalization considerations.
OPEN QUESTIONS
Can we define the
docImport
class and constructor indart:core
? This would be required if we want to usedocImport
functionality in the Flutter engine, which cannot importpackage:meta
.If not, should we instead support this feature as some sort of directive in a doc comment? For example, instead of the annotations in the OVERVIEW section above, we could instead support:
This solution has some significant drawbacks:
TESTING PLAN
Support for this syntax will be tested in:
DOCUMENTATION PLAN
The support for this feature can be documented on the
docImport
class.MIGRATION PLAN
If a developer has wanted to reference an out-of-scope element, there are a few strategies they may have ultimately chosen:
/// See `List`
. For this case, we can offer a lint and a quick fix, "this could be a doc comment reference." (This could have many false positives.)This addresses #44637.
The text was updated successfully, but these errors were encountered: