GitOrigin-RevId: 53f17d6aa9ac0e61b01ac7303d70ecbeb1c799fc
This commit is contained in:
Vladimir Krivosheev
2024-04-10 18:11:50 +00:00
committed by intellij-monorepo-bot
parent f8b4ecb14f
commit 81d76b2102
3 changed files with 84 additions and 100 deletions
@@ -42,6 +42,7 @@ import com.intellij.psi.xml.XmlTag;
import com.intellij.reference.SoftReference;
import com.intellij.util.ArrayUtil;
import com.intellij.util.EventDispatcher;
import com.intellij.util.concurrency.ThreadingAssertions;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.indexing.FileBasedIndex;
import com.intellij.util.xml.*;
@@ -69,27 +70,26 @@ public final class DomManagerImpl extends DomManager implements Disposable {
private static final Key<CachedValue<DomInvocationHandler>> HANDLER_KEY = Key.create("DomInvocationHandler");
private static final Key<CachedValue<DomInvocationHandler>> HANDLER_KEY_FOR_INDEX = Key.create("DomInvocationHandlerForIndex");
private final EventDispatcher<DomEventListener> myListeners = EventDispatcher.create(DomEventListener.class);
private final EventDispatcher<DomEventListener> listeners = EventDispatcher.create(DomEventListener.class);
private final Project myProject;
private final DomApplicationComponent myApplicationComponent;
private final Project project;
private final DomApplicationComponent applicationComponent;
private boolean myChanging;
private boolean myBulkChange;
private boolean isChanging;
private boolean isBulkChange;
public DomManagerImpl(Project project) {
super(project);
myProject = project;
myApplicationComponent = DomApplicationComponent.getInstance();
final PomModel pomModel = PomManager.getModel(project);
this.project = project;
applicationComponent = DomApplicationComponent.getInstance();
Disposable parent = project.getService(DomDisposable.class);
PomModel pomModel = PomManager.getModel(project);
pomModel.addModelListener(new PomModelListener() {
@Override
public void modelChanged(@NotNull PomModelEvent event) {
if (myChanging) return;
if (isChanging) return;
TreeChangeEvent changeSet = (TreeChangeEvent)event.getChangeSet(pomModel.getModelAspect(TreeAspect.class));
if (changeSet != null) {
@@ -153,11 +153,11 @@ public final class DomManagerImpl extends DomManager implements Disposable {
}
private List<DomEvent> calcDomChangeEvents(final VirtualFile file) {
if (!(file instanceof NewVirtualFile) || myProject.isDisposed()) {
if (!(file instanceof NewVirtualFile) || project.isDisposed()) {
return Collections.emptyList();
}
FileManager fileManager = PsiManagerEx.getInstanceEx(myProject).getFileManager();
FileManager fileManager = PsiManagerEx.getInstanceEx(project).getFileManager();
final List<DomEvent> events = new ArrayList<>();
VfsUtilCore.visitChildrenRecursively(file, new VirtualFileVisitor<Void>() {
@@ -182,7 +182,7 @@ public final class DomManagerImpl extends DomManager implements Disposable {
}
boolean isInsideAtomicChange() {
return myBulkChange;
return isBulkChange;
}
@SuppressWarnings({"MethodOverridesStaticMethodOfSuperclass"})
@@ -192,7 +192,7 @@ public final class DomManagerImpl extends DomManager implements Disposable {
@Override
public void addDomEventListener(DomEventListener listener, Disposable parentDisposable) {
myListeners.addListener(listener, parentDisposable);
listeners.addListener(listener, parentDisposable);
}
@Override
@@ -208,7 +208,7 @@ public final class DomManagerImpl extends DomManager implements Disposable {
void fireEvent(@NotNull DomEvent event) {
if (isInsideAtomicChange()) return;
clearCache();
myListeners.getMulticaster().eventOccured(event);
listeners.getMulticaster().eventOccured(event);
}
private void fireEvents(@NotNull Collection<? extends DomEvent> events) {
@@ -219,7 +219,7 @@ public final class DomManagerImpl extends DomManager implements Disposable {
@Override
public DomGenericInfo getGenericInfo(final Type type) {
return myApplicationComponent.getStaticGenericInfo(type);
return applicationComponent.getStaticGenericInfo(type);
}
public static @Nullable DomInvocationHandler getDomInvocationHandler(DomElement proxy) {
@@ -255,17 +255,17 @@ public final class DomManagerImpl extends DomManager implements Disposable {
return handler;
}
public static StableInvocationHandler<?> getStableInvocationHandler(Object proxy) {
static StableInvocationHandler<?> getStableInvocationHandler(Object proxy) {
return (StableInvocationHandler<?>)AdvancedProxy.getInvocationHandler(proxy);
}
public DomApplicationComponent getApplicationComponent() {
return myApplicationComponent;
return applicationComponent;
}
@Override
public Project getProject() {
return myProject;
return project;
}
@Override
@@ -274,15 +274,12 @@ public final class DomManagerImpl extends DomManager implements Disposable {
file.putUserData(MOCK_DESCRIPTION, new MockDomFileDescription<>(aClass, rootTagName, file.getViewProvider().getVirtualFile()));
clearCache();
}
final DomFileElementImpl<T> fileElement = getFileElement(file);
DomFileElementImpl<T> fileElement = getFileElement(file);
assert fileElement != null;
return fileElement;
}
public Set<DomFileDescription<?>> getAcceptingOtherRootTagNameDescriptions() {
return myApplicationComponent.getAcceptingOtherRootTagNameDescriptions();
}
public @NotNull @NonNls String getComponentName() {
return getClass().getName();
}
@@ -298,11 +295,11 @@ public final class DomManagerImpl extends DomManager implements Disposable {
}
boolean setChanging(final boolean changing) {
boolean oldChanging = myChanging;
boolean oldChanging = isChanging;
if (changing) {
assert !oldChanging;
}
myChanging = changing;
isChanging = changing;
return oldChanging;
}
@@ -326,7 +323,7 @@ public final class DomManagerImpl extends DomManager implements Disposable {
@Override
public @Nullable <T extends DomElement> DomFileElementImpl<T> getFileElement(XmlFile file, Class<T> domClass) {
DomFileDescription<?> description = getDomFileDescription(file);
if (description != null && myApplicationComponent.assignabilityCache.isAssignable(domClass, description.getRootElementClass())) {
if (description != null && applicationComponent.assignabilityCache.isAssignable(domClass, description.getRootElementClass())) {
return getFileElement(file);
}
return null;
@@ -334,7 +331,7 @@ public final class DomManagerImpl extends DomManager implements Disposable {
@Override
public @Nullable DomElement getDomElement(final XmlTag element) {
if (myChanging) return null;
if (isChanging) return null;
final DomInvocationHandler handler = getDomHandler(element);
return handler != null ? handler.getProxy() : null;
@@ -342,7 +339,7 @@ public final class DomManagerImpl extends DomManager implements Disposable {
@Override
public @Nullable GenericAttributeValue<?> getDomElement(final XmlAttribute attribute) {
if (myChanging) return null;
if (isChanging) return null;
DomInvocationHandler handler = getDomHandler(attribute);
return handler == null ? null : (GenericAttributeValue<?>)handler.getProxy();
@@ -390,7 +387,7 @@ public final class DomManagerImpl extends DomManager implements Disposable {
@Override
public <T extends DomElement> T createMockElement(final Class<T> aClass, final Module module, final boolean physical) {
final XmlFile file = (XmlFile)PsiFileFactory.getInstance(myProject).createFileFromText("a.xml", XmlFileType.INSTANCE, "", 0, physical);
final XmlFile file = (XmlFile)PsiFileFactory.getInstance(project).createFileFromText("a.xml", XmlFileType.INSTANCE, "", 0, physical);
file.putUserData(MOCK_ELEMENT_MODULE, module);
file.putUserData(MOCK, new Object());
return getFileElement(file, aClass, "I_sincerely_hope_that_nobody_will_have_such_a_root_tag_name").getRootElement();
@@ -424,8 +421,8 @@ public final class DomManagerImpl extends DomManager implements Disposable {
@TestOnly
public <T extends DomElement> void registerFileDescription(final DomFileDescription<T> description, Disposable parentDisposable) {
clearCache();
myApplicationComponent.registerFileDescription(description);
Disposer.register(parentDisposable, () -> myApplicationComponent.removeDescription(description));
applicationComponent.registerFileDescription(description);
Disposer.register(parentDisposable, () -> applicationComponent.removeDescription(description));
}
@Override
@@ -442,19 +439,19 @@ public final class DomManagerImpl extends DomManager implements Disposable {
@Override
public TypeChooserManager getTypeChooserManager() {
return myApplicationComponent.getTypeChooserManager();
return applicationComponent.getTypeChooserManager();
}
void performAtomicChange(@NotNull Runnable change) {
ApplicationManager.getApplication().assertWriteAccessAllowed();
ThreadingAssertions.assertWriteAccess();
final boolean oldValue = myBulkChange;
myBulkChange = true;
boolean oldValue = isBulkChange;
isBulkChange = true;
try {
change.run();
}
finally {
myBulkChange = oldValue;
isBulkChange = oldValue;
if (!oldValue) {
clearCache();
}
@@ -1,23 +1,7 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// 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.util.xml.impl;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Factory;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.xml.MergedObject;
import com.intellij.util.xml.StableElement;
@@ -28,30 +12,33 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Predicate;
import java.util.function.Supplier;
class StableInvocationHandler<T> implements InvocationHandler, StableElement {
private T myOldValue;
private T myCachedValue;
private final Set<Class<?>> myClasses;
private final Factory<? extends T> myProvider;
private final Condition<? super T> myValidator;
final class StableInvocationHandler<T> implements InvocationHandler, StableElement {
private T oldValue;
private T cachedValue;
private final Set<Class<?>> classes;
private final Supplier<? extends T> provider;
private final Predicate<? super T> validator;
StableInvocationHandler(final T initial, final Factory<? extends T> provider, Condition<? super T> validator) {
myProvider = provider;
myCachedValue = initial;
myOldValue = initial;
myValidator = validator;
final Class<?> superClass = initial.getClass().getSuperclass();
final Set<Class<?>> classes = new HashSet<>();
StableInvocationHandler(final T initial, final Supplier<? extends T> provider, Predicate<? super T> validator) {
this.provider = provider;
cachedValue = initial;
oldValue = initial;
this.validator = validator;
Class<?> superClass = initial.getClass().getSuperclass();
Set<Class<?>> classes = new HashSet<>();
ContainerUtil.addAll(classes, initial.getClass().getInterfaces());
ContainerUtil.addIfNotNull(classes, superClass);
classes.remove(MergedObject.class);
myClasses = classes;
this.classes = classes;
}
@Override
public final Object invoke(Object proxy, final Method method, final Object[] args) throws Throwable {
public Object invoke(Object proxy, final Method method, final Object[] args) throws Throwable {
if (StableElement.class.equals(method.getDeclaringClass())) {
try {
return method.invoke(this, args);
@@ -63,12 +50,12 @@ class StableInvocationHandler<T> implements InvocationHandler, StableElement {
if (AdvancedProxy.FINALIZE_METHOD.equals(method)) return null;
if (isNotValid(myCachedValue)) {
if (myCachedValue != null) {
myOldValue = myCachedValue;
if (isNotValid(cachedValue)) {
if (cachedValue != null) {
oldValue = cachedValue;
}
myCachedValue = myProvider.create();
if (isNotValid(myCachedValue)) {
cachedValue = provider.get();
if (isNotValid(cachedValue)) {
if (AdvancedProxy.EQUALS_METHOD.equals(method)) {
final Object arg = args[0];
@@ -77,11 +64,11 @@ class StableInvocationHandler<T> implements InvocationHandler, StableElement {
final StableInvocationHandler<?> handler = DomManagerImpl.getStableInvocationHandler(arg);
if (handler == null || handler.getWrappedElement() != null) return false;
return Comparing.equal(myOldValue, handler.myOldValue);
return Comparing.equal(oldValue, handler.oldValue);
}
if (myOldValue != null && Object.class.equals(method.getDeclaringClass())) {
return method.invoke(myOldValue, args);
if (oldValue != null && Object.class.equals(method.getDeclaringClass())) {
return method.invoke(oldValue, args);
}
if ("isValid".equals(method.getName())) {
@@ -94,17 +81,17 @@ class StableInvocationHandler<T> implements InvocationHandler, StableElement {
if (AdvancedProxy.EQUALS_METHOD.equals(method)) {
final Object arg = args[0];
if (arg instanceof StableElement) {
return myCachedValue.equals(((StableElement<?>)arg).getWrappedElement());
return cachedValue.equals(((StableElement<?>)arg).getWrappedElement());
}
return myCachedValue.equals(arg);
return cachedValue.equals(arg);
}
if (AdvancedProxy.HASHCODE_METHOD.equals(method)) {
return myCachedValue.hashCode();
return cachedValue.hashCode();
}
try {
return method.invoke(myCachedValue, args);
return method.invoke(cachedValue, args);
}
catch (InvocationTargetException e) {
throw e.getCause();
@@ -112,35 +99,35 @@ class StableInvocationHandler<T> implements InvocationHandler, StableElement {
}
@Override
public final void revalidate() {
final T t = myProvider.create();
if (!isNotValid(t) && !t.equals(myCachedValue)) {
myCachedValue = t;
public void revalidate() {
final T t = provider.get();
if (!isNotValid(t) && !t.equals(cachedValue)) {
cachedValue = t;
}
}
@Override
public final void invalidate() {
if (!isNotValid(myCachedValue)) {
myCachedValue = null;
public void invalidate() {
if (!isNotValid(cachedValue)) {
cachedValue = null;
}
}
@Override
public final T getWrappedElement() {
if (isNotValid(myCachedValue)) {
myCachedValue = myProvider.create();
public T getWrappedElement() {
if (isNotValid(cachedValue)) {
cachedValue = provider.get();
}
return myCachedValue;
return cachedValue;
}
public T getOldValue() {
return myOldValue;
return oldValue;
}
private boolean isNotValid(final T t) {
if (t == null || !myValidator.value(t)) return true;
for (final Class<?> aClass : myClasses) {
if (t == null || !validator.test(t)) return true;
for (final Class<?> aClass : classes) {
if (!aClass.isInstance(t)) return true;
}
return false;
@@ -76,7 +76,7 @@ public abstract class DomManager extends CompositeModificationTracker implements
* @param aClass Desired DOM element class
* @param module One may wish the result to think that it is in a particular module
* @param physical see {@link com.intellij.psi.PsiFile#isPhysical()}
* @return DOM element which doesn't have any real file under itself. A mock file is created for it. See
* @return DOM element, which doesn't have any real file under itself. A mock file is created for it. See
* {@link com.intellij.psi.PsiFileFactory#createFileFromText(String, com.intellij.openapi.fileTypes.FileType, CharSequence, long, boolean, boolean)}
*/
public abstract <T extends DomElement> T createMockElement(Class<T> aClass, final Module module, final boolean physical);
@@ -88,9 +88,10 @@ public abstract class DomManager extends CompositeModificationTracker implements
public abstract boolean isMockElement(DomElement element);
/**
* Creates DOM element of needed type, that is wrapper around real DOM element. Once the wrapped element
* becomes invalid, a new value is requested from provider parameter, so there's a possibility to
* restore the functionality. The resulting element will also implement StableElement interface.
* Creates a DOM element of a needed type, that is wrapper around a real DOM element.
* Once the wrapped element becomes invalid, a new value is requested from provider parameter, so there's a possibility to
* restore the functionality.
* The resulting element will also implement StableElement interface.
*
* @param provider provides values to be wrapped
* @return stable DOM element
@@ -108,7 +109,6 @@ public abstract class DomManager extends CompositeModificationTracker implements
public abstract ModelMerger createModelMerger();
/**
* @param element reference element
* @return element that represents the resolve scope for the given reference. {@link DomResolveConverter} uses