-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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
x/tools/gopls: Hover/DocumentHighlight for format strings #70050
Comments
Format strings are only one small step removed from the language spec in the sense that every Go file uses them and every Go reader is expected to recognize them, or at least the dozen or so most common ones. Just as I would find it odd to serve a hover box over the To your bigger implied questions:
|
I'm not following this argument. FWIW, this issue is premised on the fact that this would help me, and I'm not a beginner! We offer hover for builtins, even though they're part of the spec... Certainly one uses Unfortunately, you may be right that the hover could be a nuisance, but then aren't all hovers a nuisance? In my editor, I only trigger hover explicitly. |
Fair point. I remember I once asked you why we bothered with hover on built-ins and you responded that they're really useful. I do think there would be real value in tying each %v formatting operation with its operand, as when they are numerous it can be hard to see the correspondence at a glance (which is why Python now has f-strings). Perhaps DocumentHighlight is the ideal LSP UI? I still have concerns about efficiency if lightweight queries such as Hover and Highlight were to invoke the analysis framework, even if only in particular cases with a restricted subset of analyzers. We hack up a little experiment. |
It would be so much better if type Bar struct {}
var foo int
var bar Bar
fmt.Printf("%foo, %bar") can expands to type Bar struct {}
var foo int
var bar Bar
fmt.Printf("%d, %v", foo, bar) via completion then a (range) code action, given that go has rejected f-string proposal, it is always a pain if arguments are too many. (why we need to specify the various |
DocumentHighlight should solve the "counting" process quite well, I'm writing a lot long printf so I want to implement this feature, where should I start? (after moving the undeclared analyzer to gopls/internal, the response speed improved quit a lot, I guess it is a good thing to slowly factor the printf analyzer out?) |
You'll need a function that, given a string literal and an offset, returns an index within the denoted string; and a function that, given a logical format string and an offset, returns the index of the % conversion (if any) that it falls within. The simplest way to do the second one would be to follow the approach in #68279 (comment), which isn't perfect, but is good enough for >99.9% of strings. Once you have those, hooking into internal/golang/highlight.go for CallExpr shouldn't be hard. The only tricky bit is how to know which functions to apply it to: obviously fmt.Printf, but what about all the wrappers? We could use the analysis framework, but there are a lot of tricky problems there. Since this is only highlighting, it needn't be perfect: perhaps it's enough to observe that the format string contains a %, or approximately as many %s as arguments? |
Starting with DocumentHighlight makes sense to me.
FWIW, that's because there's a 1s debouncing before we run analysis. |
I think this can be simpler without parsing format string and args. The format syntax is
The main use case is to writing the arg list without counting which Update: let's include all information, since hover may want to show what is the meaning of a precision/width/flag. |
Should we also paint the format string with semantic highlight? Once we have a iter describing each element of a string in order, highlighting becomes free too, though vscode's textmate rule and treesitter-printf (I guess many people doesn't know it exists) can detect something similar. But it may benefit other editors. |
Change https://go.dev/cl/632598 mentions this issue: |
#68279 (comment), This method has limitations that can't handle explicit argument indexes, eg. Lines 695 to 704 in c46ba1f
This can be ignored for DocumentHighlight( just replace them with %s is fine) but may be surprised for hovering usage. Is these acceptable or should I go another way? |
Good point about %T and %p; sorry I didn't notice that sooner. (I added a warning at the other issue.)
Feel free to take another approach, such as writing a parser for the format string (with a suitable test suite---perhaps you can devise a test where your parser is cross-checked against the actual implementation of fmt.Printf to ensure that it computes the correct answer). |
This just occurred to me, when looking up a rarely used format verb for the nth time at pkg.go.dev/fmt: we should offer hover information for format strings. To start, this could simply show documentation for the active format verb under the cursor, but we could also extend it to explain more complicated formatting expressions.
We could extract the tricky bits of detecting and parsing format strings from the printf analyzer, though that begs the question of why we can't detect printf wrappers... @adonovan I wonder what you think about this idea, and more generally about the concept of exposing facts from the analysis framework to other gopls functionality.
Note that accurate detection of printf wrappers is not strictly necessary--that's more of a thought experiment. For hover, we could use a much weaker heuristic to guess whether a string is likely to be a format string.
The text was updated successfully, but these errors were encountered: