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

feature: go to implementations for dependency sources #5623

Merged

Conversation

kasiaMarek
Copy link
Contributor

@kasiaMarek kasiaMarek commented Sep 6, 2023

Go to implementation for dependency sources scalameta/metals-feature-requests#119.
resolves: #1287
We index the type hierarchy using ScalaTopLevelMtags, only saving the name of the overridden symbol and its usage position, the actual symbol is resolved lazily.

Shortcomings:

  • won't work for renamed import
Benchmark                        Mode  Cnt  Score   Error  Units
MetalsBench.toplevelsScalaIndex    ss   10  0.332 ± 0.007   s/op
MetalsBench.typeHierarchyIndex     ss   10  0.331 ± 0.004   s/op

follow up: provide solution for handling renamed symbols

@filipwiech
Copy link
Contributor

This is awesome! Thank you for working on this, it's something I was missing when coming from the IntelliJ. 👍

Copy link
Member

@jkciesluk jkciesluk left a comment

Choose a reason for hiding this comment

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

That’s an amazing feature! I have few nitpicks

symbol: String
)(implicit ec: ExecutionContext): Future[Set[ClassLocation]] = {
val workspaceImplementations = getWorkspaceLocations(symbol)
val enumCasesImplementations =
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 add a comment explaining why we have enumCases here? I feel like I will soon forget it's because they are resolved during indexing

@kasiaMarek kasiaMarek force-pushed the implementations-for-dependecy-sources branch from 7b716d1 to 37ebd1b Compare October 2, 2023 14:04
Copy link
Contributor

@tgodzik tgodzik left a comment

Choose a reason for hiding this comment

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

Great work! Sorry for taking so long to review.

@kasiaMarek kasiaMarek force-pushed the implementations-for-dependecy-sources branch from 37ebd1b to 9b91b06 Compare October 27, 2023 16:11
@kasiaMarek kasiaMarek force-pushed the implementations-for-dependecy-sources branch from 9b91b06 to 25bf321 Compare October 30, 2023 17:17
@kasiaMarek kasiaMarek force-pushed the implementations-for-dependecy-sources branch from 352fa37 to 83436ad Compare November 21, 2023 20:26
Copy link
Contributor

@tgodzik tgodzik left a comment

Choose a reason for hiding this comment

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

Should this work for Scala standard library? I am trying to find implementations of Seq but nothing is returned. Maybe you could add a test in ImplementationLspSuite?

@tgodzik
Copy link
Contributor

tgodzik commented Nov 22, 2023

Ok, it seems when I try it in the Metals repository it works sometimes, but each time it actually generates heaps of errors such as:

jar:file://<HOME>/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.12.17/scala-library-2.12.17-sources.jar!/scala/collection/immutable/MapProxy.scala
### jar%3Afile%3A%2F%2F%2Fhome%2Ftgodzik%2F.cache%2Fcoursier%2Fv1%2Fhttps%2Frepo1.maven.org%2Fmaven2%2Forg%2Fscala-lang%2Fscala-library%2F2.12.17%2Fscala-library-2.12.17-sources.jar%21%2Fscala%2Fcollection%2Fimmutable%2FMapProxy.scala:20: error: ; expected but package found
package collection
^

occurred in the presentation compiler.

action parameters:
uri: jar:file://<HOME>/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.12.17/scala-library-2.12.17-sources.jar!/scala/collection/immutable/MapProxy.scala

och after a while I get an OOM.

It seems to have work on very basic Set, on Set in Predef, but not the Set in immutable package.

Could you take a look?

@Z1kkurat
Copy link
Contributor

This is amazing, I'm so excited about this feature, thanks a million for your effort! 🎉

check(
"java-implementation",
"java-implementation".ignore,
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 ignored tests with java files. We need to implement info in java pc. Alternatively, we can force Compilers to use scala pc for info (at least for now), this should make go to impl work in java files that belong to scala build target.

Copy link
Contributor

Choose a reason for hiding this comment

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

Let's note what still need to be done in the feature request

check(
"java-classes",
"java-classes".ignore,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

To make this work we need JavaMtags (or JavaTopLevelMatgs) to return information about overridden symbols. Now we don't know that RuntimeException implements Exception, and only MyException will be found.

@kasiaMarek kasiaMarek force-pushed the implementations-for-dependecy-sources branch from 688e897 to f285962 Compare January 16, 2024 15:33

import org.eclipse.lsp4j.Location

class SymbolHierarchyOps(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

All those things are moved from ImplementationProvider. Those are not needed for go to implementation anymore but are still used by Supermethods and RenameProvider. I didn't want to try and remove those in this PR.

@kasiaMarek kasiaMarek force-pushed the implementations-for-dependecy-sources branch from 0dd0fea to 8c6fdbc Compare January 17, 2024 14:12
Copy link
Contributor

@tgodzik tgodzik left a comment

Choose a reason for hiding this comment

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

I will still check out it locally to see if we didn't miss anything.

check(
"java-implementation",
"java-implementation".ignore,
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's note what still need to be done in the feature request

Copy link
Contributor

@tgodzik tgodzik 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, just a couple of comments

@@ -840,7 +859,8 @@ class Compilers(
}

def loadCompiler(
path: AbsolutePath
path: AbsolutePath,
forceScala: Boolean = false,
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you add docs saying why this is needed?

@@ -179,6 +179,10 @@ public CompletableFuture<List<SyntheticDecoration>> syntheticDecorations(Synthet
return CompletableFuture.completedFuture(Collections.emptyList());
}

public CompletableFuture<List<PcSymbolInformation>> info(String symbol) {
Copy link
Contributor

Choose a reason for hiding this comment

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

When can it return multiple? Is there a known case?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

overloaded methods

Copy link
Contributor

Choose a reason for hiding this comment

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

Though usually they have a different symbol

method()
method(+1)
etc.

so this should not repeat.

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, but I want it to return all. When we search for implementations of methods, we find implementations of owner class/trait and only then implementations of method, needs to be this way since we index only class hierarchy. E.g. if class A extends B and we're looking for implementations of B.method(+1), the searched method will be A.method but we don't know the disambiguator so I get them all to find the one I need. In Compilers.scala there is info and infoAll, the first one does exactly what you'd expect and returns only info about that exact symbol.

If this is too odd, we can add overloadedSymbols to PcSymbolInformation to learn all the overloaded and get info about each one by one.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@tgodzik, would you prefer I change this?

Copy link
Contributor

Choose a reason for hiding this comment

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

Could we get a full method symbol ? This should be possible using Mtags class. 🤔

Copy link
Contributor

@tgodzik tgodzik left a comment

Choose a reason for hiding this comment

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

LGTM! Amazing work!

@kasiaMarek kasiaMarek merged commit 2d1738a into scalameta:main Feb 26, 2024
25 of 26 checks passed
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.

Improve efficiency of go to implementation for non workspace symbols
5 participants