package fr.adrienbrault.idea.symfony2plugin.config; import com.intellij.codeInsight.daemon.LineMarkerInfo; import com.intellij.codeInsight.daemon.LineMarkerProvider; import com.intellij.codeInsight.navigation.NavigationGutterIconBuilder; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.NotNullLazyValue; import com.intellij.psi.PsiElement; import fr.adrienbrault.idea.symfony2plugin.Symfony2Icons; import fr.adrienbrault.idea.symfony2plugin.Symfony2ProjectComponent; import fr.adrienbrault.idea.symfony2plugin.config.utils.ConfigUtil; import fr.adrienbrault.idea.symfony2plugin.config.yaml.YamlElementPatternHelper; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.yaml.YAMLTokenTypes; import org.jetbrains.yaml.psi.YAMLKeyValue; import java.util.Collection; import java.util.List; import java.util.Map; /** * @author Daniel Espendiller <daniel@espendiller.net> */ public class ConfigLineMarkerProvider implements LineMarkerProvider { @Nullable @Override public LineMarkerInfo getLineMarkerInfo(@NotNull PsiElement psiElement) { return null; } @Override public void collectSlowLineMarkers(@NotNull List<PsiElement> psiElements, @NotNull Collection<LineMarkerInfo> result) { if(psiElements.size() == 0 || !Symfony2ProjectComponent.isEnabled(psiElements.get(0))) { return; } LazyConfigTreeSignatures function = null; for (PsiElement psiElement : psiElements) { if(psiElement.getNode().getElementType() == YAMLTokenTypes.SCALAR_KEY && YamlElementPatternHelper.getRootConfigKeyPattern().accepts(psiElement)) { if(function == null) { function = new LazyConfigTreeSignatures(psiElements.get(0).getProject()); } visitRootElements(result, psiElement, function); } } } private void visitRootElements(@NotNull Collection<LineMarkerInfo> result, @NotNull PsiElement psiElement, @NotNull LazyConfigTreeSignatures function) { PsiElement parent = psiElement.getParent(); if(!(parent instanceof YAMLKeyValue)) { return; } String keyText = ((YAMLKeyValue) parent).getKeyText(); Map<String, Collection<String>> treeSignatures = function.value(); if(!treeSignatures.containsKey(keyText)) { return; } NavigationGutterIconBuilder<PsiElement> builder = NavigationGutterIconBuilder.create(Symfony2Icons.SYMFONY_LINE_MARKER) .setTargets(new MyClassIdLazyValue(psiElement.getProject(), treeSignatures.get(keyText), keyText)) .setTooltipText("Navigate to configuration"); result.add(builder.createLineMarkerInfo(psiElement)); } private static class MyClassIdLazyValue extends NotNullLazyValue<Collection<? extends PsiElement>> { @NotNull private final Project project; @NotNull private final Collection<String> configuration; @NotNull private final String root; MyClassIdLazyValue(@NotNull Project project, @NotNull Collection<String> configuration, @NotNull String root) { this.project = project; this.configuration = configuration; this.root = root; } @NotNull @Override protected Collection<? extends PsiElement> compute() { return ConfigUtil.getTreeSignatureTargets(project, root, configuration); } } private static class LazyConfigTreeSignatures { @NotNull private final Project project; private Map<String, Collection<String>> treeSignatures; LazyConfigTreeSignatures(@NotNull Project project) { this.project = project; } @NotNull public Map<String, Collection<String>> value() { if(this.treeSignatures == null) { return this.treeSignatures = ConfigUtil.getTreeSignatures(project); } return this.treeSignatures; } } }