From cab62c6ccbdab8bd3a8f20cbaf298a3126ac3b43 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Mon, 1 Jun 2020 20:34:58 +0200 Subject: [PATCH] IDEA-CR-62371 use client class as cache id because it's dangerous to rely on identity of functional expressions. GitOrigin-RevId: 41d38ae5da583af0ed4520cb2e06b9def7fb871b --- .../intellij/lang/jvm/JvmMetaLanguage.java | 2 +- .../CompletionIgnoreDumbnessEP.java | 2 +- .../ex/LocalInspectionToolWrapper.java | 2 +- .../org/jetbrains/io/jsonRpc/JsonRpcServer.kt | 4 +-- .../model/psi/impl/ReferenceProviders.java | 7 +++-- .../extensions/ExtensionPointName.java | 17 ++++++++---- .../impl/ExtensionProcessingHelper.java | 27 ++++++++++--------- .../impl/ExtensionPointImplTest.java | 17 +++++++----- .../manage/ProjectDataManagerImpl.java | 4 +-- .../execution/impl/ConsoleViewImpl.java | 2 +- .../facet/impl/FacetEventsPublisher.kt | 4 +-- .../impl/StructureViewFactoryImpl.java | 2 +- .../module/impl/ModuleTypeManagerImpl.java | 2 +- .../streams/action/ChainResolver.java | 4 +-- .../com/intellij/psi/xml/XmlChildRole.java | 21 ++++++++++----- 15 files changed, 70 insertions(+), 47 deletions(-) diff --git a/java/java-psi-api/src/com/intellij/lang/jvm/JvmMetaLanguage.java b/java/java-psi-api/src/com/intellij/lang/jvm/JvmMetaLanguage.java index 1f1061746457..9c34bf680bcf 100644 --- a/java/java-psi-api/src/com/intellij/lang/jvm/JvmMetaLanguage.java +++ b/java/java-psi-api/src/com/intellij/lang/jvm/JvmMetaLanguage.java @@ -44,7 +44,7 @@ public final class JvmMetaLanguage extends MetaLanguage { } private static boolean matchesRegisteredLanguage(@NotNull Language language, @NotNull ExtensionPointImpl> point) { - return ExtensionProcessingHelper.getByKey(point, language.getID(), LanguageExtensionPoint::getKey) != null; + return ExtensionProcessingHelper.getByKey(point, language.getID(), JvmMetaLanguage.class, LanguageExtensionPoint::getKey) != null; } private @Nullable static ExtensionPointImpl> getPoint() { diff --git a/platform/analysis-api/src/com/intellij/codeInsight/completion/CompletionIgnoreDumbnessEP.java b/platform/analysis-api/src/com/intellij/codeInsight/completion/CompletionIgnoreDumbnessEP.java index 3aca2ae6ecaf..22f7c6127189 100644 --- a/platform/analysis-api/src/com/intellij/codeInsight/completion/CompletionIgnoreDumbnessEP.java +++ b/platform/analysis-api/src/com/intellij/codeInsight/completion/CompletionIgnoreDumbnessEP.java @@ -16,7 +16,7 @@ public class CompletionIgnoreDumbnessEP extends LazyExtensionInstance { ExtensionPointName.create("com.intellij.completion.ignoringDumbnessAllowed"); public static boolean isIgnoringDumbnessAllowed(@NotNull Language language) { - return EP_NAME.getByKey(language.getID(), ep -> ep.language) != null; + return EP_NAME.getByKey(language.getID(), CompletionIgnoreDumbnessEP.class, ep -> ep.language) != null; } /** diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/ex/LocalInspectionToolWrapper.java b/platform/analysis-impl/src/com/intellij/codeInspection/ex/LocalInspectionToolWrapper.java index 3f1ce9e7472f..c5da25dccf23 100644 --- a/platform/analysis-impl/src/com/intellij/codeInspection/ex/LocalInspectionToolWrapper.java +++ b/platform/analysis-impl/src/com/intellij/codeInspection/ex/LocalInspectionToolWrapper.java @@ -11,7 +11,7 @@ import org.jetbrains.annotations.Nullable; public class LocalInspectionToolWrapper extends InspectionToolWrapper { /** This should be used in tests primarily */ public LocalInspectionToolWrapper(@NotNull LocalInspectionTool tool) { - super(tool, LocalInspectionEP.LOCAL_INSPECTION.getByKey(tool.getShortName(), InspectionEP::getShortName)); + super(tool, LocalInspectionEP.LOCAL_INSPECTION.getByKey(tool.getShortName(), LocalInspectionToolWrapper.class, InspectionEP::getShortName)); } public LocalInspectionToolWrapper(@NotNull LocalInspectionEP ep) { diff --git a/platform/built-in-server/src/org/jetbrains/io/jsonRpc/JsonRpcServer.kt b/platform/built-in-server/src/org/jetbrains/io/jsonRpc/JsonRpcServer.kt index 4058380e5be4..0707c5ebca8a 100644 --- a/platform/built-in-server/src/org/jetbrains/io/jsonRpc/JsonRpcServer.kt +++ b/platform/built-in-server/src/org/jetbrains/io/jsonRpc/JsonRpcServer.kt @@ -1,4 +1,4 @@ -// Copyright 2000-2019 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-2020 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. package org.jetbrains.io.jsonRpc import com.google.gson.Gson @@ -151,7 +151,7 @@ class JsonRpcServer(private val clientManager: ClientManager) : MessageServer { private fun findDomain(domainName: String): Any? { val testDomain = this.testDomain if (testDomain != null && testDomain.first == domainName) return testDomain.second - return JsonRpcDomainBean.EP_NAME.getByKey(domainName, JsonRpcDomainBean::name)?.instance + return JsonRpcDomainBean.EP_NAME.getByKey(domainName, JsonRpcServer::class.java, JsonRpcDomainBean::name)?.instance } private fun processClientError(client: Client, error: String, messageId: Int) { diff --git a/platform/core-impl/src/com/intellij/model/psi/impl/ReferenceProviders.java b/platform/core-impl/src/com/intellij/model/psi/impl/ReferenceProviders.java index f85da7a15e54..a41dc7013ff6 100644 --- a/platform/core-impl/src/com/intellij/model/psi/impl/ReferenceProviders.java +++ b/platform/core-impl/src/com/intellij/model/psi/impl/ReferenceProviders.java @@ -11,17 +11,20 @@ import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; +import java.util.function.Function; @ApiStatus.Internal public final class ReferenceProviders { private static final ExtensionPointName EP_NAME = new ExtensionPointName<>("com.intellij.psi.symbolReferenceProvider"); + private static final @NotNull Function VALUE_MAPPER = ReferenceProviders::byLanguageInner; + /** * Given language of a host element returns list of providers that could provide references from this language. */ static @NotNull LanguageReferenceProviders byLanguage(@NotNull Language language) { - return EP_NAME.computeIfAbsent(language, ReferenceProviders::byLanguageInner); + return EP_NAME.computeIfAbsent(language, VALUE_MAPPER); } private static @NotNull LanguageReferenceProviders byLanguageInner(@NotNull Language language) { @@ -41,6 +44,6 @@ public final class ReferenceProviders { * Given class of target returns list of providers that could provide references to this target. */ public static @NotNull List byTargetClass(@NotNull Class targetClass) { - return EP_NAME.getByGroupingKey(targetClass, bean -> bean.getResolveTargetClass().isAssignableFrom(targetClass) ? targetClass : null); + return EP_NAME.getByGroupingKey(targetClass, ReferenceProviders.class, bean -> bean.getResolveTargetClass().isAssignableFrom(targetClass) ? targetClass : null); } } diff --git a/platform/extensions/src/com/intellij/openapi/extensions/ExtensionPointName.java b/platform/extensions/src/com/intellij/openapi/extensions/ExtensionPointName.java index 254ddb4673db..8e0b9f5c66bf 100644 --- a/platform/extensions/src/com/intellij/openapi/extensions/ExtensionPointName.java +++ b/platform/extensions/src/com/intellij/openapi/extensions/ExtensionPointName.java @@ -178,10 +178,13 @@ public final class ExtensionPointName extends BaseExtensionPointName { * Build cache by arbitrary key using provided key to value mapper. Values with the same key merge into list. Return values by key. *

