Skip to content
This repository was archived by the owner on Dec 29, 2022. It is now read-only.

Implement find implementations extension #181

Merged
merged 3 commits into from
Aug 17, 2017
Merged

Implement find implementations extension #181

merged 3 commits into from
Aug 17, 2017

Conversation

jonasbb
Copy link
Contributor

@jonasbb jonasbb commented Feb 22, 2017

I tried using the recent addition to the save-analysis data to tackle two items from the wishlist.

  1. Find all implementations of trait.
    Listed under wishlist tracking issue: wishlist #142

    Fails for traits which are implemented using derive

  2. Find supertrait of trait
    Listed under wishlist tracking issue: wishlist #142

    Only proof of concept, not yet transitive.
    To Check: Which span makes more sense. The span of the supertrait (as
    currently) or the span of where the subtrait defines the dependency?

Requires the find-impls branch of https://github.com/jonasbb/rls_vscode
Also requires the find-impls branch of rls-analysis.

I have a few specific questions which I am not sure how to tackle them:

  1. Find all implementations on a library provided trait like PartialEq only produces spans with a file path like /checkout/src/libstd/. lower_span in rls_analysis is not able to convert them correctly. Should this be fixed in rustc or rls_analysis and how? The spans do not have any information in them to indicate the invalid file paths.
    partialeq
  2. Find all implementations does not work with derive. Is this considered a problem?
  3. Find supertrait currently shows the definition span of the supertrait. I find this more useful than the line were the relationship is specified (here 5).
    supertrait
  4. I currently open the references popup at the location where the users performed the request. Should the popup be moved to the def location of the type?

@nrc
Copy link
Member

nrc commented Feb 23, 2017

It would be good to communicate that you're working on this stuff before you get into it - I also have substantial changes to rls-analysis mostly implemented to support the save-analysis changes.

To answer your questions:

  1. probably in rls-analysis
  2. no, it is something we should fix, but shouldn't block landing
  3. I think find subtraits is more useful than finding super traits, since the latter basically works just by 'jump to def'. Find super-traits should jump to the super trait, not the relation site
  4. I'm not sure, we should follow what VSCode does in other cases.

@jonasbb
Copy link
Contributor Author

jonasbb commented Feb 23, 2017

@nrc If you already have the changes to rls-analysis that's good. Just use them and ignore my stuff. I do this more for fun and self-education anyway. But I try to communicate more, to avoid duplicating work.

@nrc
Copy link
Member

nrc commented Feb 23, 2017

@jonasbb to be clear, I only have the rls-analysis parts implemented (and they are on master now) - I haven't done anything in VSCode or the RLS, so I think your work here will be very useful

@nrc nrc mentioned this pull request Mar 2, 2017
3 tasks
@jonasbb jonasbb changed the title Implement two custom extensions Implement find implementations extension Mar 2, 2017
@jonasbb
Copy link
Contributor Author

jonasbb commented Mar 2, 2017

@nrc I changed it to use the upstream rls-analysis version. I dropped the find supertrait stuff for the moment. This can be added easily with some copy and paste.
I also added documentation in contributing.md.

Lastly, I decided to filter out all paths starting with /checkout/src/. I am sorry if somebody is developing their rust code in there. However, I don't know what the equivalent path would be under windows and OSX. It might be worthwhile to also filter out those.

Copy link
Member

@nrc nrc left a comment

Choose a reason for hiding this comment

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

Thanks, this is looking good. The only bit that gives me pause is the checkout filtering - more inline.

.into_iter()
// FIXME: these are part of libstd and libcore but the path probably does not
// exists and thus should be removed. Replace with correct path later.
.filter(|x| x.file.starts_with(Path::new("/checkout/src/")))
Copy link
Member

Choose a reason for hiding this comment

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

I'm curious about this - why is it needed here and not for other queries? I think ideally any filtering like this should happen in rls-analysis, not here (and probably in a more principled way). I also think, but not sure, that this is probably incorrect, since this will cover all upstream crates, not just core/std, but it is only the std/core ones that do not exist?

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 assume this is an artifact how the save-analysis data is generated. I assume this is the path used in the buildbots.

