diff --git a/project/dependencies.scala b/project/dependencies.scala index a2a65cace8c..740e8765a70 100644 --- a/project/dependencies.scala +++ b/project/dependencies.scala @@ -36,7 +36,7 @@ object Versions { val junitInterfaceVersion: String = "0.13.3" val bspVersion = "2.1.0-M3" - val sbtStructureVersion: String = "2024.1.2" + val sbtStructureVersion: String = "2024.1.2+0-38de1c9e+20240519-1859-SNAPSHOT" val sbtIdeaShellVersion: String = "2021.1.0" val compilerIndicesVersion = "1.0.14" diff --git a/sbt/sbt-api/src/org/jetbrains/sbt/project/settings/SbtProjectSettings.scala b/sbt/sbt-api/src/org/jetbrains/sbt/project/settings/SbtProjectSettings.scala index 113058a7cab..3519cfea39f 100644 --- a/sbt/sbt-api/src/org/jetbrains/sbt/project/settings/SbtProjectSettings.scala +++ b/sbt/sbt-api/src/org/jetbrains/sbt/project/settings/SbtProjectSettings.scala @@ -62,7 +62,7 @@ class SbtProjectSettings extends ExternalProjectSettings { //Settings used during SBT project import/reload @BeanProperty var resolveClassifiers: Boolean = true @BeanProperty var resolveSbtClassifiers: Boolean = false - @BeanProperty var preferScala2 = true + @BeanProperty var preferedScala: Int = 0 //See SCL-21158 for details //This should be in sync with what is used as a default value in // org.jetbrains.jps.incremental.scala.model.impl.JpsSbtDependenciesEnumerationHandler.shouldProcessDependenciesRecursively @@ -103,7 +103,7 @@ class SbtProjectSettings extends ExternalProjectSettings { result.useSbtShellForImport = useSbtShellForImport result.useSbtShellForBuild = useSbtShellForBuild result.enableDebugSbtShell = enableDebugSbtShell - result.preferScala2 = preferScala2 + result.preferedScala = preferedScala result.insertProjectTransitiveDependencies = insertProjectTransitiveDependencies result.useSeparateCompilerOutputPaths = useSeparateCompilerOutputPaths result @@ -112,7 +112,7 @@ class SbtProjectSettings extends ExternalProjectSettings { object SbtProjectSettings { // Increment if the converter algorithm is updated to trigger a reloading of previously opened projects. - val ConverterVersion = 2 + val ConverterVersion = 3 def default: SbtProjectSettings = { val settings = new SbtProjectSettings() diff --git a/sbt/sbt-impl/resources/messages/SbtBundle.properties b/sbt/sbt-impl/resources/messages/SbtBundle.properties index b3084ea75da..7b178db8448 100644 --- a/sbt/sbt-impl/resources/messages/SbtBundle.properties +++ b/sbt/sbt-impl/resources/messages/SbtBundle.properties @@ -97,9 +97,10 @@ sbt.settings.resolvers=Resolvers sbt.settings.noImplicitImportsFound=No implicit imports found ### org/jetbrains/sbt/project/settings/SbtExtraControls.scala -sbt.settings.scalaVersionPreference=Open cross-compiled Scala 3 / Scala 2 projects as Scala 2 +sbt.settings.scalaVersionPreference=Open cross-compiled Scala 3 / Scala 2 projects as: sbt.settings.scalaVersionPreference.tooltip=Projects that are cross-compiled against both Scala 2 and Scala 3 don't actually use Scala 3 features and can be opened as Scala 2 (which is more reliable) sbt.settings.useShell=use for: +sbt.settings.default=Default sbt.settings.download=Download: sbt.settings.shell.title=sbt shell sbt.settings.useShellForImport=project reload diff --git a/sbt/sbt-impl/src/org/jetbrains/sbt/project/SbtExternalSystemManager.scala b/sbt/sbt-impl/src/org/jetbrains/sbt/project/SbtExternalSystemManager.scala index 32c99f5314c..299b1e14e3f 100644 --- a/sbt/sbt-impl/src/org/jetbrains/sbt/project/SbtExternalSystemManager.scala +++ b/sbt/sbt-impl/src/org/jetbrains/sbt/project/SbtExternalSystemManager.scala @@ -88,6 +88,11 @@ object SbtExternalSystemManager { val vmOptions = getVmOptions(settingsState, jreHome) val environment = Map.empty ++ getAndroidEnvironmentVariables(projectJdkName) val sbtOptions = SbtOpts.combineOptionsWithArgs(settings.sbtOptions) + val preferedScala = projectSettings.preferedScala match { + case 0 => PreferedScala.Default + case 1 => PreferedScala.Scala2 + case 2 => PreferedScala.Scala3 + } new SbtExecutionSettings( realProjectPath = realProjectPath, @@ -103,7 +108,7 @@ object SbtExternalSystemManager { resolveSbtClassifiers = projectSettings.resolveSbtClassifiers, useShellForImport = projectSettings.useSbtShellForImport, shellDebugMode = projectSettings.enableDebugSbtShell, - preferScala2 = projectSettings.preferScala2, + preferedScala = preferedScala , userSetEnvironment = settingsState.sbtEnvironment.asScala.toMap, passParentEnvironment = settingsState.sbtPassParentEnvironment, insertProjectTransitiveDependencies = projectSettings.insertProjectTransitiveDependencies, diff --git a/sbt/sbt-impl/src/org/jetbrains/sbt/project/SbtProjectManagerListener.scala b/sbt/sbt-impl/src/org/jetbrains/sbt/project/SbtProjectManagerListener.scala index 63f5ad615c3..2e7c58e0a1f 100644 --- a/sbt/sbt-impl/src/org/jetbrains/sbt/project/SbtProjectManagerListener.scala +++ b/sbt/sbt-impl/src/org/jetbrains/sbt/project/SbtProjectManagerListener.scala @@ -11,7 +11,7 @@ private final class SbtProjectManagerListener extends ProjectManagerListener { override def projectOpened(project: Project): Unit = { SbtProjectSettings.forProject(project).foreach { settings => if (settings.converterVersion < SbtProjectSettings.ConverterVersion) { - if (project.hasScala3 && settings.preferScala2) { // TODO Remove (don't trigger the refresh unnecessarily) + if ((project.hasScala3 && settings.preferedScala == 1) || (project.hasScala2 && settings.preferedScala == 2)) { // TODO Remove (don't trigger the refresh unnecessarily) // TODO Only do this if auto-import is enabled? (more predictable, on the other hand, it's not about "build scripts", as the setting claims) ExternalSystemUtil.refreshProjects(new ImportSpecBuilder(project, SbtProjectSystem.Id).use(ProgressExecutionMode.IN_BACKGROUND_ASYNC)) // The converterVersion will be updated by SbtProjectDataService on a successful refresh. diff --git a/sbt/sbt-impl/src/org/jetbrains/sbt/project/SbtProjectResolver.scala b/sbt/sbt-impl/src/org/jetbrains/sbt/project/SbtProjectResolver.scala index e9b818fc779..6878ebbd8cd 100644 --- a/sbt/sbt-impl/src/org/jetbrains/sbt/project/SbtProjectResolver.scala +++ b/sbt/sbt-impl/src/org/jetbrains/sbt/project/SbtProjectResolver.scala @@ -160,7 +160,7 @@ class SbtProjectResolver extends ExternalSystemProjectResolver[SbtExecutionSetti val messageResult: Try[BuildMessages] = { if (useShellImport) { - val messagesF = dumper.dumpFromShell(project, structureFilePath, options, reporter, settings.preferScala2) + val messagesF = dumper.dumpFromShell(project, structureFilePath, options, reporter, settings.preferedScala) Try(Await.result(messagesF, Duration.Inf)) // TODO some kind of timeout / cancel mechanism } else { @@ -175,7 +175,7 @@ class SbtProjectResolver extends ExternalSystemProjectResolver[SbtExecutionSetti dumper.dumpFromProcess( projectRoot, structureFilePath, options, settings.vmExecutable, settings.vmOptions, settings.sbtOptions, environment, - sbtLauncher, sbtStructureJar, settings.preferScala2, settings.passParentEnvironment) + sbtLauncher, sbtStructureJar, settings.preferedScala, settings.passParentEnvironment) } } activeProcessDumper = None diff --git a/sbt/sbt-impl/src/org/jetbrains/sbt/project/settings/SbtExecutionSettings.scala b/sbt/sbt-impl/src/org/jetbrains/sbt/project/settings/SbtExecutionSettings.scala index aa557f65c4f..5739faf6a79 100644 --- a/sbt/sbt-impl/src/org/jetbrains/sbt/project/settings/SbtExecutionSettings.scala +++ b/sbt/sbt-impl/src/org/jetbrains/sbt/project/settings/SbtExecutionSettings.scala @@ -18,9 +18,16 @@ class SbtExecutionSettings(val realProjectPath: String, val resolveSbtClassifiers: Boolean, val useShellForImport: Boolean, val shellDebugMode: Boolean, - val preferScala2: Boolean, + val preferedScala: PreferedScala, val userSetEnvironment: Map[String, String], val passParentEnvironment: Boolean, val insertProjectTransitiveDependencies: Boolean, val useSeparateCompilerOutputPaths: Boolean ) extends ExternalSystemExecutionSettings + +sealed trait PreferedScala +object PreferedScala { + object Default extends PreferedScala + object Scala2 extends PreferedScala + object Scala3 extends PreferedScala +} \ No newline at end of file diff --git a/sbt/sbt-impl/src/org/jetbrains/sbt/project/settings/SbtExtraControls.scala b/sbt/sbt-impl/src/org/jetbrains/sbt/project/settings/SbtExtraControls.scala index e49640687a6..cac4b6c87a1 100644 --- a/sbt/sbt-impl/src/org/jetbrains/sbt/project/settings/SbtExtraControls.scala +++ b/sbt/sbt-impl/src/org/jetbrains/sbt/project/settings/SbtExtraControls.scala @@ -24,7 +24,7 @@ final class SbtExtraControls { val useSbtShellForImportCheckBox: JCheckBoxWithTooltip = ct(SbtBundle.message("sbt.settings.useShellForImport"), SbtBundle.message("sbt.settings.useShellForImport.tooltip")) val useSbtShellForBuildCheckBox: JCheckBoxWithTooltip = ct(SbtBundle.message("sbt.settings.useShellForBuild"), SbtBundle.message("sbt.settings.useShellForBuild.tooltip")) val remoteDebugSbtShellCheckBox: JCheckBoxWithTooltip = ct(SbtBundle.message("sbt.settings.remoteDebug"), SbtBundle.message("sbt.settings.remoteDebug.tooltip")) - val scalaVersionPreferenceCheckBox: JCheckBoxWithTooltip = ct(SbtBundle.message("sbt.settings.scalaVersionPreference"), SbtBundle.message("sbt.settings.scalaVersionPreference.tooltip")) + val scalaVersionPreferenceComboBox = new com.intellij.openapi.ui.ComboBox(Array(SbtBundle.message("sbt.settings.default"), "Scala 2", "Scala 3")) val insertProjectTransitiveDependencies: JCheckBoxWithTooltip = ct(SbtBundle.message("insert.project.transitive.dependencies"), SbtBundle.message("insert.project.transitive.dependencies.tooltip")) val useSeparateCompilerOutputPaths: JCheckBoxWithTooltip = ct(SbtBundle.message("use.separate.compiler.output.paths"), SbtBundle.message("use.separate.compiler.output.paths.tooltip")) private val useSeparateCompilerOutputPathsWarning: JBLabel = new JBLabel(SbtBundle.message("use.separate.compiler.output.paths.warning")) @@ -48,10 +48,19 @@ final class SbtExtraControls { false ) + val scalaVersionPreferencePanel = { + val panel = new JPanel() + panel.setLayout(new BoxLayout(panel, BoxLayout.LINE_AXIS)) + panel.add(new JBLabel(SbtBundle.message("sbt.settings.scalaVersionPreference"))) + panel.add(Box.createRigidArea(new Dimension(10, 0))) + panel.add(withTooltip(scalaVersionPreferenceComboBox, SbtBundle.message("sbt.settings.scalaVersionPreference.tooltip"))) + panel + } + content.add(new JBLabel(SbtBundle.message("sbt.settings.download")), new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(80, 16), null, 0, false)) content.add(resolveClassifiersCheckBox.panelWithTooltip, gc(0, 1, 1, 1)) content.add(resolveSbtClassifiersCheckBox.panelWithTooltip, gc(1, 1, 1, 1)) - content.add(scalaVersionPreferenceCheckBox.panelWithTooltip, gc(2, 0, 1, 2)) + content.add(scalaVersionPreferencePanel, new GridConstraints(2, 0, 1, 2, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)) content.add(insertProjectTransitiveDependencies.panelWithTooltip, gc(3, 0, 1, 2)) content.add(useSeparateCompilerOutputPaths.panelWithTooltip, gc(4, 0, 1, 2)) content.add(useSeparateCompilerOutputPathsWarning, warningConstraints) diff --git a/sbt/sbt-impl/src/org/jetbrains/sbt/project/settings/SbtProjectSettingsControl.scala b/sbt/sbt-impl/src/org/jetbrains/sbt/project/settings/SbtProjectSettingsControl.scala index d5c2c8a167d..357b4aad62c 100644 --- a/sbt/sbt-impl/src/org/jetbrains/sbt/project/settings/SbtProjectSettingsControl.scala +++ b/sbt/sbt-impl/src/org/jetbrains/sbt/project/settings/SbtProjectSettingsControl.scala @@ -76,7 +76,7 @@ class SbtProjectSettingsControl(context: Context, initialSettings: SbtProjectSet extraControls.useSbtShellForImportCheckBox.isSelected != settings.useSbtShellForImport || extraControls.useSbtShellForBuildCheckBox.isSelected != settings.useSbtShellForBuild || extraControls.remoteDebugSbtShellCheckBox.isSelected != settings.enableDebugSbtShell || - extraControls.scalaVersionPreferenceCheckBox.isSelected != settings.preferScala2 || + extraControls.scalaVersionPreferenceComboBox.getSelectedIndex != settings.preferedScala || extraControls.insertProjectTransitiveDependencies.isSelected != settings.insertProjectTransitiveDependencies || extraControls.useSeparateCompilerOutputPaths.isSelected != settings.useSeparateCompilerOutputPaths } @@ -97,7 +97,7 @@ class SbtProjectSettingsControl(context: Context, initialSettings: SbtProjectSet extraControls.useSbtShellForImportCheckBox.setSelected(settings.importWithShell) extraControls.useSbtShellForBuildCheckBox.setSelected(settings.buildWithShell) extraControls.remoteDebugSbtShellCheckBox.setSelected(settings.enableDebugSbtShell) - extraControls.scalaVersionPreferenceCheckBox.setSelected(settings.preferScala2) + extraControls.scalaVersionPreferenceComboBox.setSelectedIndex(settings.preferedScala) extraControls.insertProjectTransitiveDependencies.setSelected(settings.insertProjectTransitiveDependencies) extraControls.useSeparateCompilerOutputPaths.setSelected(settings.useSeparateCompilerOutputPaths) extraControls.refreshOutputPathsWarning() @@ -122,7 +122,7 @@ class SbtProjectSettingsControl(context: Context, initialSettings: SbtProjectSet settings.resolveSbtClassifiers = extraControls.resolveSbtClassifiersCheckBox.isSelected settings.useSbtShellForImport = extraControls.useSbtShellForImportCheckBox.isSelected settings.enableDebugSbtShell = extraControls.remoteDebugSbtShellCheckBox.isSelected - settings.preferScala2 = extraControls.scalaVersionPreferenceCheckBox.isSelected + settings.preferedScala = extraControls.scalaVersionPreferenceComboBox.getSelectedIndex settings.insertProjectTransitiveDependencies = extraControls.insertProjectTransitiveDependencies.isSelected settings.useSeparateCompilerOutputPaths = extraControls.useSeparateCompilerOutputPaths.isSelected diff --git a/sbt/sbt-impl/src/org/jetbrains/sbt/project/structure/SbtStructureDump.scala b/sbt/sbt-impl/src/org/jetbrains/sbt/project/structure/SbtStructureDump.scala index 32b484d26ee..850d95c828f 100644 --- a/sbt/sbt-impl/src/org/jetbrains/sbt/project/structure/SbtStructureDump.scala +++ b/sbt/sbt-impl/src/org/jetbrains/sbt/project/structure/SbtStructureDump.scala @@ -16,6 +16,7 @@ import org.jetbrains.plugins.scala.extensions.LoggerExt import org.jetbrains.plugins.scala.settings.CompilerIndicesSettings import org.jetbrains.sbt.SbtUtil._ import org.jetbrains.sbt.project.SbtProjectResolver.ImportCancelledException +import org.jetbrains.sbt.project.settings.PreferedScala import org.jetbrains.sbt.project.structure.SbtOption._ import org.jetbrains.sbt.project.structure.SbtStructureDump._ import org.jetbrains.sbt.shell.SbtShellCommunication @@ -51,7 +52,7 @@ class SbtStructureDump { structureFilePath: String, options: Seq[String], reporter: BuildReporter, - preferScala2: Boolean, + preferedScala: PreferedScala, ): Future[BuildMessages] = { reporter.start() @@ -66,8 +67,13 @@ class SbtStructureDump { val ideaPort = SbtCompilationSupervisorPort.port if (ideaPort == -1) "" else s"; set ideaPort in Global := $ideaPort" } else "" + val scalaSelection = preferedScala match { + case PreferedScala.Default => "" + case PreferedScala.Scala2 => "preferScala2;" + case PreferedScala.Scala3 => "preferScala3;" + } - val cmd = s";reload; $setCmd ;${if (preferScala2) "preferScala2;" else ""}*/*:dumpStructureTo $structureFilePath; session clear-all $ideaPortSetting" + val cmd = s";reload; $setCmd ;$scalaSelection*/*:dumpStructureTo $structureFilePath; session clear-all $ideaPortSetting" val aggregator = shellMessageAggregator(EventId(s"dump:${UUID.randomUUID()}"), shell, reporter) @@ -83,7 +89,7 @@ class SbtStructureDump { environment: Map[String, String], sbtLauncher: File, sbtStructureJar: File, - preferScala2: Boolean, + preferedScala: PreferedScala, passParentEnvironment: Boolean ) (implicit reporter: BuildReporter) @@ -96,13 +102,18 @@ class SbtStructureDump { s"""SettingKey[_root_.scala.Option[_root_.sbt.File]]("sbtStructureOutputFile") in _root_.sbt.Global := _root_.scala.Some(_root_.sbt.file("$structureFilePath"))""", s"""SettingKey[_root_.java.lang.String]("sbtStructureOptions") in _root_.sbt.Global := $optString""" ).mkString("set _root_.scala.collection.Seq(", ",", ")") + val scalaSelection = preferedScala match { + case PreferedScala.Default => Seq.empty + case PreferedScala.Scala2 => Seq("preferScala2") + case PreferedScala.Scala3 => Seq("preferScala3") + } val sbtCommands = ( Seq( setCommands, s"""apply -cp "${normalizePath(sbtStructureJar)}" "org.jetbrains.sbt.CreateTasks" "sbt.jetbrains.LogDownloadArtifacts"""" ) :++ - (if (preferScala2) Seq("preferScala2") else Seq.empty) :+ + scalaSelection :+ s"*/*:dumpStructure" ).mkString(";", ";", "") diff --git a/sbt/sbt-impl/test/org/jetbrains/sbt/shell/MaxJvmHeapParameterTest.scala b/sbt/sbt-impl/test/org/jetbrains/sbt/shell/MaxJvmHeapParameterTest.scala index 30df82fa432..ea09b92680f 100644 --- a/sbt/sbt-impl/test/org/jetbrains/sbt/shell/MaxJvmHeapParameterTest.scala +++ b/sbt/sbt-impl/test/org/jetbrains/sbt/shell/MaxJvmHeapParameterTest.scala @@ -3,7 +3,7 @@ package org.jetbrains.sbt.shell import com.intellij.openapi.util.io.FileUtil import junit.framework.TestCase import org.jetbrains.sbt.JvmMemorySize -import org.jetbrains.sbt.project.settings.SbtExecutionSettings +import org.jetbrains.sbt.project.settings.{PreferedScala, SbtExecutionSettings} import java.io.File @@ -36,7 +36,7 @@ class MaxJvmHeapParameterTest extends TestCase { resolveSbtClassifiers = false, useShellForImport = false , shellDebugMode = false, - preferScala2 = true, + preferedScala = PreferedScala.Default, userSetEnvironment = Map.empty, passParentEnvironment = true, insertProjectTransitiveDependencies = true,