diff --git a/jps/model-api/api-dump.txt b/jps/model-api/api-dump.txt index dd0627238e27..1e864fd0b5ad 100644 --- a/jps/model-api/api-dump.txt +++ b/jps/model-api/api-dump.txt @@ -102,6 +102,9 @@ org.jetbrains.jps.model.JpsNamedElement - org.jetbrains.jps.model.JpsElement - a:getName():java.lang.String - a:setName(java.lang.String):V +org.jetbrains.jps.model.JpsNamedElementCollection +- org.jetbrains.jps.model.JpsElementCollection +- a:findChild(java.lang.String):org.jetbrains.jps.model.JpsNamedElement org.jetbrains.jps.model.JpsProject - org.jetbrains.jps.model.JpsCompositeElement - org.jetbrains.jps.model.JpsReferenceableElement @@ -254,6 +257,7 @@ a:org.jetbrains.jps.model.ex.JpsExElementFactory - a:createCollection(org.jetbrains.jps.model.JpsElementChildRole):org.jetbrains.jps.model.JpsElementCollection - a:createContainer(org.jetbrains.jps.model.ex.JpsCompositeElementBase):org.jetbrains.jps.model.ex.JpsElementContainerEx - a:createContainerCopy(org.jetbrains.jps.model.ex.JpsElementContainerEx,org.jetbrains.jps.model.ex.JpsCompositeElementBase):org.jetbrains.jps.model.ex.JpsElementContainerEx +- a:createNamedElementCollection(org.jetbrains.jps.model.JpsElementChildRole):org.jetbrains.jps.model.JpsNamedElementCollection - s:getInstance():org.jetbrains.jps.model.ex.JpsExElementFactory a:org.jetbrains.jps.model.ex.JpsNamedCompositeElementBase - org.jetbrains.jps.model.ex.JpsCompositeElementBase @@ -262,6 +266,13 @@ a:org.jetbrains.jps.model.ex.JpsNamedCompositeElementBase - p:(org.jetbrains.jps.model.ex.JpsNamedCompositeElementBase):V - getName():java.lang.String - setName(java.lang.String):V +f:org.jetbrains.jps.model.ex.JpsNamedElementCollectionRole +- org.jetbrains.jps.model.ex.JpsElementChildRoleBase +- org.jetbrains.jps.model.JpsElementCreator +- create():org.jetbrains.jps.model.JpsNamedElementCollection +- s:create(org.jetbrains.jps.model.JpsElementChildRole):org.jetbrains.jps.model.ex.JpsNamedElementCollectionRole +- equals(java.lang.Object):Z +- hashCode():I a:org.jetbrains.jps.model.fileTypes.FileNameMatcherFactory - ():V - a:createMatcher(java.lang.String):com.intellij.openapi.fileTypes.FileNameMatcher diff --git a/jps/model-api/src/org/jetbrains/jps/model/JpsNamedElementCollection.java b/jps/model-api/src/org/jetbrains/jps/model/JpsNamedElementCollection.java new file mode 100644 index 000000000000..5e1b2bdc5df5 --- /dev/null +++ b/jps/model-api/src/org/jetbrains/jps/model/JpsNamedElementCollection.java @@ -0,0 +1,12 @@ +package org.jetbrains.jps.model; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public interface JpsNamedElementCollection extends JpsElementCollection { + /** + * Returns a child from this collection which {@link JpsNamedElement#getName() name} is equal to {@code name} or {@code null} if there is + * no such element. + */ + @Nullable E findChild(@NotNull String name); +} diff --git a/jps/model-api/src/org/jetbrains/jps/model/ex/JpsExElementFactory.java b/jps/model-api/src/org/jetbrains/jps/model/ex/JpsExElementFactory.java index 737c3ddb835e..1e4a0dc77783 100644 --- a/jps/model-api/src/org/jetbrains/jps/model/ex/JpsExElementFactory.java +++ b/jps/model-api/src/org/jetbrains/jps/model/ex/JpsExElementFactory.java @@ -16,9 +16,7 @@ package org.jetbrains.jps.model.ex; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jps.model.JpsElement; -import org.jetbrains.jps.model.JpsElementChildRole; -import org.jetbrains.jps.model.JpsElementCollection; +import org.jetbrains.jps.model.*; import org.jetbrains.jps.service.JpsServiceManager; public abstract class JpsExElementFactory { @@ -27,6 +25,8 @@ public abstract class JpsExElementFactory { } public abstract JpsElementCollection createCollection(JpsElementChildRole role); + + public abstract JpsNamedElementCollection createNamedElementCollection(JpsElementChildRole role); public abstract JpsElementContainerEx createContainer(@NotNull JpsCompositeElementBase parent); diff --git a/jps/model-api/src/org/jetbrains/jps/model/ex/JpsNamedElementCollectionRole.java b/jps/model-api/src/org/jetbrains/jps/model/ex/JpsNamedElementCollectionRole.java new file mode 100644 index 000000000000..379dfce59e82 --- /dev/null +++ b/jps/model-api/src/org/jetbrains/jps/model/ex/JpsNamedElementCollectionRole.java @@ -0,0 +1,37 @@ +// 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.NotNull; +import org.jetbrains.jps.model.*; + +public final class JpsNamedElementCollectionRole extends JpsElementChildRoleBase> + implements JpsElementCreator> { + private final JpsElementChildRole myChildRole; + + private JpsNamedElementCollectionRole(@NotNull JpsElementChildRole role) { + super("collection of " + role); + myChildRole = role; + } + + @Override + public @NotNull JpsNamedElementCollection create() { + return JpsExElementFactory.getInstance().createNamedElementCollection(myChildRole); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + return myChildRole.equals(((JpsNamedElementCollectionRole)o).myChildRole); + } + + @Override + public int hashCode() { + return myChildRole.hashCode(); + } + + public static JpsNamedElementCollectionRole create(@NotNull JpsElementChildRole role) { + return new JpsNamedElementCollectionRole<>(role); + } +} diff --git a/jps/model-impl/api-dump.txt b/jps/model-impl/api-dump.txt index ce6a6a6a944c..f8efb9023ef5 100644 --- a/jps/model-impl/api-dump.txt +++ b/jps/model-impl/api-dump.txt @@ -30,7 +30,8 @@ a:org.jetbrains.jps.model.impl.JpsNamedElementReferenceBase - p:(java.lang.String,org.jetbrains.jps.model.JpsElementReference):V - p:(org.jetbrains.jps.model.impl.JpsNamedElementReferenceBase):V - asExternal(org.jetbrains.jps.model.JpsModel):org.jetbrains.jps.model.JpsElementReference -- pa:getCollection(org.jetbrains.jps.model.JpsCompositeElement):org.jetbrains.jps.model.JpsElementCollection +- p:getCollection(org.jetbrains.jps.model.JpsCompositeElement):org.jetbrains.jps.model.JpsElementCollection +- p:getNamedElementCollection(org.jetbrains.jps.model.JpsCompositeElement):org.jetbrains.jps.model.JpsNamedElementCollection - getParentReference():org.jetbrains.jps.model.JpsElementReference - resolve():org.jetbrains.jps.model.JpsNamedElement - pa:resolve(org.jetbrains.jps.model.JpsNamedElement):org.jetbrains.jps.model.JpsNamedElement diff --git a/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/JpsArtifactRole.java b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/JpsArtifactRole.java index dd8ce3f48ead..a21707af0208 100644 --- a/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/JpsArtifactRole.java +++ b/jps/model-impl/src/org/jetbrains/jps/model/artifact/impl/JpsArtifactRole.java @@ -2,12 +2,12 @@ package org.jetbrains.jps.model.artifact.impl; import org.jetbrains.jps.model.artifact.JpsArtifact; -import org.jetbrains.jps.model.ex.JpsElementCollectionRole; import org.jetbrains.jps.model.ex.JpsElementChildRoleBase; +import org.jetbrains.jps.model.ex.JpsNamedElementCollectionRole; final class JpsArtifactRole extends JpsElementChildRoleBase { private static final JpsArtifactRole INSTANCE = new JpsArtifactRole(); - public static final JpsElementCollectionRole ARTIFACT_COLLECTION_ROLE = JpsElementCollectionRole.create(INSTANCE); + public static final JpsNamedElementCollectionRole ARTIFACT_COLLECTION_ROLE = JpsNamedElementCollectionRole.create(INSTANCE); private JpsArtifactRole() { super("artifact"); diff --git a/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsElementCollectionImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsElementCollectionImpl.java index 6b240c04eb0e..537045f640e0 100644 --- a/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsElementCollectionImpl.java +++ b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsElementCollectionImpl.java @@ -10,7 +10,7 @@ import org.jetbrains.jps.model.ex.JpsElementBase; import java.util.*; @ApiStatus.Internal -public final class JpsElementCollectionImpl extends JpsElementBase> implements JpsElementCollection { +public class JpsElementCollectionImpl extends JpsElementBase> implements JpsElementCollection { private final List myElements; private final Map myCopyToOriginal; private final JpsElementChildRole myChildRole; @@ -21,7 +21,7 @@ public final class JpsElementCollectionImpl extends JpsEle myCopyToOriginal = null; } - private JpsElementCollectionImpl(JpsElementCollectionImpl original) { + protected JpsElementCollectionImpl(JpsElementCollectionImpl original) { myChildRole = original.myChildRole; myElements = new ArrayList<>(original.myElements.size()); myCopyToOriginal = new HashMap<>(original.myElements.size()); diff --git a/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsExElementFactoryImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsExElementFactoryImpl.java index efb276a4e773..b81fc54bce78 100644 --- a/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsExElementFactoryImpl.java +++ b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsExElementFactoryImpl.java @@ -17,9 +17,7 @@ package org.jetbrains.jps.model.impl; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jps.model.JpsElement; -import org.jetbrains.jps.model.JpsElementChildRole; -import org.jetbrains.jps.model.JpsElementCollection; +import org.jetbrains.jps.model.*; import org.jetbrains.jps.model.ex.JpsCompositeElementBase; import org.jetbrains.jps.model.ex.JpsElementContainerEx; import org.jetbrains.jps.model.ex.JpsElementContainerImpl; @@ -42,4 +40,9 @@ public final class JpsExElementFactoryImpl extends JpsExElementFactory { public JpsElementCollection createCollection(JpsElementChildRole role) { return new JpsElementCollectionImpl<>(role); } + + @Override + public JpsNamedElementCollection createNamedElementCollection(JpsElementChildRole role) { + return new JpsNamedElementCollectionImpl<>(role); + } } diff --git a/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsNamedElementCollectionImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsNamedElementCollectionImpl.java new file mode 100644 index 000000000000..273b612f9d55 --- /dev/null +++ b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsNamedElementCollectionImpl.java @@ -0,0 +1,64 @@ +// 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.model.impl; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jps.model.JpsElementChildRole; +import org.jetbrains.jps.model.JpsElementCreator; +import org.jetbrains.jps.model.JpsNamedElement; +import org.jetbrains.jps.model.JpsNamedElementCollection; + +import java.util.HashMap; +import java.util.Map; + +final class JpsNamedElementCollectionImpl extends JpsElementCollectionImpl implements + JpsNamedElementCollection { + private final Map myElementByName = new HashMap<>(); + + JpsNamedElementCollectionImpl(JpsElementChildRole role) { + super(role); + } + + JpsNamedElementCollectionImpl(JpsNamedElementCollectionImpl original) { + super(original); + for (E element : getElements()) { + myElementByName.put(element.getName(), element); + } + } + + @Override + public @Nullable E findChild(@NotNull String name) { + return myElementByName.get(name); + } + + @Override + public @NotNull E addChild(@NotNull JpsElementCreator creator) { + E child = super.addChild(creator); + myElementByName.put(child.getName(), child); + return child; + } + + @Override + public X addChild(X element) { + X child = super.addChild(element); + myElementByName.put(child.getName(), child); + return child; + } + + @Override + public void removeChild(@NotNull E element) { + super.removeChild(element); + myElementByName.remove(element.getName()); + } + + @Override + public void removeAllChildren() { + super.removeAllChildren(); + myElementByName.clear(); + } + + @Override + public @NotNull JpsElementCollectionImpl createCopy() { + return new JpsNamedElementCollectionImpl<>(this); + } +} diff --git a/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsNamedElementReferenceBase.java b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsNamedElementReferenceBase.java index 91c266198e70..a74ecb698bde 100644 --- a/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsNamedElementReferenceBase.java +++ b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsNamedElementReferenceBase.java @@ -38,6 +38,11 @@ public abstract class JpsNamedElementReferenceBase collection = getCollection(parent); if (collection == null) return null; + if (collection instanceof JpsNamedElementCollection) { + S element = ((JpsNamedElementCollection)collection).findChild(myElementName); + return element != null ? resolve(element) : null; + } + final List elements = collection.getElements(); for (S element : elements) { if (element.getName().equals(myElementName)) { @@ -50,7 +55,18 @@ public abstract class JpsNamedElementReferenceBase getCollection(@NotNull JpsCompositeElement parent); + /** + * @deprecated override {@link #getNamedElementCollection} instead to speed up {@link #resolve()} + */ + @SuppressWarnings("DeprecatedIsStillUsed") + @Deprecated + protected @Nullable JpsElementCollection getCollection(@NotNull JpsCompositeElement parent) { + return getNamedElementCollection(parent); + } + + protected @Nullable JpsNamedElementCollection getNamedElementCollection(@NotNull JpsCompositeElement parent) { + return null; + } protected abstract @Nullable T resolve(S element); diff --git a/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsNamedElementReferenceImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsNamedElementReferenceImpl.java index 3c7a1a8c7e70..c7c6c3dd0037 100644 --- a/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsNamedElementReferenceImpl.java +++ b/jps/model-impl/src/org/jetbrains/jps/model/impl/JpsNamedElementReferenceImpl.java @@ -4,28 +4,50 @@ package org.jetbrains.jps.model.impl; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jps.model.JpsCompositeElement; -import org.jetbrains.jps.model.JpsElementCollection; -import org.jetbrains.jps.model.JpsElementReference; -import org.jetbrains.jps.model.JpsNamedElement; +import org.jetbrains.jps.model.*; +import org.jetbrains.jps.model.ex.JpsElementChildRoleBase; import org.jetbrains.jps.model.ex.JpsElementCollectionRole; +import org.jetbrains.jps.model.ex.JpsNamedElementCollectionRole; /** * This class is for internal use only, override {@link JpsNamedElementReferenceBase} instead. */ @ApiStatus.Internal public abstract class JpsNamedElementReferenceImpl> extends JpsNamedElementReferenceBase { - protected final JpsElementCollectionRole myCollectionRole; + /** + * @deprecated use {@link #getCollectionRole()} instead + */ + @SuppressWarnings("DeprecatedIsStillUsed") + @Deprecated + protected final @Nullable JpsElementCollectionRole myCollectionRole; + private final JpsElementChildRoleBase> myActualCollectionRole; + /** + * @deprecated use {@link #JpsNamedElementReferenceImpl(JpsNamedElementCollectionRole, String, JpsElementReference)} instead JpsNamedElementReferenceImpl} + */ + @Deprecated protected JpsNamedElementReferenceImpl(@NotNull JpsElementCollectionRole role, @NotNull String elementName, @NotNull JpsElementReference parentReference) { super(elementName, parentReference); myCollectionRole = role; + myActualCollectionRole = role; + } + + protected JpsNamedElementReferenceImpl(@NotNull JpsNamedElementCollectionRole role, @NotNull String elementName, + @NotNull JpsElementReference parentReference) { + super(elementName, parentReference); + myCollectionRole = null; + myActualCollectionRole = role; + } + + protected JpsElementChildRoleBase> getCollectionRole() { + return myActualCollectionRole; } protected JpsNamedElementReferenceImpl(JpsNamedElementReferenceImpl original) { super(original); myCollectionRole = original.myCollectionRole; + myActualCollectionRole = original.myActualCollectionRole; } @Override @@ -35,6 +57,6 @@ public abstract class JpsNamedElementReferenceImpl getCollection(@NotNull JpsCompositeElement parent) { - return parent.getContainer().getChild(myCollectionRole); + return parent.getContainer().getChild(myActualCollectionRole); } } diff --git a/jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsLibraryRole.java b/jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsLibraryRole.java index 69535e224880..d453c1acf050 100644 --- a/jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsLibraryRole.java +++ b/jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsLibraryRole.java @@ -2,12 +2,12 @@ package org.jetbrains.jps.model.library.impl; import org.jetbrains.jps.model.ex.JpsElementChildRoleBase; -import org.jetbrains.jps.model.ex.JpsElementCollectionRole; +import org.jetbrains.jps.model.ex.JpsNamedElementCollectionRole; import org.jetbrains.jps.model.library.JpsLibrary; public final class JpsLibraryRole extends JpsElementChildRoleBase { private static final JpsLibraryRole INSTANCE = new JpsLibraryRole(); - public static final JpsElementCollectionRole LIBRARIES_COLLECTION_ROLE = JpsElementCollectionRole.create(INSTANCE); + public static final JpsNamedElementCollectionRole LIBRARIES_COLLECTION_ROLE = JpsNamedElementCollectionRole.create(INSTANCE); private JpsLibraryRole() { super("library"); diff --git a/jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsSdkReferenceImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsSdkReferenceImpl.java index 9d6ffe77c3ef..6adf60851a37 100644 --- a/jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsSdkReferenceImpl.java +++ b/jps/model-impl/src/org/jetbrains/jps/model/library/impl/JpsSdkReferenceImpl.java @@ -3,10 +3,7 @@ package org.jetbrains.jps.model.library.impl; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jps.model.JpsCompositeElement; -import org.jetbrains.jps.model.JpsElement; -import org.jetbrains.jps.model.JpsElementCollection; -import org.jetbrains.jps.model.JpsElementReference; +import org.jetbrains.jps.model.*; import org.jetbrains.jps.model.impl.JpsNamedElementReferenceBase; import org.jetbrains.jps.model.library.JpsLibrary; import org.jetbrains.jps.model.library.JpsTypedLibrary; @@ -44,7 +41,7 @@ public final class JpsSdkReferenceImpl

extends JpsNamedEle } @Override - protected @Nullable JpsElementCollection getCollection(@NotNull JpsCompositeElement parent) { + protected @Nullable JpsNamedElementCollection getNamedElementCollection(@NotNull JpsCompositeElement parent) { return parent.getContainer().getChild(JpsLibraryRole.LIBRARIES_COLLECTION_ROLE); } diff --git a/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsModuleRole.java b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsModuleRole.java index c76779a8287b..152d5bc50bb7 100644 --- a/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsModuleRole.java +++ b/jps/model-impl/src/org/jetbrains/jps/model/module/impl/JpsModuleRole.java @@ -3,12 +3,12 @@ package org.jetbrains.jps.model.module.impl; import org.jetbrains.jps.model.JpsElementChildRole; import org.jetbrains.jps.model.ex.JpsElementChildRoleBase; -import org.jetbrains.jps.model.ex.JpsElementCollectionRole; +import org.jetbrains.jps.model.ex.JpsNamedElementCollectionRole; import org.jetbrains.jps.model.module.JpsModule; public final class JpsModuleRole extends JpsElementChildRoleBase { private static final JpsElementChildRole INSTANCE = new JpsModuleRole(); - public static final JpsElementCollectionRole MODULE_COLLECTION_ROLE = JpsElementCollectionRole.create(INSTANCE); + public static final JpsNamedElementCollectionRole MODULE_COLLECTION_ROLE = JpsNamedElementCollectionRole.create(INSTANCE); private JpsModuleRole() { super("module");