Good code red [0.36.431] - analyser uses classpath of other project Follow
Hi,
I started having a lot of issues when I updated to 0.36.431 (I'm using IntelliJ 13.1.3, but same issues happen with 13.1.2).
Some symptoms:
- StringContext macros are red, saying `Value 's' is not a member of StringContext`.
- The type of every parameter in an annonymous function (e.g. x in xOption map { x => }) is inferred as Nothing, with error: Missing parameter type: x
- .distinct is broken, among probably other things
(code compiles fine, though, if I build the project from IntelliJ)
HOWEVER:
While I first thought these things are actually broken in and of themselves, it turns out IntelliJ is using the compiled (and ProGuarded) scala library code incorporated in sbt-launch.jar (this is a project generated using gen-idea). The project's structure hasn't changed and was working fine before.
Why would it be using that? The sbt-launch.jar is not a dependency of the actual project (let's name the project xxx). Instead, it only appears as a dependency of the xxx-build project as part of the "sbt-and-plugins" dependency (this is the project tracking sbt's "project" directory, which I believe is useless to IDEA but sbt-idea adds it anyway). Removing this dependency from IntelliJ makes the errors go away.
I'm confused as to how this jar ends up on the analyser's classpath for project xxx, and why it also takes preference over the scala library, which is the 1st dependency of the project.
Please sign in to leave a comment.
It would be great to take a look for project example as I've never heard about similar issues.
Best regards,
Alexander Podkhalyuzin.
I can reproduce this with an empty sbt project (an empty build.sbt), and a single source code (put it in src/main/scala/test.scala) containing:
The `s` stringContext is red, with the error: Cannot resolve symbol s
The primary conclusion I can draw from this is that this dependency, "SBT: sbt-and-plugins", ends up on the classpath of the analyser for "foo", whereas it should not.
I wasn't able to reproduce it. With scalaVersion 2.11.1 and SBT 0.13.5 everything is ok. I still need sample project.
Best regards,
Alexander Podkhalyuzin.
Ok I figured it out. I was using a global plugin that mistakenly ended up depending on sbt-launch.jar.
So essentially, it's the same as depending on it explicitly in the build.sbt of my test project:
build.sbt
libraryDependencies += "org.scala-sbt" % "sbt-launch" % "0.13.5"
This is what made sbt-launch.jar appear in sbt-and-plugins. Rather simple. (sorry about the confusion while I didn't realize why this was happening)
However -- the underlying issue I'm talking about still remains (even in the latest version of the Scala plugin [0.40.20] under IDEA Community Edition 138.1029).
If you add that dependency in build.sbt as advised, the analyser will mistakenly pick up this launcher jar, somehow, and then this will interfere with the analysis of the base project ("foo" as in the previous example), even though "SBT: sbt-and-plugins" is a dependency of foo-build but not of foo.
Hope this will finally be reproducible.
SBT can't resolve it:
[warn] ::::::::::::::::::::::::::::::::::::::::::::::
[warn] :: UNRESOLVED DEPENDENCIES ::
[warn] ::::::::::::::::::::::::::::::::::::::::::::::
[warn] :: org.scala-sbt#sbt-launch;0.13.5: not found
[warn] ::::::::::::::::::::::::::::::::::::::::::::::
What resolver I have to add. Typesafe repository wasn't enough:
resolvers += "Typesafe Repository" at "http://repo.typesafe.com/typesafe/releases/"
Best regards,
Alexander Podkhalyuzin.
Oops forgot about that - when you have a plugin it's added automatically.
The resolver you need is sbt.Classpaths.typesafeReleases. It's a bit different to define as it's an Ivy repository (the syntax you mentioned is for Maven repositories)
Edit: typesafeReleases, not sbtPluginReleases...
In my case sbt-launch was added as foo dependency (not foo-build). And then this mistake is almost ok, as in this case everything depends on order of classpath (it's some kind of luck). So if you move sbt-launch in module foo dependencies to the first place, compiler will give you similar error:
Error:(2, 11) object scala.StringContext is not a value
val a = s"hello"
^
If it's last, then compiler will not show error. Scala plugin shows error in both cases (probably it's not completely right to do so, however I'm not sure we need to fix it right now).
Probably it's not right from SBT support to see sbt-launch dependency for foo module, but if I add to build.sbt this dependency why it shouldn't be listed in the foo dependencies?
Best regards,
Alexander Podkhalyuzin.
Oh darn it - you're completely right. The dependency should be added to project/build.sbt (in my case, it was being brought in by a plugin I wrote). That's the surprising bit - that even though it's not in foo's dependencies, it still produces that error as if it were.
I wasn't able to put it to project/build.sbt:
scala.reflect.internal.FatalError: class StringContext does not have a member f
at scala.reflect.internal.Definitions$DefinitionsClass.scala$reflect$internal$Definitions$DefinitionsClass$$fatalMissingSymbol(Definitions.scala:1037)
at scala.reflect.internal.Definitions$DefinitionsClass.getMember(Definitions.scala:1055)
at scala.reflect.internal.Definitions$DefinitionsClass.getMemberMethod(Definitions.scala:1090)
at scala.reflect.internal.Definitions$DefinitionsClass.StringContext_f(Definitions.scala:538)
at scala.tools.reflect.FastTrack$class.fastTrack(FastTrack.scala:38)
at scala.tools.nsc.Global$$anon$1.fastTrack$lzycompute(Global.scala:493)
at scala.tools.nsc.Global$$anon$1.fastTrack(Global.scala:493)
at scala.tools.nsc.typechecker.Namers$Namer.methodSig(Namers.scala:1144)
at scala.tools.nsc.typechecker.Namers$Namer.getSig$1(Namers.scala:1454)
at scala.tools.nsc.typechecker.Namers$Namer.typeSig(Namers.scala:1466)
at scala.tools.nsc.typechecker.Namers$Namer$$anonfun$monoTypeCompleter$1$$anonfun$apply$1.apply$mcV$sp(Namers.scala:731)
at scala.tools.nsc.typechecker.Namers$Namer$$anonfun$monoTypeCompleter$1$$anonfun$apply$1.apply(Namers.scala:730)
at scala.tools.nsc.typechecker.Namers$Namer$$anonfun$monoTypeCompleter$1$$anonfun$apply$1.apply(Namers.scala:730)
at scala.tools.nsc.typechecker.Namers$Namer.scala$tools$nsc$typechecker$Namers$Namer$$logAndValidate(Namers.scala:1499)
at scala.tools.nsc.typechecker.Namers$Namer$$anonfun$monoTypeCompleter$1.apply(Namers.scala:730)
at scala.tools.nsc.typechecker.Namers$Namer$$anonfun$monoTypeCompleter$1.apply(Namers.scala:729)
at scala.tools.nsc.typechecker.Namers$$anon$1.completeImpl(Namers.scala:1614)
at scala.tools.nsc.typechecker.Namers$LockingTypeCompleter$class.complete(Namers.scala:1622)
at scala.tools.nsc.typechecker.Namers$$anon$1.complete(Namers.scala:1612)
at scala.reflect.internal.Symbols$Symbol.info(Symbols.scala:1231)
at scala.reflect.internal.Symbols$Symbol.initialize(Symbols.scala:1374)
at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:5295)
at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:5642)
at scala.tools.nsc.typechecker.Typers$Typer.scala$tools$nsc$typechecker$Typers$Typer$$typedStat$1(Typers.scala:2928)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$61.apply(Typers.scala:3032)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$61.apply(Typers.scala:3032)
at scala.collection.immutable.List.loop$1(List.scala:170)
at scala.collection.immutable.List.mapConserve(List.scala:186)
at scala.tools.nsc.typechecker.Typers$Typer.typedStats(Typers.scala:3032)
at scala.tools.nsc.typechecker.Typers$Typer.typedTemplate(Typers.scala:1919)
at scala.tools.nsc.typechecker.Typers$Typer.typedModuleDef(Typers.scala:1800)
at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:5584)
at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:5642)
at scala.tools.nsc.typechecker.Typers$Typer.scala$tools$nsc$typechecker$Typers$Typer$$typedStat$1(Typers.scala:2928)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$61.apply(Typers.scala:3032)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$61.apply(Typers.scala:3032)
at scala.collection.immutable.List.loop$1(List.scala:170)
at scala.collection.immutable.List.mapConserve(List.scala:186)
at scala.tools.nsc.typechecker.Typers$Typer.typedStats(Typers.scala:3032)
at scala.tools.nsc.typechecker.Typers$Typer.typedPackageDef$1(Typers.scala:5301)
at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:5587)
at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:5642)
at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:5704)
at scala.tools.nsc.typechecker.Analyzer$typerFactory$$anon$3.apply(Analyzer.scala:99)
at scala.tools.nsc.Global$GlobalPhase.applyPhase(Global.scala:464)
at scala.tools.nsc.typechecker.Analyzer$typerFactory$$anon$3$$anonfun$run$1.apply(Analyzer.scala:91)
at scala.tools.nsc.typechecker.Analyzer$typerFactory$$anon$3$$anonfun$run$1.apply(Analyzer.scala:91)
at scala.collection.Iterator$class.foreach(Iterator.scala:727)
at scala.collection.AbstractIterator.foreach(Iterator.scala:1157)
at scala.tools.nsc.typechecker.Analyzer$typerFactory$$anon$3.run(Analyzer.scala:91)
at sbt.compiler.Eval$$anonfun$compile$1$1.apply$mcV$sp(Eval.scala:159)
at sbt.compiler.Eval$$anonfun$compile$1$1.apply(Eval.scala:159)
at sbt.compiler.Eval$$anonfun$compile$1$1.apply(Eval.scala:159)
at scala.reflect.internal.SymbolTable.atPhase(SymbolTable.scala:207)
at sbt.compiler.Eval.compile$1(Eval.scala:159)
at sbt.compiler.Eval.compileAndLoad(Eval.scala:164)
at sbt.compiler.Eval.evalCommon(Eval.scala:135)
at sbt.compiler.Eval.eval(Eval.scala:86)
at sbt.EvaluateConfigurations$.evaluateSetting(EvaluateConfigurations.scala:144)
at sbt.EvaluateConfigurations$$anonfun$9.apply(EvaluateConfigurations.scala:106)
at sbt.EvaluateConfigurations$$anonfun$9.apply(EvaluateConfigurations.scala:105)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
at scala.collection.immutable.List.foreach(List.scala:318)
at scala.collection.TraversableLike$class.map(TraversableLike.scala:244)
at scala.collection.AbstractTraversable.map(Traversable.scala:105)
at sbt.EvaluateConfigurations$.evaluateSbtFile(EvaluateConfigurations.scala:105)
at sbt.Load$.sbt$Load$$loadSettingsFile$1(Load.scala:507)
at sbt.Load$$anonfun$sbt$Load$$memoLoadSettingsFile$1$1.apply(Load.scala:502)
at sbt.Load$$anonfun$sbt$Load$$memoLoadSettingsFile$1$1.apply(Load.scala:501)
at scala.Option.getOrElse(Option.scala:120)
at sbt.Load$.sbt$Load$$memoLoadSettingsFile$1(Load.scala:501)
at sbt.Load$$anonfun$loadSettings$1$2.apply(Load.scala:500)
at sbt.Load$$anonfun$loadSettings$1$2.apply(Load.scala:500)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
at scala.collection.mutable.ResizableArray$class.foreach(ResizableArray.scala:59)
at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:47)
at scala.collection.TraversableLike$class.map(TraversableLike.scala:244)
at scala.collection.AbstractTraversable.map(Traversable.scala:105)
at sbt.Load$.loadSettings$1(Load.scala:500)
at sbt.Load$.sbt$Load$$expand$1(Load.scala:523)
at sbt.Load$.loadSettings(Load.scala:528)
at sbt.Load$.sbt$Load$$loadSbtFiles$1(Load.scala:464)
at sbt.Load$.defaultLoad$1(Load.scala:475)
at sbt.Load$.loadTransitive(Load.scala:478)
at sbt.Load$.loadProjects$1(Load.scala:418)
at sbt.Load$.loadUnit(Load.scala:419)
at sbt.Load$$anonfun$15$$anonfun$apply$11.apply(Load.scala:256)
at sbt.Load$$anonfun$15$$anonfun$apply$11.apply(Load.scala:256)
at sbt.BuildLoader$$anonfun$componentLoader$1$$anonfun$apply$4$$anonfun$apply$5$$anonfun$apply$6.apply(BuildLoader.scala:93)
at sbt.BuildLoader$$anonfun$componentLoader$1$$anonfun$apply$4$$anonfun$apply$5$$anonfun$apply$6.apply(BuildLoader.scala:92)
at sbt.BuildLoader.apply(BuildLoader.scala:143)
at sbt.Load$.loadAll(Load.scala:312)
at sbt.Load$.loadURI(Load.scala:264)
at sbt.Load$.load(Load.scala:260)
at sbt.Load$.load(Load.scala:251)
at sbt.Load$.apply(Load.scala:134)
at sbt.Load$.defaultLoad(Load.scala:37)
at sbt.BuiltinCommands$.doLoadProject(Main.scala:473)
at sbt.BuiltinCommands$$anonfun$loadProjectImpl$2.apply(Main.scala:467)
at sbt.BuiltinCommands$$anonfun$loadProjectImpl$2.apply(Main.scala:467)
at sbt.Command$$anonfun$applyEffect$1$$anonfun$apply$2.apply(Command.scala:60)
at sbt.Command$$anonfun$applyEffect$1$$anonfun$apply$2.apply(Command.scala:60)
at sbt.Command$$anonfun$applyEffect$2$$anonfun$apply$3.apply(Command.scala:62)
at sbt.Command$$anonfun$applyEffect$2$$anonfun$apply$3.apply(Command.scala:62)
at sbt.Command$.process(Command.scala:95)
at sbt.MainLoop$$anonfun$1$$anonfun$apply$1.apply(MainLoop.scala:100)
at sbt.MainLoop$$anonfun$1$$anonfun$apply$1.apply(MainLoop.scala:100)
at sbt.State$$anon$1.process(State.scala:179)
at sbt.MainLoop$$anonfun$1.apply(MainLoop.scala:100)
at sbt.MainLoop$$anonfun$1.apply(MainLoop.scala:100)
at sbt.ErrorHandling$.wideConvert(ErrorHandling.scala:18)
at sbt.MainLoop$.next(MainLoop.scala:100)
at sbt.MainLoop$.run(MainLoop.scala:93)
at sbt.MainLoop$$anonfun$runWithNewLog$1.apply(MainLoop.scala:71)
at sbt.MainLoop$$anonfun$runWithNewLog$1.apply(MainLoop.scala:66)
at sbt.Using.apply(Using.scala:25)
at sbt.MainLoop$.runWithNewLog(MainLoop.scala:66)
at sbt.MainLoop$.runAndClearLast(MainLoop.scala:49)
at sbt.MainLoop$.runLoggedLoop(MainLoop.scala:33)
at sbt.MainLoop$.runLogged(MainLoop.scala:25)
at sbt.StandardMain$.runManaged(Main.scala:57)
at sbt.xMain.run(Main.scala:29)
at xsbt.boot.Launch$$anonfun$run$1.apply(Launch.scala:109)
at xsbt.boot.Launch$.withContextLoader(Launch.scala:129)
at xsbt.boot.Launch$.run(Launch.scala:109)
at xsbt.boot.Launch$$anonfun$apply$1.apply(Launch.scala:36)
at xsbt.boot.Launch$.launch(Launch.scala:117)
at xsbt.boot.Launch$.apply(Launch.scala:19)
at xsbt.boot.Boot$.runImpl(Boot.scala:44)
at xsbt.boot.Boot$.main(Boot.scala:20)
at xsbt.boot.Boot.main(Boot.scala)
But when I manually move library sbt-launch to foo-build dependencies in foo module everything looks ok.
By the way, why do you need sbt-launch as dependency? It's jar, where Scala library is proguarded, that's why Scala bytecode looks like Java file (because Scala annotation was removed). So nor Scala plugin, nor Scala compiler itself can't normally compile with this jar in dependencies, only luck can help, when sbt-launch is after scala-library.jar in your classpath, but it looks like bad practice.
Best regards,
Alexander Podkhalyuzin.