decoupling CachedValueManager from PSI

This commit is contained in:
Dmitry Avdeev
2009-09-01 14:33:18 +04:00
parent 6985bba71b
commit c7285bb5d3
31 changed files with 799 additions and 475 deletions
@@ -10,8 +10,8 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.ModificationTracker;
import com.intellij.psi.*;
import com.intellij.psi.impl.ParameterizedCachedValueImpl;
import com.intellij.psi.impl.PsiManagerEx;
import com.intellij.psi.impl.PsiParameterizedCachedValue;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.ParameterizedCachedValue;
import com.intellij.psi.util.ParameterizedCachedValueProvider;
@@ -123,7 +123,7 @@ public class JavaConcatenationInjectorManager implements ProjectComponent, Modif
if (registrar.result != null) {
// store this everywhere
ParameterizedCachedValue<Places, PsiElement> cachedValue = context.getManager().getCachedValuesManager().createParameterizedCachedValue(this, false);
((ParameterizedCachedValueImpl<Places, PsiElement>)cachedValue).setValue(result);
((PsiParameterizedCachedValue<Places, PsiElement>)cachedValue).setValue(result);
for (PsiElement operand : operands) {
operand.putUserData(INJECTED_PSI_IN_CONCATENATION, cachedValue);
@@ -150,6 +150,8 @@ public abstract class PsiManager extends UserDataHolderBase {
* which are automatically recalculated based on changes of the elements on which they depend.
*
* @return the cached values manager instance.
* @deprecated
* @see CachedValuesManager#getManager(com.intellij.openapi.project.Project)
*/
@NotNull
public abstract CachedValuesManager getCachedValuesManager();
@@ -17,7 +17,6 @@ package com.intellij.psi.meta;
import com.intellij.psi.PsiElement;
import com.intellij.psi.filters.ElementFilter;
import com.intellij.psi.util.CachedValue;
import org.jetbrains.annotations.NonNls;
/**
@@ -39,7 +38,7 @@ public interface PsiMetaData {
/**
* @return objects this meta data depends on.
* @see CachedValue
* @see com.intellij.psi.util.CachedValue
*/
Object[] getDependences();
}
@@ -14,9 +14,9 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.Module;
import com.intellij.psi.PsiManager;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.CachedValuesManager;
import com.intellij.psi.util.CachedValue;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.util.SmartList;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.NotNull;
@@ -9,10 +9,7 @@ import com.intellij.openapi.util.Key;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.impl.CachedValuesManagerImpl;
import com.intellij.psi.impl.PsiManagerEx;
import com.intellij.psi.impl.PsiModificationTrackerImpl;
import com.intellij.psi.impl.PsiTreeChangeEventImpl;
import com.intellij.psi.impl.*;
import com.intellij.psi.impl.cache.CacheManager;
import com.intellij.psi.impl.cache.impl.CompositeCacheManager;
import com.intellij.psi.impl.file.impl.FileManager;
@@ -24,6 +21,7 @@ import com.intellij.psi.util.CachedValuesManager;
import com.intellij.psi.util.PsiModificationTracker;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.ThrowableRunnable;
import com.intellij.util.CachedValuesManagerImpl;
import gnu.trove.THashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -112,7 +110,7 @@ public class MockPsiManager extends PsiManagerEx {
@NotNull
public CachedValuesManager getCachedValuesManager() {
if (myCachedValuesManager == null) {
myCachedValuesManager = new CachedValuesManagerImpl(this);
myCachedValuesManager = new CachedValuesManagerImpl(myProject, new PsiCachedValuesFactory(this));
}
return myCachedValuesManager;
}
@@ -1,295 +0,0 @@
/*
* Created by IntelliJ IDEA.
* User: mike
* Date: Jun 6, 2002
* Time: 5:41:42 PM
* To change template for new class use
* Code Style | Class Templates options (Tools | IDE Options).
*/
package com.intellij.psi.impl;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.ModificationTracker;
import com.intellij.openapi.util.Ref;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.ParameterizedCachedValue;
import com.intellij.psi.util.ParameterizedCachedValueProvider;
import com.intellij.psi.util.PsiModificationTracker;
import com.intellij.reference.SoftReference;
import com.intellij.util.TimedReference;
import com.intellij.util.ArrayUtil;
import com.intellij.util.concurrency.JBLock;
import com.intellij.util.concurrency.JBReentrantReadWriteLock;
import com.intellij.util.concurrency.LockFactory;
import gnu.trove.TLongArrayList;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.ref.Reference;
import java.util.ArrayList;
import java.util.List;
public class ParameterizedCachedValueImpl<T,P> implements ParameterizedCachedValue<T,P> {
private static final Object NULL = new Object();
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.CachedValueImpl");
private final PsiManager myManager;
private final ParameterizedCachedValueProvider<T,P> myProvider;
private final boolean myTrackValue;
private final MyTimedReference<T> myData = new MyTimedReference<T>();
private volatile long myLastPsiTimeStamp = -1;
private final JBReentrantReadWriteLock rw = LockFactory.createReadWriteLock();
private final JBLock r = rw.readLock();
private final JBLock w = rw.writeLock();
public ParameterizedCachedValueImpl(@NotNull PsiManager manager, @NotNull ParameterizedCachedValueProvider<T,P> provider, boolean trackValue) {
myManager = manager;
myProvider = provider;
myTrackValue = trackValue;
}
private static class Data<T> implements Disposable {
private final T myValue;
private final Object[] myDependencies;
private final long[] myTimeStamps;
private Data(final T value, final Object[] dependencies, final long[] timeStamps) {
myValue = value;
myDependencies = dependencies;
myTimeStamps = timeStamps;
}
public void dispose() {
if (myValue instanceof Disposable) {
Disposer.dispose((Disposable)myValue);
}
}
}
@Nullable
public T getValue(P param) {
r.lock();
T value;
try {
value = getUpToDateOrNull();
if (value != null) {
return value == NULL ? null : value;
}
} finally {
r.unlock();
}
w.lock();
try {
value = getUpToDateOrNull();
if (value != null) {
return value == NULL ? null : value;
}
CachedValueProvider.Result<T> result = myProvider.compute(param);
value = result == null ? null : result.getValue();
setValue(value, result);
return value;
}
finally {
w.unlock();
}
}
private void setValue(final T value, final CachedValueProvider.Result<T> result) {
myData.setData(computeData(value == null ? (T) NULL : value, result == null ? null : result.getDependencyItems()));
if (result != null) {
myData.setIsLocked(result.isLockValue());
}
else {
myData.setIsLocked(false);
}
}
public void setDataLocked(boolean value) {
myData.setIsLocked(value);
}
public boolean hasUpToDateValue() {
r.lock();
try {
return getUpToDateOrNull() != null;
}
finally {
r.unlock();
}
}
@Nullable
private T getUpToDateOrNull() {
final Data<T> data = myData.getData();
if (data != null) {
T value = data.myValue;
if (isUpToDate(data)) {
return value;
}
if (value instanceof Disposable) {
Disposer.dispose((Disposable)value);
}
}
return null;
}
private boolean isUpToDate(@NotNull Data data) {
if (data.myTimeStamps == null) return true;
if (myManager.isDisposed()) return false;
for (int i = 0; i < data.myDependencies.length; i++) {
Object dependency = data.myDependencies[i];
if (dependency == null) continue;
if (isDependencyOutOfDate(dependency, data.myTimeStamps[i])) return false;
}
return true;
}
private boolean isDependencyOutOfDate(Object dependency, long oldTimeStamp) {
if (dependency instanceof PsiElement &&
myLastPsiTimeStamp == myManager.getModificationTracker().getModificationCount()) {
return false;
}
final long timeStamp = getTimeStamp(dependency);
return timeStamp < 0 || timeStamp != oldTimeStamp;
}
private Data<T> computeData(T value, Object[] dependencies) {
if (dependencies == null) {
return new Data<T>(value, null, null);
}
TLongArrayList timeStamps = new TLongArrayList();
List<Object> deps = new ArrayList<Object>();
collectDependencies(timeStamps, deps, dependencies);
if (myTrackValue) {
collectDependencies(timeStamps, deps, new Object[]{value});
}
myLastPsiTimeStamp = myManager.getModificationTracker().getModificationCount();
return new Data<T>(value, ArrayUtil.toObjectArray(deps), timeStamps.toNativeArray());
}
private void collectDependencies(TLongArrayList timeStamps, List<Object> resultingDeps, Object[] dependencies) {
for (Object dependency : dependencies) {
if (dependency == null || dependency == NULL) continue;
if (dependency instanceof Object[]) {
collectDependencies(timeStamps, resultingDeps, (Object[])dependency);
}
else {
resultingDeps.add(dependency);
timeStamps.add(getTimeStamp(dependency));
}
}
}
private long getTimeStamp(Object dependency) {
if (dependency instanceof Reference){
final Object original = ((Reference)dependency).get();
if(original == null) return -1;
return getTimeStamp(original);
}
if (dependency instanceof Ref) {
final Object original = ((Ref)dependency).get();
if(original == null) return -1;
return getTimeStamp(original);
}
if (dependency instanceof ModificationTracker) {
return ((ModificationTracker)dependency).getModificationCount();
}
if (dependency instanceof PsiDirectory) {
return myManager.getModificationTracker().getOutOfCodeBlockModificationCount();
}
if (dependency instanceof PsiElement) {
PsiElement element = (PsiElement)dependency;
if (!element.isValid()) return -1;
PsiFile containingFile = element.getContainingFile();
if (containingFile == null) return -1;
return containingFile.getModificationStamp();
}
if (dependency == PsiModificationTracker.MODIFICATION_COUNT) {
return myManager.getModificationTracker().getModificationCount();
}
else if (dependency == PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT) {
return myManager.getModificationTracker().getOutOfCodeBlockModificationCount();
}
else if (dependency == PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT) {
return myManager.getModificationTracker().getJavaStructureModificationCount();
}
else if (dependency instanceof Document) {
return ((Document)dependency).getModificationStamp();
}
else {
LOG.error("Wrong dependency type: " + dependency.getClass());
return -1;
}
}
public ParameterizedCachedValueProvider<T,P> getValueProvider() {
return myProvider;
}
public T setValue(final CachedValueProvider.Result<T> result) {
w.lock();
try {
T value = result.getValue();
setValue(value, result);
return value;
}
finally {
w.unlock();
}
}
private static class MyTimedReference<T> extends TimedReference<SoftReference<Data<T>>> {
private boolean myIsLocked;
public MyTimedReference() {
super(null);
}
public void setIsLocked(final boolean isLocked) {
myIsLocked = isLocked;
}
protected boolean isLocked() {
return super.isLocked() || myIsLocked;
}
public void setData(final Data<T> data) {
set(new SoftReference<Data<T>>(data));
}
@Nullable
public Data<T> getData() {
final SoftReference<Data<T>> ref = get();
return ref != null ? ref.get() : null;
}
}
}
@@ -0,0 +1,78 @@
package com.intellij.psi.impl;
import com.intellij.psi.PsiManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiModificationTracker;
import com.intellij.openapi.project.Project;
import com.intellij.util.CachedValueBase;
import org.jetbrains.annotations.NotNull;
/**
* @author Dmitry Avdeev
*/
public class PsiCachedValue<T> extends CachedValueBase<T> {
private final PsiManager myManager;
protected long myLastPsiTimeStamp = -1;
public PsiCachedValue(PsiManager manager) {
super();
myManager = manager;
}
@Override
protected Data<T> computeData(T value, Object[] dependencies) {
Data<T> data = super.computeData(value, dependencies);
myLastPsiTimeStamp = myManager.getModificationTracker().getModificationCount();
return data;
}
@Override
protected boolean isUpToDate(@NotNull Data data) {
return !myManager.isDisposed() && super.isUpToDate(data);
}
@Override
protected boolean isDependencyOutOfDate(Object dependency, long oldTimeStamp) {
return !(dependency instanceof PsiElement && myLastPsiTimeStamp == myManager.getModificationTracker().getModificationCount()) &&
super.isDependencyOutOfDate(dependency, oldTimeStamp);
}
@Override
protected long getTimeStamp(Object dependency) {
if (dependency instanceof PsiDirectory) {
return myManager.getModificationTracker().getOutOfCodeBlockModificationCount();
}
if (dependency instanceof PsiElement) {
PsiElement element = (PsiElement)dependency;
if (!element.isValid()) return -1;
PsiFile containingFile = element.getContainingFile();
if (containingFile == null) return -1;
return containingFile.getModificationStamp();
}
if (dependency == PsiModificationTracker.MODIFICATION_COUNT) {
return myManager.getModificationTracker().getModificationCount();
}
else if (dependency == PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT) {
return myManager.getModificationTracker().getOutOfCodeBlockModificationCount();
}
else if (dependency == PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT) {
return myManager.getModificationTracker().getJavaStructureModificationCount();
}
return super.getTimeStamp(dependency);
}
@Override
public boolean isFromMyProject(Project project) {
return myManager.getProject() == project;
}
}
@@ -0,0 +1,56 @@
package com.intellij.psi.impl;
import com.intellij.psi.PsiManager;
import com.intellij.psi.util.CachedValue;
import com.intellij.psi.util.CachedValueProvider;
import org.jetbrains.annotations.Nullable;
/**
* @author Dmitry Avdeev
*/
public class PsiCachedValueImpl<T> extends PsiCachedValue<T> implements CachedValue<T> {
private CachedValueProvider<T> myProvider;
public PsiCachedValueImpl(PsiManager manager, CachedValueProvider<T> provider) {
super(manager);
myProvider = provider;
}
@Nullable
public T getValue() {
r.lock();
T value;
try {
value = getUpToDateOrNull();
if (value != null) {
return value == NULL ? null : value;
}
} finally {
r.unlock();
}
w.lock();
try {
value = getUpToDateOrNull();
if (value != null) {
return value == NULL ? null : value;
}
CachedValueProvider.Result<T> result = myProvider.compute();
value = result == null ? null : result.getValue();
setValue(value, result);
return value;
}
finally {
w.unlock();
}
}
public CachedValueProvider<T> getValueProvider() {
return myProvider;
}
}
@@ -0,0 +1,54 @@
package com.intellij.psi.impl;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiManager;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.ParameterizedCachedValueProvider;
import com.intellij.psi.util.ParameterizedCachedValue;
import com.intellij.psi.util.CachedValue;
import com.intellij.util.*;
import org.jetbrains.annotations.NotNull;
/**
* @author Dmitry Avdeev
*/
public class PsiCachedValuesFactory implements CachedValuesFactory {
private final Project myProject;
private final PsiManager myManager;
public PsiCachedValuesFactory(PsiManager manager) {
myManager = manager;
myProject = manager.getProject();
}
public <T> CachedValue<T> createCachedValue(@NotNull CachedValueProvider<T> provider, boolean trackValue) {
return trackValue ? new PsiCachedValueImpl<T>(myManager, provider) {
@Override
protected Object[] getDependencies(CachedValueProvider.Result<T> result) {
return getDependenciesPlusValue(result);
}
} : new PsiCachedValueImpl<T>(myManager, provider) {
};
}
public <T, P> ParameterizedCachedValue<T, P> createParameterizedCachedValue(@NotNull ParameterizedCachedValueProvider<T, P> provider,
boolean trackValue) {
return trackValue ? new PsiParameterizedCachedValue<T, P>(myManager, provider) {
@Override
public boolean isFromMyProject(Project project) {
return myProject == project;
}
@Override
protected Object[] getDependencies(CachedValueProvider.Result<T> tResult) {
return getDependenciesPlusValue(tResult);
}
} : new PsiParameterizedCachedValue<T, P>(myManager, provider) {
@Override
public boolean isFromMyProject(Project project) {
return myProject == project;
}
};
}
}
@@ -22,6 +22,7 @@ import com.intellij.openapi.startup.StartupManager;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.NotNullLazyValue;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileFilter;
import com.intellij.psi.*;
@@ -64,7 +65,13 @@ public class PsiManagerImpl extends PsiManagerEx implements ProjectComponent {
private final CacheManager myCacheManager;
private final PsiModificationTrackerImpl myModificationTracker;
private final ResolveCache myResolveCache;
private final CachedValuesManager myCachedValuesManager;
private final NotNullLazyValue<CachedValuesManager> myCachedValuesManager = new NotNullLazyValue<CachedValuesManager>() {
@NotNull
@Override
protected CachedValuesManager compute() {
return CachedValuesManager.getManager(myProject);
}
};
private final List<PsiTreeChangePreprocessor> myTreeChangePreprocessors = ContainerUtil.createEmptyCOWList();
private final List<PsiTreeChangeListener> myTreeChangeListeners = ContainerUtil.createEmptyCOWList();
@@ -119,7 +126,6 @@ public class PsiManagerImpl extends PsiManagerEx implements ProjectComponent {
myModificationTracker = new PsiModificationTrackerImpl(myProject);
myTreeChangePreprocessors.add(myModificationTracker);
myResolveCache = new ResolveCache(this);
myCachedValuesManager = new CachedValuesManagerImpl(this);
if (startupManager != null) {
((StartupManagerEx)startupManager).registerPreStartupActivity(
@@ -695,7 +701,7 @@ public class PsiManagerImpl extends PsiManagerEx implements ProjectComponent {
@NotNull
public CachedValuesManager getCachedValuesManager() {
return myCachedValuesManager;
return myCachedValuesManager.getValue();
}
public void moveDirectory(@NotNull final PsiDirectory dir, @NotNull PsiDirectory newParent) throws IncorrectOperationException {
@@ -0,0 +1,64 @@
/*
* Created by IntelliJ IDEA.
* User: mike
* Date: Jun 6, 2002
* Time: 5:41:42 PM
* To change template for new class use
* Code Style | Class Templates options (Tools | IDE Options).
*/
package com.intellij.psi.impl;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.ParameterizedCachedValueProvider;
import com.intellij.psi.util.ParameterizedCachedValue;
import com.intellij.psi.PsiManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class PsiParameterizedCachedValue<T,P> extends PsiCachedValue<T> implements ParameterizedCachedValue<T,P> {
private final ParameterizedCachedValueProvider<T,P> myProvider;
public PsiParameterizedCachedValue(PsiManager manager, @NotNull ParameterizedCachedValueProvider<T, P> provider) {
super(manager);
myProvider = provider;
}
@Nullable
public T getValue(P param) {
r.lock();
T value;
try {
value = getUpToDateOrNull();
if (value != null) {
return value == NULL ? null : value;
}
} finally {
r.unlock();
}
w.lock();
try {
value = getUpToDateOrNull();
if (value != null) {
return value == NULL ? null : value;
}
CachedValueProvider.Result<T> result = myProvider.compute(param);
value = result == null ? null : result.getValue();
setValue(value, result);
return value;
}
finally {
w.unlock();
}
}
public ParameterizedCachedValueProvider<T,P> getValueProvider() {
return myProvider;
}
}
@@ -33,7 +33,7 @@ import com.intellij.psi.util.ParameterizedCachedValueProvider;
import com.intellij.psi.util.CachedValuesManager;
import com.intellij.util.containers.HashMap;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.ArrayUtil;
import com.intellij.util.*;
import java.util.ArrayList;
import java.util.List;
@@ -8,13 +8,13 @@ import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.UserDataCache;
import com.intellij.patterns.ElementPattern;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.CachedValue;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.filters.ElementFilter;
import com.intellij.psi.filters.position.PatternFilter;
import com.intellij.psi.meta.MetaDataContributor;
import com.intellij.psi.meta.MetaDataRegistrar;
import com.intellij.psi.meta.PsiMetaData;
import com.intellij.psi.util.CachedValue;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -9,10 +9,10 @@ import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.util.CachedValue;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.CachedValuesManager;
import com.intellij.psi.util.PsiModificationTracker;
import com.intellij.psi.util.CachedValue;
import com.intellij.psi.util.*;
import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -16,7 +16,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.*;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.impl.ParameterizedCachedValueImpl;
import com.intellij.util.ParameterizedCachedValueImpl;
import com.intellij.psi.impl.PsiDocumentManagerImpl;
import com.intellij.psi.impl.PsiManagerEx;
import com.intellij.psi.impl.source.DummyHolder;
@@ -0,0 +1,25 @@
/*
* Copyright 2000-2007 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.
*/
package com.intellij.psi.util;
public interface CachedValue<T> {
T getValue();
CachedValueProvider<T> getValueProvider();
boolean hasUpToDateValue();
}
@@ -0,0 +1,61 @@
/*
* Copyright 2000-2007 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.
*/
package com.intellij.psi.util;
import org.jetbrains.annotations.Nullable;
public interface CachedValueProvider<T> {
@Nullable
Result<T> compute();
class Result<T> {
private final T myValue;
private final Object[] myDependencyItems;
private boolean myLockValue = false;
public Result(T value, Object... dependencyItems) {
myValue = value;
myDependencyItems = dependencyItems;
}
public T getValue() {
return myValue;
}
public Object[] getDependencyItems() {
return myDependencyItems;
}
public static <T> Result<T> createSingleDependency(T value, Object dependency) {
return create(value, dependency);
}
public static <T> Result<T> create(T value, Object... dependencies) {
return new Result<T>(value, dependencies);
}
public boolean isLockValue() {
return myLockValue;
}
/**
* If the value is locked it won't be released after 60 seconds of inactivity
*/
public void setLockValue(final boolean lockValue) {
myLockValue = lockValue;
}
}
}
@@ -0,0 +1,86 @@
/*
* Copyright 2000-2007 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.
*/
package com.intellij.psi.util;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.UserDataHolder;
import com.intellij.openapi.util.UserDataHolderEx;
import com.intellij.openapi.components.ServiceManager;
import org.jetbrains.annotations.NotNull;
public abstract class CachedValuesManager {
public static CachedValuesManager getManager(@NotNull Project project) {
return ServiceManager.getService(project, CachedValuesManager.class);
}
/**
* Creates new CachedValue instance with given provider.
*
* @param provider computes values.
* @param trackValue if value tracking required. T should be trackable in this case.
* @return new CachedValue instance.
*/
public abstract <T> CachedValue<T> createCachedValue(@NotNull CachedValueProvider<T> provider, boolean trackValue);
public abstract <T,P> ParameterizedCachedValue<T,P> createParameterizedCachedValue(@NotNull ParameterizedCachedValueProvider<T,P> provider, boolean trackValue);
public <T> CachedValue<T> createCachedValue(@NotNull CachedValueProvider<T> provider) {
return createCachedValue(provider, true);
}
public <T, D extends UserDataHolder, P> T getParameterizedCachedValue(@NotNull D dataHolder,
@NotNull Key<ParameterizedCachedValue<T,P>> key,
@NotNull ParameterizedCachedValueProvider<T, P> provider,
boolean trackValue,
P parameter) {
ParameterizedCachedValue<T,P> value;
if (dataHolder instanceof UserDataHolderEx) {
UserDataHolderEx dh = (UserDataHolderEx)dataHolder;
value = dh.getUserData(key);
if (value == null) {
value = createParameterizedCachedValue(provider, trackValue);
value = dh.putUserDataIfAbsent(key, value);
}
}
else {
synchronized (dataHolder) {
value = dataHolder.getUserData(key);
if (value == null) {
value = createParameterizedCachedValue(provider, trackValue);
dataHolder.putUserData(key, value);
}
}
}
return value.getValue(parameter);
}
/**
* Utility method storing created cached values in a {@link com.intellij.openapi.util.UserDataHolder}.
*
* @param dataHolder holder to store the cached value, e.g. a PsiElement.
* @param key key to store the cached value.
* @param provider provider creating the cached value.
* @param trackValue if value tracking required. T should be trackable in this case.
* @return up-to-date value.
*/
public abstract <T, D extends UserDataHolder> T getCachedValue(@NotNull D dataHolder,
@NotNull Key<CachedValue<T>> key,
@NotNull CachedValueProvider<T> provider,
boolean trackValue);
}
@@ -0,0 +1,28 @@
/*
* Copyright 2000-2007 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.
*/
package com.intellij.psi.util;
import org.jetbrains.annotations.Nullable;
public interface ParameterizedCachedValue<T, P> {
@Nullable
T getValue(P param);
ParameterizedCachedValueProvider<T,P> getValueProvider();
boolean hasUpToDateValue();
}
@@ -0,0 +1,23 @@
/*
* Copyright 2000-2007 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.
*/
package com.intellij.psi.util;
import org.jetbrains.annotations.Nullable;
public interface ParameterizedCachedValueProvider<T, P> {
@Nullable
CachedValueProvider.Result<T> compute(P param);
}
@@ -1,12 +1,4 @@
/*
* Created by IntelliJ IDEA.
* User: mike
* Date: Jun 6, 2002
* Time: 5:41:42 PM
* To change template for new class use
* Code Style | Class Templates options (Tools | IDE Options).
*/
package com.intellij.psi.impl;
package com.intellij.util;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.project.Project;
@@ -14,16 +6,10 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.ModificationTracker;
import com.intellij.openapi.util.Ref;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.util.CachedValue;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.PsiModificationTracker;
import com.intellij.reference.SoftReference;
import com.intellij.util.TimedReference;
import com.intellij.util.ArrayUtil;
import com.intellij.util.TimedReference;
import com.intellij.util.concurrency.JBLock;
import com.intellij.util.concurrency.JBReentrantReadWriteLock;
import com.intellij.util.concurrency.LockFactory;
@@ -35,88 +21,38 @@ import java.lang.ref.Reference;
import java.util.ArrayList;
import java.util.List;
public class CachedValueImpl<T> implements CachedValue<T> {
private static final Object NULL = new Object();
/**
* @author Dmitry Avdeev
*/
public abstract class CachedValueBase<T> {
protected static final Object NULL = new Object();
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.CachedValueImpl");
private final PsiManager myManager;
private final CachedValueProvider<T> myProvider;
private final boolean myTrackValue;
private final MyTimedReference<T> myData = new MyTimedReference<T>();
protected final JBLock r;
protected final JBLock w;
private long myLastPsiTimeStamp = -1;
private final JBLock r;
private final JBLock w;
public CachedValueImpl(@NotNull PsiManager manager, @NotNull CachedValueProvider<T> provider, boolean trackValue) {
myManager = manager;
myProvider = provider;
myTrackValue = trackValue;
public CachedValueBase() {
JBReentrantReadWriteLock rw = LockFactory.createReadWriteLock();
r = rw.readLock();
w = rw.writeLock();
}
public boolean isFromMyProject(Project project) {
return project == myManager.getProject();
protected Data<T> computeData(T value, Object[] dependencies) {
if (dependencies == null) {
return new Data<T>(value, null, null);
}
TLongArrayList timeStamps = new TLongArrayList();
List<Object> deps = new ArrayList<Object>();
collectDependencies(timeStamps, deps, dependencies);
return new Data<T>(value, ArrayUtil.toObjectArray(deps), timeStamps.toNativeArray());
}
private static class Data<T> implements Disposable {
private final T myValue;
private final Object[] myDependencies;
private final long[] myTimeStamps;
public Data(final T value, final Object[] dependencies, final long[] timeStamps) {
myValue = value;
myDependencies = dependencies;
myTimeStamps = timeStamps;
}
public void dispose() {
if (myValue instanceof Disposable) {
Disposer.dispose((Disposable)myValue);
}
}
}
@Nullable
public T getValue() {
r.lock();
T value;
try {
value = getUpToDateOrNull();
if (value != null) {
return value == NULL ? null : value;
}
} finally {
r.unlock();
}
w.lock();
try {
value = getUpToDateOrNull();
if (value != null) {
return value == NULL ? null : value;
}
CachedValueProvider.Result<T> result = myProvider.compute();
value = result == null ? null : result.getValue();
setValue(value, result);
return value;
}
finally {
w.unlock();
}
}
private void setValue(final T value, final CachedValueProvider.Result<T> result) {
myData.setData(computeData(value == null ? (T) NULL : value, result == null ? null : result.getDependencyItems()));
protected void setValue(final T value, final CachedValueProvider.Result<T> result) {
myData.setData(computeData(value == null ? (T) NULL : value, getDependencies(result)));
if (result != null) {
myData.setIsLocked(result.isLockValue());
}
@@ -125,6 +61,22 @@ public class CachedValueImpl<T> implements CachedValue<T> {
}
}
@Nullable
protected Object[] getDependencies(CachedValueProvider.Result<T> result) {
return result == null ? null : result.getDependencyItems();
}
@Nullable
protected Object[] getDependenciesPlusValue(CachedValueProvider.Result<T> result) {
if (result == null) {
return null;
}
else {
Object[] items = result.getDependencyItems();
return result.getValue() == null ? items : ArrayUtil.append(items, result.getValue());
}
}
public void clear() {
myData.set(null);
}
@@ -145,7 +97,7 @@ public class CachedValueImpl<T> implements CachedValue<T> {
}
@Nullable
private T getUpToDateOrNull() {
protected T getUpToDateOrNull() {
final Data<T> data = myData.getData();
if (data != null) {
@@ -160,9 +112,8 @@ public class CachedValueImpl<T> implements CachedValue<T> {
return null;
}
private boolean isUpToDate(@NotNull Data data) {
protected boolean isUpToDate(@NotNull Data data) {
if (data.myTimeStamps == null) return true;
if (myManager.isDisposed()) return false;
for (int i = 0; i < data.myDependencies.length; i++) {
Object dependency = data.myDependencies[i];
@@ -173,33 +124,12 @@ public class CachedValueImpl<T> implements CachedValue<T> {
return true;
}
private boolean isDependencyOutOfDate(Object dependency, long oldTimeStamp) {
if (dependency instanceof PsiElement &&
myLastPsiTimeStamp == myManager.getModificationTracker().getModificationCount()) {
return false;
}
protected boolean isDependencyOutOfDate(Object dependency, long oldTimeStamp) {
final long timeStamp = getTimeStamp(dependency);
return timeStamp < 0 || timeStamp != oldTimeStamp;
}
private Data<T> computeData(T value, Object[] dependencies) {
if (dependencies == null) {
return new Data<T>(value, null, null);
}
TLongArrayList timeStamps = new TLongArrayList();
List<Object> deps = new ArrayList<Object>();
collectDependencies(timeStamps, deps, dependencies);
if (myTrackValue) {
collectDependencies(timeStamps, deps, new Object[]{value});
}
myLastPsiTimeStamp = myManager.getModificationTracker().getModificationCount();
return new Data<T>(value, ArrayUtil.toObjectArray(deps), timeStamps.toNativeArray());
}
private void collectDependencies(TLongArrayList timeStamps, List<Object> resultingDeps, Object[] dependencies) {
protected void collectDependencies(TLongArrayList timeStamps, List<Object> resultingDeps, Object[] dependencies) {
for (Object dependency : dependencies) {
if (dependency == null || dependency == NULL) continue;
if (dependency instanceof Object[]) {
@@ -212,13 +142,13 @@ public class CachedValueImpl<T> implements CachedValue<T> {
}
}
private long getTimeStamp(Object dependency) {
protected long getTimeStamp(Object dependency) {
if (dependency instanceof Reference){
final Object original = ((Reference)dependency).get();
if(original == null) return -1;
return getTimeStamp(original);
}
if (dependency instanceof Ref) {
final Object original = ((Ref)dependency).get();
if(original == null) return -1;
@@ -228,38 +158,12 @@ public class CachedValueImpl<T> implements CachedValue<T> {
if (dependency instanceof ModificationTracker) {
return ((ModificationTracker)dependency).getModificationCount();
}
if (dependency instanceof PsiDirectory) {
return myManager.getModificationTracker().getOutOfCodeBlockModificationCount();
}
if (dependency instanceof PsiElement) {
PsiElement element = (PsiElement)dependency;
if (!element.isValid()) return -1;
PsiFile containingFile = element.getContainingFile();
if (containingFile == null) return -1;
return containingFile.getModificationStamp();
}
if (dependency == PsiModificationTracker.MODIFICATION_COUNT) {
return myManager.getModificationTracker().getModificationCount();
}
else if (dependency == PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT) {
return myManager.getModificationTracker().getOutOfCodeBlockModificationCount();
}
else if (dependency == PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT) {
return myManager.getModificationTracker().getJavaStructureModificationCount();
}
else {
LOG.error("Wrong dependency type: " + dependency.getClass());
return -1;
}
}
public CachedValueProvider<T> getValueProvider() {
return myProvider;
}
public T setValue(final CachedValueProvider.Result<T> result) {
w.lock();
@@ -273,6 +177,26 @@ public class CachedValueImpl<T> implements CachedValue<T> {
}
}
public abstract boolean isFromMyProject(Project project);
protected static class Data<T> implements Disposable {
private final T myValue;
private final Object[] myDependencies;
private final long[] myTimeStamps;
public Data(final T value, final Object[] dependencies, final long[] timeStamps) {
myValue = value;
myDependencies = dependencies;
myTimeStamps = timeStamps;
}
public void dispose() {
if (myValue instanceof Disposable) {
Disposer.dispose((Disposable)myValue);
}
}
}
private static class MyTimedReference<T> extends TimedReference<SoftReference<Data<T>>> {
private boolean myIsLocked;
@@ -0,0 +1,65 @@
/*
* Created by IntelliJ IDEA.
* User: mike
* Date: Jun 6, 2002
* Time: 5:41:42 PM
* To change template for new class use
* Code Style | Class Templates options (Tools | IDE Options).
*/
package com.intellij.util;
import com.intellij.psi.util.CachedValue;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.util.CachedValueBase;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class CachedValueImpl<T> extends CachedValueBase<T> implements CachedValue<T> {
private final CachedValueProvider<T> myProvider;
public CachedValueImpl(@NotNull CachedValueProvider<T> provider) {
super();
myProvider = provider;
}
@Nullable
public T getValue() {
r.lock();
T value;
try {
value = getUpToDateOrNull();
if (value != null) {
return value == NULL ? null : value;
}
} finally {
r.unlock();
}
w.lock();
try {
value = getUpToDateOrNull();
if (value != null) {
return value == NULL ? null : value;
}
CachedValueProvider.Result<T> result = myProvider.compute();
value = result == null ? null : result.getValue();
setValue(value, result);
return value;
}
finally {
w.unlock();
}
}
public CachedValueProvider<T> getValueProvider() {
return myProvider;
}
}
@@ -0,0 +1,17 @@
package com.intellij.util;
import com.intellij.psi.util.CachedValue;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.ParameterizedCachedValue;
import com.intellij.psi.util.ParameterizedCachedValueProvider;
import org.jetbrains.annotations.NotNull;
/**
* @author Dmitry Avdeev
*/
public interface CachedValuesFactory {
<T> CachedValue<T> createCachedValue(@NotNull CachedValueProvider<T> provider, boolean trackValue);
<T,P> ParameterizedCachedValue<T,P> createParameterizedCachedValue(@NotNull ParameterizedCachedValueProvider<T,P> provider, boolean trackValue);
}
@@ -1,10 +1,10 @@
package com.intellij.psi.impl;
package com.intellij.util;
import com.intellij.psi.PsiManager;
import com.intellij.psi.util.*;
import com.intellij.openapi.util.UserDataHolder;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.UserDataHolderEx;
import com.intellij.openapi.project.Project;
import com.intellij.psi.util.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -12,18 +12,21 @@ import org.jetbrains.annotations.Nullable;
* @author ven
*/
public class CachedValuesManagerImpl extends CachedValuesManager {
private final PsiManager myManager;
public CachedValuesManagerImpl(PsiManager manager) {
myManager = manager;
private final Project myProject;
private final CachedValuesFactory myFactory;
public CachedValuesManagerImpl(Project project, CachedValuesFactory factory) {
myProject = project;
myFactory = factory == null ? new DefaultCachedValuesFactory(project) : factory;
}
public <T> CachedValue<T> createCachedValue(@NotNull CachedValueProvider<T> provider, boolean trackValue) {
return new CachedValueImpl<T>(myManager, provider, trackValue);
return myFactory.createCachedValue(provider, trackValue);
}
public <T,P> ParameterizedCachedValue<T,P> createParameterizedCachedValue(@NotNull ParameterizedCachedValueProvider<T,P> provider, boolean trackValue) {
return new ParameterizedCachedValueImpl<T,P>(myManager, provider, trackValue);
return myFactory.createParameterizedCachedValue(provider, trackValue);
}
@Override
@@ -37,20 +40,20 @@ public class CachedValuesManagerImpl extends CachedValuesManager {
if (dataHolder instanceof UserDataHolderEx) {
UserDataHolderEx dh = (UserDataHolderEx)dataHolder;
value = dh.getUserData(key);
if (value instanceof CachedValueImpl && !((CachedValueImpl)value).isFromMyProject(myManager.getProject())) {
if (value instanceof CachedValueBase && !((CachedValueBase)value).isFromMyProject(myProject)) {
value = null;
dataHolder.putUserData(key, null);
}
if (value == null) {
value = createCachedValue(provider, trackValue);
assert ((CachedValueImpl)value).isFromMyProject(myManager.getProject());
assert ((CachedValueBase)value).isFromMyProject(myProject);
value = dh.putUserDataIfAbsent(key, value);
}
}
else {
synchronized (dataHolder) {
value = dataHolder.getUserData(key);
if (value instanceof CachedValueImpl && !((CachedValueImpl)value).isFromMyProject(myManager.getProject())) {
if (value instanceof CachedValueBase && !((CachedValueBase)value).isFromMyProject(myProject)) {
value = null;
}
if (value == null) {
@@ -61,4 +64,8 @@ public class CachedValuesManagerImpl extends CachedValuesManager {
}
return value.getValue();
}
public Project getProject() {
return myProject;
}
}
@@ -0,0 +1,59 @@
package com.intellij.util;
import com.intellij.psi.util.ParameterizedCachedValueProvider;
import com.intellij.openapi.project.Project;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.ParameterizedCachedValue;
import com.intellij.psi.util.*;
import org.jetbrains.annotations.NotNull;
/**
* @author Dmitry Avdeev
*/
public class DefaultCachedValuesFactory implements CachedValuesFactory {
private final Project myProject;
public DefaultCachedValuesFactory(Project project) {
myProject = project;
}
public <T> CachedValue<T> createCachedValue(@NotNull CachedValueProvider<T> provider, boolean trackValue) {
return trackValue ? new CachedValueImpl<T>(provider) {
@Override
protected Object[] getDependencies(CachedValueProvider.Result<T> result) {
return getDependenciesPlusValue(result);
}
@Override
public boolean isFromMyProject(Project project) {
return myProject == project;
}
} : new CachedValueImpl<T>(provider) {
@Override
public boolean isFromMyProject(Project project) {
return myProject == project;
}
};
}
public <T, P> ParameterizedCachedValue<T, P> createParameterizedCachedValue(@NotNull ParameterizedCachedValueProvider<T, P> provider,
boolean trackValue) {
return trackValue ? new ParameterizedCachedValueImpl<T, P>(provider) {
@Override
public boolean isFromMyProject(Project project) {
return myProject == project;
}
@Override
protected Object[] getDependencies(CachedValueProvider.Result<T> tResult) {
return getDependenciesPlusValue(tResult);
}
} : new ParameterizedCachedValueImpl<T, P>(provider) {
@Override
public boolean isFromMyProject(Project project) {
return myProject == project;
}
};
}
}
@@ -0,0 +1,64 @@
/*
* Created by IntelliJ IDEA.
* User: mike
* Date: Jun 6, 2002
* Time: 5:41:42 PM
* To change template for new class use
* Code Style | Class Templates options (Tools | IDE Options).
*/
package com.intellij.util;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.ParameterizedCachedValue;
import com.intellij.psi.util.ParameterizedCachedValueProvider;
import com.intellij.util.CachedValueBase;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class ParameterizedCachedValueImpl<T,P> extends CachedValueBase<T> implements ParameterizedCachedValue<T,P> {
private final ParameterizedCachedValueProvider<T,P> myProvider;
public ParameterizedCachedValueImpl(@NotNull ParameterizedCachedValueProvider<T,P> provider) {
super();
myProvider = provider;
}
@Nullable
public T getValue(P param) {
r.lock();
T value;
try {
value = getUpToDateOrNull();
if (value != null) {
return value == NULL ? null : value;
}
} finally {
r.unlock();
}
w.lock();
try {
value = getUpToDateOrNull();
if (value != null) {
return value == NULL ? null : value;
}
CachedValueProvider.Result<T> result = myProvider.compute(param);
value = result == null ? null : result.getValue();
setValue(value, result);
return value;
}
finally {
w.unlock();
}
}
public ParameterizedCachedValueProvider<T,P> getValueProvider() {
return myProvider;
}
}
@@ -140,6 +140,9 @@
serviceImplementation="com.intellij.pom.core.impl.PomModelImpl"/>
<projectService serviceInterface="com.intellij.psi.impl.include.FileIncludeManager"
serviceImplementation="com.intellij.psi.impl.include.FileIncludeManagerImpl"/>
<projectService serviceInterface="com.intellij.util.CachedValuesFactory"
serviceImplementation="com.intellij.psi.impl.PsiCachedValuesFactory"/>
<projectService serviceInterface="com.intellij.openapi.roots.impl.libraries.ProjectLibraryTable"
serviceImplementation="com.intellij.openapi.roots.impl.libraries.ProjectLibraryTable"/>
@@ -48,6 +48,8 @@
<extensionPoint name="projectUndoProvider" interface="com.intellij.openapi.command.impl.UndoProvider"
area="IDEA_PROJECT"/>
<extensionPoint name="cachedValuesFactory" interface="com.intellij.util.CachedValuesFactory" area="IDEA_PROJECT"/>
<extensionPoint name="syntaxHighlighter"
beanClass="com.intellij.openapi.extensions.KeyedFactoryEPBean"/>
@@ -114,6 +114,9 @@
<projectService serviceInterface="com.intellij.openapi.project.DumbService" serviceImplementation="com.intellij.openapi.project.DumbServiceImpl"/>
<projectService serviceInterface="com.intellij.psi.util.CachedValuesManager"
serviceImplementation="com.intellij.util.CachedValuesManagerImpl"/>
<projectService serviceInterface="com.intellij.openapi.vcs.impl.projectlevelman.AllVcsesI"
serviceImplementation="com.intellij.openapi.vcs.impl.projectlevelman.AllVcses"/>
@@ -22,7 +22,6 @@ import com.intellij.profile.Profile;
import com.intellij.profile.ProfileChangeAdapter;
import com.intellij.profile.codeInspection.InspectionProfileManager;
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
import com.intellij.psi.PsiManager;
import com.intellij.psi.util.CachedValue;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.CachedValuesManager;
@@ -99,11 +98,7 @@ public class DomElementAnnotationsManagerImpl extends DomElementAnnotationsManag
private final ProjectRootManager myProjectRootManager;
private final CachedValuesManager myCachedValuesManager;
private long myModificationCount;
public DomElementAnnotationsManagerImpl(Project project, InspectionProfileManager manager, ProjectRootManager projectRootManager,
PsiManager psiManager) {
this(project, manager, projectRootManager, psiManager.getCachedValuesManager());
}
public DomElementAnnotationsManagerImpl(Project project, final InspectionProfileManager inspectionProfileManager, ProjectRootManager projectRootManager,
final CachedValuesManager cachedValuesManager) {
myCachedValuesManager = cachedValuesManager;
@@ -11,7 +11,7 @@ import com.intellij.pom.impl.PomTransactionBase;
import com.intellij.pom.xml.XmlAspect;
import com.intellij.pom.xml.impl.events.XmlDocumentChangedImpl;
import com.intellij.psi.*;
import com.intellij.psi.impl.CachedValueImpl;
import com.intellij.psi.impl.PsiCachedValueImpl;
import com.intellij.psi.impl.meta.MetaRegistry;
import com.intellij.psi.impl.source.html.dtd.HtmlNSDescriptorImpl;
import com.intellij.psi.impl.source.tree.TreeElement;
@@ -133,7 +133,7 @@ public class XmlDocumentImpl extends XmlElementImpl implements XmlDocument {
CachedValue<XmlNSDescriptor> cachedValue = defaultDescriptorsCache.get(namespace);
if (cachedValue == null) {
defaultDescriptorsCache.put(namespace, cachedValue = new CachedValueImpl<XmlNSDescriptor>(getManager(), new CachedValueProvider<XmlNSDescriptor>() {
defaultDescriptorsCache.put(namespace, cachedValue = new PsiCachedValueImpl<XmlNSDescriptor>(getManager(), new CachedValueProvider<XmlNSDescriptor>() {
public Result<XmlNSDescriptor> compute() {
final XmlNSDescriptor defaultNSDescriptorInner = getDefaultNSDescriptorInner(namespace, strict);
@@ -145,7 +145,7 @@ public class XmlDocumentImpl extends XmlElementImpl implements XmlDocument {
? defaultNSDescriptorInner.getDependences()
: ExternalResourceManager.getInstance());
}
}, false));
}));
}
return cachedValue.getValue();
}