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

feat: support Find References LSP request #4271

Merged
merged 8 commits into from
Jul 25, 2023

Conversation

alex-chew
Copy link
Contributor

@alex-chew alex-chew commented Jul 11, 2023

Fixes #2320.

  • Implement basic functionality
  • Add tests (WIP)
  • Update release notes

By submitting this pull request, I confirm that my contribution is made under the terms of the MIT license.

@alex-chew alex-chew changed the title feat: implement LS find-references; add tests feat: implement LS find-references Jul 11, 2023
@alex-chew alex-chew changed the title feat: implement LS find-references feat: support Find References LSP request Jul 11, 2023
await AssertReferences(source);
}

// It seems that type declaration/usage information is not tracked
Copy link
Member

@keyboardDrummer keyboardDrummer Jul 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably resolved by adding implementing IHasUsages on more AST nodes, but we can fix that in another PR.

Relevant, I would like to change the way resolver is implemented so there's a stronger integration between the resolver and building the usage graph, so that if a usage if resolved then it automatically becomes available to the language server and there's no longer the possibility of forgetting to add IHasUsages

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that's a good idea, and I agree that it would be better to address in another PR.

On a related note, it would be nice if the declaration graph were reflexive on declarations, i.e. GetDeclarations(myDecl.Position) would include myDecl itself. This seems moreintuitive to me, and it would also simplify the implementation of DafnyDefinitionHandler.Handle.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't follow. Instead of GetDeclarations and DafnyDefinitionHandler.Handle, do you mean GetUsages and DafnyReferencesHandler.Handle ?

Note that LSP allows the client to request usages of a declaration that doesn't return the declaration itself:

image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I did mean GetUsages and DafnyReferencesHandle.Handle.

I'll implement support for includeDeclaration being false.

}

[Fact]
public async Task Module() {
Copy link
Member

@keyboardDrummer keyboardDrummer Jul 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder whether find references on definitions that may be visible outside of the file, should be enabled when not in project mode, since it might cause too few results to be returned leading to confusion.

One option is to do the least amount of work, which is to have it be enabled as you have now, and then gather feedback from users.

The other option is to for each definition say whether it's local to the file or not, and only if it is to return references results outside of project mode.

What do you think we should do?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think whether or not we return references of definitions outside of the current file, it will be true that (a) the list of references will be incomplete in the general case (and so users may be confused), and (b) we will want to somehow encourage users to adopt the project mode.

To address (b) I'll look into ways we can warn the users that results may be incomplete, and guide the users towards documentation on how to add an appropriate project file. But then under those circumstances, I'd rather give a "best effort" list of references, i.e. including some-but-maybe-not-all references/declarations outside the current file, rather than intentionally withholding them.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For (b), I'm thinking of a notification that pops up whenever a file is opened that's not using project mode, that does include other files, and then ideally you could say "OK" or "OK and don't warn me again"

@alex-chew alex-chew marked this pull request as ready for review July 12, 2023 15:47
};
}

public override async Task<LocationContainer> Handle(ReferenceParams request, CancellationToken cancellationToken) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This implementation doesn't respect request.context.includeDeclaration

@alex-chew
Copy link
Contributor Author

(The force-push rebases this branch onto master.)

@@ -39,6 +39,12 @@
<None Update="Lookup\TestFiles\foreign-verify.dfy">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Lookup\TestFiles\find-refs-a.dfy">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I think it's easier to read tests if all the relevant code is in the test. Alternatives to this are either opening these files in memory, or writing them to disk in the test.

public class ReferencesTest : ClientBasedLanguageServerTest {
private async Task<LocationContainer> RequestReferences(
TextDocumentItem documentItem, Position position) {
// We don't want resolution errors, but other diagnostics (like a cyclic-include warning) are okay
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I feel the method call implies what the comment says.


namespace Microsoft.Dafny.LanguageServer.IntegrationTest.Lookup {
public class ReferencesTest : ClientBasedLanguageServerTest {
private async Task<LocationContainer> RequestReferences(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I would move this and the next method to the bottom of the file, so the file is more callgraph topologically ordered.

var declaration = state.SymbolTable.GetDeclaration(requestUri, request.Position);

// The declaration graph is not reflexive, so the position might be on a declaration; return references to it
if (declaration == null) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I would replace this with:

// The declaration graph is not reflexive, so the position might be on a declaration
FilePosition declarationPosition = declaration == null 
  ? new FilePosition(requestUri, request.Position) 
  : new FilePosition(declaration.Uri.ToUri(), declaration.Range.Start)

return state.SymbolTable.GetUsages(declarationPosition.Uri, declarationPosition.Position).ToArray();

Copy link
Member

@keyboardDrummer keyboardDrummer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! Amazing

@keyboardDrummer keyboardDrummer enabled auto-merge (squash) July 25, 2023 09:15
@keyboardDrummer keyboardDrummer merged commit c5d909a into dafny-lang:master Jul 25, 2023
18 checks passed
keyboardDrummer added a commit to keyboardDrummer/dafny that referenced this pull request Sep 15, 2023
Fixes dafny-lang#2320.

- [x] Implement basic functionality
- [x] Add tests (WIP)
- [x] Update release notes

<small>By submitting this pull request, I confirm that my contribution
is made under the terms of the [MIT
license](https://github.com/dafny-lang/dafny/blob/master/LICENSE.txt).</small>

---------

Co-authored-by: Remy Willems <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support the "Find references" LSP request
2 participants