Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scala Installations support stage II : choose your own installation #731

Merged
merged 27 commits into from Jul 15, 2014

Conversation

huitseeker
Copy link
Member

This is here to help advance review for the second phase of the Scala Installations support

The basic functionality is here, meaning you can choose a scala installation instead of a source level, and add your own scala installation as just a bunch of jars. A few missing items that will be added quickly:

  • Directory installation tests (@skyluc)
  • Scala Installation switches tests (@huitseeker)
  • Classpath Container edition window should set the initially selected container to the current one
  • Classpath Container edition should prohibit edition and redirect to compiler settings if both compiler and library containers are on classpath
  • in Compiler Settings, Scala Installation combo field selection should update the Apply button and the dirtiness.
  • A project with differently-versioned libraries ("cross-compiled" case of the classpath check, e.g. sbteclipse) should offer a Scala installation preference change.
  • A project with the wrong scala-library ("previous version" case of the classpath check, currently suggesting -Xsource) should offer a Scala installation preference change
  • Detection of a no-longer-valid scala installation (currently falling back to desired source level or platform) should offer a Scala Installation preference change.
  • Change the "Installed Scalas" name on the workspace-wide install page to smoething else
  • Adapt w.r.t Don’t reuse platform classloader when ScalaInstallation matches its version #733

@ghprb-bot
Copy link

Test PASSed.
Refer to this link for build results: https://jenkins.scala-ide.org:8496/jenkins/job/ghprb-scala-ide-validator/847/

}
}

class LabelProvider extends org.eclipse.jface.viewers.LabelProvider {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since I have to nitpick, it would nice to have a pretty icon to go with that text ;-)

@dragos
Copy link
Member

dragos commented Jul 3, 2014

I didn't look too closely at the preferences code (and the publish-subscribe mechanism), but in my simple tests it worked well.

I noticed that sources are not found for custom installations (not a big problem).

I also noticed that the "Remove" button is not disabled for bundled/default (but it correctly doesn't remove them)

@huitseeker
Copy link
Member Author

@dragos The ListViewer under the Scala Installations listing is multi-select by construction. What should the behavior be in case the user tries to press Remove on a multiple selection, which would include both bundled and custom installations ?

@dragos
Copy link
Member

dragos commented Jul 3, 2014

Do what your conscience dictates :)

@huitseeker
Copy link
Member Author

@dragos : what's your test case for sources jars not being found for custom installs ? in particular, what are the source jar file names ?
EDIT: We determined not finding the source jars was because they weren't in the same directory, which is ok because as of now this is unsupported behavior.

@ghprb-bot
Copy link

Test PASSed.
Refer to this link for build results: https://jenkins.scala-ide.org:8496/jenkins/job/ghprb-scala-ide-validator/862/

import org.eclipse.jface.viewers.ISelection
import org.eclipse.jface.viewers.StructuredSelection
import org.scalaide.core.internal.project.ScalaProject
import org.scalaide.ui.internal.project.ScalaInstallationChoiceUIProviders
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are a lot of unused imports in this list

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ghprb-bot
Copy link

Test FAILed.
Refer to this link for build results: https://jenkins.scala-ide.org:8496/jenkins/job/ghprb-scala-ide-validator/869/

@dragos
Copy link
Member

dragos commented Jul 8, 2014

I'll have to look through the code. In my tests so far, it worked well. I would like to suggest a simpler description string for Scala installations. I think it's very confusing, and I couldn't really parse it easily (see screenshot). I'd like the string in there to be really clear:

Scala 2.11.2-....
Scala 2.10.5.---
...

I think that currently it shows multi-bundle/bundle/legacy and some hash number. Users won't have a clue as to what that is, nor why should they care.

For the dropdown (in preferences and in the classpath container) I'd also like to remove clutter (it's all valuable debugging info, but I don't think hey belong in user-facing strings). They should hopefully be very similar to what there's in Installed Scalas, namely

Scala 2.11 (dynamic)
Scala 2.10 (dynamic)
Scala 2.10.5.-..
Scala 2.11.2.-...