* To exclude extension from cache, return null key. + * + * {@code cacheId} is required because it's dangerous to rely on identity of functional expressions. + * JLS doesn't specify whether a new instance is produced or some common instance is reused for lambda expressions (see 15.27.4). */ @ApiStatus.Experimental - public final <@NotNull K> @NotNull List getByGroupingKey(@NotNull K key, @NotNull Function<@NotNull T, @Nullable K> keyMapper) { - return ExtensionProcessingHelper.getByGroupingKey(getPointImpl(null), key, keyMapper); + public final <@NotNull K> @NotNull List getByGroupingKey(@NotNull K key, @NotNull Class cacheId, @NotNull Function<@NotNull T, @Nullable K> keyMapper) { + return ExtensionProcessingHelper.getByGroupingKey(getPointImpl(null), cacheId, key, keyMapper); } /** @@ -190,8 +193,8 @@ public final class ExtensionPointName extends BaseExtensionPointName { * To exclude extension from cache, return null key. */ @ApiStatus.Experimental - public final <@NotNull K> @Nullable T getByKey(@NotNull K key, @NotNull Function<@NotNull T, @Nullable K> keyMapper) { - return ExtensionProcessingHelper.getByKey(getPointImpl(null), key, keyMapper); + public final <@NotNull K> @Nullable T getByKey(@NotNull K key, @NotNull Class cacheId, @NotNull Function<@NotNull T, @Nullable K> keyMapper) { + return ExtensionProcessingHelper.getByKey(getPointImpl(null), key, cacheId, keyMapper); } /** @@ -201,11 +204,15 @@ public final class ExtensionPointName extends BaseExtensionPointName { */ @ApiStatus.Experimental public final <@NotNull K, @NotNull V> @Nullable V getByKey(@NotNull K key, + @NotNull Class cacheId, @NotNull Function<@NotNull T, @Nullable K> keyMapper, @NotNull Function<@NotNull T, @Nullable V> valueMapper) { - return ExtensionProcessingHelper.getByKey(getPointImpl(null), key, keyMapper, valueMapper); + return ExtensionProcessingHelper.getByKey(getPointImpl(null), key, cacheId, keyMapper, valueMapper); } + /** + * {@code valueMapper} used as cache id and therefore must be extracted to a static final field. + */ @ApiStatus.Experimental public final <@NotNull K, @NotNull V> @NotNull V computeIfAbsent(@NotNull K key, @NotNull Function<@NotNull K, @NotNull V> valueMapper) { diff --git a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionProcessingHelper.java b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionProcessingHelper.java index f3abb8ff271c..d71871e776db 100644 --- a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionProcessingHelper.java +++ b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionProcessingHelper.java @@ -1,6 +1,7 @@ // Copyright 2000-2020 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. package com.intellij.openapi.extensions.impl; +import com.intellij.openapi.extensions.ExtensionPoint; import com.intellij.openapi.progress.ProcessCanceledException; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import org.jetbrains.annotations.ApiStatus; @@ -71,13 +72,14 @@ public final class ExtensionProcessingHelper { * See {@link com.intellij.openapi.extensions.ExtensionPointName#getByGroupingKey}. */ public static <@NotNull K, @NotNull T> @NotNull List getByGroupingKey(@NotNull ExtensionPointImpl point, + @NotNull Class cacheId, @NotNull K key, @NotNull Function<@NotNull T, @Nullable K> keyMapper) { - ConcurrentMap, Map>> keyMapperToCache = point.getCacheMap(); - Map> cache = keyMapperToCache.get(keyMapper); + ConcurrentMap, Map>> keyMapperToCache = point.getCacheMap(); + Map> cache = keyMapperToCache.get(cacheId); if (cache == null) { cache = buildCacheForGroupingKeyMapper(keyMapper, point); - Map> prev = keyMapperToCache.putIfAbsent(keyMapper, cache); + Map> prev = keyMapperToCache.putIfAbsent(cacheId, cache); if (prev != null) { cache = prev; } @@ -93,10 +95,10 @@ public final class ExtensionProcessingHelper { @ApiStatus.Internal public static <@NotNull K, @NotNull T, @NotNull V> @Nullable V getByKey(@NotNull ExtensionPointImpl point, @NotNull K key, + @NotNull Class cacheId, @NotNull Function<@NotNull T, @Nullable K> keyMapper, @NotNull Function<@NotNull T, @Nullable V> valueMapper) { - SimpleImmutableEntry, Function> cacheKey = new SimpleImmutableEntry<>(keyMapper, valueMapper); - return doGetByKey(point, cacheKey, key, keyMapper, valueMapper, point.getCacheMap()); + return doGetByKey(point, cacheId, key, keyMapper, valueMapper, point.getCacheMap()); } /** @@ -105,8 +107,9 @@ public final class ExtensionProcessingHelper { @ApiStatus.Internal public static <@NotNull K, @NotNull T> @Nullable T getByKey(@NotNull ExtensionPointImpl point, @NotNull K key, + @NotNull Class cacheId, @NotNull Function<@NotNull T, @Nullable K> keyMapper) { - return doGetByKey(point, keyMapper, key, keyMapper, Function.identity(), point.getCacheMap()); + return doGetByKey(point, cacheId, key, keyMapper, Function.identity(), point.getCacheMap()); } /** @@ -121,16 +124,16 @@ public final class ExtensionProcessingHelper { return cache.computeIfAbsent(new SimpleImmutableEntry<>(key, valueProducer), entry -> valueProducer.apply(entry.getKey())); } - private static @Nullable V doGetByKey(@NotNull ExtensionPointImpl point, - @NotNull CACHE_KEY cacheKey, + private static @Nullable V doGetByKey(@NotNull ExtensionPoint point, + @NotNull CACHE_KEY cacheId, @NotNull K key, @NotNull Function keyMapper, @NotNull Function<@NotNull T, @Nullable V> valueMapper, @NotNull ConcurrentMap> keyMapperToCache) { - Map cache = keyMapperToCache.get(cacheKey); + Map cache = keyMapperToCache.get(cacheId); if (cache == null) { cache = buildCacheForKeyMapper(keyMapper, valueMapper, point); - Map prev = keyMapperToCache.putIfAbsent(cacheKey, cache); + Map prev = keyMapperToCache.putIfAbsent(cacheId, cache); if (prev != null) { cache = prev; } @@ -139,7 +142,7 @@ public final class ExtensionProcessingHelper { } private static @NotNull Map> buildCacheForGroupingKeyMapper(@NotNull Function keyMapper, - @NotNull ExtensionPointImpl point) { + @NotNull ExtensionPoint point) { // use HashMap instead of THashMap - a lot of keys not expected, nowadays HashMap is a more optimized (e.g. computeIfAbsent implemented in an efficient manner) Map> cache = new HashMap<>(); for (T extension : point.getExtensionList()) { @@ -154,7 +157,7 @@ public final class ExtensionProcessingHelper { private static @NotNull Map buildCacheForKeyMapper(@NotNull Function keyMapper, @NotNull Function<@NotNull T, @Nullable V> valueMapper, - @NotNull ExtensionPointImpl point) { + @NotNull ExtensionPoint point) { List extensions = point.getExtensionList(); Map cache = new Object2ObjectOpenHashMap<>(extensions.size()); for (T extension : extensions) { diff --git a/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionPointImplTest.java b/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionPointImplTest.java index e7cded075e17..e343939d542f 100644 --- a/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionPointImplTest.java +++ b/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionPointImplTest.java @@ -290,14 +290,17 @@ public class ExtensionPointImplTest { assertThat(extensionPoint.getExtensionList()).containsExactly(4, 2); - assertThat(ExtensionProcessingHelper.getByGroupingKey(extensionPoint, "foo", it -> "foo")).isEqualTo(extensionPoint.getExtensionList()); - assertThat(ExtensionProcessingHelper.getByKey(extensionPoint, 2, Function.identity(), Function.identity())).isEqualTo(2); - assertThat(ExtensionProcessingHelper.getByKey(extensionPoint, 2, Function.identity(), (Integer it) -> it * 2)).isEqualTo(4); + Function f = it -> "foo"; + assertThat(ExtensionProcessingHelper.getByGroupingKey(extensionPoint, f.getClass(), "foo", f)).isEqualTo(extensionPoint.getExtensionList()); + assertThat(ExtensionProcessingHelper.getByKey(extensionPoint, 2, ExtensionPointImplTest.class, Function.identity(), Function.identity())).isEqualTo(2); + Function f2 = (Integer it) -> it * 2; + assertThat(ExtensionProcessingHelper.getByKey(extensionPoint, 2, f2.getClass(), Function.identity(), f2)).isEqualTo(4); - Function<@NotNull Integer, @Nullable Integer> filteringKeyMapper = it -> it < 3 ? it : null; - assertThat(ExtensionProcessingHelper.getByKey(extensionPoint, 2, filteringKeyMapper, Function.identity())).isEqualTo(2); - assertThat(ExtensionProcessingHelper.getByKey(extensionPoint, 4, filteringKeyMapper, Function.identity())).isNull(); - assertThat(ExtensionProcessingHelper.getByKey(extensionPoint, 4, Function.identity(), (Integer it) -> (Integer)null)).isNull(); + Function filteringKeyMapper = it -> it < 3 ? it : null; + assertThat(ExtensionProcessingHelper.getByKey(extensionPoint, 2, filteringKeyMapper.getClass(), filteringKeyMapper, Function.identity())).isEqualTo(2); + assertThat(ExtensionProcessingHelper.getByKey(extensionPoint, 4, filteringKeyMapper.getClass(), filteringKeyMapper, Function.identity())).isNull(); + Function<@NotNull Integer, @Nullable Integer> f3 = (Integer it) -> (Integer)null; + assertThat(ExtensionProcessingHelper.getByKey(extensionPoint, 4, f3.getClass(), Function.identity(), f3)).isNull(); } @Test diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ProjectDataManagerImpl.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ProjectDataManagerImpl.java index 4195f8b153ef..a327c11354a5 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ProjectDataManagerImpl.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ProjectDataManagerImpl.java @@ -1,4 +1,4 @@ -// Copyright 2000-2019 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-2020 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. package com.intellij.openapi.externalSystem.service.project.manage; import com.intellij.openapi.application.ApplicationManager; @@ -48,7 +48,7 @@ public class ProjectDataManagerImpl implements ProjectDataManager { @Override @NotNull public List> findService(@NotNull Key key) { - List> result = ProjectDataService.EP_NAME.getByGroupingKey(key, KEY_MAPPER); + List> result = ProjectDataService.EP_NAME.getByGroupingKey(key, ProjectDataManagerImpl.class, KEY_MAPPER); ExternalSystemApiUtil.orderAwareSort(result); return result; } diff --git a/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java index 655f2e314f45..ea6483251669 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java @@ -1079,7 +1079,7 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo startLine > 0 ? myEditor.getFoldingModel().getCollapsedRegionAtOffset(document.getLineStartOffset(startLine - 1)) : null; String lastFoldingFqn = USED_FOLDING_FQN_KEY.get(existingRegion); ConsoleFolding lastFolding = lastFoldingFqn != null - ? ConsoleFolding.EP_NAME.getByKey(lastFoldingFqn, consoleFolding -> consoleFolding.getClass().getName()) + ? ConsoleFolding.EP_NAME.getByKey(lastFoldingFqn, ConsoleViewImpl.class, consoleFolding -> consoleFolding.getClass().getName()) : null; int lastStartLine = lastFolding == null ? Integer.MAX_VALUE : existingRegion.getStartOffset() == 0 ? 0 : diff --git a/platform/lang-impl/src/com/intellij/facet/impl/FacetEventsPublisher.kt b/platform/lang-impl/src/com/intellij/facet/impl/FacetEventsPublisher.kt index 57264351d53d..87f0ce3232b8 100644 --- a/platform/lang-impl/src/com/intellij/facet/impl/FacetEventsPublisher.kt +++ b/platform/lang-impl/src/com/intellij/facet/impl/FacetEventsPublisher.kt @@ -175,7 +175,7 @@ class FacetEventsPublisher(private val project: Project) { @Suppress("UNCHECKED_CAST") private inline fun > processListeners(facetType: FacetType, action: (ProjectFacetListener) -> Unit) { - for (listenerEP in LISTENER_EP.getByGroupingKey(facetType.stringId, LISTENER_EP_CACHE_KEY)) { + for (listenerEP in LISTENER_EP.getByGroupingKey(facetType.stringId, LISTENER_EP_CACHE_KEY::class.java, LISTENER_EP_CACHE_KEY)) { action(listenerEP.listenerInstance as ProjectFacetListener) } manuallyRegisteredListeners.filter { it.first == facetType.id }.forEach { @@ -185,7 +185,7 @@ class FacetEventsPublisher(private val project: Project) { @Suppress("UNCHECKED_CAST") private inline fun processListeners(action: (ProjectFacetListener>) -> Unit) { - for (listenerEP in LISTENER_EP.getByGroupingKey(ANY_TYPE, LISTENER_EP_CACHE_KEY)) { + for (listenerEP in LISTENER_EP.getByGroupingKey(ANY_TYPE, LISTENER_EP_CACHE_KEY::class.java, LISTENER_EP_CACHE_KEY)) { action(listenerEP.listenerInstance as ProjectFacetListener>) } manuallyRegisteredListeners.filter { it.first == null }.forEach { diff --git a/platform/lang-impl/src/com/intellij/ide/structureView/impl/StructureViewFactoryImpl.java b/platform/lang-impl/src/com/intellij/ide/structureView/impl/StructureViewFactoryImpl.java index 3af432cb84fb..66af89f7c620 100644 --- a/platform/lang-impl/src/com/intellij/ide/structureView/impl/StructureViewFactoryImpl.java +++ b/platform/lang-impl/src/com/intellij/ide/structureView/impl/StructureViewFactoryImpl.java @@ -90,7 +90,7 @@ public final class StructureViewFactoryImpl extends StructureViewFactoryEx imple for (StructureViewExtension extension : point.getExtensionList()) { Class registeredType = extension.getType(); if (ReflectionUtil.isAssignable(registeredType, type) && visitedTypes.add(registeredType)) { - result.addAll(ExtensionProcessingHelper.getByGroupingKey(point, registeredType, StructureViewExtension::getType)); + result.addAll(ExtensionProcessingHelper.getByGroupingKey(point, StructureViewExtension.class, registeredType, StructureViewExtension::getType)); } } diff --git a/platform/lang-impl/src/com/intellij/openapi/module/impl/ModuleTypeManagerImpl.java b/platform/lang-impl/src/com/intellij/openapi/module/impl/ModuleTypeManagerImpl.java index 9f61b8d53d02..47f8de152f59 100644 --- a/platform/lang-impl/src/com/intellij/openapi/module/impl/ModuleTypeManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/module/impl/ModuleTypeManagerImpl.java @@ -75,7 +75,7 @@ public class ModuleTypeManagerImpl extends ModuleTypeManager { } } - ModuleTypeEP result = EP_NAME.getByKey(moduleTypeId, it -> it.id); + ModuleTypeEP result = EP_NAME.getByKey(moduleTypeId, ModuleTypeManagerImpl.class, it -> it.id); if (result != null) { return result.getModuleType(); } diff --git a/plugins/stream-debugger/src/com/intellij/debugger/streams/action/ChainResolver.java b/plugins/stream-debugger/src/com/intellij/debugger/streams/action/ChainResolver.java index 825399d0b688..3e16c068f228 100644 --- a/plugins/stream-debugger/src/com/intellij/debugger/streams/action/ChainResolver.java +++ b/plugins/stream-debugger/src/com/intellij/debugger/streams/action/ChainResolver.java @@ -80,8 +80,8 @@ class ChainResolver { return chains; } - private static List forLanguage(@NotNull Language language) { - return LibrarySupportProvider.EP_NAME.getByGroupingKey(language.getID(), LibrarySupportProvider::getLanguageId); + private static @NotNull List forLanguage(@NotNull Language language) { + return LibrarySupportProvider.EP_NAME.getByGroupingKey(language.getID(), ChainResolver.class, LibrarySupportProvider::getLanguageId); } enum ChainStatus { diff --git a/xml/xml-psi-impl/src/com/intellij/psi/xml/XmlChildRole.java b/xml/xml-psi-impl/src/com/intellij/psi/xml/XmlChildRole.java index a42ef125882e..44acd7ecdafa 100644 --- a/xml/xml-psi-impl/src/com/intellij/psi/xml/XmlChildRole.java +++ b/xml/xml-psi-impl/src/com/intellij/psi/xml/XmlChildRole.java @@ -11,6 +11,8 @@ import com.intellij.xml.util.XmlTagUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.function.Function; + public interface XmlChildRole { RoleFinder START_TAG_NAME_FINDER = new RoleFinder() { @@ -36,14 +38,9 @@ public interface XmlChildRole { RoleFinder ATTRIBUTE_NAME_FINDER = new DefaultRoleFinder(XmlTokenType.XML_NAME); RoleFinder ATTRIBUTE_VALUE_VALUE_FINDER = new DefaultRoleFinder(XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN); + RoleFinder START_TAG_END_FINDER = new DefaultRoleFinder(() -> { - return StartTagEndTokenProvider.EP_NAME.computeIfAbsent("the key", s -> { - IElementType[] elementTypes = new IElementType[]{XmlTokenType.XML_TAG_END}; - for (StartTagEndTokenProvider tokenProvider : StartTagEndTokenProvider.EP_NAME.getExtensionList()) { - elementTypes = ArrayUtil.mergeArrays(elementTypes, tokenProvider.getTypes()); - } - return elementTypes; - }); + return StartTagEndTokenProvider.EP_NAME.computeIfAbsent("the key", Helper.START_TAG_END_FINDER); }); RoleFinder START_TAG_START_FINDER = new DefaultRoleFinder(XmlTokenType.XML_START_TAG_START); @@ -69,3 +66,13 @@ public interface XmlChildRole { int XML_ATTRIBUTE_VALUE = 243; int HTML_DOCUMENT = 252; } + +final class Helper { + static final Function START_TAG_END_FINDER = s -> { + IElementType[] elementTypes = new IElementType[]{XmlTokenType.XML_TAG_END}; + for (StartTagEndTokenProvider tokenProvider : StartTagEndTokenProvider.EP_NAME.getExtensionList()) { + elementTypes = ArrayUtil.mergeArrays(elementTypes, tokenProvider.getTypes()); + } + return elementTypes; + }; +} \ No newline at end of file