Skip to content
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: highlight deprecated symbols #40447

Closed
ainar-g opened this issue Jul 28, 2020 · 35 comments
Closed

x/tools/gopls: highlight deprecated symbols #40447

ainar-g opened this issue Jul 28, 2020 · 35 comments
Labels
FeatureRequest gopls Issues related to the Go language server, gopls. help wanted Tools This label describes issues relating to any tools in the x/tools repository.
Milestone

Comments

@ainar-g
Copy link
Contributor

ainar-g commented Jul 28, 2020

I'm using gopls (see version information below) with Vim (version 8.1) and natebosch/vim-lsc (version 632d49bf7a).

$ gopls version
golang.org/x/tools/gopls master
    golang.org/x/tools/gopls@v0.0.0-20200727233628-55644ead90ce h1:IYtWwbxt1Jl45OJO6l9OnkvIlOQlRyaHgIvg+Rm2qNQ=

Currently, when I hover over a deprecated symbol, I don't see any messages about the deprecation in Vim's statusline, and the symbol isn't highlighted. I assume, it's because gopls doesn't support that. I would like to see those messages.

@gopherbot gopherbot added Tools This label describes issues relating to any tools in the x/tools repository. gopls Issues related to the Go language server, gopls. labels Jul 28, 2020
@gopherbot gopherbot added this to the Unreleased milestone Jul 28, 2020
@stamblerre stamblerre removed this from the Unreleased milestone Jul 28, 2020
@stamblerre stamblerre added this to the gopls/unplanned milestone Oct 21, 2020
@jotdl
Copy link

jotdl commented Dec 1, 2020

May I have a take on this? I would be happy to support gopls :)

Actually, I already started to investigate and think I might found the correct place to implement:
As an additional analyzer under golang.org/x/tools/go/analysis/passes.

Do you agree that this is the correct place this needs to be implemented or would you recommend somewhere else?

@stamblerre
Copy link
Contributor

@jotdl: Absolutely, we'd love to have you contribute! You're right that this would be another analysis pass, though the feature may already be available through Staticcheck (which is off-by-default right now): https://staticcheck.io/docs/checks#SA1019.

