Skip to content

add Twig "include" and "extends" lookup element weight sorting #1783

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,11 @@ public List<String> getTopStrings() {
}
}

private static class MyLookupElementWeigher extends LookupElementWeigher {
public static class MyLookupElementWeigher extends LookupElementWeigher {
@NotNull
private final List<String> elements;

MyLookupElementWeigher(@NotNull List<String> elements) {
public MyLookupElementWeigher(@NotNull List<String> elements) {
super("topElement");
this.elements = elements;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ public class TemplateLookupElement extends LookupElement {
@NotNull
private final String templateName;

private boolean bold = false;

@Nullable
private InsertHandler<LookupElement> insertHandler = null;

Expand All @@ -32,6 +34,11 @@ public TemplateLookupElement(@NotNull String templateName, @NotNull VirtualFile
this.projectBaseDir = projectBaseDir;
}

public TemplateLookupElement(@NotNull String templateName, @NotNull VirtualFile virtualFile, @NotNull VirtualFile projectBaseDir, boolean bold) {
this(templateName, virtualFile, projectBaseDir);
this.bold = bold;
}

@NotNull
@Override
public String getLookupString() {
Expand All @@ -49,5 +56,6 @@ public void renderElement(LookupElementPresentation presentation) {
presentation.setIcon(this.virtualFile.getFileType().getIcon());
presentation.setTypeText(VfsUtil.getRelativePath(this.virtualFile, this.projectBaseDir, '/'));
presentation.setTypeGrayed(true);
presentation.setItemTextBold(bold);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import fr.adrienbrault.idea.symfony2plugin.Symfony2ProjectComponent;
import fr.adrienbrault.idea.symfony2plugin.asset.AssetDirectoryReader;
import fr.adrienbrault.idea.symfony2plugin.asset.provider.AssetCompletionProvider;
import fr.adrienbrault.idea.symfony2plugin.dic.ServiceCompletionProvider;
import fr.adrienbrault.idea.symfony2plugin.routing.RouteHelper;
import fr.adrienbrault.idea.symfony2plugin.templating.completion.QuotedInsertionLookupElement;
import fr.adrienbrault.idea.symfony2plugin.templating.dict.TwigExtension;
Expand Down Expand Up @@ -71,7 +72,7 @@ public TwigTemplateCompletionContributor() {
TwigPattern.getPrintBlockOrTagFunctionPattern("include", "source"),
TwigPattern.getIncludeTagArrayPattern(),
TwigPattern.getTagTernaryPattern(TwigElementTypes.INCLUDE_TAG)
), new TemplateCompletionProvider());
), new TemplateCompletionProvider());

// provides support for 'a<xxx>'|trans({'%foo%' : bar|default}, 'Domain')
// provides support for 'a<xxx>'|transchoice(2, {'%foo%' : bar|default}, 'Domain')
Expand Down Expand Up @@ -503,7 +504,7 @@ protected void addCompletions(@NotNull CompletionParameters parameters, Processi
return;
}

resultSet.addAllElements(TwigUtil.getTwigLookupElements(parameters.getPosition().getProject()));
resultSet.addAllElements(TwigUtil.getTwigLookupElements(parameters.getPosition().getProject(), Collections.emptyList()));
}
}

Expand Down Expand Up @@ -573,16 +574,33 @@ protected void addCompletions(@NotNull CompletionParameters parameters, Processi

}

private class TemplateCompletionProvider extends CompletionProvider<CompletionParameters> {
private static class TemplateCompletionProvider extends CompletionProvider<CompletionParameters> {
public void addCompletions(@NotNull CompletionParameters parameters,
ProcessingContext context,
@NotNull CompletionResultSet resultSet) {
@NotNull ProcessingContext context,
@NotNull CompletionResultSet resultSet) {

if(!Symfony2ProjectComponent.isEnabled(parameters.getPosition())) {
return;
}

resultSet.addAllElements(TwigUtil.getTwigLookupElements(parameters.getPosition().getProject()));
List<String> prioritizedKeys = new ArrayList<>();
Project project = parameters.getPosition().getProject();

if (TwigPattern.getTemplateFileReferenceTagPattern("extends").accepts(parameters.getPosition())) {
prioritizedKeys.addAll(TwigUtil.getExtendsTemplateUsageAsOrderedList(project, 50));
} else if(TwigPattern.getTemplateFileReferenceTagPattern("include").accepts(parameters.getPosition())) {
prioritizedKeys.addAll(TwigUtil.getIncludeTemplateUsageAsOrderedList(project, 50));
}

if (prioritizedKeys.size() > 0) {
CompletionSorter completionSorter = CompletionService.getCompletionService()
.defaultSorter(parameters, resultSet.getPrefixMatcher())
.weighBefore("priority", new ServiceCompletionProvider.MyLookupElementWeigher(prioritizedKeys));

resultSet = resultSet.withRelevanceSorter(completionSorter);
}

resultSet.addAllElements(TwigUtil.getTwigLookupElements(project, new HashSet<>(prioritizedKeys)));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,17 @@
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.source.html.HtmlFileImpl;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.ThrowableRunnable;
import com.intellij.util.indexing.FileBasedIndex;
import com.jetbrains.php.completion.insert.PhpInsertHandlerUtil;
import com.jetbrains.twig.TwigFile;
import fr.adrienbrault.idea.symfony2plugin.Symfony2ProjectComponent;
import fr.adrienbrault.idea.symfony2plugin.stubs.indexes.TwigExtendsStubIndex;
import fr.adrienbrault.idea.symfony2plugin.templating.util.TwigUtil;
import org.jetbrains.annotations.NotNull;

import java.util.*;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -53,23 +49,7 @@ public void invoke(@NotNull Project project, @NotNull Editor editor, @NotNull Ps
return;
}

Set<String> allKeys = FileBasedIndex.getInstance().getAllKeys(TwigExtendsStubIndex.KEY, project)
.stream()
.filter(s -> !s.toLowerCase().contains("@webprofiler") && !s.toLowerCase().contains("/profiler/") && !s.toLowerCase().contains("@twig") && !s.equalsIgnoreCase("form_div_layout.html.twig"))
.collect(Collectors.toSet());

Map<String, Integer> extendsWithFileCountUsage = new HashMap<>();
for (String allKey : allKeys) {
Collection<VirtualFile> containingFiles = FileBasedIndex.getInstance().getContainingFiles(TwigExtendsStubIndex.KEY, allKey, GlobalSearchScope.allScope(project));
extendsWithFileCountUsage.put(allKey, containingFiles.size());
}

List<String> prioritizedKeys = extendsWithFileCountUsage.entrySet()
.stream()
.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
.map(Map.Entry::getKey)
.limit(40)
.collect(Collectors.toList());
List<String> prioritizedKeys = TwigUtil.getExtendsTemplateUsageAsOrderedList(project, 40);

if (prioritizedKeys.size() == 0) {
if (!ApplicationManager.getApplication().isHeadlessEnvironment()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,7 @@
import fr.adrienbrault.idea.symfony2plugin.extension.TwigNamespaceExtensionParameter;
import fr.adrienbrault.idea.symfony2plugin.stubs.SymfonyProcessors;
import fr.adrienbrault.idea.symfony2plugin.stubs.dict.TemplateUsage;
import fr.adrienbrault.idea.symfony2plugin.stubs.indexes.PhpTwigTemplateUsageStubIndex;
import fr.adrienbrault.idea.symfony2plugin.stubs.indexes.TwigBlockIndexExtension;
import fr.adrienbrault.idea.symfony2plugin.stubs.indexes.TwigExtendsStubIndex;
import fr.adrienbrault.idea.symfony2plugin.stubs.indexes.TwigMacroFunctionStubIndex;
import fr.adrienbrault.idea.symfony2plugin.stubs.indexes.*;
import fr.adrienbrault.idea.symfony2plugin.templating.TemplateLookupElement;
import fr.adrienbrault.idea.symfony2plugin.templating.TwigPattern;
import fr.adrienbrault.idea.symfony2plugin.templating.dict.*;
Expand Down Expand Up @@ -1527,17 +1524,20 @@ public static Collection<PsiElement> getTwigMacroTargets(final Project project,

/**
* Lookup elements for Twig files
* @return
*/
@NotNull
public static Collection<LookupElement> getTwigLookupElements(@NotNull Project project) {
public static Collection<LookupElement> getTwigLookupElements(@NotNull Project project, @NotNull Collection<String> highlight) {
VirtualFile baseDir = ProjectUtil.getProjectDir(project);

return getTemplateMap(project).entrySet()
.stream()
.filter(entry -> entry.getValue().size() > 0)
.map((java.util.function.Function<Map.Entry<String, Set<VirtualFile>>, LookupElement>) entry ->
new TemplateLookupElement(entry.getKey(), entry.getValue().iterator().next(), baseDir)
)
.map((java.util.function.Function<Map.Entry<String, Set<VirtualFile>>, LookupElement>) entry -> new TemplateLookupElement(
entry.getKey(),
entry.getValue().iterator().next(),
baseDir,
highlight.contains(entry.getKey())
))
.collect(Collectors.toList());
}

Expand Down Expand Up @@ -2787,6 +2787,46 @@ public void visitElement(PsiElement element) {
});
}

public static List<String> getIncludeTemplateUsageAsOrderedList(@NotNull Project project, int limit) {
Set<String> allKeys = FileBasedIndex.getInstance().getAllKeys(TwigIncludeStubIndex.KEY, project)
.stream()
.filter(s -> !s.toLowerCase().contains("@webprofiler") && !s.toLowerCase().contains("/profiler/") && !s.toLowerCase().contains("@twig") && !s.equalsIgnoreCase("form_div_layout.html.twig"))
.collect(Collectors.toSet());

Map<String, Integer> extendsWithFileCountUsage = new HashMap<>();
for (String allKey : allKeys) {
Collection<VirtualFile> containingFiles = FileBasedIndex.getInstance().getContainingFiles(TwigIncludeStubIndex.KEY, allKey, GlobalSearchScope.allScope(project));
extendsWithFileCountUsage.put(allKey, containingFiles.size());
}

return extendsWithFileCountUsage.entrySet()
.stream()
.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
.map(Map.Entry::getKey)
.limit(limit)
.collect(Collectors.toList());
}

public static List<String> getExtendsTemplateUsageAsOrderedList(@NotNull Project project, int limit) {
Set<String> allKeys = FileBasedIndex.getInstance().getAllKeys(TwigExtendsStubIndex.KEY, project)
.stream()
.filter(s -> !s.toLowerCase().contains("@webprofiler") && !s.toLowerCase().contains("/profiler/") && !s.toLowerCase().contains("@twig") && !s.equalsIgnoreCase("form_div_layout.html.twig"))
.collect(Collectors.toSet());

Map<String, Integer> extendsWithFileCountUsage = new HashMap<>();
for (String allKey : allKeys) {
Collection<VirtualFile> containingFiles = FileBasedIndex.getInstance().getContainingFiles(TwigExtendsStubIndex.KEY, allKey, GlobalSearchScope.allScope(project));
extendsWithFileCountUsage.put(allKey, containingFiles.size());
}

return extendsWithFileCountUsage.entrySet()
.stream()
.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
.map(Map.Entry::getKey)
.limit(limit)
.collect(Collectors.toList());
}

/**
* Visit each "controller()" with its normalized parameter
*/
Expand Down