screen shot 2014-07-08 at 17 40 02

getName().fold(jarSeq)(str => str +: jarSeq).mkString
}

override def hashCode() = getHashString().hashCode()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should override equals as well, otherwise this only solves the first step in a hashmap lookup. Equality is still checked when hashcodes match.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@huitseeker
Copy link
Member Author

@dragos, as of now (huitseeker@6a83af6) the Scala Installations list looks like this :
installs

François Garillot and others added 9 commits July 11, 2014 13:30
Some cleaning:
- Project has simpler getDesiredScalaInstallationChoice.
- actually it's easy to have Scala installation saving log (harder for reading)
- factory method for directoryScalaInstallations
- more logging on install serialization
- cleaner Classpath test project
- cleaned imports
Tweaks the source jar resolution to be more strict
@dragos
Copy link
Member

dragos commented Jul 11, 2014

Seems to be working fine at this point, except that I get a dialog for every library that is cross-compiled with a different version. My project has 4 dependencies with _2.10. If I select a 2.11 installation, I get the warning, and suggestion to choose a different scala installation.

I do it once, but then the remaining 3 dependencies (each) trigger a dialog that is out dated (I already changed the Scala installation to a compatible one). I think the dialog should be shown only once, at the end of the classpath check.

@dragos
Copy link
Member

dragos commented Jul 11, 2014

I'll try to fix it myself, let's see... :)

@huitseeker
Copy link
Member Author

@dragos huitseeker@d764529

@dragos
Copy link
Member

dragos commented Jul 11, 2014

@huitseeker Instead of more mutable state and flags, could we pull that code out of the loop?

@dragos
Copy link
Member

dragos commented Jul 11, 2014

I can regularly get into the following bad state just by following the dialogs:

  • Scala Installation: Latest 2.10
  • Scala classpath container: 2.11
  • Error markers for libraries cross-compiled with 2.10

I start with a 2.10 install, I switch to 2.11 and hit apply. Then I get the dialog asking me to change the Scala installation (twice). I do it. Everything closes down, but the containers are still on 2.11

@dragos
Copy link
Member

dragos commented Jul 11, 2014

Here's pulling out the dialog from the loop. I still might get two dialogs, but only because of the explicit call to classpathHasChanged. Turning off listeners might not be enough to ensure you don't get a certain event. I think they might be broadcasted on a different thread, so by the time they fire, you already added back the listener.

Should we just drop all this crazy UI logic that seems to never work well, and do less for the user? Just do whatever he tells us, and don't offer any quick fix dialogs. We could offer smarter quickfixes at the level of error markers, maybe?

--- a/org.scala-ide.sdt.core/src/org/scalaide/core/internal/project/ClasspathManagement.scala
+++ b/org.scala-ide.sdt.core/src/org/scalaide/core/internal/project/ClasspathManagement.scala
@@ -438,36 +438,36 @@ trait ClasspathManagement extends HasLogger { self: ScalaProject =>
     }
   }

