/*
* Copyright 2013-2017 consulo.io
*
* 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 consulo.csharp.lang.psi.impl.search;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.jetbrains.annotations.NotNull;
import consulo.csharp.lang.psi.impl.stub.index.ExtendsListIndex;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.progress.ProgressIndicatorProvider;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.search.EverythingGlobalScope;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.SearchScope;
import com.intellij.util.Processor;
import com.intellij.util.QueryExecutor;
import com.intellij.util.containers.HashMap;
import consulo.dotnet.psi.DotNetTypeDeclaration;
import consulo.dotnet.psi.DotNetTypeList;
import consulo.dotnet.psi.search.searches.DirectTypeInheritorsSearch;
import consulo.internal.dotnet.msil.decompiler.util.MsilHelper;
/**
* @author max
* <p/>
* Copied from Java plugin by Jetbrains (com.intellij.psi.search.searches.ClassInheritorsSearch)
*/
public class CSharpDirectTypeInheritorsSearcherExecutor implements QueryExecutor<DotNetTypeDeclaration, DirectTypeInheritorsSearch.SearchParameters>
{
@Override
public boolean execute(@NotNull final DirectTypeInheritorsSearch.SearchParameters p, @NotNull final Processor<DotNetTypeDeclaration> consumer)
{
String vmQName = p.getVmQName();
/*if(DotNetTypes.System_Object.equals(qualifiedName))
{
final SearchScope scope = useScope;
return AllClassesSearch.search(scope, aClass.getProject()).forEach(new Processor<DotNetTypeDeclaration>()
{
@Override
public boolean process(final DotNetTypeDeclaration typeDcl)
{
if(typeDcl.isInterface())
{
return consumer.process(typeDcl);
}
final DotNetTypeDeclaration superClass = typeDcl.getSuperClass();
if(superClass != null && DotNetTypes.System_Object.equals(ApplicationManager.getApplication().runReadAction(
new Computable<String>()
{
public String compute()
{
return superClass.getPresentableQName();
}
})))
{
return consumer.process(typeDcl);
}
return true;
}
});
} */
SearchScope useScope = p.getScope();
final GlobalSearchScope scope = useScope instanceof GlobalSearchScope ? (GlobalSearchScope) useScope : new EverythingGlobalScope(p
.getProject());
final String searchKey = MsilHelper.cutGenericMarker(StringUtil.getShortName(vmQName));
if(StringUtil.isEmpty(searchKey))
{
return true;
}
Collection<DotNetTypeList> candidates = ApplicationManager.getApplication().runReadAction(new Computable<Collection<DotNetTypeList>>()
{
@Override
public Collection<DotNetTypeList> compute()
{
return ExtendsListIndex.getInstance().get(searchKey, p.getProject(), scope);
}
});
Map<String, List<DotNetTypeDeclaration>> classes = new HashMap<String, List<DotNetTypeDeclaration>>();
for(DotNetTypeList referenceList : candidates)
{
ProgressIndicatorProvider.checkCanceled();
final DotNetTypeDeclaration candidate = (DotNetTypeDeclaration) referenceList.getParent();
if(!checkInheritance(p, vmQName, candidate))
{
continue;
}
String fqn = ApplicationManager.getApplication().runReadAction(new Computable<String>()
{
@Override
public String compute()
{
return candidate.getPresentableQName();
}
});
List<DotNetTypeDeclaration> list = classes.get(fqn);
if(list == null)
{
list = new ArrayList<DotNetTypeDeclaration>();
classes.put(fqn, list);
}
list.add(candidate);
}
for(List<DotNetTypeDeclaration> sameNamedClasses : classes.values())
{
for(DotNetTypeDeclaration sameNamedClass : sameNamedClasses)
{
if(!consumer.process(sameNamedClass))
{
return false;
}
}
}
return true;
}
private static boolean checkInheritance(final DirectTypeInheritorsSearch.SearchParameters p,
final String vmQName,
final DotNetTypeDeclaration candidate)
{
return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>()
{
@Override
public Boolean compute()
{
return !p.isCheckInheritance() || candidate.isInheritor(vmQName, false);
}
});
}
}