[java, test] add tests for "Generate module-info descriptors" IDEA-187523

GitOrigin-RevId: 4b3e2dd82bf085d36e2104ef6e13e9412e3cce19
This commit is contained in:
Aleksey Dobrynin
2023-12-14 21:28:40 +00:00
committed by intellij-monorepo-bot
parent 6aebaca523
commit 7d7ba2c4b3
63 changed files with 702 additions and 14 deletions
@@ -1,4 +1,4 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInspection.java19api;
import com.intellij.codeInsight.daemon.impl.analysis.JavaModuleGraphUtil;
@@ -14,7 +14,7 @@ import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.application.ex.ApplicationEx;
import com.intellij.openapi.application.ex.ApplicationManagerEx;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.compiler.CompileScope;
import com.intellij.openapi.compiler.CompilerManager;
@@ -27,6 +27,7 @@ import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.progress.impl.CoreProgressManager;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.JavaSdkVersion;
@@ -251,14 +252,20 @@ public final class Java9GenerateModuleDescriptorsAction extends AnAction {
}
private void createFilesLater(List<ModuleInfo> moduleInfos) {
ApplicationManager.getApplication().invokeLater(() -> {
if (!myProject.isDisposed()) {
CommandProcessor.getInstance().executeCommand(myProject, () ->
((ApplicationEx)ApplicationManager.getApplication()).runWriteActionWithCancellableProgressInDispatchThread(
getCommandTitle(), myProject, null,
indicator -> createFiles(myProject, moduleInfos, indicator)), getCommandTitle(), null);
}
});
Runnable createFiles = () -> {
if (myProject.isDisposed()) return;
CommandProcessor.getInstance().executeCommand(myProject, () ->
ApplicationManagerEx.getApplicationEx().runWriteActionWithCancellableProgressInDispatchThread(
getCommandTitle(), myProject, null,
indicator -> createFiles(myProject, moduleInfos, indicator)), getCommandTitle(), null);
};
if (CoreProgressManager.shouldKeepTasksAsynchronous()) {
ApplicationManager.getApplication().invokeLater(createFiles);
}
else {
ApplicationManager.getApplication().invokeAndWait(createFiles);
}
}
private Map<String, Set<ModuleNode>> collectDependencies(Map<Module, List<File>> classFiles) {
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_9" project-jdk-name="9" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/target" />
</component>
</project>
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/A/proj-a.iml" filepath="$PROJECT_DIR$/A/proj-a.iml" />
<module fileurl="file://$PROJECT_DIR$/B/proj-b.iml" filepath="$PROJECT_DIR$/B/proj-b.iml" />
<module fileurl="file://$PROJECT_DIR$/C/proj-c.iml" filepath="$PROJECT_DIR$/C/proj-c.iml" />
</modules>
</component>
</project>
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="proj-b" />
</component>
</module>
@@ -0,0 +1,3 @@
module proj.a {
requires proj.b;
}
@@ -0,0 +1,9 @@
package org.client;
import org.driver.Monitor;
public class Browser {
public static void main(String[] args) {
new Monitor().exec();
}
}
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="proj-c" />
</component>
</module>
@@ -0,0 +1,5 @@
module proj.b {
requires proj.c;
exports org.driver;
}
@@ -0,0 +1,9 @@
package org.driver;
import org.driver.factory.ApiFactory;
public class Monitor {
public void exec() {
System.out.println(ApiFactory.create().name());
}
}
@@ -0,0 +1,10 @@
package org.driver.factory;
import org.declaration.API;
import org.declaration.impl.DummyApi;
public class ApiFactory {
public static API create() {
return new DummyApi();
}
}
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
@@ -0,0 +1,4 @@
module proj.c {
exports org.declaration;
exports org.declaration.impl;
}
@@ -0,0 +1,5 @@
package org.declaration;
public interface API {
String name();
}
@@ -0,0 +1,10 @@
package org.declaration.impl;
import org.declaration.API;
public class DummyApi implements API {
@Override
public String name() {
return "dummy";
}
}
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_9" project-jdk-name="9" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/target" />
</component>
</project>
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/A/proj-a.iml" filepath="$PROJECT_DIR$/A/proj-a.iml" />
<module fileurl="file://$PROJECT_DIR$/B/proj-b.iml" filepath="$PROJECT_DIR$/B/proj-b.iml" />
<module fileurl="file://$PROJECT_DIR$/C/proj-c.iml" filepath="$PROJECT_DIR$/C/proj-c.iml" />
</modules>
</component>
</project>
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="proj-b" />
</component>
</module>
@@ -0,0 +1,9 @@
package org.client;
import org.driver.Monitor;
public class Browser {
public static void main(String[] args) {
new Monitor().exec();
}
}
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="proj-c" />
</component>
</module>
@@ -0,0 +1,9 @@
package org.driver;
import org.driver.factory.ApiFactory;
public class Monitor {
public void exec() {
System.out.println(ApiFactory.create().name());
}
}
@@ -0,0 +1,10 @@
package org.driver.factory;
import org.declaration.API;
import org.declaration.impl.DummyApi;
public class ApiFactory {
public static API create() {
return new DummyApi();
}
}
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
@@ -0,0 +1,5 @@
package org.declaration;
public interface API {
String name();
}
@@ -0,0 +1,10 @@
package org.declaration.impl;
import org.declaration.API;
public class DummyApi implements API {
@Override
public String name() {
return "dummy";
}
}
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_9" project-jdk-name="9" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/target" />
</component>
</project>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/proj-a.iml" filepath="$PROJECT_DIR$/proj-a.iml" />
</modules>
</component>
</project>
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
@@ -0,0 +1,7 @@
package org.client;
public class Main {
public static void main(String[] args) {
System.out.println("main");
}
}
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_9" project-jdk-name="9" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/target" />
</component>
</project>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/proj-a.iml" filepath="$PROJECT_DIR$/proj-a.iml" />
</modules>
</component>
</project>
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
@@ -0,0 +1,7 @@
package org.client;
public class Main {
public static void main(String[] args) {
System.out.println("main");
}
}
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
<option name="workspaceImportForciblyTurnedOn" value="true" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_9" project-jdk-name="9" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/target" />
</component>
</project>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/maven-project.iml" filepath="$PROJECT_DIR$/maven-project.iml" />
</modules>
</component>
</project>
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$MODULE_DIR$/.idea/annotations.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
</component>
</module>
@@ -0,0 +1,21 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.jetbrains</groupId>
<artifactId>client</artifactId>
<version>1.0</version>
<properties>
<maven.compiler.source>9</maven.compiler.source>
<maven.compiler.target>9</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>24.1.0</version>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,3 @@
module maven.project {
requires org.jetbrains.annotations;
}
@@ -0,0 +1,9 @@
package org.client;
import org.jetbrains.annotations.NotNull;
public class Main {
public static void main(@NotNull String[] args) {
System.out.println("main");
}
}
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
<option name="workspaceImportForciblyTurnedOn" value="true" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_9" project-jdk-name="9" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/target" />
</component>
</project>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/maven-project.iml" filepath="$PROJECT_DIR$/maven-project.iml" />
</modules>
</component>
</project>
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$MODULE_DIR$/.idea/annotations.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
</component>
</module>
@@ -0,0 +1,21 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.jetbrains</groupId>
<artifactId>client</artifactId>
<version>1.0</version>
<properties>
<maven.compiler.source>9</maven.compiler.source>
<maven.compiler.target>9</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>24.1.0</version>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,9 @@
package org.client;
import org.jetbrains.annotations.NotNull;
public class Main {
public static void main(@NotNull String[] args) {
System.out.println("main");
}
}
@@ -0,0 +1,255 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.java.codeInsight.actions;
import com.intellij.JavaTestUtil;
import com.intellij.compiler.CompilerManagerImpl;
import com.intellij.conversion.ModuleSettings;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.compiler.CompileScope;
import com.intellij.openapi.compiler.CompilerManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.ModuleWithNameAlreadyExists;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.DumbServiceImpl;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.impl.ProjectImpl;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.util.JDOMUtil;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.vfs.pointers.VirtualFilePointer;
import com.intellij.openapi.vfs.pointers.VirtualFilePointerManager;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.refactoring.LightMultiFileTestCase;
import com.intellij.testFramework.*;
import com.intellij.testFramework.fixtures.DefaultLightProjectDescriptor;
import kotlinx.coroutines.CoroutineScopeKt;
import kotlinx.coroutines.JobKt;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.model.java.JavaSourceRootType;
import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
import org.jetbrains.jps.model.serialization.JDomSerializationUtil;
import org.jetbrains.jps.model.serialization.JpsProjectLoader;
import java.io.IOException;
import java.net.URL;
import java.nio.file.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Predicate;
import java.util.stream.Stream;
import static org.jetbrains.jps.model.serialization.module.JpsModuleRootModelSerializer.*;
public class Java9GenerateModuleDescriptorsActionTest extends LightMultiFileTestCase {
@Override
protected @NotNull LightProjectDescriptor getProjectDescriptor() {
return new FakeModuleDescriptor(Paths.get(getTestDataPath() + "/" + getTestName(true)));
}
@Override
protected String getTestDataPath() {
return JavaTestUtil.getJavaTestDataPath() + "/actions/generateModuleDescriptors";
}
public void testSingleModule() throws IOException {
performReformatAction();
}
public void testSingleModuleWithDependency() throws IOException {
performReformatAction();
}
public void testDependentModules() throws IOException {
performReformatAction();
}
protected void performReformatAction() throws IOException {
// INIT
final AnAction action = ActionManager.getInstance().getAction("GenerateModuleDescriptors");
final AnActionEvent event = AnActionEvent.createFromAnAction(action, null, "", dataId -> {
if (CommonDataKeys.VIRTUAL_FILE_ARRAY.is(dataId)) return Collections.emptyList();
if (CommonDataKeys.PROJECT.is(dataId)) return getProject();
return null;
});
// EXEC
action.actionPerformed(event);
// CHECK
final FakeModuleDescriptor descriptor = (FakeModuleDescriptor)getProjectDescriptor();
PlatformTestUtil.assertDirectoriesEqual(LocalFileSystem.getInstance().findFileByNioFile(descriptor.myAfterPath),
LocalFileSystem.getInstance().findFileByPath(getProject().getBasePath()));
}
private static class FakeModuleDescriptor extends DefaultLightProjectDescriptor {
private final Path myBeforePath;
private final Path myAfterPath;
private final Path myProjectPath;
FakeModuleDescriptor(@NotNull Path path) {
myBeforePath = path.resolve("before");
myAfterPath = path.resolve("after");
myProjectPath = TemporaryDirectory.generateTemporaryPath(ProjectImpl.LIGHT_PROJECT_NAME);
}
@Override
public @NotNull Path getProjectPath() {
return myProjectPath;
}
@Override
public Sdk getSdk() {
return IdeaTestUtil.getMockJdk11(); // TODO
}
@Override
public void setUpProject(@NotNull Project project, @NotNull SetupHandler handler) throws Exception {
WriteAction.run(() -> {
final Path basePath = Paths.get(project.getBasePath());
FileUtil.copyDir(myBeforePath.toFile(), basePath.toFile());
VfsUtil.markDirtyAndRefresh(false, true, true, basePath.toFile());
final Element miscXml = JDomSerializationUtil.findComponent(JDOMUtil.load(basePath.resolve(".idea").resolve("misc.xml")),
"ProjectRootManager");
final String outputUrl = miscXml.getChild("output").getAttributeValue("url").replace("$PROJECT_DIR$", basePath.toString());
final CompilerProjectExtension compilerProjectExtension = CompilerProjectExtension.getInstance(project);
compilerProjectExtension.setCompilerOutputUrl(outputUrl);
final VirtualFilePointer pointer = VirtualFilePointerManager.getInstance()
.create(outputUrl, (Disposable)compilerProjectExtension, null);
compilerProjectExtension.setCompilerOutputPointer(pointer);
//CompilerModuleExtension
//ModuleElementsEditor
ServiceContainerUtil.replaceService(project, DumbService.class,
new DumbServiceImpl(project, CoroutineScopeKt.CoroutineScope(JobKt.Job(null))) {
@Override
public void smartInvokeLater(@NotNull Runnable runnable) {
runnable.run();
}
}, project);
ServiceContainerUtil.replaceService(project, CompilerManager.class, new CompilerManagerImpl(project) {
@Override
public boolean isUpToDate(@NotNull CompileScope scope) {
return true;
}
}, project);
final Element modulesXml = JDomSerializationUtil.findComponent(JDOMUtil.load(basePath.resolve(".idea").resolve("modules.xml")),
JpsProjectLoader.MODULE_MANAGER_COMPONENT);
final Element modulesElement = modulesXml.getChild(JpsProjectLoader.MODULES_TAG);
final List<Element> moduleElements = modulesElement.getChildren(JpsProjectLoader.MODULE_TAG);
for (Element moduleAttr : moduleElements) {
Path modulePath = Paths.get(moduleAttr.getAttributeValue(JpsProjectLoader.FILE_PATH_ATTRIBUTE)
.replace("$PROJECT_DIR$", basePath.toString()));
final ModuleDescriptor descriptor = new ModuleDescriptor(modulePath);
final Module module = makeModule(project, descriptor);
handler.moduleCreated(module);
final VirtualFile vSrc = VirtualFileManager.getInstance().refreshAndFindFileByNioPath(descriptor.src());
handler.sourceRootCreated(vSrc);
createContentEntry(module, vSrc);
}
});
}
@NotNull
private Module makeModule(@NotNull Project project, @NotNull ModuleDescriptor descriptor)
throws ModuleWithNameAlreadyExists, IOException {
final Module module;
Path iml = getIml(descriptor.basePath);
if (iml != null && Files.exists(iml)) {
module = ModuleManager.getInstance(project).loadModule(iml);
}
else {
iml = descriptor.basePath.resolve(descriptor.basePath.getFileName() + ".iml");
module = createModule(project, iml);
}
ModuleRootModificationUtil.updateModel(module, model -> configureModule(module, model, descriptor));
return module;
}
private void configureModule(@NotNull Module module, @NotNull ModifiableRootModel model, @NotNull ModuleDescriptor descriptor) {
model.getModuleExtension(LanguageLevelModuleExtension.class).setLanguageLevel(descriptor.languageLevel());
model.setSdk(IdeaTestUtil.getMockJdk(descriptor.languageLevel().toJavaVersion()));
final BiConsumer<Path, JpsModuleSourceRootType<?>> register = (path, type) -> {
if (path == null) return;
final VirtualFile src = Files.exists(path)
? VirtualFileManager.getInstance().refreshAndFindFileByNioPath(path)
: createSourceRoot(module, path.toString());
registerSourceRoot(module.getProject(), src);
model.addContentEntry(src).addSourceFolder(src, type);
};
register.accept(descriptor.src(), JavaSourceRootType.SOURCE);
register.accept(descriptor.testSrc(), JavaSourceRootType.TEST_SOURCE);
//JavaResourceRootType.RESOURCE
//JavaResourceRootType.TEST_RESOURCE
// Maven
final Path mavenOutputPath = Paths.get(module.getModuleFilePath()).getParent().resolve("target").resolve("classes");
if (Files.exists(mavenOutputPath)) {
final CompilerModuleExtension compiler = model.getModuleExtension(CompilerModuleExtension.class);
compiler.setCompilerOutputPath(mavenOutputPath.toString());
compiler.inheritCompilerOutputPath(false);
}
}
private record ModuleDescriptor(@NotNull String name, @NotNull Path basePath, @NotNull Path src, @Nullable Path testSrc,
@NotNull LanguageLevel languageLevel) {
@SuppressWarnings("SwitchStatementWithTooFewBranches")
private ModuleDescriptor(@NotNull Path iml) throws IOException, JDOMException {
this(iml.getFileName().toString().replace(".iml", ""), iml.getParent(),
Paths.get(new URL(getData(iml, List.of(CONTENT_TAG, SOURCE_FOLDER_TAG), e -> switch (e.getName()) {
case SOURCE_FOLDER_TAG -> e.getAttributeValue(IS_TEST_SOURCE_ATTRIBUTE).equals("false");
default -> true;
}).stream().findFirst().orElseThrow().getAttributeValue(URL_ATTRIBUTE)
.replace("$MODULE_DIR$", iml.getParent().toString())).getPath()), null, LanguageLevel.JDK_11);
}
private static List<Element> getData(@NotNull Path iml, List<String> tags, @NotNull Predicate<Element> condition)
throws IOException, JDOMException {
final Element component = JDomSerializationUtil.findComponent(JDOMUtil.load(iml), ModuleSettings.MODULE_ROOT_MANAGER_COMPONENT);
List<Element> elements = List.of(component);
for (String tag : tags) {
List<Element> newElements = new ArrayList<>();
for (Element element : elements) {
newElements.addAll(element.getChildren(tag).stream().filter(condition).toList());
}
elements = newElements;
}
return elements;
}
}
}
@Nullable
private static Path getIml(@NotNull Path path) {
return findFiles(path, "glob:**/*.iml").stream().findFirst().orElse(null);
}
@NotNull
private static List<Path> findFiles(@NotNull Path path, @NotNull String mask) {
final PathMatcher matcher = FileSystems.getDefault().getPathMatcher(mask);
try (final Stream<Path> stream = Files.walk(path)) {
return stream.filter(matcher::matches).sorted().toList();
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
}
@@ -1,11 +1,10 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.testFramework;
import com.intellij.application.options.CodeStyle;
import com.intellij.codeInspection.InspectionProfileEntry;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.ex.InspectionToolWrapper;
import com.intellij.ide.highlighter.ProjectFileType;
import com.intellij.ide.startup.StartupManagerEx;
import com.intellij.idea.IdeaLogger;
import com.intellij.lang.Language;
@@ -171,7 +170,7 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da
}
ApplicationManager.getApplication().runWriteAction(() -> cleanPersistedVFSContent());
Path tempDirectory = TemporaryDirectory.generateTemporaryPath(ProjectImpl.LIGHT_PROJECT_NAME + ProjectFileType.DOT_DEFAULT_EXTENSION);
Path tempDirectory = descriptor.getProjectPath();
ourProject = Objects.requireNonNull(ProjectManagerEx.getInstanceEx().newProject(tempDirectory, descriptor.getOpenProjectOptions()));
HeavyPlatformTestCase.synchronizeTempDirVfs(tempDirectory);
ourPsiManager = null;
@@ -1,6 +1,7 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.testFramework;
import com.intellij.ide.highlighter.ProjectFileType;
import com.intellij.ide.impl.OpenProjectTask;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.WriteAction;
@@ -8,6 +9,7 @@ import com.intellij.openapi.module.EmptyModuleType;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.impl.ProjectImpl;
import com.intellij.openapi.projectRoots.ProjectJdkTable;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ContentEntry;
@@ -35,6 +37,11 @@ public class LightProjectDescriptor {
public static final LightProjectDescriptor EMPTY_PROJECT_DESCRIPTOR = new LightProjectDescriptor();
public static final String TEST_MODULE_NAME = "light_idea_test_case";
private final Path myProjectPath;
public LightProjectDescriptor() {
myProjectPath = TemporaryDirectory.generateTemporaryPath(ProjectImpl.LIGHT_PROJECT_NAME + ProjectFileType.DOT_DEFAULT_EXTENSION);
}
public void setUpProject(@NotNull Project project, @NotNull SetupHandler handler) throws Exception {
WriteAction.run(() -> {
@@ -176,6 +183,11 @@ public class LightProjectDescriptor {
}
}
@NotNull
public Path getProjectPath() {
return myProjectPath;
}
protected void configureModule(@NotNull Module module, @NotNull ModifiableRootModel model, @NotNull ContentEntry contentEntry) { }
public interface SetupHandler {