scalameta / metals

Scala language server with rich IDE features 🚀
https://scalameta.org/metals/
Apache License 2.0
2.07k stars 323 forks source link

Autocomplete misses some classes #6630

Open kostaskougios opened 1 month ago

kostaskougios commented 1 month ago

Describe the bug

I got a class TroopsClientState and TroopsClientNextState. If I search for a class and type TCS I can see both, but in the editor when I do i.e. def tcs:TCS(Ctrl-Space) I only get TroopsClientNextState for some reason.

I am using scala 3.4.2 with sbt.

Expected behavior

TCS(Ctrl-Space) should show both classes

Operating system

macOS

Editor/Extension

VS Code

Version of Metals

v1.38.0

Extra context or search terms

No response

kasiaMarek commented 1 month ago

Thanks, for the report, could you add information about what Scala version you are using?

kostaskougios commented 1 month ago

Thanks, for the report, could you add information about what Scala version you are using?

Yes sorry added the scala version (3.4.2)

Also in the logs sometime I get this exception, not sure if it is related:

2024.07.26 10:38:52 WARN  org.h2.jdbc.JdbcBatchUpdateException: Unique index or primary key violation: "PUBLIC.PRIMARY_KEY_3 ON PUBLIC.TOPLEVEL_SYMBOL(JAR, PATH, SYMBOL) VALUES ( /* key:8874 */ 170, '/org/scalatest/enablers/TableAsserting.scala', 'org/scalatest/enablers/ForResult#')"; SQL statement:
insert into toplevel_symbol (symbol, path, jar) values (?, ?, ?) [23505-230]
    at org.h2.jdbc.JdbcPreparedStatement.executeBatch(JdbcPreparedStatement.java:1277)
    at scala.meta.internal.metals.JarTopLevels.putToplevels(JarTopLevels.scala:139)
    at scala.meta.internal.metals.JarTopLevels.$anonfun$putJarIndexingInfo$1(JarTopLevels.scala:85)
    at scala.runtime.java8.JFunction1$mcII$sp.apply(JFunction1$mcII$sp.scala:17)
    at scala.Option.map(Option.scala:242)
    at scala.meta.internal.metals.JarTopLevels.putJarIndexingInfo(JarTopLevels.scala:84)
    at scala.meta.internal.metals.Indexer.addSourceJarSymbols(Indexer.scala:666)
    at scala.meta.internal.metals.Indexer.$anonfun$indexDependencySources$5(Indexer.scala:491)
    at scala.collection.IterableOnceOps.foreach(IterableOnce.scala:619)
    at scala.collection.IterableOnceOps.foreach$(IterableOnce.scala:617)
    at scala.collection.AbstractIterable.foreach(Iterable.scala:935)
    at scala.collection.IterableOps$WithFilter.foreach(Iterable.scala:905)
    at scala.meta.internal.metals.Indexer.$anonfun$indexDependencySources$1(Indexer.scala:482)
    at scala.meta.internal.metals.Indexer.$anonfun$indexDependencySources$1$adapted(Indexer.scala:481)
    at scala.collection.IterableOnceOps.foreach(IterableOnce.scala:619)
    at scala.collection.IterableOnceOps.foreach$(IterableOnce.scala:617)
    at scala.collection.AbstractIterable.foreach(Iterable.scala:935)
    at scala.meta.internal.metals.Indexer.indexDependencySources(Indexer.scala:481)
    at scala.meta.internal.metals.Indexer.$anonfun$indexWorkspace$17(Indexer.scala:302)
    at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.scala:18)
    at scala.meta.internal.metals.TimerProvider.timedThunk(TimerProvider.scala:25)
    at scala.meta.internal.metals.Indexer.$anonfun$indexWorkspace$16(Indexer.scala:295)
    at scala.meta.internal.metals.Indexer.$anonfun$indexWorkspace$16$adapted(Indexer.scala:291)
    at scala.collection.immutable.List.foreach(List.scala:334)
    at scala.meta.internal.metals.Indexer.indexWorkspace(Indexer.scala:291)
    at scala.meta.internal.metals.Indexer.$anonfun$profiledIndexWorkspace$2(Indexer.scala:167)
    at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.scala:18)
    at scala.meta.internal.metals.TimerProvider.timedThunk(TimerProvider.scala:25)
    at scala.meta.internal.metals.Indexer.$anonfun$profiledIndexWorkspace$1(Indexer.scala:167)
    at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.scala:18)
    at scala.concurrent.Future$.$anonfun$apply$1(Future.scala:687)
    at scala.concurrent.impl.Promise$Transformation.run(Promise.scala:467)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
    at java.lang.Thread.run(Thread.java:1570)
tgodzik commented 1 month ago

I can't seem to reproduce, but might be this connected to the issue where the compiler would not get all the symbols from symbol search @kasiaMarek ?

@kostaskougios are you able to add a small reproduction. Any small data might be useful. Are both of those objects, classes etc. Are they in the same package. Best would be a small repro in a repository or text snippets here.

kostaskougios commented 1 month ago

@tgodzik , I tried and couldn't reproduce exactly but something similar happens to this repo of mine ( that I've created in the past for a different metals bug)

https://github.com/kostaskougios/metals-bugs

If you clone it then open class TroopsClientState and have a look. Now open "trymain" and uncomment the "val x=.." code:

@main def trymain() = println("Hi.") val x = TCS() Put the cursor just after TCS (before the parenthesis) and press Ctrl-Space. You should see some dependency-related classes in the autocomplete but not TroopsClientState or TroopClientNextState.

Now remove the parenthesis and try autocomplete for "val x = TCS". You should now see both classes in the autocomplete.

Maybe a different issue but worth having a look.

Also this repo will trigger the exception during (probably) indexing:

2024.07.26 16:29:19 WARN  org.h2.jdbc.JdbcBatchUpdateException: Unique index or primary key violation: "PUBLIC.PRIMARY_KEY_3 ON PUBLIC.TOPLEVEL_SYMBOL(JAR, PATH, SYMBOL) VALUES ( /* key:8178 */ 22, '/org/scalatest/enablers/TableAsserting.scala', 'org/scalatest/enablers/ForResult#')"; SQL statement:
insert into toplevel_symbol (symbol, path, jar) values (?, ?, ?) [23505-230]
    at org.h2.jdbc.JdbcPreparedStatement.executeBatch(JdbcPreparedStatement.java:1277)
kostaskougios commented 1 month ago

One thing I notice is that if I ctrl-space a non-imported class of my project, it is not recommended. But if I save the file and Cmd-. then the classes or my project are recommended to be imported.

kasiaMarek commented 1 month ago

I can't seem to reproduce, but might be this connected to the issue where the compiler would not get all the symbols from symbol search @kasiaMarek ?

No I don't think so. EDIT: ~There seems to be an odd behavior connected to symbol search.~ It may be just the matter of fuzzy search. Fuzzy search for symbols from compiler was only added after 3.4.2 so doing TCS won't suggest things that are already in scope.

Side note: Here type not module should be suggested (TroopClientNextState is imported). [EDIT: works fine on 3.5.0-RC6]

Zrzut ekranu 2024-07-30 o 15 36 27

Also this repo will trigger the exception during (probably) indexing:

It seems the scopes are incorrectly detected and indexer produces the same symbol twice.

Maybe a different issue but worth having a look.

Heh, that's a funny one. It does seem to be a different thing.