In general this can only become a problem for the values ref_spans and impls in PerCreateAnalysis, because here we map to a span. ref_spans is only filled by the "refs": array in the serialized json. globs and def_id_for_span map a span to something else. If they contain such a broken span this only leads to a failed lookup but not to wrong filenames being presented to the user.

In the local (target/rls) analysis data I can only find references to the path /checkout/src/libcore/macros.rs. They appear here only in the macro_ref section, which is currently unused by rls-analysis, thus they could not have been a problem. No span in "refs" contains such a path.

In the global ('rustlib/.../analysis') analysis data I see references to a lot of different files of the libraries. But none of those json files have any values in "refs", which is the only existing possibly problematic case.

This mean, neither the local nor global data could have contributed until this change with broken spans.

src/server.rs Outdated
@@ -351,6 +354,12 @@ impl LsService {
trace!("command(reformat range): {:?}", params);
this.handler.reformat(id, params.text_document, &*this.output);
}

// custom extensions
Copy link
Member

Choose a reason for hiding this comment

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

comment is unnecessary

@jonasbb
Copy link
Contributor Author

jonasbb commented Mar 2, 2017

@nrc I addressed both comments by you. I just thought that a temporary solution for the checkout stuff would have been better than none. I opened a bug for this rust-dev-tools/rls-analysis#49

Copy link
Member

@nrc nrc left a comment

Choose a reason for hiding this comment

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

Thanks for the change, I thought of something else we need to do - sorry I should have included this in the last review, but didn't think of it.

.unwrap_or(vec![])
.into_iter()
.map(|x| ls_util::rls_to_location(&x))
.collect();
Copy link
Member

Choose a reason for hiding this comment

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

Could we spawn a thread with timeout to do this please? We do that for the other queries (e.g., find all refs) and I think we should do it here too).

@nrc
Copy link
Member

nrc commented Mar 3, 2017

It would also be great to add a test for this.

@Xanewok
Copy link
Member

Xanewok commented May 8, 2017

Hey @jonasbb, are you still working on the issue by any chance?

@jonasbb
Copy link
Contributor Author

jonasbb commented Jun 13, 2017

I updated the implementation and implemented a test case for it.
This PR depends somewhat on rust-dev-tools/rls-analysis#70, to make it better usable for traits defined in std lib, however, it also compiles with the current version of rls-analysis.

This generates two new warnings for unused items, once in src/actions/lsp_extensions.rs:16 and in src/server.rs:17, but I am not sure if I should just put a couple of allow annotations on them. The import is needed for the code generated by the macro, but somehow rust still annotates it as unused_import.

The updated client changes are in https://github.com/jonasbb/rls_vscode/tree/find-impls

Copy link
Member

@nrc nrc left a comment

Choose a reason for hiding this comment

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

Looks good. Could we put this behind the unstable features config flag please? (At least to start with)