LSP also has a diagnostic tag that allows us to mark something as deprecated (https://microsoft.github.io/language-server-protocol/specifications/specification-3-16/#diagnostic), so one option might be to enable this particular check by default and set the tag for any of its warnings.

@jotdl
Copy link

jotdl commented Dec 1, 2020

Yes, you are absolutely right.

I didn't know yet that gopls comes with staticcheck. Sorry about that!

So it seems that in order to solve this, we actually don't need to implement the analysis part itself and could rely on staticcheck instead.

I did give this a try, but couldn't get it to work. A look into the staticcheck analysis code for deprecation warnings shows that it relies on facts produced by package dependencies (deprecated.go L59).

After a bit of debugging I found that we currently don't execute analysis for package dependencies anymore (due #35089 ):
internal/lsp/cache/analysis.go#L114-L117

After reenabling this code the analysis rule works again and then it's just a matter of adding the correct diagnostic tag which should be as easy as (as addition to Analyze in internal/lsp/source/diagnostics.go):

if e.Category == "SA1019" {
  tags = append(tags, protocol.Deprecated)
}

But I am not sure how to proceed in perspective to #35089 . Are there any plans to reenable it?

@stamblerre
Copy link
Contributor

Thank you for doing all of this investigation, and I'm sorry you had to do so much digging! Re-enabling that logic more correctly is now tracked by #38278, which will not happen for a while, but it seems like we can probably re-enable it for this case.

The changes you describe seem reasonable to me, so if you'd like to mail them, we'd love to get your contribution! One note is that we will be freezing the gopls codebase soon to focus on stability, so your change will likely not be merged until after the Go 1.16 release in February.

@jotdl
Copy link

jotdl commented Dec 2, 2020

Thank you for doing all of this investigation, and I'm sorry you had to do so much digging!

No worries, I didn't expect something different as language servers are usually quite complicated and it's fun to read through all the code and get an idea of what's happening :)

So just to sum up things:

  • We would reactivate the analysis of package dependencies for SA1019
  • Set the correct diagnostic tag for analysis errors produced by SA1019
  • Leave it to the user to enable staticcheck via gopls configuration

Please correct me if I misunderstood something.

I'll try to get a PR up this evening. But I also need to check the contribution guidelines as this would be my first contribution.

Edit: Sorry, I didn't make it tonight. Everything is setup now, but I am not sure yet how and where this change is supposed to be tested. Need to look more into the testing part of gopls tomorrow.

@stamblerre
Copy link
Contributor

Yep, that all sounds correct to me! The contribution guidelines can be found at https://golang.org/doc/contribute.html, and there are some testing-related docs here: https://github.com/golang/tools/tree/master/internal/lsp/tests.

@jotdl
Copy link

jotdl commented Dec 9, 2020

I am still on it, but sadly I am currently stuck:

When I enable the analyzation of package dependencies for SA1019 in analysis.go line 117 via

if a.Name == "fact_deprecated" { // enable SA1019
   ...
}

running the tests via go test ./... get stuck and they never finish.

It took me a while to figure out which tests are causing this behaviour and it seems like

  • internal/lsp/testdata/analyzer/bad_test
  • internal/lsp/testdata/suggestedfix/has_suggested_fix

are the cause of this issue. At least removing them fixes the hanging tests.

I could already mail the changes. But without fixing the tests I guess the changes are not worth much.

@stamblerre
Copy link
Contributor

If you'd like to mail the changes, I'd be happy to take a look and see if I can identify the issue.

@pjweinb
Copy link

pjweinb commented Mar 2, 2021

There doesn't seem to be any standard way of saying that something is deprecated. For instance, io/ioutil just says that there are better alternatives, while net/http uses the word Deprecated. Is the list the staticcheck uses (https://github.com/dominikh/go-tools/blob/v0.0.1-2020.1.6/deprecated/stdlib.go) hand generated? (last updated for go1.14)

@jotdl
Copy link

jotdl commented Mar 2, 2021

@pjweinb There is no "enforced" way of marking something as deprecated, but I think it's widely accepted to use the Deprecated word as documented in https://github.com/golang/go/wiki/Deprecated and the majority of go developers deprecate code as documented there.

I am not sure if t the staticcheck list you mentioned is written by hand, but it looks to me like it was. I could think of a couple of reasons why they did so, but that's something you would better ask in the staticcheck repository as I sadly don't know a lot about it.

@jotdl
Copy link

jotdl commented Mar 2, 2021

@stamblerre I am really sorry that I was unable to push this further during the last two months. As I was unable to test this and just got stuck I felt like it's not worth to push my changes as they are so minimal and even not tested.

Anyways, I'll rebase my changes and check what the current state is. Maybe I can figure out now what needs to be done in order to get the tests running.

@stamblerre
Copy link
Contributor

@jotdl: No worries--not a problem at all! @pjweinb was just interested in adding deprecated markers to completion or document symbols, which is related but not necessarily overlapping with this issue.

@pjweinb
Copy link

pjweinb commented Mar 3, 2021

Yes. I apologize for the misunderstanding. My point was about trying to automate the process of finding out what was obsolete, and I thought this would be a good place to remember what I found. Some languages use @deprecated in function documentation, but Go doesn't.

@eryajf
Copy link

eryajf commented Jun 20, 2022

I don't know enough information, and now it comes to this question. I want to make sure that this problem still exists.

I use vscode to develop the go language, and I find that it doesn't work when the method is annotated as follows

// this is test func
// Deprecated
func TestFunc() {
	fmt.Println("aaa")
}

If the previous line next to the deprecated also has a comment, it will not work properly,Add a newline to the deprecated comment and it will work properly

my gopls version is:

$ gopls version
golang.org/x/tools/gopls v0.8.4
    golang.org/x/tools/gopls@v0.8.4 h1:zGZsAXAb0LLws/Z+2BCWR17dkPHhIO2GYwYSSkeXX5c=

@ainar-g
Copy link
Contributor Author

ainar-g commented Jun 20, 2022

@eryajf, the comment in that code does not conform to the deprecation notice convention. The deprecation notice must be on in separate paragraph and have a short comment.

@eryajf
Copy link

eryajf commented Jun 20, 2022

the comment in that code does not conform to the deprecation notice convention. The deprecation notice must be on in separate paragraph and have a short comment.

So should the correct usage be like this?

// this is test func

// Deprecated: this is old func, the new func is NewTestFunc()
func TestFunc() {
	fmt.Println("aaa")
}

At this point, the original comment // this is test func is cut off from the current method, and it doesn't feel good. Or should I delete this comment?

@ainar-g
Copy link
Contributor Author

ainar-g commented Jun 20, 2022

@eryajf, that is a separate comment, not a paragraph within the same comment. The Wiki page has an example. Something like:

// TestFunc is a test func.
//
// Deprecated: use NewTestFunc instead.

@eryajf
Copy link

eryajf commented Jun 20, 2022

@ainar-g When I write like this, it doesn't work.

image

@ainar-g
Copy link
Contributor Author

ainar-g commented Jun 20, 2022

@eryajf, I've only now noticed that this issue is not closed. So it's no wonder that gopls doesn't highlight it. The highlight over TestFunc2 is probably some other tool or VSCode itself.

The format is correct now, and if you need some checker right now, you can use staticcheck, which has a check against using deprecated identifiers from other packages.

@eryajf
Copy link

eryajf commented Jun 20, 2022

@ainar-g

Maybe it's just vscode's problem. When I use goland, the problem disappears

image

I came here from this question golang/vscode-go/issues/599 . The problem on the other side has been closed, but it doesn't seem to be solved.

@hyangah
Copy link
Contributor

hyangah commented Jun 21, 2022

vscode-go side issue was closed because it's a duplicate of this issue.

@eryajf
Copy link

eryajf commented Jun 21, 2022

vscode-go side issue was closed because it's a duplicate of this issue.

I understand. I hope gopls can pay attention to this problem again here, so that it can be solved in vscode development.

@tooltitude-support

This comment was marked as off-topic.

@hyangah
Copy link
Contributor

hyangah commented Mar 10, 2023

staticcheck's SA1019 already implements it. VS Code Go extension uses staticcheck as the default linter, so if the lint running outside gopls is not disabled, users will already see reports like this.

Screenshot 2023-03-09 at 8 18 42 PM

Gopls also has staticcheck integration. Not sure if the staticcheck embedded in gopls depends on the fact propagation in gopls or not. If it depends on gopls's driver, good news is I think the gopls at master already fixed the issue. From the gopls built from master, I see SA1019 check working as expected when I enabled "gopls": { "ui.diagnostics.staticcheck": true } setting.

Screenshot 2023-03-09 at 8 21 40 PM

However, some may prefer strikethrough to this squiggle presentation. I played a bit with SA1019 diagnostics in gopls. It looks like if we change SA1019 diagnostics to be mapped to Diagnostics with severity=hint(4), tags=[Deprecated], this will produce the effect we want:

Screenshot 2023-03-09 at 8 16 05 PM

The easiest path I see to enable this is to use honnef.co/go/tools/analysis/facts/deprecated which already is x/tools/go/analysis.Analyzer. (@dominikh )
Once done, we can disable SA1019 in the hook setup.

We also need to sort out

  • How/where to set a different severity for diagnostics generated from x/tools/go/analysis.Diagnostic.
  • Where to set the protocol.Diagnostic's Tags field.
  • Do we still want to provide an option to report deprecated symbol usages as severity level = Warning or Information? If so, should there be an option? (@findleyr @golang/tools-team )

Another minor caveat is staticcheck module requires go1.19+. Not sure if the deprecated package can be included in the gopls built with older versions of go if gopls's buildable go version support window is larger.

In addition to this diagnostics that are presented on the callsites, I think it is also cool if we can add deprecation info to

  • DocumentSymbol (so VS Code Document Outline marks deprecated symbols inside the package)
  • WorkspaceSymbols (so workspace symbols can also show deprecated symbol info.

☝️ Help wanted.

@dominikh
Copy link
Member

dominikh commented Mar 10, 2023

Not sure if the staticcheck embedded in gopls depends on the fact propagation in gopls or not

It does.

Another minor caveat is staticcheck module requires go1.19+. Not sure if the deprecated package can be included in the gopls built with older versions of go if gopls's buildable go version support window is larger.

There is a good chance that the deprecated package doesn't need Go 1.19 at the moment, and else I'd be happy to accept patches for that package specifically.

It's also worth noting that deprecated only does the work required for extracting the Deprecated markers. SA1019 does additional work around handling the Go standard library and Go versions (https://github.com/dominikh/go-tools/blob/cc140e9b3719aadd3b628b7a7b00523681c8b34d/staticcheck/lint.go#L3082-L3146)

@gopherbot
Copy link

Change https://go.dev/cl/508508 mentions this issue: gopls/internal/lsp/source: highlight deprecated symbols

@hitzhangjie
Copy link
Contributor

hitzhangjie commented Aug 10, 2023

How to enable this 'highlight depreated symbols' feature? I installed gopls from the master branch, which contains the merged PR: https://go-review.googlesource.com/c/tools/+/508508, And I also restart the vscode.
But the used deprecated functions still not rendered by strikethrough.

@hyangah
Copy link
Contributor

hyangah commented Aug 10, 2023

It's enabled by default and the feature is available in the latest release.
Can you provide the example code?

@hitzhangjie
Copy link
Contributor

hitzhangjie commented Aug 10, 2023

@hyangah Here's my example code:
image

this is my gopls setting in settings.json:

  "gopls": {
    "ui.completion.usePlaceholders": true, 
    "ui.diagnostic.staticcheck": true,
  },

gopls version is v0.13.1 (latest now):

gopls version
golang.org/x/tools/gopls v0.13.1
    golang.org/x/tools/gopls@v0.13.1 h1:Q0cfPbEG1WVfgxcRZ9uKTA6/ckIRNXx6Ym7KgT/VFE4=

go version is go1.19.5:

go version
go version go1.19.5 linux/amd64

@hyangah
Copy link
Contributor

hyangah commented Aug 10, 2023

@hitzhangjie Can you hover over the package main and tell us what error is present there? That often indicates the files couldn't be parsed and analyzed correctly for some reason. In that case, secondary analysis like deprecated symbol check doesn't (or cannot) run.

For example, editor setting errors (build tags), or issues related to the module boundary (doc) are some of the common issues we've seen.

@hitzhangjie
Copy link
Contributor

hitzhangjie commented Aug 10, 2023

@hyangah Sorry for this example. I put the example under a module but I doesn't use go.work.

After I put the main.go, add.go under a new clean project folder, the yellow error message gone, and:
1 )The expected strikethrough still not displayed.
2) but I moved add.go to new a new package (not main), the strikethrough is displayed.

image

I also tried another example, pkg.(*type).method, it works only when put the definition in separate package.

@hyangah
Copy link
Contributor

hyangah commented Aug 10, 2023

Thanks @hitzhangjie
Yes, the feature marks only deprecated symbols from other packages.
That is intended behavior. The reasoning is that the package owners know what symbols are deprecated already and use of deprecated symbols inside the package often has a reason. One of the pathological cases is, for example, io/ioutil. The entire package is deprecated but they won't disappear from the project due to the go1 compatibility policy. Managing tests and part of code that use deprecated symbols is part of normal operation.

@hitzhangjie
Copy link
Contributor

@hyangah OK. Thanks for the explaination.

@fantapop
Copy link

This is still not quite working for me. I see the strikethrough in the popup only if the godoc on the function is a single line with "Deprecated: " as a prefix. If the godoc includes multiple paragraphs, one of which is prefixed with Deprecated, I can see the strikethrough in editor pane but not in the popup. Does the fact that its working for the editor pane and not the pop-up indicate that this is on the vscode side?

Here are the 2 examples. You can see what the content is in the popup box:

A single line document string correctly striking through in the popup and the source code:
Screenshot 2024-03-18 at 1 40 02 PM

A multi-paragraph document string only striking through the text in the source code:
Screenshot 2024-03-18 at 1 44 45 PM

@GOodCoffeeLover
Copy link

@hyangah
Hi, is there any possibilities for creating some feature flag that would enable deprecation marks in same package?

In my case i want it to highlight to colleagues use another private methods because they (method, not colleagues %) ) will be removed in short time, but can't be removed just now for backward compatibility. And visually highlighting this would be better, that if i just say it.

It would be very helpful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
FeatureRequest gopls Issues related to the Go language server, gopls. help wanted Tools This label describes issues relating to any tools in the x/tools repository.
Projects
None yet
Development

No branches or pull requests