-  private var crossCompiledMessageWasShown = new java.util.concurrent.atomic.AtomicBoolean(false)
   private def validateBinaryVersionsOnClasspath(): Seq[(Int, String)] = {
     import scala.concurrent.ExecutionContext.Implicits.global
     import org.scalaide.ui.internal.handlers.BadScalaInstallationPromptStatusHandler

     val entries = scalaClasspath.userCp
     val errors = mutable.ListBuffer[(Int, String)]()
+    var status: IStatus = Status.OK_STATUS

     for (entry <- entries if entry ne null) {
       entry.lastSegment() match {
         case VersionInFile(version) =>
           if (!plugin.isCompatibleVersion(version, this)) {
             val msg = s"${entry.lastSegment()} is cross-compiled with an incompatible version of Scala (${version.unparse}). In case this report is mistaken, this check can be disabled
-            if (!crossCompiledMessageWasShown.getAndSet(true)) {
-             val handlerSuffix = "Configure a Scala Installation for this specific project ?"
-               val status = new Status(IStatus.ERROR, ScalaPlugin.plugin.pluginId, BadScalaInstallationPromptStatusHandler.STATUS_CODE_PREV_CLASSPATH, msg + handlerSuffix, null)
-             try{
-              val handler = DebugPlugin.getDefault().getStatusHandler(status)
-                if (!classpathContinuation.isCompleted) handler.handleStatus(status, (this, classpathContinuation))
-                classpathContinuation.future onSuccess {
-                case f => f()
-                }
-             } finally { classpathContinuation = Promise[() => Unit]; crossCompiledMessageWasShown.set(false)}
-            }
+            val handlerSuffix = "\nConfigure a Scala Installation for this specific project ?"
+            status = new Status(IStatus.ERROR, ScalaPlugin.plugin.pluginId, BadScalaInstallationPromptStatusHandler.STATUS_CODE_PREV_CLASSPATH, msg + handlerSuffix, null)
             errors += ((IMarker.SEVERITY_ERROR, msg))
           }
         case _ =>
           // ignore libraries that aren't cross compiled/are compatible
       }
     }
+
+    if (!status.isOK()) try {
+      val handler = DebugPlugin.getDefault().getStatusHandler(status)
+      if (!classpathContinuation.isCompleted) handler.handleStatus(status, (this, classpathContinuation))
+      classpathContinuation.future onSuccess {
+        case f => f()
+      }
+    } finally { classpathContinuation = Promise[() => Unit]}
+
     errors.toSeq
   }

@huitseeker
Copy link
Member Author

@dragos huitseeker@ef2320e

- better name for scala installs
- equals for ScalaInstallation
- formatting, error messages typos
- no Default & apply for Scala Installations
- legacy bundles have a better tag
- sparser labels for Scala isntallations
- cleaner, unified names for installs in dialogs
- don't modify the existing install in case of refused solution
@@ -144,22 +166,20 @@ class CompilerSettings extends PropertyPage with IWorkbenchPreferencePage with E

var useProjectSettingsWidget: Option[UseProjectSettingsWidget] = None
var additionalParamsWidget: AdditionalParametersWidget = _
var dslWidget: Option[DesiredSourceLevelWidget] = None
var dslWidget: Option[DesiredInstallationWidget] = None

def save(): Unit = {
val project = getConcernedProject()
val scalaProject = project flatMap (ScalaPlugin.plugin.asScalaProject(_))
scalaProject foreach (p => preferenceStore0.removePropertyChangeListener(p.compilerSettingsListener))
var wasClasspathChanged = new AtomicIntegerArray(3)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't notice this in the first part of this PR, but

  • this var could be a val, right?
  • is there no other way than to have an array of bits to encode what happened? I'd prefer to have at least symbolic constants for what each bit stands for.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was referring to var wasClasspathChanged. I believe that one is never reassigned.

My main issue is with using 1 and 2 to refer to flags. I'm surprised I need to justify this, but here it goes: I can easily see myself messing this up next time I update this code. Having these constants have a name would be way more robust, and I believe, standard practice.. :)

François Garillot added 5 commits July 14, 2014 16:03
Also corrects initialize semantics change in compiler settings upon
background change
Also, more informative error markers.
Error markers do not create threading issues, especially since the
Property Dialog they create is modal.

The Dialogs go away.
@ghprb-bot
Copy link

Test PASSed.
Refer to this link for build results: https://jenkins.scala-ide.org:8496/jenkins/job/ghprb-scala-ide-validator/904/

@dragos
Copy link
Member

dragos commented Jul 15, 2014

@huitseeker, do we need to update the docs/blog?

@huitseeker
Copy link
Member Author

@dragos Done since yesterday huitseeker/scala-ide.github.com@6cef1bc
scala-ide/scala-ide.github.com#74
(I linked to the update on Flowdock)

skyluc added a commit that referenced this pull request Jul 15, 2014
Scala Installations support stage II : choose your own installation
@skyluc skyluc merged commit 73a785d into scala-ide:master Jul 15, 2014
@skyluc skyluc mentioned this pull request Jul 15, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
5 participants