new dependencies collection method (fixed serious threading issues)

This commit is contained in:
Sascha Weinreuter
2011-12-14 17:46:41 +01:00
parent 196d5d6eb8
commit aef5aef05f
4 changed files with 77 additions and 62 deletions
@@ -15,7 +15,6 @@
*/
package org.intellij.lang.xpath.psi.impl;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
@@ -25,25 +24,41 @@ import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlAttributeValue;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.CommonProcessors;
import com.intellij.util.Processor;
import org.jetbrains.annotations.Nullable;
import gnu.trove.THashSet;
import gnu.trove.TObjectHashingStrategy;
import org.intellij.lang.xpath.xslt.impl.XsltIncludeIndex;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class ResolveUtil {
public static final Key<List<PsiElement>> DEPENDENCIES = Key.create("XSLT_DEPENDENCIES");
@SuppressWarnings({"unchecked"})
@SuppressWarnings({"unchecked"})
private final THashSet<PsiElement> myHistory = new THashSet<PsiElement>(TObjectHashingStrategy.IDENTITY);
private ResolveUtil() {
}
@Nullable
public static Collection<XmlFile> getDependencies(XmlFile element) {
final CommonProcessors.CollectUniquesProcessor<XmlFile> processor = new CommonProcessors.CollectUniquesProcessor<XmlFile>() {
@Override
public boolean process(XmlFile file) {
if (!getResults().contains(file)) {
XsltIncludeIndex.processForwardDependencies(file, this);
}
return super.process(file);
}
};
XsltIncludeIndex.processForwardDependencies(element, processor);
return processor.getResults();
}
@Nullable
public static PsiFile resolveFile(String name, PsiFile baseFile) {
if (baseFile == null) return null;
@@ -18,7 +18,6 @@ package org.intellij.lang.xpath.xslt.context;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.UserDataCache;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.CachedValuesManager;
import com.intellij.psi.util.ParameterizedCachedValue;
@@ -27,7 +26,6 @@ import com.intellij.psi.xml.XmlElement;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.ArrayUtil;
import com.intellij.util.SmartList;
import org.apache.commons.collections.map.CompositeMap;
import org.intellij.lang.xpath.context.ContextType;
import org.intellij.lang.xpath.context.XPathVersion;
@@ -45,8 +43,8 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.xml.namespace.QName;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Xslt2ContextProvider extends XsltContextProviderBase {
@@ -170,14 +168,15 @@ public class Xslt2ContextProvider extends XsltContextProviderBase {
candidates.put(Pair.create(function.getQName(), function.getParameters().length), function);
}
List<PsiElement> data = param.getUserData(ResolveUtil.DEPENDENCIES);
if (data == null) {
data = new SmartList<PsiElement>(param);
final Collection<XmlFile> data = ResolveUtil.getDependencies(param);
final Object[] dependencies;
if (data == null || data.size() == 0) {
dependencies = new Object[]{ param };
} else {
data.add(param);
param.putUserData(ResolveUtil.DEPENDENCIES, null);
dependencies = ArrayUtil.toObjectArray(data);
}
return CachedValueProvider.Result.create(candidates, ArrayUtil.toObjectArray(data));
return CachedValueProvider.Result.create(candidates, dependencies);
}
}
}
@@ -40,41 +40,55 @@ public class XsltIncludeIndex {
public static boolean isReachableFrom(XmlFile which, XmlFile from) {
return from == which || _isReachableFrom(from.getVirtualFile(), FileIncludeManager.getManager(which.getProject()).getIncludingFiles(which.getVirtualFile(), true));
}
}
private static boolean _isReachableFrom(VirtualFile from, VirtualFile[] which) {
//noinspection ForLoopReplaceableByForEach
for (int i = 0; i < which.length; i++) {
final VirtualFile file = which[i];
if (file == from) {
return true;
}
}
return false;
}
public static boolean processBackwardDependencies(@NotNull XmlFile file, Processor<XmlFile> processor) {
final VirtualFile virtualFile = file.getVirtualFile();
if (virtualFile == null) {
private static boolean _isReachableFrom(VirtualFile from, VirtualFile[] which) {
//noinspection ForLoopReplaceableByForEach
for (int i = 0; i < which.length; i++) {
final VirtualFile file = which[i];
if (file == from) {
return true;
}
final Project project = file.getProject();
final PsiManager psiManager = PsiManager.getInstance(project);
}
return false;
}
final VirtualFile[] files = FileIncludeManager.getManager(project).getIncludingFiles(virtualFile, true);
final PsiFile[] psiFiles = ContainerUtil.map2Array(files, PsiFile.class, new NullableFunction<VirtualFile, PsiFile>() {
public PsiFile fun(VirtualFile file) {
return psiManager.findFile(file);
}
});
for (final PsiFile psiFile : psiFiles) {
if (XsltSupport.isXsltFile(psiFile)) {
if (!processor.process((XmlFile)psiFile)) {
return false;
}
}
}
public static boolean processForwardDependencies(@NotNull XmlFile file, Processor<XmlFile> processor) {
final VirtualFile virtualFile = file.getVirtualFile();
if (virtualFile == null) {
return true;
}
final Project project = file.getProject();
}
final VirtualFile[] files = FileIncludeManager.getManager(project).getIncludedFiles(virtualFile, true);
return _process(files, project, processor);
}
public static boolean processBackwardDependencies(@NotNull XmlFile file, Processor<XmlFile> processor) {
final VirtualFile virtualFile = file.getVirtualFile();
if (virtualFile == null) {
return true;
}
final Project project = file.getProject();
final VirtualFile[] files = FileIncludeManager.getManager(project).getIncludingFiles(virtualFile, true);
return _process(files, project, processor);
}
private static boolean _process(VirtualFile[] files, Project project, Processor<XmlFile> processor) {
final PsiManager psiManager = PsiManager.getInstance(project);
final PsiFile[] psiFiles = ContainerUtil.map2Array(files, PsiFile.class, new NullableFunction<VirtualFile, PsiFile>() {
public PsiFile fun(VirtualFile file) {
return psiManager.findFile(file);
}
});
for (final PsiFile psiFile : psiFiles) {
if (XsltSupport.isXsltFile(psiFile)) {
if (!processor.process((XmlFile)psiFile)) {
return false;
}
}
}
return true;
}
}
@@ -15,20 +15,15 @@
*/
package org.intellij.lang.xpath.xslt.util;
import com.intellij.psi.PsiElement;
import com.intellij.util.SmartList;
import com.intellij.psi.PsiFile;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlDocument;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import org.intellij.lang.xpath.psi.impl.ResolveUtil;
import org.intellij.lang.xpath.xslt.XsltSupport;
import com.intellij.psi.xml.XmlTag;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlDocument;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public abstract class IncludeAwareMatcher extends BaseMatcher {
protected final XmlDocument myDocument;
@@ -53,14 +48,6 @@ public abstract class IncludeAwareMatcher extends BaseMatcher {
final PsiFile file = ResolveUtil.resolveFile(href, f);
if (file instanceof XmlFile) {
final List<PsiElement> data = myDocument.getContainingFile().getUserData(ResolveUtil.DEPENDENCIES);
if (data == null) {
myDocument.getContainingFile().putUserData(ResolveUtil.DEPENDENCIES, new SmartList<PsiElement>(file));
} else if (!data.contains(file)) {
data.add(file);
}
return Result.create(changeDocument(((XmlFile)file).getDocument()));
}
}