dart-lang / sdk

The Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.
https://dart.dev
BSD 3-Clause "New" or "Revised" License
10.08k stars 1.56k forks source link

Show descriptive hover/tooltips for keywords in IDEs #50085

Open DanTup opened 1 year ago

DanTup commented 1 year ago
final a = '';
const b = '';

I often see questions posted on Reddit/etc. about the difference between final/const. It would be nice if hovering over their keywords here provided some description that explains the difference (perhaps the text from https://dart.dev/guides/language/language-tour#final-and-const).

Similarly, some users may be less familiar with sync*, async*, yield* so when browsing package/SDK code, being able to hover over those for descriptions (and/or links out to docs) would probably also provide some benefit.

I don't know if many other languages do this. I know Rust does, though I don't have any experience with it.

DanTup commented 1 year ago

This could be useful for symbols like ? too. Recently I heard some confusion around use of ? in switch expressions:

Uri(:final data?) => data,

If you could hover over ? here and get some description of what it means in this context (versus when used in uri?.data for example) I think that would be really useful (both as a reminder, and to help those looking at code they didn't write to understand what it's doing).

@bwilkerson I suspect the implementation of this would be relatively straight-forward, and the bigger question is where we can get the content for this (ideally it would match similar reference material on the Dart website, but I don't know if that exists, or how easily we could scrape it).

bwilkerson commented 1 year ago

I like the idea of hovers for non-user-defined operators.

@MaryaBelanger for the question of where this text would come from.

parlough commented 1 year ago

We've talked a little bit about introducing a sort of language construct reference similar to this Kotlin Keywords and operators page. The original thinking was to have a page to search for constructs easier now that we split up the language tour, but this could be a second use for it.

We could generate it from a shared YAML file, so this tooling could use those definitions and links as well.

MaryaBelanger commented 1 year ago

The Glossary page! @parlough and I have been talking about implementing a hover-over within the docs itself (like, "something, something, refutable pattern...", and hovering over the keyword shows the glossary definition in a little pop up, and clicking takes you to the glossary page.

So just explaining that to say that the definitions could live there and be used across the site and the tips. And if this implementation is relatively straight forward, we can start filling out the glossary right away

Edit:


@parlough after seeing your comment, not sure if it would make sense to use the glossary page, what do you think?

DanTup commented 1 year ago

We've talked a little bit about introducing a sort of language construct reference similar to this Kotlin Keywords and operators page.

Something like that would be great - as long as we can differentiate between things like a ? used in a conditional expression vs a ? in a null check pattern. I don't know if these things already have identifiers anywhere we can use - if not, we might need to agree some (so the server knows how to select the correct docs in each context).

We should store the data in a way that the server can parse it (probably we'd want a script in the server codebase we can use to periodically save the latest version into the codebase to avoid needing to call out to the web at runtime?). JSON or YAML would work (JSON is probably easier for server, though I don't know YAML is easier for how the website works?).

bwilkerson commented 1 year ago

We should store the data in a way that the server can parse it ...

Yes, I think that's key to making this work.

I don't know whether we'd want to display the full content of the entry or whether we'd want to display a subset with a link to the longer text. That might depend on whether we can include links in the hover text. It looks like we can, but I haven't verified that.

parlough commented 1 year ago

@parlough after seeing your comment, not sure if it would make sense to use the glossary page, what do you think?

I don't know whether we'd want to display the full content of the entry or whether we'd want to display a subset with a link to the longer text...

Yeah I guess before we determine what can (or should) be shared or where to put that documentation, we need a more clear idea of what and how much information we want to show in the tooltip.

I just checked out Rust Analyzer and it shows a lot more information than I expected, multiple paragraphs and code samples, and then links to the reference material for the keyword or operator as well as a related entry in the Rust Book.

Personally, it didn't seem like a tooltip was a great place to learn all of that though, so maybe a sentence or two to provide that context with links is enough, I'm not sure.

DanTup commented 1 year ago

I don't know whether we'd want to display the full content of the entry or whether we'd want to display a subset with a link to the longer text. That might depend on whether we can include links in the hover text. It looks like we can, but I haven't verified that.

Yep, links work fine:

Screenshot 2023-04-26 at 11 05 24

We do have this user preference that we use to decide whether to show full or summary docs in hovers:

Screenshot 2023-04-26 at 11 06 21

But we default to "full" and I'm not sure we want to put too much here. I think having a reasonable summary and a link to website (which could have expanded docs) would probably be better. We'd need to ensure the data in the website can contain both summary + detailed data in that case (so the website can render it all, but the server scripts can just pull the summaries). We'd also need to ensure server can compute a link to the expanded docs.

I think even having only summaries on the website initially would still be useful. Users clicking the links might not get any additional info than what was in the tooltip, but they might be interested in seeing information about the other operators all in one place without having to discover/hover them in the editor.

Do we have an easily available list of all keywords/operators that we might want to include, or do we need to compile one?

bwilkerson commented 1 year ago

We'd also need to ensure server can compute a link to the expanded docs.

A hardcoded link in the doc text might be just as good here (because users can't add new operators, so we know everything we need to know in advance). Either way server will produce a predetermined link.

We will, of course, need to be careful about breaking links if we ever want to change the location of the docs.

bwilkerson commented 1 year ago

I'll also note that we don't strictly need to have links before we can have some kind of hover text. We could add some initial text and then update the text later, including adding links. One advantage of this approach is that we could find out whether the feature is worth spending more effort on before we actually spend a lot on it.

DanTup commented 9 months ago

This came up recently at https://github.com/Dart-Code/Dart-Code/issues/4864.

Perhaps we can start with a JSON file in the server that contains some snippets and links for keywords/modifiers and show them where they exist. For example:

{
  "sealed: {
    // Documentation tagged onto the hover
    "documentation": "The [sealed](https://dart.dev/language/class-modifiers#sealed) modifier prevents a class from being extended or implemented outside its own library. Sealed classes are implicitly [abstract](https://dart.dev/language/class-modifiers#abstract)."
    // an object so we could add additional fields in future, for example a specific URI that isn't
    // just inside the text
    // "documentationUrl": "https://dart.dev/language/class-modifiers#sealed"
  }
}

We could have an integration test to verify the URLs are all still valid (and there are matching anchors in the page), and in the future (or now, if the website developers are happy to add it) we could move this JSON to the website and/or pull data from the website and generate this file in the server (committed to the repo, so we're not reliant on an internet connection and we version with the SDK).

bwilkerson commented 9 months ago

@MaryaBelanger For doc team input.

parlough commented 9 months ago

I'm glad you brought this up again, it crossed my mind the other day.

I'm personally all for starting with some file in the SDK, but either way, I think we need to determine a link structure we can support long-term on the website, so old SDKs don't link to missing pages or fragments.

Perhaps dart.dev/go/keyword/<keyword> and dart.dev/go/operator/<operator> or something similar, then we can make sure those work and stay updated on the website.

osaxma commented 8 months ago

class modifiers brought me here -- I always try to hover over them to see what a modifier mean 😅

I think this feature would really be helpful as the number of keywords in Dart seems to be increasing with new language features.

parlough commented 3 months ago

@DanTup Can we start with just docs sourced from a YAML file in the analyzer and hold off on the links to elsewhere?

DanTup commented 3 months ago

It could - though if we might ultimately pull the content from somewhere else (like the website), maybe just using a constant map would be easier (it would give us some safety around identifiers, since I think the raw keywords alone won't be enough because of context - for example final in classes vs variables):

enum DocumentationKeyword {
  abstract,
  as,
  /// `final` keyword used in a variable declaration
  final_var,
  /// `final` keyword used in a class declaration
  final_class,
}

const keywordDocumentation = <DocumentationKeyword, String>{
  DocumentationKeyword.abstract: '...',
  DocumentationKeyword.as: '...',
  DocumentationKeyword.final_var: '...',
  DocumentationKeyword.final_class: '...',
};

If we implemented this, do we have existing content we can use (or someone that could provide it)? Should we just use the description taken from each page linked to from https://dart.dev/language/keywords and adjust the wording as necessary?