mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-CR-62371 use client class as cache id because it's dangerous to rely on identity of functional expressions.
GitOrigin-RevId: 41d38ae5da583af0ed4520cb2e06b9def7fb871b
This commit is contained in:
committed by
intellij-monorepo-bot
parent
9c22edb681
commit
cab62c6ccb
@@ -44,7 +44,7 @@ public final class JvmMetaLanguage extends MetaLanguage {
|
||||
}
|
||||
|
||||
private static boolean matchesRegisteredLanguage(@NotNull Language language, @NotNull ExtensionPointImpl<LanguageExtensionPoint<JvmDeclarationSearcher>> 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<LanguageExtensionPoint<JvmDeclarationSearcher>> getPoint() {
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ public class CompletionIgnoreDumbnessEP extends LazyExtensionInstance<Object> {
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
public class LocalInspectionToolWrapper extends InspectionToolWrapper<LocalInspectionTool, LocalInspectionEP> {
|
||||
/** 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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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<PsiSymbolReferenceProviderBean> EP_NAME =
|
||||
new ExtensionPointName<>("com.intellij.psi.symbolReferenceProvider");
|
||||
|
||||
private static final @NotNull Function<Language, LanguageReferenceProviders> 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<PsiSymbolReferenceProviderBean> byTargetClass(@NotNull Class<? extends Symbol> 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,10 +178,13 @@ public final class ExtensionPointName<T> extends BaseExtensionPointName<T> {
|
||||
* Build cache by arbitrary key using provided key to value mapper. Values with the same key merge into list. Return values by key.
|
||||
* <p>
|
||||
* 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<T> getByGroupingKey(@NotNull K key, @NotNull Function<@NotNull T, @Nullable K> keyMapper) {
|
||||
return ExtensionProcessingHelper.getByGroupingKey(getPointImpl(null), key, keyMapper);
|
||||
public final <@NotNull K> @NotNull List<T> 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<T> extends BaseExtensionPointName<T> {
|
||||
* 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<T> extends BaseExtensionPointName<T> {
|
||||
*/
|
||||
@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) {
|
||||
|
||||
+15
-12
@@ -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<T> getByGroupingKey(@NotNull ExtensionPointImpl<T> point,
|
||||
@NotNull Class<?> cacheId,
|
||||
@NotNull K key,
|
||||
@NotNull Function<@NotNull T, @Nullable K> keyMapper) {
|
||||
ConcurrentMap<Function<T, K>, Map<K, List<T>>> keyMapperToCache = point.getCacheMap();
|
||||
Map<K, List<T>> cache = keyMapperToCache.get(keyMapper);
|
||||
ConcurrentMap<Class<?>, Map<K, List<T>>> keyMapperToCache = point.getCacheMap();
|
||||
Map<K, List<T>> cache = keyMapperToCache.get(cacheId);
|
||||
if (cache == null) {
|
||||
cache = buildCacheForGroupingKeyMapper(keyMapper, point);
|
||||
Map<K, List<T>> prev = keyMapperToCache.putIfAbsent(keyMapper, cache);
|
||||
Map<K, List<T>> 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<T> point,
|
||||
@NotNull K key,
|
||||
@NotNull Class<?> cacheId,
|
||||
@NotNull Function<@NotNull T, @Nullable K> keyMapper,
|
||||
@NotNull Function<@NotNull T, @Nullable V> valueMapper) {
|
||||
SimpleImmutableEntry<Function<T, K>, Function<T, V>> 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<T> 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 <CACHE_KEY, K, T, V> @Nullable V doGetByKey(@NotNull ExtensionPointImpl<T> point,
|
||||
@NotNull CACHE_KEY cacheKey,
|
||||
private static <CACHE_KEY, K, T, V> @Nullable V doGetByKey(@NotNull ExtensionPoint<T> point,
|
||||
@NotNull CACHE_KEY cacheId,
|
||||
@NotNull K key,
|
||||
@NotNull Function<T, K> keyMapper,
|
||||
@NotNull Function<@NotNull T, @Nullable V> valueMapper,
|
||||
@NotNull ConcurrentMap<CACHE_KEY, Map<K, V>> keyMapperToCache) {
|
||||
Map<K, V> cache = keyMapperToCache.get(cacheKey);
|
||||
Map<K, V> cache = keyMapperToCache.get(cacheId);
|
||||
if (cache == null) {
|
||||
cache = buildCacheForKeyMapper(keyMapper, valueMapper, point);
|
||||
Map<K, V> prev = keyMapperToCache.putIfAbsent(cacheKey, cache);
|
||||
Map<K, V> prev = keyMapperToCache.putIfAbsent(cacheId, cache);
|
||||
if (prev != null) {
|
||||
cache = prev;
|
||||
}
|
||||
@@ -139,7 +142,7 @@ public final class ExtensionProcessingHelper {
|
||||
}
|
||||
|
||||
private static <K, T> @NotNull Map<K, List<T>> buildCacheForGroupingKeyMapper(@NotNull Function<T, K> keyMapper,
|
||||
@NotNull ExtensionPointImpl<T> point) {
|
||||
@NotNull ExtensionPoint<T> 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<K, List<T>> cache = new HashMap<>();
|
||||
for (T extension : point.getExtensionList()) {
|
||||
@@ -154,7 +157,7 @@ public final class ExtensionProcessingHelper {
|
||||
|
||||
private static @NotNull <K, T, V> Map<K, V> buildCacheForKeyMapper(@NotNull Function<T, K> keyMapper,
|
||||
@NotNull Function<@NotNull T, @Nullable V> valueMapper,
|
||||
@NotNull ExtensionPointImpl<T> point) {
|
||||
@NotNull ExtensionPoint<T> point) {
|
||||
List<T> extensions = point.getExtensionList();
|
||||
Map<K, V> cache = new Object2ObjectOpenHashMap<>(extensions.size());
|
||||
for (T extension : extensions) {
|
||||
|
||||
+10
-7
@@ -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<Integer, String> 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<Integer, Integer> 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<Integer, Integer> 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
|
||||
|
||||
+2
-2
@@ -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<ProjectDataService<?, ?>> findService(@NotNull Key<?> key) {
|
||||
List<ProjectDataService<?, ?>> result = ProjectDataService.EP_NAME.getByGroupingKey(key, KEY_MAPPER);
|
||||
List<ProjectDataService<?, ?>> result = ProjectDataService.EP_NAME.getByGroupingKey(key, ProjectDataManagerImpl.class, KEY_MAPPER);
|
||||
ExternalSystemApiUtil.orderAwareSort(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -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 :
|
||||
|
||||
@@ -175,7 +175,7 @@ class FacetEventsPublisher(private val project: Project) {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private inline fun <F : Facet<*>> processListeners(facetType: FacetType<F, *>, action: (ProjectFacetListener<F>) -> Unit) {
|
||||
for (listenerEP in LISTENER_EP.getByGroupingKey<String>(facetType.stringId, LISTENER_EP_CACHE_KEY)) {
|
||||
for (listenerEP in LISTENER_EP.getByGroupingKey<String>(facetType.stringId, LISTENER_EP_CACHE_KEY::class.java, LISTENER_EP_CACHE_KEY)) {
|
||||
action(listenerEP.listenerInstance as ProjectFacetListener<F>)
|
||||
}
|
||||
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<Facet<*>>) -> Unit) {
|
||||
for (listenerEP in LISTENER_EP.getByGroupingKey<String>(ANY_TYPE, LISTENER_EP_CACHE_KEY)) {
|
||||
for (listenerEP in LISTENER_EP.getByGroupingKey<String>(ANY_TYPE, LISTENER_EP_CACHE_KEY::class.java, LISTENER_EP_CACHE_KEY)) {
|
||||
action(listenerEP.listenerInstance as ProjectFacetListener<Facet<*>>)
|
||||
}
|
||||
manuallyRegisteredListeners.filter { it.first == null }.forEach {
|
||||
|
||||
+1
-1
@@ -90,7 +90,7 @@ public final class StructureViewFactoryImpl extends StructureViewFactoryEx imple
|
||||
for (StructureViewExtension extension : point.getExtensionList()) {
|
||||
Class<? extends PsiElement> 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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -80,8 +80,8 @@ class ChainResolver {
|
||||
return chains;
|
||||
}
|
||||
|
||||
private static List<LibrarySupportProvider> forLanguage(@NotNull Language language) {
|
||||
return LibrarySupportProvider.EP_NAME.getByGroupingKey(language.getID(), LibrarySupportProvider::getLanguageId);
|
||||
private static @NotNull List<LibrarySupportProvider> forLanguage(@NotNull Language language) {
|
||||
return LibrarySupportProvider.EP_NAME.getByGroupingKey(language.getID(), ChainResolver.class, LibrarySupportProvider::getLanguageId);
|
||||
}
|
||||
|
||||
enum ChainStatus {
|
||||
|
||||
@@ -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<String, IElementType[]> 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;
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user