[java] Warn on JDK/OS arch mismatch when building the project

- Sends a sticky balloon notification on the first build with a JDK every session in case of arch mismatch (shown again after changing JDK)
- New checkbox in Build | Compiler | Java Compiler to disable warnings

#IDEA-343661 Fixed

GitOrigin-RevId: ac9b36b05403ac38acc7a55944850608f86d4e59
This commit is contained in:
Louis Vignier
2024-03-26 14:13:06 +01:00
committed by intellij-monorepo-bot
parent 4c6ac30a11
commit 9b9f155f70
9 changed files with 96 additions and 2 deletions

View File

@@ -166,6 +166,7 @@ public final class CompilerConfigurationImpl extends CompilerConfiguration imple
public int BUILD_PROCESS_HEAP_SIZE = DEFAULT_BUILD_PROCESS_HEAP_SIZE;
public String BUILD_PROCESS_ADDITIONAL_VM_OPTIONS = "";
public boolean USE_RELEASE_OPTION = true;
public boolean WARN_ON_ARCH_MISMATCH = true;
}
@Override
@@ -369,6 +370,16 @@ public final class CompilerConfigurationImpl extends CompilerConfiguration imple
return myBytecodeTargetLevel;
}
@Override
public boolean warnOnArchMismatch() {
return myState.WARN_ON_ARCH_MISMATCH;
}
@Override
public void setWarnOnArchMismatch(boolean warnOnArchMismatch) {
myState.WARN_ON_ARCH_MISMATCH = warnOnArchMismatch;
}
private void loadDefaultWildcardPatterns() {
if (!myWildcardPatterns.isEmpty()) {
removeWildcardPatterns();

View File

@@ -78,6 +78,7 @@ public class JavaCompilersTab extends CompositeConfigurable<Configurable> implem
myUi.useReleaseOptionCb.isSelected() != myCompilerConfiguration.useReleaseOption() ||
!Objects.equals(myUi.targetOptionsComponent.getProjectBytecodeTarget(), myCompilerConfiguration.getProjectBytecodeTarget()) ||
!Comparing.equal(myUi.targetOptionsComponent.getModulesBytecodeTargetMap(), myCompilerConfiguration.getModulesBytecodeTargetMap()) ||
myUi.warnOnArchMismatchCb.isSelected() != myCompilerConfiguration.warnOnArchMismatch() ||
super.isModified();
}
@@ -88,6 +89,7 @@ public class JavaCompilersTab extends CompositeConfigurable<Configurable> implem
myCompilerConfiguration.setUseReleaseOption(myUi.useReleaseOptionCb.isSelected());
myCompilerConfiguration.setProjectBytecodeTarget(myUi.targetOptionsComponent.getProjectBytecodeTarget());
myCompilerConfiguration.setModulesBytecodeTargetMap(myUi.targetOptionsComponent.getModulesBytecodeTargetMap());
myCompilerConfiguration.setWarnOnArchMismatch(myUi.warnOnArchMismatchCb.isSelected());
super.apply();
@@ -109,6 +111,7 @@ public class JavaCompilersTab extends CompositeConfigurable<Configurable> implem
myUi.useReleaseOptionCb.setSelected(myCompilerConfiguration.useReleaseOption());
myUi.targetOptionsComponent.setProjectBytecodeTargetLevel(myCompilerConfiguration.getProjectBytecodeTarget());
myUi.targetOptionsComponent.setModuleTargetLevels(myCompilerConfiguration.getModulesBytecodeTargetMap());
myUi.warnOnArchMismatchCb.setSelected(myCompilerConfiguration.warnOnArchMismatch());
}
private void selectCompiler(BackendCompiler compiler) {

View File

@@ -6,7 +6,10 @@ import com.intellij.openapi.compiler.JavaCompilerBundle
import com.intellij.openapi.options.Configurable
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.ComboBox
import com.intellij.ui.dsl.builder.*
import com.intellij.ui.dsl.builder.AlignX
import com.intellij.ui.dsl.builder.BottomGap
import com.intellij.ui.dsl.builder.Panel
import com.intellij.ui.dsl.builder.panel
import com.intellij.ui.dsl.listCellRenderer.textListCellRenderer
import java.util.function.Consumer
import javax.swing.JCheckBox
@@ -16,9 +19,10 @@ class JavaCompilersTabUi(
val compilers: Collection<BackendCompiler>,
configurableConsumer: Consumer<Configurable>,
val compilerSelected: Consumer<BackendCompiler>,
) {
) {
lateinit var compilerComboBox: ComboBox<BackendCompiler>
lateinit var warnOnArchMismatchCb: JCheckBox
lateinit var useReleaseOptionCb: JCheckBox
lateinit var targetOptionsComponent: TargetOptionsComponent
@@ -41,6 +45,11 @@ class JavaCompilersTabUi(
.component
}
row {
warnOnArchMismatchCb = checkBox(JavaCompilerBundle.message("settings.warn.on.arch.mismatch"))
.component
}
row {
targetOptionsComponent = cell(TargetOptionsComponent(project))
.resizableColumn()

View File

@@ -1308,11 +1308,13 @@ public final class BuildManager implements Disposable {
}
vmExecutablePath = projectJdkType.getVMExecutablePath(projectJdk);
project.getService(BuildManagerVersionChecker.class).checkArch(projectJdk.getHomePath());
}
else {
sdkName = forcedCompiledJdkHome;
compilerPath = new File(forcedCompiledJdkHome, "lib/tools.jar").getAbsolutePath();
vmExecutablePath = new File(forcedCompiledJdkHome, "bin/java").getAbsolutePath();
project.getService(BuildManagerVersionChecker.class).checkArch(forcedCompiledJdkHome);
}
final CompilerConfiguration projectConfig = CompilerConfiguration.getInstance(project);

View File

@@ -0,0 +1,60 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.compiler.server
import com.intellij.compiler.CompilerConfiguration
import com.intellij.ide.IdeBundle
import com.intellij.java.JavaBundle
import com.intellij.notification.Notification
import com.intellij.notification.NotificationAction
import com.intellij.notification.NotificationGroupManager
import com.intellij.notification.NotificationType
import com.intellij.openapi.actionSystem.ActionManager
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.components.Service
import com.intellij.openapi.project.Project
import com.intellij.util.system.CpuArch
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import org.jetbrains.jps.model.java.JdkVersionDetector
@Service(Service.Level.PROJECT)
class BuildManagerVersionChecker(val project: Project, val scope: CoroutineScope) {
private var lastWarned: String? = null
fun checkArch(sdkHome: String?) {
val home = sdkHome ?: return
if (lastWarned == home) return
lastWarned = home
scope.launch {
val versionInfo = JdkVersionDetector.getInstance().detectJdkVersionInfo(home) ?: return@launch
val jdkArch = versionInfo.arch ?: return@launch
if (jdkArch != CpuArch.CURRENT) {
val notification = NotificationGroupManager.getInstance()
.getNotificationGroup("JDK Arch Check")
.createNotification(JavaBundle.message("arch.checker.notification.title"), JavaBundle.message("arch.checker.notification.content"), NotificationType.WARNING)
notification.apply {
addAction(object : NotificationAction(JavaBundle.message("arch.checker.notification.project.structure")) {
override fun actionPerformed(e: AnActionEvent, notification: Notification) {
ActionManager.getInstance().getAction("ShowProjectStructureSettings").actionPerformed(e)
notification.expire()
}
})
addAction(object : NotificationAction(IdeBundle.message("action.Anonymous.text.do.not.show.again")) {
override fun actionPerformed(e: AnActionEvent, notification: Notification) {
CompilerConfiguration.getInstance(project).setWarnOnArchMismatch(false)
notification.expire()
}
})
notify(project)
}
}
}
}
}

View File

@@ -145,6 +145,7 @@ settings.warning=<b>WARNING!<br>If enabled, the entire contents of directories w
settings.use.release.option.for.cross.compilation=Use '--release' option for cross-compilation (Java 9 and later)
settings.project.bytecode.version=Project bytecode version:
settings.per.module.bytecode.version=Per-module bytecode version:
settings.warn.on.arch.mismatch=Warn if the JDK and system architectures do not match
settings.same.as.language.level=Same as language level
settings.all.modules.will.be.compiled.with.project.bytecode.version=All modules will be compiled with project bytecode version
settings.module.column=Module

View File

@@ -32,6 +32,9 @@ public abstract class CompilerConfiguration {
public abstract String getProjectBytecodeTarget();
public abstract void setProjectBytecodeTarget(String level);
public abstract boolean warnOnArchMismatch();
public abstract void setWarnOnArchMismatch(boolean warnOnArchMismatch);
public abstract boolean isParallelCompilationEnabled();
/**

View File

@@ -301,6 +301,7 @@
key="notification.group.jdk.resolve.problems"/>
<notificationGroup id="Package File" displayType="BALLOON" hideFromSettings="true"/>
<notificationGroup id="Infer Nullity" displayType="TOOL_WINDOW" toolWindowId="Infer Nullity" bundle="messages.JavaBundle" key="dialog.title.infer.nullity"/>
<notificationGroup id="JDK Arch Check" displayType="STICKY_BALLOON" bundle="messages.JavaBundle" key="notification.group.arch.checker"/>
<registryKey key="ide.jps.use.build.tool.window" defaultValue="true" description="Enables 'Build' toolwindow for JPS compilation messages"/>
<applicationService serviceInterface="com.intellij.refactoring.util.CommonJavaInlineUtil" serviceImplementation="com.intellij.refactoring.util.InlineUtil"/>

View File

@@ -1819,6 +1819,10 @@ notification.group.setup.sdk=JDK configured
notification.group.setup.external.annotations=Failed to load external annotations
notification.group.testintegration=Failed to generate tests for @TestDataPath
notification.group.legacy.library=Legacy library depends on IDE installation
notification.group.arch.checker=JDK and system architectures are different
arch.checker.notification.title=JDK can cause slow builds
arch.checker.notification.content=The JDK and system architectures do not match. Builds can be much slower as a consequence.
arch.checker.notification.project.structure=Configure JDK
inspection.io.stream.constructor.description='InputStream' and 'OutputStream' can be constructed using 'Files' methods
inspection.input.stream.constructor.message='InputStream' can be constructed using 'Files.newInputStream()'
inspection.output.stream.constructor.message='OutputStream' can be constructed using 'Files.newOutputStream()'