Skip to content

Commit df846be

Browse files
committed
add testing for doctrine types in yaml and provide navigation #555
1 parent 84386fd commit df846be

File tree

5 files changed

+169
-14
lines changed

5 files changed

+169
-14
lines changed

src/fr/adrienbrault/idea/symfony2plugin/config/doctrine/DoctrineStaticTypeLookupBuilder.java

+49-7
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@
33
import com.intellij.codeInsight.lookup.LookupElement;
44
import com.intellij.codeInsight.lookup.LookupElementBuilder;
55
import com.intellij.openapi.project.Project;
6+
import com.intellij.psi.PsiElement;
67
import com.jetbrains.php.PhpIndex;
78
import com.jetbrains.php.lang.psi.elements.PhpClass;
89
import fr.adrienbrault.idea.symfony2plugin.Symfony2Icons;
910
import fr.adrienbrault.idea.symfony2plugin.util.PhpElementsUtil;
1011
import fr.adrienbrault.idea.symfony2plugin.util.completion.annotations.AnnotationMethodInsertHandler;
1112
import fr.adrienbrault.idea.symfony2plugin.util.completion.annotations.AnnotationTagInsertHandler;
1213
import org.jetbrains.annotations.NotNull;
14+
import org.jetbrains.annotations.Nullable;
1315

1416
import java.util.*;
1517

