sonatype/m2eclipse-scala

m2eclipse-scala does not set scala library container properly

scottcarey opened this issue · 13 comments

With Eclipse Luna and the Eclipse IDE 4.0 milestone 3, loading maven projects configured to use scala 2.10 does not work. The projects get configured to use scala 2.11.2 as the library container.

This leads to "The version of scala library found in the build path (2.11.2) is incompatible with the one expected by scala IDE (2.10). Please replace the scala library with the scala container or a compatible scala library jar."

Or if -Xsource:2.10 is not present "akka-actor_2.10-2.3.0.jar of rrScalaCommon build path is cross-compiled with an incompatible version of Scala (2.10.0.). In case this report is mistaken, this check can be disabled in the compiler preference page."

The m2e integration for eclipse should:
Set the Scala Library container on a per project basis in accordance with the major version specified in the project pom's scala-library dependency.

This is very obnoxious at the moment, as I will have to manually set the version for 30+ projects.

Hi,

I didn't check ' Eclipse Luna and the Eclipse IDE 4.0 milestone 3'. But
IIRC m2eclipse-scala replace any version scala-library from pom.xml in
eclipse 'classpath by "SCALA_CONTAINER" provide by Scala-IDE plugin without
taking care of the version. because :

  • scala-ide doesn't work correclty with other version of
    scala-library/compiler than its own
  • scala-ide doesn't work correclty with several version of scala-library in
    the classpath
  • scala-ide doesn't "officialy" support multiple version of scala, or
    setting scala version per project (only the version installed with the
    plugin)

So m2eclipse doesn't "say" use scala version X, but "say" use THE scala
version provided by the plugin.

