scalafix
scalafix copied to clipboard
Broken signatures: scala.meta.internal.classpath.MissingSymbolException: missing symbol
TL;DR
Hit scalafix.internal.v1.FileException while testing a snapshot release (0.3.0+9-86c91c86-SNAPSHOT) of the OrganizeImports rule against Metals master.
How to reproduce
-
Checkout scalameta/metals@7b88c09
-
Apply the following diff:
diff --git a/.scalafix.conf b/.scalafix.conf index 6d486e27..7edcce92 100644 --- a/.scalafix.conf +++ b/.scalafix.conf @@ -1,6 +1,11 @@ rules = [ - RemoveUnused, + OrganizeImports, ExplicitResultTypes, ] ExplicitResultTypes.rewriteStructuralTypesToNamedSubclass = false + +OrganizeImports { + expandRelative = true + groups = ["re:javax?\\.", "scala.", "scala.meta.", "*"] +} diff --git a/build.sbt b/build.sbt index e405fe98..0fea2ea1 100644 --- a/build.sbt +++ b/build.sbt @@ -31,6 +31,7 @@ val MUnitFramework = new TestFramework("munit.Framework") inThisBuild( List( + scalafixDependencies += "com.github.liancheng" %% "organize-imports" % "0.3.0+9-86c91c86-SNAPSHOT", version ~= { dynVer => if (isCI) dynVer else localSnapshotVersion // only for local publishing -
Running
sbt scalafixproduces the following exception on two source files:scalafix.internal.v1.FileException: unexpected error processing file <file-path> Caused by: scala.meta.internal.classpath.MissingSymbolException: missing symbol: snailgun at scala.meta.internal.scalacp.SymbolOps$XtensionSymbolSSpec.descriptor(SymbolOps.scala:119) at scala.meta.internal.scalacp.SymbolOps$XtensionSymbolSSymbol.uncached$1(SymbolOps.scala:18) at scala.meta.internal.scalacp.SymbolOps$XtensionSymbolSSymbol.toSemantic(SymbolOps.scala:25) at scala.meta.internal.scalacp.SymbolOps$XtensionSymbol.ssym(SymbolOps.scala:185) at scala.meta.internal.scalacp.SymbolOps$XtensionSymbolSSpec.owner(SymbolOps.scala:58) at scala.meta.internal.scalacp.SymbolOps$XtensionSymbolSSymbol.uncached$1(SymbolOps.scala:18) at scala.meta.internal.scalacp.SymbolOps$XtensionSymbolSSymbol.toSemantic(SymbolOps.scala:25) at scala.meta.internal.scalacp.SymbolOps$XtensionSymbol.ssym(SymbolOps.scala:185) at scala.meta.internal.scalacp.SymbolOps$XtensionSymbolSSpec.owner(SymbolOps.scala:58) at scala.meta.internal.scalacp.SymbolOps$XtensionSymbolSSymbol.uncached$1(SymbolOps.scala:18) at scala.meta.internal.scalacp.SymbolOps$XtensionSymbolSSymbol.toSemantic(SymbolOps.scala:25) at scala.meta.internal.scalacp.SymbolOps$XtensionSymbol.ssym(SymbolOps.scala:185) at scala.meta.internal.scalacp.TypeOps$XtensionTypeSType.loop$1(TypeOps.scala:22) at scala.meta.internal.scalacp.TypeOps$XtensionTypeSType.toSemanticTpe(TypeOps.scala:94) at scala.meta.internal.scalacp.TypeOps$XtensionTypeSType.loop$2(TypeOps.scala:136) at scala.meta.internal.scalacp.TypeOps$XtensionTypeSType.toSemanticSig(TypeOps.scala:139) at scala.meta.internal.scalacp.SymbolInformationOps$XtensionGSymbolSSymbolInformation.sig(SymbolInformationOps.scala:164) at scala.meta.internal.scalacp.SymbolInformationOps$XtensionGSymbolSSymbolInformation.toSymbolInformation(SymbolInformationOps.scala:251) at scala.meta.internal.scalacp.Scalacp.sinfos(Scalacp.scala:32) at scala.meta.internal.scalacp.Scalacp.$anonfun$parse$1(Scalacp.scala:20) at scala.collection.immutable.List.flatMap(List.scala:338) at scala.meta.internal.scalacp.Scalacp.parse(Scalacp.scala:19) at scala.meta.internal.scalacp.Scalacp$.parse(Scalacp.scala:50) at scala.meta.internal.metacp.ClassfileInfos$.fromClassNode(ClassfileInfos.scala:47) at scala.meta.internal.symtab.GlobalSymbolTable.loadSymbol(GlobalSymbolTable.scala:38) at scala.meta.internal.symtab.GlobalSymbolTable.info(GlobalSymbolTable.scala:67) at scalafix.internal.v1.InternalSemanticDoc.info(InternalSemanticDoc.scala:71) at scalafix.v1.SemanticDocument.info(SemanticDocument.scala:38) at scalafix.v1.Symbol.info(Symbol.scala:21) at fix.OrganizeImports.$anonfun$partitionImplicits$3(OrganizeImports.scala:196) at fix.OrganizeImports.$anonfun$partitionImplicits$3$adapted(OrganizeImports.scala:196) at scala.collection.TraversableLike.noneIn$1(TraversableLike.scala:306) at scala.collection.TraversableLike.filterImpl(TraversableLike.scala:372) at scala.collection.TraversableLike.filterImpl$(TraversableLike.scala:284) at scala.collection.AbstractTraversable.filterImpl(Traversable.scala:108) at scala.collection.TraversableLike.filter(TraversableLike.scala:382) at scala.collection.TraversableLike.filter$(TraversableLike.scala:382) at scala.collection.AbstractTraversable.filter(Traversable.scala:108) at fix.OrganizeImports.$anonfun$partitionImplicits$1(OrganizeImports.scala:196) at scala.collection.TraversableLike.$anonfun$flatMap$1(TraversableLike.scala:280) at scala.collection.immutable.List.foreach(List.scala:392) at scala.collection.TraversableLike.flatMap(TraversableLike.scala:280) at scala.collection.TraversableLike.flatMap$(TraversableLike.scala:277) at scala.collection.immutable.List.flatMap(List.scala:355) at fix.OrganizeImports.partitionImplicits(OrganizeImports.scala:192) at fix.OrganizeImports.organizeGlobalImports(OrganizeImports.scala:90) at fix.OrganizeImports.fix(OrganizeImports.scala:77) at scalafix.internal.v1.Rules.$anonfun$semanticPatch$1(Rules.scala:75) at scala.collection.immutable.List.map(List.scala:286) at scalafix.internal.v1.Rules.semanticPatch(Rules.scala:73) at scalafix.internal.v1.MainOps$.unsafeHandleFile(MainOps.scala:234)The problematic source files are:
metals/src/main/scala/scala/meta/internal/metals/BloopServers.scala metals/src/main/scala/scala/meta/internal/pantsbuild/commands/SharedCommand.scalaThis exception is triggered by a
Symbol#infocall in this line.
I have had a similar issue on sources using the wire macro from https://github.com/softwaremill/macwire, resulting in MissingSymbolException: com.softwaremill.macwire.Wired (and that macro only, which should NOT exercise https://github.com/softwaremill/macwire/blob/d509b04bb95567a935497bbef186875c60fce13b/macros/src/main/scala/com/softwaremill/macwire/MacwireMacros.scala#L118).
Changing in these source files the global import from com.softwaremill.macwire.wire (which is enough to compile) to com.softwaremill.macwire._ did the trick. https://github.com/liancheng/scalafix-organize-imports/pull/51 also silences the issue.
I'll try to write a repro.
I got a repro: https://github.com/bjaglin/scalafix/commit/d1d6afdd964cfe1835e248f649c0e4ad507234d2
My specific problem (which might not be the one originally reported, but looks very similar), is related to a broken runtime dependency: "com.softwaremill.macwire" %% "macros" is built against "com.softwaremill.macwire" %% "macros % Provided", so when the latter is missing in the classpath (which is weird but a common/documented usage of the lib), lookups on a symbol that is in a class file that refer to one that was provided at compilation time fail.
So when looking up com.softwaremill.macwire.package.wire(), we get through https://github.com/softwaremill/macwire/blob/release-2.3.3/macros/src/main/scala/com/softwaremill/macwire/package.scala#L33 (which happens to be a macro, but I don't think it matters):
missing symbol: com.softwaremill.macwire.Wired
scala.meta.internal.classpath.MissingSymbolException: missing symbol: com.softwaremill.macwire.Wired
at scala.meta.internal.scalacp.SymbolOps$XtensionSymbolSSpec.descriptor(SymbolOps.scala:119)
at scala.meta.internal.scalacp.SymbolOps$XtensionSymbolSSymbol.uncached$1(SymbolOps.scala:18)
at scala.meta.internal.scalacp.SymbolOps$XtensionSymbolSSymbol.toSemantic(SymbolOps.scala:25)
at scala.meta.internal.scalacp.SymbolOps$XtensionSymbol.ssym(SymbolOps.scala:185)
at scala.meta.internal.scalacp.TypeOps$XtensionTypeSType.loop$1(TypeOps.scala:22)
at scala.meta.internal.scalacp.TypeOps$XtensionTypeSType.toSemanticTpe(TypeOps.scala:94)
at scala.meta.internal.scalacp.TypeOps$XtensionTypeSType.loop$2(TypeOps.scala:108)
at scala.meta.internal.scalacp.TypeOps$XtensionTypeSType.toSemanticSig(TypeOps.scala:139)
at scala.meta.internal.scalacp.SymbolInformationOps$XtensionGSymbolSSymbolInformation.sig(SymbolInformationOps.scala:164)
at scala.meta.internal.scalacp.SymbolInformationOps$XtensionGSymbolSSymbolInformation.toSymbolInformation(SymbolInformationOps.scala:251)
at scala.meta.internal.scalacp.Scalacp.sinfos(Scalacp.scala:32)
at scala.meta.internal.scalacp.Scalacp.$anonfun$parse$1(Scalacp.scala:20)
at scala.collection.immutable.List.flatMap(List.scala:338)
at scala.meta.internal.scalacp.Scalacp.parse(Scalacp.scala:19)
at scala.meta.internal.scalacp.Scalacp$.parse(Scalacp.scala:50)
at scala.meta.internal.metacp.ClassfileInfos$.fromClassNode(ClassfileInfos.scala:47)
at scala.meta.internal.symtab.GlobalSymbolTable.loadSymbol(GlobalSymbolTable.scala:38)
at scala.meta.internal.symtab.GlobalSymbolTable.info(GlobalSymbolTable.scala:67)
at scalafix.internal.v1.InternalSemanticDoc.info(InternalSemanticDoc.scala:72)
at scalafix.v1.SemanticDocument.info(SemanticDocument.scala:38)
at scalafix.v1.Symbol.info(Symbol.scala:21)
It looks like scalameta has support for a graceful handling of this via https://github.com/scalameta/scalameta/blob/v4.3.10/semanticdb/metacp/src/main/scala/scala/meta/internal/scalacp/SymbolInformationOps.scala#L188-L192. However, in the current codepath, there is no way to enable that stubBrokenSignatures flag since settings are not exposed. I guess that would be doable?
Letting the exception bubble up to scalafix which would recover to None is not an option I guess, since in that case, we do want to return the information we have about the symbol we are looking up - it's just that one of the overall parsing of the class fail in https://github.com/scalameta/scalameta/blob/v4.3.10/semanticdb/metacp/src/main/scala/scala/meta/internal/scalacp/Scalacp.scala#L19-L20.