diff --git a/jps/model-api/src/org/jetbrains/jps/model/ex/JpsReferenceCustomFactory.java b/jps/model-api/src/org/jetbrains/jps/model/ex/JpsReferenceCustomFactory.java new file mode 100644 index 000000000000..92cb3d0c9ad7 --- /dev/null +++ b/jps/model-api/src/org/jetbrains/jps/model/ex/JpsReferenceCustomFactory.java @@ -0,0 +1,23 @@ +// 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.ex; + +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jps.model.JpsCompositeElement; +import org.jetbrains.jps.model.JpsElementReference; +import org.jetbrains.jps.model.library.JpsLibraryReference; +import org.jetbrains.jps.model.module.JpsModuleReference; + +/** + * This is an internal API used to create custom implementation of {@link org.jetbrains.jps.model.JpsElementReference} if the implementation + * of JPS Model based on the workspace model is used. + */ +@ApiStatus.Internal +public interface JpsReferenceCustomFactory { + boolean isEnabled(); + + @NotNull JpsModuleReference createModuleReference(@NotNull String moduleName); + + @NotNull JpsLibraryReference createLibraryReference(@NotNull String libraryName, + @NotNull JpsElementReference parentReference); +} diff --git a/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsElementFactoryImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsElementFactoryImpl.java index 197bf8a9d939..c53698967707 100644 --- a/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsElementFactoryImpl.java +++ b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsElementFactoryImpl.java @@ -19,6 +19,7 @@ import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.model.*; +import org.jetbrains.jps.model.ex.JpsReferenceCustomFactory; import org.jetbrains.jps.model.library.JpsLibraryReference; import org.jetbrains.jps.model.library.JpsLibraryType; import org.jetbrains.jps.model.library.JpsTypedLibrary; @@ -33,9 +34,12 @@ import org.jetbrains.jps.model.module.*; import org.jetbrains.jps.model.module.impl.JpsModuleImpl; import org.jetbrains.jps.model.module.impl.JpsModuleReferenceImpl; import org.jetbrains.jps.model.module.impl.JpsModuleSourceRootImpl; +import org.jetbrains.jps.service.JpsServiceManager; @ApiStatus.Internal public final class JpsElementFactoryImpl extends JpsElementFactory { + private volatile Boolean hasCustomReferenceFactory; + @Override public JpsModel createModel() { return new JpsModelImpl(); @@ -72,6 +76,13 @@ public final class JpsElementFactoryImpl extends JpsElementFactory { @NotNull @Override public JpsModuleReference createModuleReference(@NotNull String moduleName) { + if (hasCustomReferenceFactory()) { + for (JpsReferenceCustomFactory extension : JpsServiceManager.getInstance().getExtensions(JpsReferenceCustomFactory.class)) { + if (extension.isEnabled()) { + return extension.createModuleReference(moduleName); + } + } + } return new JpsModuleReferenceImpl(moduleName); } @@ -79,6 +90,13 @@ public final class JpsElementFactoryImpl extends JpsElementFactory { @Override public JpsLibraryReference createLibraryReference(@NotNull String libraryName, @NotNull JpsElementReference parentReference) { + if (hasCustomReferenceFactory()) { + for (JpsReferenceCustomFactory extension : JpsServiceManager.getInstance().getExtensions(JpsReferenceCustomFactory.class)) { + if (extension.isEnabled()) { + return extension.createLibraryReference(libraryName, parentReference); + } + } + } return new JpsLibraryReferenceImpl(libraryName, parentReference); } @@ -88,6 +106,20 @@ public final class JpsElementFactoryImpl extends JpsElementFactory { return new JpsSdkReferenceImpl<>(sdkName, sdkType, createGlobalReference()); } + private boolean hasCustomReferenceFactory() { + if (hasCustomReferenceFactory == null) { + boolean hasEnabledFactory = false; + for (JpsReferenceCustomFactory extension : JpsServiceManager.getInstance().getExtensions(JpsReferenceCustomFactory.class)) { + if (extension.isEnabled()) { + hasEnabledFactory = true; + break; + } + } + hasCustomReferenceFactory = hasEnabledFactory; + } + return hasCustomReferenceFactory; + } + @NotNull @Override public JpsElementReference createProjectReference() { diff --git a/platform/workspace/jps/resources/META-INF/services/org.jetbrains.jps.model.ex.JpsReferenceCustomFactory b/platform/workspace/jps/resources/META-INF/services/org.jetbrains.jps.model.ex.JpsReferenceCustomFactory new file mode 100644 index 000000000000..34cd4d479dc9 --- /dev/null +++ b/platform/workspace/jps/resources/META-INF/services/org.jetbrains.jps.model.ex.JpsReferenceCustomFactory @@ -0,0 +1,2 @@ +# Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +com.intellij.platform.workspace.jps.bridge.impl.JpsReferenceCustomFactoryImpl \ No newline at end of file diff --git a/platform/workspace/jps/src/com/intellij/platform/workspace/jps/bridge/impl/JpsReferenceCustomFactoryImpl.kt b/platform/workspace/jps/src/com/intellij/platform/workspace/jps/bridge/impl/JpsReferenceCustomFactoryImpl.kt new file mode 100644 index 000000000000..3c62c2c02d50 --- /dev/null +++ b/platform/workspace/jps/src/com/intellij/platform/workspace/jps/bridge/impl/JpsReferenceCustomFactoryImpl.kt @@ -0,0 +1,35 @@ +// 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.platform.workspace.jps.bridge.impl + +import com.intellij.platform.workspace.jps.bridge.impl.library.JpsLibraryCollectionsCache +import com.intellij.platform.workspace.jps.bridge.impl.library.JpsLibraryReferenceBridge +import com.intellij.platform.workspace.jps.bridge.impl.module.JpsModuleReferenceBridge +import com.intellij.platform.workspace.jps.entities.LibraryId +import com.intellij.platform.workspace.jps.entities.LibraryTableId +import com.intellij.platform.workspace.jps.entities.ModuleId +import org.jetbrains.jps.model.JpsCompositeElement +import org.jetbrains.jps.model.JpsElementReference +import org.jetbrains.jps.model.ex.JpsReferenceCustomFactory +import org.jetbrains.jps.model.impl.JpsGlobalElementReference +import org.jetbrains.jps.model.impl.JpsProjectElementReference +import org.jetbrains.jps.model.library.JpsLibraryReference +import org.jetbrains.jps.model.module.JpsModuleReference +import org.jetbrains.jps.model.serialization.impl.JpsSerializationViaWorkspaceModel + +internal class JpsReferenceCustomFactoryImpl : JpsReferenceCustomFactory { + override fun isEnabled(): Boolean = JpsSerializationViaWorkspaceModel.IS_ENABLED + + override fun createModuleReference(moduleName: String): JpsModuleReference { + return JpsModuleReferenceBridge(moduleName) + } + + override fun createLibraryReference(libraryName: String, parentReference: JpsElementReference): JpsLibraryReference { + val tableId = when (parentReference) { + is JpsGlobalElementReference -> JpsLibraryCollectionsCache.GLOBAL_LIBRARY_TABLE_ID + is JpsProjectElementReference -> LibraryTableId.ProjectLibraryTableId + is JpsModuleReference -> LibraryTableId.ModuleLibraryTableId(ModuleId(parentReference.moduleName)) + else -> throw UnsupportedOperationException("Reference to library in $parentReference is not supported") //todo support custom library tables + } + return JpsLibraryReferenceBridge(LibraryId(libraryName, tableId)) + } +}