Skip to content

Commit 1348519

Browse files
committed
support iterator in twig loop completion #1097 #1035
1 parent b6d3c01 commit 1348519

File tree

2 files changed

+84
-2
lines changed

2 files changed

+84
-2
lines changed

src/fr/adrienbrault/idea/symfony2plugin/templating/util/TwigTypeResolveUtil.java

+36-1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import java.util.*;
3838
import java.util.regex.Matcher;
3939
import java.util.regex.Pattern;
40+
import java.util.stream.Collectors;
4041

4142
/**
4243
* @author Daniel Espendiller <daniel@espendiller.net>
@@ -258,8 +259,42 @@ public static Map<String, PsiVariable> collectScopeVariables(@NotNull PsiElement
258259
globalVars.putAll(convertHashMapToTypeSet(findInlineStatementVariableDocBlock(psiElement, TwigElementTypes.MACRO_STATEMENT)));
259260
globalVars.putAll(convertHashMapToTypeSet(findInlineStatementVariableDocBlock(psiElement, TwigElementTypes.FOR_STATEMENT)));
260261

262+
// @TODO find core stuff for resolve possible class return values
263+
// getIterator / __iterator
264+
// Foobar[]
261265
for(Map.Entry<String, Set<String>> entry: globalVars.entrySet()) {
262-
controllerVars.put(entry.getKey(), new PsiVariable(entry.getValue(), null));
266+
Set<String> types = entry.getValue();
267+
268+
Set<String> arrayValues = new HashSet<>();
269+
270+
for (String s : types) {
271+
PhpClass phpClass = PhpElementsUtil.getClassInterface(psiElement.getProject(), s);
272+
if(phpClass != null) {
273+
for (String methodName : new String[]{"getIterator", "__iterator"}) {
274+
Method method = phpClass.findMethodByName(methodName);
275+
if(method != null) {
276+
// @method Foo __iterator
277+
// @method Foo[] __iterator
278+
Set<String> typesIterator = method.getType().getTypes();
279+
if("__iterator".equals(methodName)) {
280+
arrayValues.addAll(typesIterator.stream().map(x ->
281+
!x.endsWith("[]") ? x + "[]" : x
282+
).collect(Collectors.toSet()));
283+
} else {
284+
// Foobar[]
285+
for (String type : typesIterator) {
286+
if(type.endsWith("[]")) {
287+
arrayValues.add(type);
288+
}
289+
}
290+
}
291+
}
292+
}
293+
}
294+
}
295+
296+
types.addAll(arrayValues);
297+
controllerVars.put(entry.getKey(), new PsiVariable(types, null));
263298
}
264299

265300
// check if we are in "for" scope and resolve types ending with []

tests/fr/adrienbrault/idea/symfony2plugin/tests/templating/variable/collector/FileDocVariableCollectorTest.java

+48-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package fr.adrienbrault.idea.symfony2plugin.tests.templating.variable.collector;
22

3+
import com.jetbrains.php.lang.PhpFileType;
34
import com.jetbrains.twig.TwigFileType;
45
import fr.adrienbrault.idea.symfony2plugin.tests.SymfonyLightCodeInsightFixtureTestCase;
56

@@ -25,9 +26,10 @@ public void setUp() throws Exception {
2526
" private function privateBar() {}\n" +
2627
" /** @return FooClass[] */\n" +
2728
" public function getNested() {}\n" +
29+
" /** @return FooClass[] */\n" +
30+
" public function getIterator() {}\n" +
2831
"}"
2932
);
30-
3133
}
3234

3335
public void testFileBasedVarDocPhpTypes() {
@@ -91,7 +93,52 @@ public void testVarArrayIteration() {
9193
"{% endfor %}\n"
9294
, "fooBar"
9395
);
96+
}
97+
98+
public void testVarArrayIterationViaIterationClassImplementations() {
99+
myFixture.configureByText("class1.php", "<?php\n" +
100+
"namespace Bar;\n" +
101+
"/**\n" +
102+
" * @method FooClassIteratorArray[] __iterator\n" +
103+
" */\n" +
104+
"class FooClassIteratorArray {\n" +
105+
" public function getFooBar() {}\n" +
106+
"}"
107+
);
94108

109+
myFixture.configureByText("class2.php", "<?php\n" +
110+
"namespace Bar;\n" +
111+
"/**\n" +
112+
" * @method FooClassIterator __iterator\n" +
113+
" */\n" +
114+
"class FooClassIterator {\n" +
115+
" public function getFooBar() {}\n" +
116+
"}"
117+
);
118+
119+
assertCompletionContains(TwigFileType.INSTANCE, "" +
120+
"{# @var bars \\Bar\\FooClass #}\n" +
121+
"{% for bar in bars %}\n" +
122+
" {{ bar.<caret> }}\n" +
123+
"{% endfor %}\n"
124+
, "fooBar"
125+
);
126+
127+
assertCompletionContains(TwigFileType.INSTANCE, "" +
128+
"{# @var bars \\Bar\\FooClassIteratorArray #}\n" +
129+
"{% for bar in bars %}\n" +
130+
" {{ bar.<caret> }}\n" +
131+
"{% endfor %}\n"
132+
, "fooBar"
133+
);
134+
135+
assertCompletionContains(TwigFileType.INSTANCE, "" +
136+
"{# @var bars \\Bar\\FooClassIterator #}\n" +
137+
"{% for bar in bars %}\n" +
138+
" {{ bar.<caret> }}\n" +
139+
"{% endfor %}\n"
140+
, "fooBar"
141+
);
95142
}
96143

97144
/**

0 commit comments

Comments
 (0)