[jps model] refactoring: move code which reads external data for compiler configuration to the corresponding serializer

JpsProjectExtensionWithExternalDataSerializer is introduced to support project components which may have data in the external storage. Code related to loading the compiler configuration is moved from JpsProjectLoader to JpsJavaCompilerConfigurationSerializer. This is needed to refactor JpsProjectLoader to allow reusing its code in the new implementation of the JPS model (IJPL-409).

GitOrigin-RevId: c0e64c02c49e4a451da9b9743c240227bd6465a4
This commit is contained in:
Nikolay Chashnikov
2024-06-26 10:54:10 +02:00
committed by intellij-monorepo-bot
parent 1d2b8c2b86
commit 395c030d98
6 changed files with 79 additions and 43 deletions

View File

@@ -24,7 +24,7 @@ public class JpsGlobalLoader extends JpsLoaderBase {
private final JpsGlobalExtensionSerializer @NotNull [] myBundledSerializers;
public JpsGlobalLoader(JpsMacroExpander macroExpander, JpsGlobal global, JpsGlobalExtensionSerializer @NotNull [] bundledSerializers) {
super(macroExpander);
super(macroExpander, null);
myGlobal = global;
myBundledSerializers = bundledSerializers;
}

View File

@@ -14,6 +14,7 @@ import org.jetbrains.jps.TimingLog;
import org.jetbrains.jps.model.JpsElement;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
@@ -21,10 +22,12 @@ import java.nio.file.Path;
public abstract class JpsLoaderBase {
private static final Logger LOG = Logger.getInstance(JpsLoaderBase.class);
private static final int MAX_ATTEMPTS = 5;
protected final @Nullable Path myExternalConfigurationDirectory;
private final JpsMacroExpander myMacroExpander;
protected JpsLoaderBase(JpsMacroExpander macroExpander) {
protected JpsLoaderBase(JpsMacroExpander macroExpander, @Nullable Path externalConfigurationDirectory) {
myMacroExpander = macroExpander;
myExternalConfigurationDirectory = externalConfigurationDirectory;
}
/**
@@ -51,8 +54,36 @@ public abstract class JpsLoaderBase {
timingLog.run();
}
protected @Nullable <E extends JpsElement> Element loadComponentData(@NotNull JpsElementExtensionSerializerBase<E> serializer, @NotNull Path configFile) {
return JDomSerializationUtil.findComponent(loadRootElement(configFile), serializer.getComponentName());
private @Nullable <E extends JpsElement> Element loadComponentData(@NotNull JpsElementExtensionSerializerBase<E> serializer, @NotNull Path configFile) {
String componentName = serializer.getComponentName();
Element component = JDomSerializationUtil.findComponent(loadRootElement(configFile), componentName);
if (!(serializer instanceof JpsProjectExtensionWithExternalDataSerializer) || myExternalConfigurationDirectory == null) {
return component;
}
JpsProjectExtensionWithExternalDataSerializer externalDataSerializer = (JpsProjectExtensionWithExternalDataSerializer)serializer;
Path externalConfigFile = myExternalConfigurationDirectory.resolve(externalDataSerializer.getExternalConfigFilePath());
if (!Files.exists(externalConfigFile)) {
return component;
}
Element externalData = null;
String externalComponentName = externalDataSerializer.getExternalComponentName();
for (Element child : JDOMUtil.getChildren(loadRootElement(externalConfigFile))) {
// be ready to handle both original name and prefixed
if (child.getName().equals(externalComponentName) || JDomSerializationUtil.isComponent(externalComponentName, child) ||
child.getName().equals(componentName) || JDomSerializationUtil.isComponent(componentName, child)) {
externalData = child;
break;
}
}
if (externalData == null) {
return component;
}
if (component == null) {
return externalData;
}
externalDataSerializer.mergeExternalData(component, externalData);
return component;
}
/**

View File

@@ -0,0 +1,31 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.jps.model.serialization;
import org.jdom.Element;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
@ApiStatus.Internal
public abstract class JpsProjectExtensionWithExternalDataSerializer extends JpsProjectExtensionSerializer {
private final String myExternalComponentName;
private final String myExternalConfigFilePath;
protected JpsProjectExtensionWithExternalDataSerializer(@NotNull String configFileName,
@NotNull String componentName,
@NotNull String externalConfigFilePath,
@NotNull String externalComponentName) {
super(configFileName, componentName);
myExternalConfigFilePath = externalConfigFilePath;
myExternalComponentName = externalComponentName;
}
public abstract void mergeExternalData(@NotNull Element internalComponent, @NotNull Element externalComponent);
public String getExternalConfigFilePath() {
return myExternalConfigFilePath;
}
public final @NotNull String getExternalComponentName() {
return myExternalComponentName;
}
}

View File

@@ -44,8 +44,6 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import static org.jetbrains.jps.model.serialization.java.compiler.JpsJavaCompilerConfigurationSerializer.BYTECODE_TARGET_LEVEL;
/**
* Use {@link JpsSerializationManager} to load a project.
*/
@@ -73,7 +71,6 @@ public final class JpsProjectLoader extends JpsLoaderBase {
private final Map<String, String> myPathVariables;
private final JpsPathMapper myPathMapper;
private final boolean myLoadUnloadedModules;
private final @Nullable Path myExternalConfigurationDirectory;
private JpsProjectLoader(JpsProject project,
Map<String, String> pathVariables,
@@ -81,11 +78,10 @@ public final class JpsProjectLoader extends JpsLoaderBase {
@NotNull Path baseDir,
@Nullable Path externalConfigurationDirectory,
boolean loadUnloadedModules) {
super(createProjectMacroExpander(pathVariables, baseDir));
super(createProjectMacroExpander(pathVariables, baseDir), externalConfigurationDirectory);
myProject = project;
myPathVariables = pathVariables;
myPathMapper = pathMapper;
myExternalConfigurationDirectory = externalConfigurationDirectory;
myProject.getContainer().setChild(JpsProjectSerializationDataExtensionImpl.ROLE, new JpsProjectSerializationDataExtensionImpl(baseDir));
myLoadUnloadedModules = loadUnloadedModules;
}
@@ -158,36 +154,6 @@ public final class JpsProjectLoader extends JpsLoaderBase {
return name != null ? name : JpsPathUtil.getDefaultProjectName(dir);
}
@Override
protected @Nullable <E extends JpsElement> Element loadComponentData(@NotNull JpsElementExtensionSerializerBase<E> serializer, @NotNull Path configFile) {
Path externalConfigDir = myExternalConfigurationDirectory != null ? myExternalConfigurationDirectory.resolve("project") : null;
Element data = super.loadComponentData(serializer, configFile);
String componentName = serializer.getComponentName();
if (externalConfigDir == null || !(componentName.equals("CompilerConfiguration"))) {
return data;
}
String prefixedComponentName = "External" + componentName;
Element externalData = null;
for (Element child : JDOMUtil.getChildren(loadRootElement(externalConfigDir.resolve(configFile.getFileName())))) {
// be ready to handle both original name and prefixed
if (child.getName().equals(prefixedComponentName) || JDomSerializationUtil.isComponent(prefixedComponentName, child) ||
child.getName().equals(componentName) || JDomSerializationUtil.isComponent(componentName, child)) {
externalData = child;
break;
}
}
return deepMergeCompilerConfigurations(data, externalData);
}
private static @Nullable Element deepMergeCompilerConfigurations(@Nullable Element data, @Nullable Element externalData) {
if (data == null) return externalData;
if (externalData == null) return data;
JDOMUtil.deepMerge(data, externalData);
JDOMUtil.reduceChildren(BYTECODE_TARGET_LEVEL, data);
return data;
}
private void loadFromDirectory(@NotNull Path dir, @NotNull Executor executor) {
myProject.setName(getDirectoryBaseProjectName(dir));
Path defaultConfigFile = dir.resolve("misc.xml");

View File

@@ -10,11 +10,11 @@ import org.jetbrains.jps.model.JpsProject;
import org.jetbrains.jps.model.java.JpsJavaExtensionService;
import org.jetbrains.jps.model.java.compiler.JpsCompilerExcludes;
import org.jetbrains.jps.model.java.compiler.JpsJavaCompilerConfiguration;
import org.jetbrains.jps.model.serialization.JpsProjectExtensionSerializer;
import org.jetbrains.jps.model.serialization.JpsProjectExtensionWithExternalDataSerializer;
import java.util.List;
public final class JpsJavaCompilerConfigurationSerializer extends JpsProjectExtensionSerializer {
public final class JpsJavaCompilerConfigurationSerializer extends JpsProjectExtensionWithExternalDataSerializer {
public static final String EXCLUDE_FROM_COMPILE = "excludeFromCompile";
public static final String RESOURCE_EXTENSIONS = "resourceExtensions";
public static final String ANNOTATION_PROCESSING = "annotationProcessing";
@@ -32,7 +32,9 @@ public final class JpsJavaCompilerConfigurationSerializer extends JpsProjectExte
List.of("!?*.java", "!?*.form", "!?*.class", "!?*.groovy", "!?*.scala", "!?*.flex", "!?*.kt", "!?*.clj", "!?*.aj");
public JpsJavaCompilerConfigurationSerializer() {
super("compiler.xml", "CompilerConfiguration");
super("compiler.xml", "CompilerConfiguration",
"project/compiler.xml",
"ExternalCompilerConfiguration");
}
@Override
@@ -96,6 +98,12 @@ public final class JpsJavaCompilerConfigurationSerializer extends JpsProjectExte
}
}
@Override
public void mergeExternalData(@NotNull Element internalComponent, @NotNull Element externalComponent) {
JDOMUtil.deepMerge(internalComponent, externalComponent);
JDOMUtil.reduceChildren(BYTECODE_TARGET_LEVEL, internalComponent);
}
@Override
public void loadExtensionWithDefaultSettings(@NotNull JpsProject project) {
JpsJavaCompilerConfiguration configuration = JpsJavaExtensionService.getInstance().getCompilerConfiguration(project);

View File

@@ -10,7 +10,7 @@ import org.jetbrains.jps.model.serialization.JpsMacroExpander
import org.jetbrains.jps.util.JpsPathUtil
import kotlin.io.path.Path
internal class DirectJpsFileContentReader(private val macroExpander: JpsMacroExpander) : JpsLoaderBase(macroExpander), JpsFileContentReader {
internal class DirectJpsFileContentReader(private val macroExpander: JpsMacroExpander) : JpsLoaderBase(macroExpander, null), JpsFileContentReader {
override fun loadComponent(fileUrl: String, componentName: String, customModuleFilePath: String?): Element? {
val rootElement = loadRootElement(Path(JpsPathUtil.urlToPath(fileUrl))) ?: return null
return JDomSerializationUtil.findComponent(rootElement, componentName)