Support of -Xsource (http://www.scala-lang.org/news/2.11.1) and
multi-version in scala-ide (
http://scala-ide.org/blog/scala-installations.html) is recent. I'll see if
m2eclipse-scala can enable it without breaking other configuration.
Currently m2eclipse-scala has no dependency to scala-ide => works with
every version without special build, tricks...

On Fri, Aug 29, 2014 at 7:01 AM, Scott Carey notifications@github.com
wrote:

With Eclipse Luna and the Eclipse IDE 4.0 milestone 3, loading maven
projects configured to use scala 2.10 does not work. The projects get
configured to use scala 2.11.2 as the library container.

This leads to "The version of scala library found in the build path
(2.11.2) is incompatible with the one expected by scala IDE (2.10). Please
replace the scala library with the scala container or a compatible scala
library jar."

Or if -Xsource:2.10 is not present "akka-actor_2.10-2.3.0.jar of
rrScalaCommon build path is cross-compiled with an incompatible version of
Scala (2.10.0.). In case this report is mistaken, this check can be
disabled in the compiler preference page."

The m2e integration for eclipse should:
Set the Scala Library container on a per project basis in accordance with
the major version specified in the project pom's scala-library dependency.

This is very obnoxious at the moment, as I will have to manually set the
version for 30+ projects.


Reply to this email directly or view it on GitHub
#30.

The scala IDE 4.0 installed has both 2.10 and 2.11 environments available, and I can change it on a per project basis by hand. Manually setting it to 2.11 changed the "Scala Library container" in each project to 2.10.4 and allowing it to work on this set of projects, which are all scala 2.10 for now (because of downstream dependencies that have not produced a 2.11 build).

screen shot 2014-08-29 at 1 04 33 am
screen shot 2014-08-29 at 1 04 50 am

I chose the "latest 2.10 bundle" and then after saving, it automatically added the 'Additional command line parameters listed' -- I did not set those.

A flaw in the Scala IDE that makes this worse is that the above drop-down is only available at the per-project level, and is not available globally, so I can't set it in one place.

The Java maven integration for eclipse will set the java JRE and compile target on a per project basis, based on what is configured in Maven.

Hi @davidB, and thanks for your attention on this issue.

The classpath containers management has indeed changed a lot since multi-version support. Whatever you will find in getContainer(javaProject, SCALA_CONTAINER_PATH) will reflect the correct state of the project as it is currently configured (provided you ask the right javaProject of course : since we have 2.11 & 2.10 projects one beside the other, the configuration is project-dependent).

But changing the classpath (and I believeit is done in https://github.com/sonatype/m2eclipse-scala/blob/master/org.maven.ide.eclipse.scala/src/org/maven/ide/eclipse/scala/ScalaProjectConfigurator.java#L166) triggers a listener that creates a cascade of changes that make sure the various settings (-xSource flag, chosen scala installation, library on classpath), stay aligned in a consistent manner (or to trigger the right errors if they get out of sync). I'm afraid this is what @scottcarey is witnessing above : this classpath rewriting is triggering errors when it can't (for a moment) find the correct library on classpath.

I'm looking deeper into m2eclipse to try to understand why you need to modify the classpath like that. I'm unfamiliar with m2eclipse, so don't hesitate to shoot me some pointers by email — en français si ça t'arrange.

Bonjour Francois,

Depuis la version 0.0.1 (voir le README) de m2eclipse-scala (IIRC ~ scala
2.7), un de ses roles est de supprimer scala-library, scala-compiler,... du
container MAVEN pour utiliser la version du plugin Scala-IDE. Le plugin se
comportant assez mal s'il y avait plusieurs version de scala ou des version
differentes et pas de SCALA_CONTAINER.

On Fri, Sep 12, 2014 at 2:29 PM, François Garillot <notifications@github.com

wrote:

Hi @davidB https://github.com/davidB, and thanks for your attention on
this issue.

The classpath containers management has indeed changed a lot since
multi-version support. Whatever you will find in getContainer(javaProject,
SCALA_CONTAINER_PATH) will reflect the correct state of the project as it
is currently configured (provided you ask the right javaProject of course
: since we have 2.11 & 2.10 projects one beside the other, the
configuration is project-dependent).

But changing the classpath (and I believeit is done in
https://github.com/sonatype/m2eclipse-scala/blob/master/org.maven.ide.eclipse.scala/src/org/maven/ide/eclipse/scala/ScalaProjectConfigurator.java#L166)
triggers a listener that creates a cascade of changes that make sure the
various settings (-xSource flag, chosen scala installation, library on
classpath), stay aligned in a consistent manner (or to trigger the right
errors if they get out of sync). I'm afraid this is what @scottcarey
https://github.com/scottcarey is witnessing above : this classpath
rewriting is triggering errors when it can't (for a moment) find the
correct library on classpath.

I'm looking deeper into m2eclipse to try to understand why you need to
modify the classpath like that. I'm unfamiliar with m2eclipse, so don't
hesitate to shoot me some pointers by email — en français si ça t'arrange.


Reply to this email directly or view it on GitHub
#30 (comment)
.

OK, donc, si j'ai bien compris :

  • tu as besoin de faire une modification (attribut deployable) pour chaque CONTAINER (SCALA_LIBRARY, SCALA_COMPILER), qui ne change en rien sa version
  • tu as besoin d'enlever les scala-library-2.xx.jar, scala-compiler-2xx.jar pour que l'IDE utilise à la place ses propres indirections (les containers SCALA_COMPILER, SCALA_LIBRARY, ci-dessus).

Je pensais à ouvrir dans l'API deux fonctions :

  • mutateScalaClasspath(transform: IClasspathEntry => IClasspathEntry, select: IClasspathEntry => Boolean)
    mutateScalaClasspath applique transform aux éléments du classpath qui vérifient select. Ça te permettrait de changer l'attribut des containers.
  • replaceScalaArtifact(scalaLib : IClasspathEntry): Boolean, où replaceScalaArtifact se charge tout seul de comprendre quel est le meilleur analogue 'scala' à la librairie passée en entrée (scalaLib = un parmi scala-library, scala-compiler, ...), de replacer ce scalaLib par un élément du classpath idoine (probablement un container SCALA_* ci-dessus), de configurer le projet (2.10, 2.11, ...) et de renvoyer True s'il a réussi. En cas d'échec (retour False), tu peux toujours faire la modif à la main comme auparavant.

Qu'en penses-tu ? Ça couvrirait à peu près tes besoins pour ce qui est du classpath ?

OK.
Je ne comprend pas l'expression "ouvrir dans l'API" (l'api de qui ?).
Tu peux changer le code de m2eclipse-scala (et faire un PR).
Rappel :

  • il ne faut pas que m2eclipse-scala dépende (compilation) de scala-ide ou
    de scala.
  • le plugin fonctionne que scala-ide soit present ou non (comportement
    different).
    => le plugin est écrit en java.

2014-09-14 11:33 GMT+02:00 François Garillot notifications@github.com:

OK, donc, si j'ai bien compris :

  • tu as besoin de faire une modification (attribut deployable) pour
    chaque CONTAINER (SCALA_LIBRARY, SCALA_COMPILER), qui ne change en rien sa
    version
  • tu as besoin d'enlever les scala-library-2.xx.jar,
    scala-compiler-2xx.jar pour que l'IDE utilise à la place ses propres
    indirections (les containers SCALA_COMPILER, SCALA_LIBRARY, ci-dessus).

Je pensais à ouvrir dans l'API deux fonctions :

mutateScalaClasspath(transform: IClasspathEntry => IClasspathEntry,
select: IClasspathEntry => Boolean)
où mutateScalaClasspath applique transform aux éléments du classpath
qui vérifient select. Ça te permettrait de changer l'attribut des
containers.

replaceScalaArtifact(scalaLib : IClasspathEntry): Boolean, où
replaceScalaArtifact se charge tout seul de comprendre quel est le
meilleur analogue 'scala' à la librairie passée en entrée (scalaLib = un
parmi scala-library, scala-compiler, ...), de replacer ce scalaLib par
un élément du classpath idoine (probablement un container SCALA_*
ci-dessus), de configurer le projet (2.10, 2.11, ...) et de renvoyer
True s'il a réussi. En cas d'échec (retour False), tu peux toujours
faire la modif à la main comme auparavant.

Qu'en penses-tu ? Ça couvrirait à peu près tes besoins pour ce qui est du
classpath ?


Reply to this email directly or view it on GitHub
#30 (comment)
.

OK, alors en fait c'est encore plus simple.

  • ton ScalaProjectConfigurator est appellé à chaque ouverture de projet.
  • il "nettoie" le classpath de tout élément qui permette de déterminer la bonne configuration pour le projet (en particulier la présence d' un jar 'scala-library').
  • Il "resette" le container SCALA_LIBRARY (pour ajouter l'attribut deployable) [1]

Or :

  • depuis le support multi-versions, l'IDE regarde ce qui se trouve dans le classpath pour savoir avec quel 'mode' (2.10/2.11) du compilateur traiter le projet, lors de son ouverture (et tout ça prend du temps, pour diverses raisons).
  • Pour ça il s'aide de la configuration du projet ou en son absence des jars du classpath
  • par ailleurs afin que les différents éléments soient 'raccord' toute modification 1/du classpath 2/des préférences influe sur l'autre (si tu modifies le container scala en 2.10, tes préférences passent en 2.10,et inversement)

Donc dans notre cas:

  • l'IDE reçoit un projet au classpath sans scala-library,
  • il ne peut donc s'aider que des préférences
  • ce qui va échouer au premier import, mais on peut espérer que ça marche quand l'utilisateur réouvre son projet après l'avoir bien configuré
  • sauf que tu resettes le SCALA_CONTAINER avec une valeur que tu as lue très tôt pendant l'ouverture du projet (i.e. ce container n'est pas encore initialisé avec le bonne config), et que ceci déclenche donc une configuration dictée par ce container (qui vaut le défaut = 2.11)

Deux solutions (qui ne requièrent ni Scala ni Scala-IDE en dépendance):

  • faire [1] avec l'API de JavaCore, en particulier requestContainerUpdate et getClasspathContainerInitializer. Sachant que le ClasspathContainerInitializer de Scala est updateable (canUpdateClasspathContainer == true) : si tu lis le container depuis cette API, tu devrais obtenir le bon.
  • avoir une option de configuration du plugin m2eclipse-scala qui dit si oui ou non tu enlèves (scala-library, scala-dbc ...) du classpath : c'est ce que fait sbt-eclipse qui est un peu l'analogue sbt de m2eclipse-scala, et Scala-IDE se débrouille bien pour s'autoconfigurer avec un scala-library correct sur le classpath. Cet appel serait conditionné par l'option en question.

Merci pour l'analyze, Je regarderai plus en detail ce soir.

A chaud, la deuxieme solution est la moins adaptée car m2eclipse-scala
n'est pas un plugin pour maven (comme sbt-eclipse pour sbt) et ne possède
aucun paramètre de conf. Donc cela necessiterai d'ajouter un écran de
préférence,...

2014-09-15 17:50 GMT+02:00 François Garillot notifications@github.com:

OK, alors en fait c'est encore plus simple.

  • ton ScalaProjectConfigurator est appellé à chaque ouverture de
    projet.
  • il "nettoie" le classpath de tout élément qui permette de déterminer
    la bonne configuration pour le projet (en particulier la présence d' un jar
    'scala-library').
  • Il "resette" le container SCALA_LIBRARY (pour ajouter l'attribut
    deployable) [1]

Or :

  • depuis le support multi-versions, l'IDE regarde ce qui se trouve
    dans le classpath pour savoir avec quel 'mode' (2.10/2.11) du compilateur
    traiter le projet, lors de son ouverture.
  • Pour ça il s'aide de la configuration du projet ou en son absence
    des jars du classpath
  • par ailleurs afin que les différents éléments soient 'raccord' toute
    modification 1/du classpath 2/des préférences influe sur l'autre (si tu
    modifies le container scala en 2.10, tes préférences passent en 2.10,et
    inversement)

Donc dans notre cas:

Deux solutions (qui ne requièrent ni Scala ni Scala-IDE en dépendance):


Reply to this email directly or view it on GitHub
#30 (comment)
.

François,

Y a-t'il un moyen de setter un attribut du SCALA_CONTAINER pour indiquer la
version souhaitée (eg en indiquant la version de scala-librairie presente
dans le pom.xml) ?
Une autre solution serai que le plugin ne touche pas au classpath si la
version de Scala-IDE est superieur a ...... . Dans ce cas Scala-IDE
trouvera scala-librarie-x.y.z.jar dans le classpath (dans le container
MAVEN) et fairai sa sauce tout seul. (A chaque update de projet via m2e le
container MAVEN est reconstruit depuis le pom.xml)

On Tue, Sep 16, 2014 at 4:23 PM, François Garillot <notifications@github.com

wrote:

Link to related Scala-IDE ticket:
https://www.assembla.com/spaces/scala-ide/tickets/1002243#/activity/ticket
:


Reply to this email directly or view it on GitHub
#30 (comment)
.

@davidB Oui, ce serait une bonne solution. J'ai backporté les tests d'ordre du classpath à la dernière version stable de scala-ide :
scala-ide/scala-ide#807
scala-ide/scala-ide#806
Donc tu peux éviter de réordonner si la version de Scala-IDE est >= 3.0.4, au moins.

This issue has not been a problem for me on recent ScalaIDE / m2eclipse combinations.