/*
* 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.unity3d.csharp.codeInsight;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.swing.Icon;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import com.intellij.codeHighlighting.Pass;
import com.intellij.codeInsight.daemon.LineMarkerInfo;
import com.intellij.codeInsight.daemon.LineMarkerProviderDescriptor;
import com.intellij.codeInsight.daemon.impl.PsiElementListNavigator;
import com.intellij.ide.util.DefaultPsiElementCellRenderer;
import com.intellij.openapi.editor.markup.GutterIconRenderer;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.NavigatablePsiElement;
import com.intellij.psi.PsiElement;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.util.CommonProcessors;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.indexing.FileBasedIndex;
import consulo.annotations.RequiredReadAction;
import consulo.csharp.ide.lineMarkerProvider.CSharpLineMarkerUtil;
import consulo.csharp.lang.psi.CSharpTypeDeclaration;
import consulo.unity3d.Unity3dIcons;
import consulo.unity3d.editor.UnitySceneFile;
import consulo.unity3d.scene.Unity3dAssetUtil;
import consulo.unity3d.scene.index.Unity3dYMLAssetIndexExtension;
/**
* @author VISTALL
* @since 02-May-17
*/
public class UnitySceneCSharpTypeLineMarkerProvider extends LineMarkerProviderDescriptor
{
@Nullable
@Override
public String getName()
{
return "Unity C# Scene Component";
}
@NotNull
public Icon getIcon()
{
return Unity3dIcons.Unity3dLineMarker;
}
@RequiredReadAction
@Nullable
@Override
public LineMarkerInfo getLineMarkerInfo(@NotNull PsiElement element)
{
CSharpTypeDeclaration typeDeclaration = CSharpLineMarkerUtil.getNameIdentifierAs(element, CSharpTypeDeclaration.class);
if(typeDeclaration != null)
{
String uuid = Unity3dAssetUtil.getUUID(PsiUtilCore.getVirtualFile(typeDeclaration));
if(uuid == null || typeDeclaration.isNested())
{
return null;
}
GlobalSearchScope filter = GlobalSearchScope.projectScope(typeDeclaration.getProject());
CommonProcessors.FindFirstProcessor<VirtualFile> processor = new CommonProcessors.FindFirstProcessor<>();
FileBasedIndex.getInstance().processFilesContainingAllKeys(Unity3dYMLAssetIndexExtension.KEY, Collections.singleton(uuid), filter, null, processor);
if(processor.isFound())
{
return new LineMarkerInfo<>(element, element.getTextRange(), Unity3dIcons.Unity3dLineMarker, Pass.LINE_MARKERS, element12 ->
{
final CSharpTypeDeclaration typeDeclaration12 = CSharpLineMarkerUtil.getNameIdentifierAs(element12, CSharpTypeDeclaration.class);
if(typeDeclaration12 != null)
{
String uuid12 = Unity3dAssetUtil.getUUID(PsiUtilCore.getVirtualFile(typeDeclaration12));
if(uuid12 == null)
{
return "";
}
Collection<VirtualFile> containingFiles = FileBasedIndex.getInstance().getContainingFiles(Unity3dYMLAssetIndexExtension.KEY, uuid12, GlobalSearchScope.projectScope
(typeDeclaration12.getProject()));
MultiMap<String, String> map = MultiMap.create();
for(VirtualFile file : containingFiles)
{
map.putValue(file.getExtension(), VfsUtil.getRelativePath(file, typeDeclaration12.getProject().getBaseDir()));
}
StringBuilder builder = new StringBuilder();
boolean first = true;
for(Map.Entry<String, Collection<String>> entry : map.entrySet())
{
String text = "";
if(!first)
{
text = "<br>";
}
else
{
first = false;
}
text += "<b>Imported in *." + entry.getKey() + ":</b><br>";
List<String> items = new ArrayList<>(entry.getValue());
ContainerUtil.sort(items);
List<String> firstItems = ContainerUtil.getFirstItems(items, 10);
if(firstItems.size() != items.size())
{
firstItems.add("<b>... " + (items.size() - firstItems.size()) + " others.</b>");
}
text += StringUtil.join(firstItems, s -> " > " + s, "<br>");
builder.append(text);
}
return builder.toString();
}
return "";
}, (e, elt) ->
{
CSharpTypeDeclaration typeDeclaration1 = CSharpLineMarkerUtil.getNameIdentifierAs(elt, CSharpTypeDeclaration.class);
if(typeDeclaration1 != null)
{
String uuid1 = Unity3dAssetUtil.getUUID(PsiUtilCore.getVirtualFile(typeDeclaration1));
if(uuid1 == null)
{
return;
}
Collection<VirtualFile> temp = FileBasedIndex.getInstance().getContainingFiles(Unity3dYMLAssetIndexExtension.KEY, uuid1, GlobalSearchScope.projectScope(typeDeclaration1
.getProject()));
VirtualFile[] assetFiles = temp.toArray(new VirtualFile[temp.size()]);
assetFiles = Unity3dAssetUtil.sortAssetFiles(assetFiles);
List<UnitySceneFile> map = ContainerUtil.map(assetFiles, virtualFile -> new UnitySceneFile(element.getProject(), virtualFile));
PsiElementListNavigator.openTargets(e, map.toArray(new NavigatablePsiElement[0]), "View Unity assets", "View Unity " + "assets", new DefaultPsiElementCellRenderer()
{
@Override
protected Icon getIcon(PsiElement element1)
{
return ((NavigatablePsiElement) element1).getPresentation().getIcon(false);
}
});
}
}, GutterIconRenderer.Alignment.LEFT);
}
}
return null;
}
}