src/server.rs Outdated
@@ -247,6 +247,7 @@ messages! {
"textDocument/rename" => Rename(RenameParams);
"textDocument/formatting" => Formatting(DocumentFormattingParams);
"textDocument/rangeFormatting" => RangeFormatting(DocumentRangeFormattingParams);
"rustDocument/implementations" => FindImpls(TextDocumentPositionParams);
Copy link
Member

Choose a reason for hiding this comment

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

Can we use the const here?

let analysis = self.analysis.clone();

let handle = thread::spawn(move || {
// FIXME send failure
Copy link
Member

Choose a reason for hiding this comment

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

Could you expand this comment please

}
Err(_) => {
out.failure(id, "Find Implementations failed to complete successfully");
}
Copy link
Member

Choose a reason for hiding this comment

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

style nit: I'd get rid of the {} here

@nrc
Copy link
Member

nrc commented Jun 14, 2017

This generates two new warnings for unused items

That is kind of disturbing - I guess this happens because the identifier is put together with concat_idents - this is presumably a bug in the Rust compiler. Could you add the allow annotations please?

@jonasbb
Copy link
Contributor Author

jonasbb commented Aug 15, 2017

Lets give this one more try.
@nrc

@nrc
Copy link
Member

nrc commented Aug 16, 2017

The new test seems to be failing, hard to tell why.

List all implementation block for traits, structs, and enums.
Fails for traits which are implemented using derive
Listed under wishlist #142

Requires the find-impls branch of https://github.com/jonasbb/rls_vscode
@jonasbb
Copy link
Contributor Author

jonasbb commented Aug 16, 2017

This test contains code for testing implementations of Eq. However, rust-analysis is not installed on Travis making rls-analysis fail why retrieving the typeid. Installing rust-analysis is also not an option, because this makes other test timeout. As such I commented the failing code.

@nrc
Copy link
Member

nrc commented Aug 17, 2017

I don't really understand the test issue - what is rust-analysis and why is it needed for the test? What do type ids have to do with it? The URL in the comment links to a passing Travis test, so I can't see any error messages. The Cargo.toml doesn't mention rust-analysis, so I don't know why Cargo needs to install it.

Could you just test for the literal impls in the test code (including Eq) and skip the derive completely? If that still doesn't work, remove all the Eq tests and just test for Sub and Super impls.

@jonasbb
Copy link
Contributor Author

jonasbb commented Aug 17, 2017

@nrc sorry for being so brief. It was late last night.
Summary: the test required the rustup rust-analysis component (for type definitions in the stdlib) which isn't and can't easily be installed on Travis.

I wrote tests to find implementation for three different spans in the test. The last span is Eq. The find_impls implementation asks rls-analysis for the typeid of the Eq type (trait). Eq is defined in the stdlib, however Travis does not install the rustup rust-analysis component which would be needed. This means rls-analysis fails to find the typeid for Eq.

The url in the comment is passing because for debugging I installed the rust-analysis component once on Travis. If I do this the test passes.

Now the code tests Sub and Super. The Eq is commented out with a reasoning why it does not work on Travis. Derives where never tested in the first place.

@nrc
Copy link
Member

nrc commented Aug 17, 2017

Ah, OK, I understand thanks! And thanks for working on this for so long!

@nrc nrc merged commit 85724ef into rust-lang:master Aug 17, 2017
@jonasbb
Copy link
Contributor Author

jonasbb commented Aug 17, 2017

I'm just glad that finally everything is in order :)

@Xanewok
Copy link
Member

Xanewok commented Sep 16, 2017

@jonasbb I tried to use the Find Implementations, but got this error:
Analysis: Getting typeid from span: Unclassified.
Got any idea what's causing it? Can I help debug it somehow? I tried trying it out in member package inside a workspace, can that affect it somehow?

@jonasbb jonasbb deleted the find-impls branch September 16, 2017 11:46
@jonasbb
Copy link
Contributor Author

jonasbb commented Sep 16, 2017

The error message means, that rls-analysis is not able to get a typeid from a span. This either means the span (selected characters) does not match any known type or somehow the analysis data is missing a Def definition for this type. It would help if you could mention what was under your cursor when invoking the command.

I don't know if a workspace has any influence on the analysis data.

@Xanewok
Copy link
Member

Xanewok commented Sep 16, 2017

@jonasbb
Given:

struct MyStruct;
trait MyTrait {}
impl MyTrait for MyStruct {}

I had crashes for MyStructs and MyTraits, either with cursor inside or when selecting a whole symbol. Am I doing it wrong?


Meta:
Using rls from current master branch.

$ rustc --version
rustc 1.22.0-nightly (539f2083d 2017-09-13)
$ rustup --version
rustup 1.6.0 (a11c01e8c 2017-08-30)
$ rustup toolchain list
nightly-x86_64-unknown-linux-gnu (default)
$ rustup component list
cargo-x86_64-unknown-linux-gnu (default)
rls-x86_64-unknown-linux-gnu (installed)
rust-analysis-x86_64-unknown-linux-gnu (installed)
rust-docs-x86_64-unknown-linux-gnu (default)
rust-src (installed)

@jonasbb
Copy link
Contributor Author

jonasbb commented Sep 16, 2017

@Xanewok For a simple library project (only a lib.rs with your content above) it works for me. I try to look at a workspace later. Although I have never used them before, so it might take a while.

find-impl

@Xanewok
Copy link
Member

Xanewok commented Sep 17, 2017

I tried doing the same in bare lib or bare bin project, but to no avail. I'll try fixing my setup.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants