metals icon indicating copy to clipboard operation
metals copied to clipboard

Ammonite support is broken when using sources defined as symbolic links

Open WojciechMazur opened this issue 2 years ago • 1 comments

Describe the bug

Using sources that are symbolic links instead of regular files leads to throwing exceptions when running Metals with Ammonite support.

Reproduction steps:

  1. mkdir source usage
  2. touch source/script.sc
  3. ln -fs source/script.sc usage/script.sc
  4. Open metals in usage directory, start ammonite server and try to import the build

Leads to exceptions listed below, replacing symlinks with regular files fixes the problem

java.nio.file.NoSuchFileException: <project-path>/.ammonite/scala-2.13.4/amm-2.5.2/source/script/src/ammonite/$file/^/source/script.scala
	at sun.nio.fs.UnixException.translateToIOException(UnixException.java:92)
	at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111)
	at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:116)
	at sun.nio.fs.UnixFileSystemProvider.newByteChannel(UnixFileSystemProvider.java:219)
	at java.nio.file.Files.newByteChannel(Files.java:370)
	at java.nio.file.Files.newByteChannel(Files.java:421)
	at java.nio.file.Files.readAllBytes(Files.java:3205)
	at scala.meta.internal.io.PlatformFileIO$.slurp(PlatformFileIO.scala:45)
	at scala.meta.internal.io.FileIO$.slurp(FileIO.scala:24)
	at scala.meta.internal.metals.InteractiveSemanticdbs.$anonfun$textDocument$2(InteractiveSemanticdbs.scala:90)
	at scala.Option.getOrElse(Option.scala:189)
	at scala.meta.internal.metals.InteractiveSemanticdbs.$anonfun$textDocument$1(InteractiveSemanticdbs.scala:90)
	at java.util.HashMap.compute(HashMap.java:1228)
	at java.util.Collections$SynchronizedMap.compute(Collections.java:2692)
	at scala.meta.internal.metals.InteractiveSemanticdbs.textDocument(InteractiveSemanticdbs.scala:89)
	at scala.meta.internal.metals.InteractiveSemanticdbs.textDocument(InteractiveSemanticdbs.scala:63)
	at scala.meta.internal.metals.AggregateSemanticdbs.loop$1(AggregateSemanticdbs.scala:30)
	at scala.meta.internal.metals.AggregateSemanticdbs.textDocument(AggregateSemanticdbs.scala:36)
	at scala.meta.internal.metals.CodeLensProvider.findLenses(CodeLensProvider.scala:22)
	at scala.meta.internal.metals.MetalsLanguageServer.$anonfun$codeLens$2(MetalsLanguageServer.scala:1628)
	at scala.meta.internal.metals.TimerProvider.timedThunk(TimerProvider.scala:25)
	at scala.meta.internal.metals.MetalsLanguageServer.$anonfun$codeLens$1(MetalsLanguageServer.scala:1626)
	at scala.meta.internal.metals.CancelTokens$.$anonfun$apply$2(CancelTokens.scala:26)
	at scala.concurrent.Future$.$anonfun$apply$1(Future.scala:659)
	at scala.util.Success.$anonfun$map$1(Try.scala:255)
	at scala.util.Success.map(Try.scala:213)
	at scala.concurrent.Future.$anonfun$map$1(Future.scala:292)
	at scala.concurrent.impl.Promise.liftedTree1$1(Promise.scala:33)
	at scala.concurrent.impl.Promise.$anonfun$transform$1(Promise.scala:33)
	at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:64)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.lang.Thread.run(Thread.java:834)

2022.04.06 13:24:54 ERROR text document: file:///<project-path>/.ammonite/scala-2.13.4/amm-2.5.2/source/script/src/ammonite/$file/%5E/source/script.scala
java.nio.file.NoSuchFileException: <project-path>/.ammonite/scala-2.13.4/amm-2.5.2/project-builder/mill/MillCommunityBuild/src/ammonite/$file/^/project-builder/mill/MillCommunityBuild.scala
	at sun.nio.fs.UnixException.translateToIOException(UnixException.java:92)
	at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111)
	at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:116)
	at sun.nio.fs.UnixFileSystemProvider.newByteChannel(UnixFileSystemProvider.java:219)
	at java.nio.file.Files.newByteChannel(Files.java:370)
	at java.nio.file.Files.newByteChannel(Files.java:421)
	at java.nio.file.Files.readAllBytes(Files.java:3205)
	at scala.meta.internal.io.PlatformFileIO$.slurp(PlatformFileIO.scala:45)
	at scala.meta.internal.io.FileIO$.slurp(FileIO.scala:24)
	at scala.meta.internal.metals.InteractiveSemanticdbs.$anonfun$textDocument$2(InteractiveSemanticdbs.scala:90)
	at scala.Option.getOrElse(Option.scala:189)
	at scala.meta.internal.metals.InteractiveSemanticdbs.$anonfun$textDocument$1(InteractiveSemanticdbs.scala:90)
	at java.util.HashMap.compute(HashMap.java:1228)
	at java.util.Collections$SynchronizedMap.compute(Collections.java:2692)
	at scala.meta.internal.metals.InteractiveSemanticdbs.textDocument(InteractiveSemanticdbs.scala:89)
	at scala.meta.internal.metals.InteractiveSemanticdbs.textDocument(InteractiveSemanticdbs.scala:63)
	at scala.meta.internal.metals.AggregateSemanticdbs.loop$1(AggregateSemanticdbs.scala:30)
	at scala.meta.internal.metals.AggregateSemanticdbs.textDocument(AggregateSemanticdbs.scala:36)
	at scala.meta.internal.metals.CodeLensProvider.findLenses(CodeLensProvider.scala:22)
	at scala.meta.internal.metals.MetalsLanguageServer.$anonfun$codeLens$2(MetalsLanguageServer.scala:1628)
	at scala.meta.internal.metals.TimerProvider.timedThunk(TimerProvider.scala:25)
	at scala.meta.internal.metals.MetalsLanguageServer.$anonfun$codeLens$1(MetalsLanguageServer.scala:1626)
	at scala.meta.internal.metals.CancelTokens$.$anonfun$apply$2(CancelTokens.scala:26)
	at scala.concurrent.Future$.$anonfun$apply$1(Future.scala:659)
	at scala.util.Success.$anonfun$map$1(Try.scala:255)
	at scala.util.Success.map(Try.scala:213)
	at scala.concurrent.Future.$anonfun$map$1(Future.scala:292)
	at scala.concurrent.impl.Promise.liftedTree1$1(Promise.scala:33)
	at scala.concurrent.impl.Promise.$anonfun$transform$1(Promise.scala:33)
	at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:64)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.lang.Thread.run(Thread.java:834)

2022.04.06 13:24:55 WARN  no build target for: <project-path>/repo/.ammonite/scala-2.13.4/amm-2.5.2/source/script//src/ammonite/$file/^/source/script/.scala

Expected behavior

It should not throw exceptions and allow to correctly use metals

Operating system

Linux

Editor/Extension

VS Code

Version of Metals

v0.11.2

Extra context or search terms

No response

WojciechMazur avatar Apr 06 '22 11:04 WojciechMazur

It seems the issue is due to the fact that we always unalias all the file uris we get, but ammonite produces ones using the symbolic name. We could add the check in:

https://github.com/scalameta/metals/blob/main/metals/src/main/scala/scala/meta/internal/metals/ammonite/Ammonite.scala#L126

if the file doesn't exist we could fallback to the link without dealias.

tgodzik avatar Apr 07 '22 15:04 tgodzik