@TestOnly public static void checkInjectorsAreDisposed(@NotNull Project project) { InjectedLanguageManagerImpl cachedManager = (InjectedLanguageManagerImpl)project.getUserData(INSTANCE_CACHE); if (cachedManager == null) { return; } try { ClassMapCachingNulls<MultiHostInjector> cached = cachedManager.cachedInjectors; if (cached == null) return; for (Map.Entry<Class, MultiHostInjector[]> entry : cached.getBackingMap().entrySet()) { Class key = entry.getKey(); if (cachedManager.myInjectorsClone.isEmpty()) return; MultiHostInjector[] oldInjectors = cachedManager.myInjectorsClone.get(key); for (MultiHostInjector injector : entry.getValue()) { if (!ArrayUtil.contains(injector, oldInjectors)) { throw new AssertionError("Injector was not disposed: " + key + " -> " + injector); } } } } finally { cachedManager.myInjectorsClone.clear(); } }
@Override public void registerMultiHostInjector(@NotNull MultiHostInjector injector) { for (Class<? extends PsiElement> place : injector.elementsToInjectIn()) { LOG.assertTrue(place != null, injector); while (true) { MultiHostInjector[] injectors = this.injectors.get(place); if (injectors == null) { if (this.injectors.putIfAbsent(place, new MultiHostInjector[]{injector}) == null) break; } else { MultiHostInjector[] newInfos = ArrayUtil.append(injectors, injector); if (this.injectors.replace(place, injectors, newInfos)) break; } } } cachedInjectors.clearCache(); }
@Override public boolean unregisterMultiHostInjector(@NotNull MultiHostInjector injector) { boolean removed = false; Iterator<Map.Entry<Class,MultiHostInjector[]>> iterator = injectors.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry<Class,MultiHostInjector[]> entry = iterator.next(); MultiHostInjector[] infos = entry.getValue(); int i = ArrayUtil.find(infos, injector); if (i != -1) { MultiHostInjector[] newInfos = ArrayUtil.remove(infos, i); if (newInfos.length == 0) { iterator.remove(); } else { injectors.put(entry.getKey(), newInfos); } removed = true; } } cachedInjectors.clearCache(); return removed; }
@TestOnly public static void checkInjectorsAreDisposed(@NotNull Project project) { InjectedLanguageManagerImpl cachedManager = (InjectedLanguageManagerImpl)project.getUserData(INSTANCE_CACHE); if (cachedManager == null) { return; } try { for (Map.Entry<Class, MultiHostInjector[]> entry : cachedManager.injectors.entrySet()) { Class key = entry.getKey(); if (cachedManager.myInjectorsClone.isEmpty()) return; MultiHostInjector[] oldInjectors = cachedManager.myInjectorsClone.get(key); for (MultiHostInjector injector : entry.getValue()) { if (!ArrayUtil.contains(injector, oldInjectors)) { throw new AssertionError("Injector was not disposed: " + key + " -> " + injector); } } } } finally { cachedManager.myInjectorsClone.clear(); } }
@TestOnly public static void checkInjectorsAreDisposed(@Nullable Project project) { InjectedLanguageManagerImpl cachedManager = project == null ? null : (InjectedLanguageManagerImpl)project.getUserData(INSTANCE_CACHE); if (cachedManager == null) return; try { ClassMapCachingNulls<MultiHostInjector> cached = cachedManager.cachedInjectors; if (cached == null) return; for (Map.Entry<Class, MultiHostInjector[]> entry : cached.getBackingMap().entrySet()) { Class key = entry.getKey(); if (cachedManager.myInjectorsClone.isEmpty()) return; MultiHostInjector[] oldInjectors = cachedManager.myInjectorsClone.get(key); for (MultiHostInjector injector : entry.getValue()) { if (ArrayUtil.indexOf(oldInjectors, injector) == -1) { throw new AssertionError("Injector was not disposed: " + key + " -> " + injector); } } } } finally { cachedManager.myInjectorsClone.clear(); } }
@Override protected void setUp() throws Exception { super.setUp(); Disposer.register(my, BlockExtensions.create(Extensions.getRootArea().getExtensionPoint(LanguageAnnotators.EP_NAME))); Disposer.register(my, BlockExtensions.create(Extensions.getRootArea().getExtensionPoint(LineMarkerProviders.EP_NAME))); Disposer.register(my, BlockExtensions.create(Extensions.getArea(getProject()).getExtensionPoint(JavaConcatenationInjectorManager.CONCATENATION_INJECTOR_EP_NAME))); Disposer.register(my, BlockExtensions.create(Extensions.getArea(getProject()).getExtensionPoint(MultiHostInjector.MULTIHOST_INJECTOR_EP_NAME))); IntentionManager.getInstance().getAvailableIntentionActions(); // hack to avoid slowdowns in PyExtensionFactory PathManagerEx.getTestDataPath(); // to cache stuff }
public void processInjectableElements(Collection<PsiElement> in, Processor<PsiElement> processor) { ClassMapCachingNulls<MultiHostInjector> map = getInjectorMap(); for (PsiElement element : in) { if (map.get(element.getClass()) != null) processor.process(element); } }
private ClassMapCachingNulls<MultiHostInjector> getInjectorMap() { ClassMapCachingNulls<MultiHostInjector> cached = cachedInjectors; if (cached != null) { return cached; } Map<Class, MultiHostInjector[]> injectors = ContainerUtil.newHashMap(); List<MultiHostInjector> allInjectors = ContainerUtil.newArrayList(); allInjectors.addAll(myManualInjectors); Collections.addAll(allInjectors, MultiHostInjector.MULTIHOST_INJECTOR_EP_NAME.getExtensions(myProject)); if (LanguageInjector.EXTENSION_POINT_NAME.getExtensions().length > 0) { allInjectors.add(PsiManagerRegisteredInjectorsAdapter.INSTANCE); } for (MultiHostInjector injector : allInjectors) { for (Class<? extends PsiElement> place : injector.elementsToInjectIn()) { LOG.assertTrue(place != null, injector); MultiHostInjector[] existing = injectors.get(place); injectors.put(place, existing == null ? new MultiHostInjector[]{injector} : ArrayUtil.append(existing, injector)); } } ClassMapCachingNulls<MultiHostInjector> result = new ClassMapCachingNulls<MultiHostInjector>(injectors, new MultiHostInjector[0]); cachedInjectors = result; return result; }
@Override public boolean unregisterMultiHostInjector(@NotNull MultiHostInjector injector) { try { return myManualInjectors.remove(injector); } finally { clearInjectorCache(); } }
public void processInPlaceInjectorsFor(@NotNull PsiElement element, @NotNull InjProcessor processor) { MultiHostInjector[] infos = getInjectorMap().get(element.getClass()); if (infos != null) { final boolean dumb = myDumbService.isDumb(); for (MultiHostInjector injector : infos) { if (dumb && !DumbService.isDumbAware(injector)) { continue; } if (!processor.process(element, injector)) return; } } }
@Override public boolean process(PsiElement element, MultiHostInjector injector) { if (hostRegistrar == null) { hostRegistrar = new MultiHostRegistrarImpl(myProject, myHostPsiFile, element); } injector.getLanguagesToInject(hostRegistrar, element); List<Pair<Place,PsiFile>> result = hostRegistrar.getResult(); return result == null; }
public void psiManagerInjectorsChanged() { LanguageInjector[] extensions = Extensions.getExtensions(LanguageInjector.EXTENSION_POINT_NAME); if (extensions.length == 0) { MultiHostInjector prev = myPsiManagerRegisteredInjectorsAdapter.getAndSet(null); if (prev != null) { unregisterMultiHostInjector(prev); } } else { PsiManagerRegisteredInjectorsAdapter adapter = new PsiManagerRegisteredInjectorsAdapter(); if (myPsiManagerRegisteredInjectorsAdapter.compareAndSet(null, adapter)) { registerMultiHostInjector(adapter); } } }
public void processInPlaceInjectorsFor(@NotNull PsiElement element, @NotNull InjProcessor processor) { MultiHostInjector[] infos = cachedInjectors.get(element.getClass()); if (infos != null) { final boolean dumb = myDumbService.isDumb(); for (MultiHostInjector injector : infos) { if (dumb && !DumbService.isDumbAware(injector)) { continue; } if (!processor.process(element, injector)) return; } } }
public void processInjectableElements(@Nonnull Collection<PsiElement> in, @Nonnull Processor<PsiElement> processor) { ClassMapCachingNulls<MultiHostInjector> map = getInjectorMap(); for (PsiElement element : in) { if (map.get(element.getClass()) != null) { processor.process(element); } } }
@Nonnull private ClassMapCachingNulls<MultiHostInjector> getInjectorMap() { ClassMapCachingNulls<MultiHostInjector> cached = cachedInjectors; if (cached != null) { return cached; } Map<Class, MultiHostInjector[]> injectors = ContainerUtil.newHashMap(); MultiMap<Class, MultiHostInjector> allInjectors = new MultiMap<>(); allInjectors.putAllValues(myManualInjectors); if (LanguageInjector.EXTENSION_POINT_NAME.getExtensions().length > 0) { allInjectors.putValue(PsiLanguageInjectionHost.class, PsiManagerRegisteredInjectorsAdapter.INSTANCE); } for (MultiHostInjectorExtensionPoint point : MultiHostInjector.EP_NAME.getExtensions(myProject)) { Class<PsiElement> key = point.getKey(); MultiHostInjector multiHostInjector = point.getInstance(myProject); allInjectors.putValue(key, multiHostInjector); } for (Map.Entry<Class, Collection<MultiHostInjector>> entry : allInjectors.entrySet()) { injectors.put(entry.getKey(), entry.getValue().toArray(MultiHostInjector.EMPTY_ARRAY)); } ClassMapCachingNulls<MultiHostInjector> result = new ClassMapCachingNulls<>(injectors, MultiHostInjector.EMPTY_ARRAY, new ArrayList<>(allInjectors.values())); cachedInjectors = result; return result; }
@SafeVarargs @Override public final void registerMultiHostInjector(@Nonnull MultiHostInjector injector, @Nonnull Class<? extends PsiElement>... elements) { if (elements.length == 0) { throw new IllegalArgumentException(""); } for (Class<? extends PsiElement> element : elements) { myManualInjectors.putValue(element, injector); } clearInjectorCache(); }
@SafeVarargs @Override public final void registerMultiHostInjector(@Nonnull MultiHostInjector injector, @Nonnull Disposable parentDisposable, @Nonnull Class<? extends PsiElement>... elements) { if (elements.length == 0) { throw new IllegalArgumentException(""); } registerMultiHostInjector(injector); Disposer.register(parentDisposable, () -> unregisterMultiHostInjector(injector)); }
@SafeVarargs private final boolean unregisterMultiHostInjector(@Nonnull MultiHostInjector injector, @Nonnull Class<? extends PsiElement>... elements) { try { boolean unregister = false; for (Class<? extends PsiElement> element : elements) { unregister |= myManualInjectors.remove(element, injector); } return unregister; } finally { clearInjectorCache(); } }
void processInPlaceInjectorsFor(@Nonnull PsiElement element, @Nonnull InjProcessor processor) { MultiHostInjector[] infos = getInjectorMap().get(element.getClass()); if (infos != null) { final boolean dumb = myDumbService.isDumb(); for (MultiHostInjector injector : infos) { if (dumb && !DumbService.isDumbAware(injector)) { continue; } if (!processor.process(element, injector)) return; } } }
@Override public boolean process(@Nonnull PsiElement element, @Nonnull MultiHostInjector injector) { if (hostRegistrar == null) { hostRegistrar = new InjectionRegistrarImpl(myProject, myHostPsiFile, element); } injector.injectLanguages(hostRegistrar, element); return hostRegistrar.getInjectedResult() == null; }
@Override protected void setUp() throws Exception { super.setUp(); Disposer.register(my, BlockExtensions.create(Extensions.getRootArea().getExtensionPoint(LanguageAnnotators.EP_NAME))); Disposer.register(my, BlockExtensions.create(Extensions.getRootArea().getExtensionPoint(LineMarkerProviders.EP_NAME))); Disposer.register(my, BlockExtensions.create(Extensions.getArea(getProject()).getExtensionPoint(JavaConcatenationInjectorManager.CONCATENATION_INJECTOR_EP_NAME))); Disposer.register(my, BlockExtensions.create(Extensions.getArea(getProject()).getExtensionPoint(MultiHostInjector.EP_NAME))); IntentionManager.getInstance().getAvailableIntentionActions(); // hack to avoid slowdowns in PyExtensionFactory }
@Override public void registerMultiHostInjector(@NotNull MultiHostInjector injector) { myManualInjectors.add(injector); clearInjectorCache(); }
@Nonnull public MultiHostInjector getInstance(@Nonnull ComponentManager componentManager) { return instantiate(myImplementationClassHandler.getValue(), componentManager.getPicoContainer()); }
boolean process(PsiElement element, MultiHostInjector injector);
boolean process(@Nonnull PsiElement element, @Nonnull MultiHostInjector injector);