@@ -22,22 +24,62 @@ public class DoctrineStaticTypeLookupBuilder {
2224

2325
public static Collection<LookupElement> getTypes(@NotNull Project project) {
2426

25-
Map<String, LookupElement> lookupElements = new HashMap<String, LookupElement>();
27+
final Collection<LookupElement> lookupElements = new ArrayList<LookupElement>();
28+
29+
visitCustomTypes(project, new ColumnTypeVisitor() {
30+
@Override
31+
public void visit(@NotNull String name, @Nullable PhpClass phpClass, @Nullable PsiElement psiElement) {
32+
LookupElementBuilder lookupElementBuilder = LookupElementBuilder.create(name).withIcon(Symfony2Icons.DOCTRINE);
33+
34+
if(phpClass != null) {
35+
lookupElementBuilder = lookupElementBuilder.withTypeText(phpClass.getName(), true);
36+
}
37+
38+
lookupElements.add(lookupElementBuilder);
39+
}
40+
});
41+
42+
return lookupElements;
43+
}
44+
45+
public static void visitCustomTypes(@NotNull Project project, @NotNull ColumnTypeVisitor visitor) {
46+
47+
Set<String> found = new HashSet<String>();
2648

2749
for (PhpClass phpClass : PhpIndex.getInstance(project).getAllSubclasses("\\Doctrine\\DBAL\\Types\\Type")) {
28-
String getName = PhpElementsUtil.getMethodReturnAsString(phpClass, "getName");
29-
if(getName != null) {
30-
lookupElements.put(getName, LookupElementBuilder.create(getName).withIcon(Symfony2Icons.DOCTRINE).withTypeText(phpClass.getName(), true));
50+
String name = PhpElementsUtil.getMethodReturnAsString(phpClass, "getName");
51+
if(name != null) {
52+
found.add(name);
53+
visitor.visit(name, phpClass, phpClass.findMethodByName("getName"));
3154
}
3255
}
3356

3457
for (String s : Arrays.asList("id", "string", "integer", "smallint", "bigint", "boolean", "decimal", "date", "time", "datetime", "text", "array", "float")) {
35-
if(!lookupElements.containsKey(s)) {
36-
lookupElements.put(s, LookupElementBuilder.create(s).withIcon(Symfony2Icons.DOCTRINE));
58+
if(!found.contains(s)) {
59+
visitor.visit(s, null, null);
3760
}
3861
}
3962

40-
return lookupElements.values();
63+
}
64+
65+
private interface ColumnTypeVisitor {
66+
void visit(@NotNull String name, @Nullable PhpClass phpClass, @Nullable PsiElement psiElement);
67+
}
68+
69+
public static Collection<PsiElement> getColumnTypesTargets(@NotNull Project project, final @NotNull String contents) {
70+
71+
final Collection<PsiElement> targets = new ArrayList<PsiElement>();
72+
73+
visitCustomTypes(project, new ColumnTypeVisitor() {
74+
@Override
75+
public void visit(@NotNull String name, @Nullable PhpClass phpClass, @Nullable PsiElement psiElement) {
76+
if(name.equals(contents) && phpClass != null) {
77+
targets.add(phpClass);
78+
}
79+
}
80+
});
81+
82+
return targets;
4183
}
4284

4385
public ArrayList<LookupElement> getNullAble() {

src/fr/adrienbrault/idea/symfony2plugin/config/yaml/YamlGoToKnownDeclarationHandler.java

+16-6
Original file line numberDiff line numberDiff line change
@@ -9,30 +9,26 @@
99
import com.intellij.psi.PsiFile;
1010
import com.intellij.psi.util.PsiTreeUtil;
1111
import com.jetbrains.php.PhpIndex;
12-
import com.jetbrains.php.completion.PhpLookupElement;
1312
import com.jetbrains.php.lang.psi.elements.Method;
1413
import com.jetbrains.php.lang.psi.elements.PhpClass;
15-
import com.jetbrains.php.lang.psi.resolve.PhpResolveResult;
1614
import fr.adrienbrault.idea.symfony2plugin.Symfony2ProjectComponent;
1715
import fr.adrienbrault.idea.symfony2plugin.config.EventDispatcherSubscriberUtil;
18-
import fr.adrienbrault.idea.symfony2plugin.dic.XmlTagParser;
16+
import fr.adrienbrault.idea.symfony2plugin.config.doctrine.DoctrineStaticTypeLookupBuilder;
1917
import fr.adrienbrault.idea.symfony2plugin.routing.RouteHelper;
2018
import fr.adrienbrault.idea.symfony2plugin.util.PhpElementsUtil;
2119
import fr.adrienbrault.idea.symfony2plugin.util.PsiElementUtils;
2220
import fr.adrienbrault.idea.symfony2plugin.util.SymfonyBundleUtil;
23-
import fr.adrienbrault.idea.symfony2plugin.util.controller.ControllerIndex;
2421
import fr.adrienbrault.idea.symfony2plugin.util.dict.ServiceUtil;
2522
import fr.adrienbrault.idea.symfony2plugin.util.dict.SymfonyBundle;
26-
import fr.adrienbrault.idea.symfony2plugin.util.service.ServiceXmlParserFactory;
2723
import fr.adrienbrault.idea.symfony2plugin.util.yaml.YamlHelper;
2824
import org.apache.commons.lang.StringUtils;
25+
import org.jetbrains.annotations.NotNull;
2926
import org.jetbrains.annotations.Nullable;
3027
import org.jetbrains.yaml.psi.YAMLCompoundValue;
3128
import org.jetbrains.yaml.psi.YAMLKeyValue;
3229

3330
import java.util.ArrayList;
3431
import java.util.Arrays;
35-
import java.util.Collections;
3632
import java.util.List;
3733

3834
/**
@@ -94,9 +90,23 @@ public PsiElement[] getGotoDeclarationTargets(PsiElement psiElement, int i, Edit
9490
this.getArrayMethodGoto(psiElement, results);
9591
}
9692

93+
if(YamlElementPatternHelper.getOrmSingleLineScalarKey("type").accepts(psiElement)) {
94+
this.getOrmTypesNavigation(psiElement, results);
95+
}
96+
9797
return results.toArray(new PsiElement[results.size()]);
9898
}
9999

100+
private void getOrmTypesNavigation(@NotNull PsiElement psiElement, @NotNull List<PsiElement> results) {
101+
102+
String text = PsiElementUtils.trimQuote(psiElement.getText());
103+
if(StringUtils.isBlank(text)) {
104+
return;
105+
}
106+
107+
results.addAll(DoctrineStaticTypeLookupBuilder.getColumnTypesTargets(psiElement.getProject(), text));
108+
}
109+
100110
private void getArrayMethodGoto(PsiElement psiElement, List<PsiElement> results) {
101111

102112
String text = PsiElementUtils.trimQuote(psiElement.getText());

tests/fr/adrienbrault/idea/symfony2plugin/tests/SymfonyLightCodeInsightFixtureTestCase.java

+10-1
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,18 @@ public void assertNavigationMatchWithParent(LanguageFileType languageFileType, S
117117
assertNavigationMatch(languageFileType, configureByText, PlatformPatterns.psiElement().withParent(PlatformPatterns.psiElement(iElementType)));
118118
}
119119

120-
public void assertNavigationMatch(LanguageFileType languageFileType, String configureByText, ElementPattern<?> pattern) {
120+
public void assertNavigationMatch(String filename, String configureByText, ElementPattern<?> pattern) {
121+
myFixture.configureByText(filename, configureByText);
122+
assertNavigationMatch(pattern);
123+
}
121124

125+
public void assertNavigationMatch(LanguageFileType languageFileType, String configureByText, ElementPattern<?> pattern) {
122126
myFixture.configureByText(languageFileType, configureByText);
127+
assertNavigationMatch(pattern);
128+
}
129+
130+
private void assertNavigationMatch(ElementPattern<?> pattern) {
131+
123132
PsiElement psiElement = myFixture.getFile().findElementAt(myFixture.getCaretOffset());
124133

125134
Set<String> targetStrings = new HashSet<String>();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package fr.adrienbrault.idea.symfony2plugin.tests.config.yaml.doctrine;
2+
3+
import com.intellij.patterns.PlatformPatterns;
4+
import com.jetbrains.php.lang.psi.elements.PhpClass;
5+
import fr.adrienbrault.idea.symfony2plugin.tests.SymfonyLightCodeInsightFixtureTestCase;
6+
7+
import java.io.File;
8+
9+
/**
10+
* @author Daniel Espendiller <daniel@espendiller.net>
11+
*/
12+
public class DoctrineOrmYamlTest extends SymfonyLightCodeInsightFixtureTestCase {
13+
14+
public void setUp() throws Exception {
15+
super.setUp();
16+
myFixture.configureFromExistingVirtualFile(myFixture.copyFileToProject("DoctrineTypes.php"));
17+
}
18+
19+
public String getTestDataPath() {
20+
return new File(this.getClass().getResource("fixtures").getFile()).getAbsolutePath();
21+
}
22+
23+
/**
24+
* @see fr.adrienbrault.idea.symfony2plugin.config.yaml.YamlCompletionContributor
25+
*/
26+
public void testDoctrineOrmFieldCompletion() {
27+
28+
assertCompletionContains("foo.orm.yml", "foo:\n" +
29+
" fields:\n" +
30+
" field_1:\n" +
31+
" type: <caret>",
32+
"BAR", "foo_const", "id"
33+
);
34+
35+
assertCompletionContains("foo.orm.yml", "foo:\n" +
36+
" id:\n" +
37+
" field_1:\n" +
38+
" type: <caret>",
39+
"BAR", "foo_const", "id"
40+
);
41+
}
42+
43+
/**
44+
* @see fr.adrienbrault.idea.symfony2plugin.config.yaml.YamlGoToKnownDeclarationHandler
45+
*/
46+
public void testDoctrineOrmFieldNavigation() {
47+
48+
assertNavigationMatch("foo.orm.yml", "foo:\n" +
49+
" fields:\n" +
50+
" field_1:\n" +
51+
" type: BA<caret>R",
52+
PlatformPatterns.psiElement(PhpClass.class)
53+
);
54+
55+
assertNavigationMatch("foo.orm.yml", "foo:\n" +
56+
" fields:\n" +
57+
" field_1:\n" +
58+
" type: foo_c<caret>onst",
59+
PlatformPatterns.psiElement(PhpClass.class)
60+
);
61+
62+
assertNavigationMatch("foo.orm.yml", "foo:\n" +
63+
" id:\n" +
64+
" field_1:\n" +
65+
" type: BA<caret>R",
66+
PlatformPatterns.psiElement(PhpClass.class)
67+
);
68+
}
69+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
namespace Doctrine\DBAL\Types {
4+
interface Type {
5+
const FOO = "foo_const";
6+
public function getName();
7+
}
8+
}
9+
10+
namespace {
11+
12+
use Doctrine\DBAL\Types\Type;
13+
14+
class Foo implements Type {
15+
public function getName() {
16+
return Doctrine\DBAL\Types\Type::FOO;
17+
}
18+
}
19+
20+
class Bar implements Type {
21+
public function getName() {
22+
return "BAR";
23+
}
24+
}
25+
}

0 commit comments

Comments
 (0)