Skip to content

Commit

Permalink
provide incomplete completion for "form_theme"
Browse files Browse the repository at this point in the history
  • Loading branch information
Haehnchen committed Jun 24, 2023
1 parent ff56aa2 commit 4b6bb16
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,13 @@ public void addCompletions(@NotNull CompletionParameters parameters, ProcessingC
TwigPattern.getCompletablePattern(),
new IncompleteFormPrintBlockCompletionProvider()
);

// {{ form_theme => "form_theme form 'TEMPLATE'"
extend(
CompletionType.BASIC,
PlatformPatterns.psiElement(TwigTokenTypes.TAG_NAME),
new IncompleteFormThemeTemplateCompletionProvider()
);
}

private boolean isCompletionStartingMatch(@NotNull String fullText, @NotNull CompletionParameters completionParameters, int minLength) {
Expand Down Expand Up @@ -1072,6 +1079,66 @@ public boolean accepts(@NotNull String s, ProcessingContext processingContext) {
}
}

private class IncompleteFormThemeTemplateCompletionProvider extends CompletionProvider<CompletionParameters> {
@Override
protected void addCompletions(@NotNull CompletionParameters completionParameters, @NotNull ProcessingContext processingContext, @NotNull CompletionResultSet resultSet) {
PsiElement originalPosition = completionParameters.getOriginalPosition();
if (originalPosition == null) {
return;
}

if(!Symfony2ProjectComponent.isEnabled(originalPosition)) {
return;
}

resultSet.restartCompletionOnPrefixChange(StandardPatterns.string().longerThan(1).with(new PatternCondition<>("include startsWith") {
@Override
public boolean accepts(@NotNull String s, ProcessingContext processingContext) {
return "form_theme".startsWith(s);
}
}));

if (!isCompletionStartingMatch("form_theme", completionParameters, 3)) {
return;
}

List<String> orderedList = null;

Project project = completionParameters.getPosition().getProject();
for (Map.Entry<String, PsiVariable> entry : TwigTypeResolveUtil.collectScopeVariables(originalPosition).entrySet()) {
PhpType phpType = PhpIndex.getInstance(project).completeType(project, PhpType.from(entry.getValue().getTypes().toArray(new String[0])), new HashSet<>());
if (!FormFieldResolver.isFormView(phpType)) {
continue;
}

PsiElement element = entry.getValue().getElement();
if (element == null) {
continue;
}

String typeText = null;
Collection<PhpClass> formTypeFromFormFactory = FormFieldResolver.getFormTypeFromFormFactory(element);
if (formTypeFromFormFactory.size() > 0) {
typeText = StringUtils.stripStart(formTypeFromFormFactory.iterator().next().getFQN(), "\\");
}

if (orderedList == null) {
orderedList = TwigUtil.getFormThemeTemplateUsageAsOrderedList(completionParameters.getPosition().getProject());
}

CompletionSorter completionSorter = CompletionService.getCompletionService()
.defaultSorter(completionParameters, resultSet.getPrefixMatcher())
.weighBefore("priority", new ServiceCompletionProvider.MyLookupElementWeigher(orderedList));

resultSet = resultSet.withRelevanceSorter(completionSorter);

for (String s : orderedList) {
resultSet.addElement(LookupElementBuilder.create(String.format("form_theme %s '%s'", entry.getKey(), s)).withTypeText(typeText).withIcon(TwigIcons.TwigFileIcon));
}
}
}
}

/**
* {% for => "for flash in app.flashes"
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ public enum NamespaceType {
private static final Key<CachedValue<List<String>>> SYMFONY_TEMPLATE_EMBED_LIST = new Key<>("SYMFONY_TEMPLATE_EMBED_LIST");
private static final Key<CachedValue<List<String>>> SYMFONY_TEMPLATE_EXTENDS_LIST = new Key<>("SYMFONY_TEMPLATE_EXTENDS_LIST");

private static final Key<CachedValue<List<String>>> SYMFONY_TEMPLATE_FORM_THEME_LIST = new Key<>("SYMFONY_TEMPLATE_FORM_THEME_LIST");

private static final Key<CachedValue<Set<String>>> SYMFONY_NAMED_TOKEN_TAGS = new Key<>("SYMFONY_NAMED_TOKEN_TAGS");
private static final Key<CachedValue<Map<String, String>>> SYMFONY_DEPRECATED_NAMED_TOKEN_TAGS = new Key<>("SYMFONY_DEPRECATED_NAMED_TOKEN_TAGS");

Expand Down Expand Up @@ -2898,6 +2900,55 @@ public static List<String> getIncludeTemplateUsageAsOrderedList(@NotNull Project
}, false);
}

public static List<String> getFormThemeTemplateUsageAsOrderedList(@NotNull Project project) {
return CachedValuesManager.getManager(project).getCachedValue(project, SYMFONY_TEMPLATE_FORM_THEME_LIST, () -> {
Set<String> allKeys = FileBasedIndex.getInstance().getAllKeys(TwigIncludeStubIndex.KEY, project)
.stream()
.filter(s -> !s.toLowerCase().contains("@webprofiler") && !s.toLowerCase().contains("/profiler/") && !s.toLowerCase().contains("@twig"))
.collect(Collectors.toSet());

Map<String, Integer> usage = new HashMap<>();

// try to find core
for (Map.Entry<String, Set<VirtualFile>> entry : getTemplateMap(project, true).entrySet()) {
for (VirtualFile virtualFile : entry.getValue()) {
String path = virtualFile.getPath().replace("\\", "/");
if (path.contains("/twig-bridge/Resources/views/")) {
int j = path.lastIndexOf("/");
if (j > 0) {
int i = path.lastIndexOf("/", j - 1);
if (i > 0) {
String output = path.substring(i + 1);
if (output.startsWith("Form/")) {
usage.putIfAbsent(entry.getKey(), 0);
}
}
}
}
}
}

for (String allKey : allKeys) {
List<fr.adrienbrault.idea.symfony2plugin.stubs.dict.TemplateInclude> values = FileBasedIndex.getInstance().getValues(TwigIncludeStubIndex.KEY, allKey, GlobalSearchScope.allScope(project));
for (fr.adrienbrault.idea.symfony2plugin.stubs.dict.TemplateInclude value : values) {
if (value.getType() == TemplateInclude.TYPE.FORM_THEME) {
usage.putIfAbsent(allKey, 0);
usage.put(allKey, usage.get(allKey) + 1);
}
}
}

List<String> collect = usage.entrySet()
.stream()
.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
.map(Map.Entry::getKey)
.limit(10)
.collect(Collectors.toList());

return CachedValueProvider.Result.create(collect, FileIndexCaches.getModificationTrackerForIndexId(project, TwigIncludeStubIndex.KEY));
}, false);
}

public static List<String> getEmbedTemplateUsageAsOrderedList(@NotNull Project project) {
return CachedValuesManager.getManager(project).getCachedValue(project, SYMFONY_TEMPLATE_EMBED_LIST, () -> {
Set<String> allKeys = FileBasedIndex.getInstance().getAllKeys(TwigIncludeStubIndex.KEY, project)
Expand Down

0 comments on commit 4b6bb16

Please sign in to comment.