revert change breaking module resolution from output path; explicit '--patch-module' compiler option enables compilation with 'module-path' instead of 'classpath'

GitOrigin-RevId: 5c22cf1b937a783aa02e298ea995c863dc8c567c
This commit is contained in:
Eugene Zhuravlev
2025-02-18 14:03:03 +01:00
committed by intellij-monorepo-bot
parent 9818164a11
commit e381284d13
9 changed files with 68 additions and 20 deletions

View File

@@ -0,0 +1,7 @@
package aaa;
public class Main {
public static void main(String[] args) {
System.out.println("Hello");
}
}

View File

@@ -0,0 +1,7 @@
package aaa;
public class Main {
public static void main(String[] args) {
Class<?> srvClass = ppp.api.Service.class;
}
}

View File

@@ -2,7 +2,10 @@
package org.jetbrains.jps.javac;
import com.intellij.openapi.util.io.FileUtilRt;
import org.jetbrains.annotations.*;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.builders.java.JavaSourceTransformer;
import org.jetbrains.jps.javac.Iterators.BooleanFunction;
import org.jetbrains.jps.javac.Iterators.Function;
@@ -146,11 +149,7 @@ public final class JpsJavacFileManager extends ForwardingJavaFileManager<Standar
throw new IllegalArgumentException("Invalid kind: " + kind);
}
final JavaFileObject fo = super.getJavaFileForInput(location, className, kind); // todo
boolean isModuleInfo = "module-info".equals(className);
if (location == StandardLocation.CLASS_OUTPUT && isModuleInfo) {
return null;
}
if (fo == null && !isModuleInfo) {
if (fo == null && !"module-info".equals(className)) {
// workaround javac bug (missing null-check): throwing exception here instead of returning null
throw new FileNotFoundException("Java resource does not exist : " + location + '/' + kind + '/' + className);
}

View File

@@ -106,6 +106,7 @@ public final class JavaBuilder extends ModuleLevelBuilder {
private static final String PROCESSOR_MODULE_PATH_OPTION = "--processor-module-path";
private static final String SOURCE_OPTION = "-source";
private static final String SYSTEM_OPTION = "--system";
private static final String PATCH_MODULE_OPTION = "--patch-module";
private static final Set<String> FILTERED_OPTIONS = Set.of(
TARGET_OPTION, RELEASE_OPTION, "-d"
);
@@ -471,12 +472,15 @@ public final class JavaBuilder extends ModuleLevelBuilder {
final Iterable<? extends File> classPath;
final ModulePath modulePath;
final Iterable<? extends File> upgradeModulePath;
if (moduleInfoFile != null) { // has modules
if (moduleInfoFile != null || Iterators.contains(options, PATCH_MODULE_OPTION)) { // has modules or trying to patch a module
final ModulePathSplitter splitter = MODULE_PATH_SPLITTER.get(context);
final Pair<ModulePath, Collection<File>> pair = splitter.splitPath(
moduleInfoFile, outs.keySet(), ProjectPaths.getCompilationModulePath(chunk, false), collectAdditionalRequires(options)
);
final boolean useModulePathOnly = Boolean.parseBoolean(System.getProperty(USE_MODULE_PATH_ONLY_OPTION))/*compilerConfig.useModulePathOnly()*/;
// always add everything to ModulePath if module path usagfe is forced or '--patch-module' is explicitly specified in the command line
final boolean useModulePathOnly = moduleInfoFile == null || Boolean.parseBoolean(System.getProperty(USE_MODULE_PATH_ONLY_OPTION))/*compilerConfig.useModulePathOnly()*/;
if (useModulePathOnly) {
// in Java 9, named modules are not allowed to read classes from the classpath
// moreover, the compiler requires all transitive dependencies to be on the module path

View File

@@ -1,4 +1,4 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.jps.incremental.java;
import com.intellij.openapi.util.Pair;
@@ -83,11 +83,11 @@ public final class ModulePathSplitter {
myModuleNameSearch = moduleNameSearch;
}
public Pair<ModulePath, Collection<File>> splitPath(File chunkModuleInfo, Set<? extends File> chunkOutputs, Collection<? extends File> path) {
public Pair<ModulePath, Collection<File>> splitPath(@Nullable File chunkModuleInfo, Set<? extends File> chunkOutputs, Collection<? extends File> path) {
return splitPath(chunkModuleInfo, chunkOutputs, path, Collections.emptySet());
}
public Pair<ModulePath, Collection<File>> splitPath(File chunkModuleInfo, Set<? extends File> chunkOutputs, Collection<? extends File> path, Collection<String> addReads) {
public Pair<ModulePath, Collection<File>> splitPath(@Nullable File chunkModuleInfo, Set<? extends File> chunkOutputs, Collection<? extends File> path, Collection<String> addReads) {
if (myModuleFinderCreateMethod == null) {
// the module API is not available
return Pair.create(ModulePath.create(path), Collections.emptyList());
@@ -140,14 +140,16 @@ public final class ModulePathSplitter {
return fName;
}
private Set<String> collectRequired(File chunkModuleInfo, Iterable<? extends File> path) {
private Set<String> collectRequired(@Nullable File chunkModuleInfo, Iterable<? extends File> path) {
final Set<String> result = new HashSet<>();
// first, add all requires from chunk module-info
final JavaModuleDescriptor chunkDescr = new JavaProjectBuilder(new OrderedClassLibraryBuilder()).addSourceFolder(chunkModuleInfo.getParentFile()).getDescriptor();
for (JavaModuleDescriptor.JavaRequires require : chunkDescr.getRequires()) {
final JavaModule rm = require.getModule();
if (rm != null) {
result.add(rm.getName());
if (chunkModuleInfo != null) {
// first, add all requires from chunk module-info
final JavaModuleDescriptor chunkDescr = new JavaProjectBuilder(new OrderedClassLibraryBuilder()).addSourceFolder(chunkModuleInfo.getParentFile()).getDescriptor();
for (JavaModuleDescriptor.JavaRequires require : chunkDescr.getRequires()) {
final JavaModule rm = require.getModule();
if (rm != null) {
result.add(rm.getName());
}
}
}
for (File file : path) {

View File

@@ -1,4 +1,4 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.ether;
import com.intellij.openapi.projectRoots.JavaSdkVersion;
@@ -158,6 +158,24 @@ public class Java9Test extends IncrementalTestCase {
assertTrue(classpath.contains(new File(libDir, "module_lib_3.jar")));
}
public void testPartialModuleCompilation() {
setupInitialProject();
final Map<String, JpsModule> modules = setupModules();
assertEquals(1, modules.size());
final JpsModule module = modules.values().iterator().next();
final File libDir = new File(getAbsolutePath("lib"));
for (File jarFile : libDir.listFiles((dir, name) -> name.endsWith(".jar"))) {
JpsLibrary lib = addLibrary(jarFile.getName(), jarFile);
JpsModuleRootModificationUtil.addDependency(module, lib, JpsJavaDependencyScope.COMPILE, false);
}
doBuild(CompileScopeTestBuilder.rebuild().allModules()).assertSuccessful();
modify(0);
doBuild(CompileScopeTestBuilder.make().allModules()).assertSuccessful();
}
public void testExplodedAutoModule() {
setupInitialProject();

View File

@@ -93,6 +93,9 @@ class MultiReleaseOutputTest : MavenCompilingTestCase() {
}
/*
todo: commented until IDEA-367746 is fixed
@Test
fun `test java module compilation`() = runBlocking {
createProjectSubFile("src/main/java/module-info.java", """
@@ -107,7 +110,7 @@ class MultiReleaseOutputTest : MavenCompilingTestCase() {
<artifactId>project</artifactId>
<version>1</version>
<properties>
<maven.compiler.release>9</maven.compiler.release>
<maven.compiler.release>9</maven.compiler.release>
</properties>
<build>
<plugins>
@@ -123,6 +126,10 @@ class MultiReleaseOutputTest : MavenCompilingTestCase() {
<compileSourceRoots>
<root>${'$'}{project.basedir}/src/main/java-additional</root>
</compileSourceRoots>
<compilerArgs>
<arg>--patch-module</arg>
<arg>project=${'$'}{project.basedir}/src/main/java-additional</arg>
</compilerArgs>
</configuration>
</execution>
</executions>
@@ -145,4 +152,5 @@ class MultiReleaseOutputTest : MavenCompilingTestCase() {
assertExists("target/classes/A.class")
assertExists("target/classes/B.class")
}
*/
}