Skip to content

Commit 901fbb5

Browse files
authored
Merge pull request #1453 from Haehnchen/feature/phpstorm-2020-1
add PhpStorm 2020.1 build gradle support
2 parents 0ea6389 + 4cb1288 commit 901fbb5

File tree

13 files changed

+120
-137
lines changed

13 files changed

+120
-137
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ before_install:
2323
- "export ORG_GRADLE_PROJECT_annotationPluginVersion=${ANNOTATION_PLUGIN_VERSION}"
2424

2525
env:
26-
- PHPSTORM_ENV="skip incomplete" IDEA_VERSION="IU-2019.2" PHP_PLUGIN_VERSION="192.5728.108" TWIG_PLUGIN_VERSION="192.5728.26" TOOLBOX_PLUGIN_VERSION="0.4.6" ANNOTATION_PLUGIN_VERSION="5.3" DQL_PLUGIN_VERSION="192.5728.12"
26+
- PHPSTORM_ENV="skip incomplete" IDEA_VERSION="IU-2020.1" PHP_PLUGIN_VERSION="201.6668.153" TWIG_PLUGIN_VERSION="201.6668.153" TOOLBOX_PLUGIN_VERSION="0.4.6" ANNOTATION_PLUGIN_VERSION="5.3" DQL_PLUGIN_VERSION="201.6668.60"
2727

2828
script:
2929
- "./gradlew check verifyPlugin buildPlugin"

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ intellij {
4545
}
4646

4747
patchPluginXml {
48-
sinceBuild '192'
48+
sinceBuild '201'
4949
changeNotes = htmlFixer('src/main/resources/META-INF/change-notes.html')
5050
}
5151

gradle.properties

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
ideaVersion = IU-2019.2
2-
phpPluginVersion = 192.5728.108
3-
twigPluginVersion = 192.5728.26
4-
dqlPluginVersion = 192.5728.12
1+
ideaVersion = IU-2020.1
2+
phpPluginVersion = 201.6668.153
3+
twigPluginVersion = 201.6668.153
4+
dqlPluginVersion = 201.6668.60
55
toolboxPluginVersion = 0.4.6
66
annotationPluginVersion = 5.3

src/main/java/fr/adrienbrault/idea/symfony2plugin/action/SymfonySymbolSearchAction.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ private Map<String, LookupElement> getModelLookupElements() {
132132
}
133133

134134
@Override
135-
public void processNames(@NotNull Processor<String> processor, @NotNull GlobalSearchScope scope, @Nullable IdFilter filter) {
135+
public void processNames(@NotNull Processor<? super String> processor, @NotNull GlobalSearchScope scope, @Nullable IdFilter filter) {
136136
for(String name: getServiceCollector().getServices().keySet()) {
137137
processor.process(name);
138138
}
@@ -174,7 +174,7 @@ public void processNames(@NotNull Processor<String> processor, @NotNull GlobalSe
174174
}
175175

176176
@Override
177-
public void processElementsWithName(@NotNull String name, @NotNull Processor<NavigationItem> processor, @NotNull FindSymbolParameters parameters) {
177+
public void processElementsWithName(@NotNull String name, @NotNull Processor<? super NavigationItem> processor, @NotNull FindSymbolParameters parameters) {
178178

179179
for(ContainerService containerService: getServiceCollector().collect()) {
180180
if(containerService.getName().equals(name)) {

src/main/java/fr/adrienbrault/idea/symfony2plugin/doctrine/ObjectRepositoryResultTypeProvider.java

Lines changed: 50 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,35 @@
22

33
import com.intellij.openapi.project.Project;
44
import com.intellij.openapi.util.text.StringUtil;
5-
import com.intellij.patterns.PlatformPatterns;
65
import com.intellij.psi.PsiElement;
76
import com.jetbrains.php.PhpIndex;
8-
import com.jetbrains.php.lang.parser.PhpElementTypes;
97
import com.jetbrains.php.lang.psi.elements.Method;
108
import com.jetbrains.php.lang.psi.elements.MethodReference;
119
import com.jetbrains.php.lang.psi.elements.PhpClass;
1210
import com.jetbrains.php.lang.psi.elements.PhpNamedElement;
1311
import com.jetbrains.php.lang.psi.resolve.types.PhpType;
14-
import com.jetbrains.php.lang.psi.resolve.types.PhpTypeProvider3;
12+
import com.jetbrains.php.lang.psi.resolve.types.PhpTypeProvider4;
1513
import fr.adrienbrault.idea.symfony2plugin.Settings;
1614
import fr.adrienbrault.idea.symfony2plugin.util.MethodMatcher;
1715
import fr.adrienbrault.idea.symfony2plugin.util.PhpElementsUtil;
1816
import fr.adrienbrault.idea.symfony2plugin.util.PhpTypeProviderUtil;
17+
import org.jetbrains.annotations.NotNull;
1918
import org.jetbrains.annotations.Nullable;
20-
2119
import java.util.Arrays;
2220
import java.util.Collection;
23-
import java.util.Collections;
21+
import java.util.HashSet;
2422
import java.util.Set;
23+
import java.util.stream.Collectors;
2524

2625
/**
26+
* Resolve "find*" and attach the entity from the getRepository method
27+
*
28+
* "$om->getRepository('\Foo\Bar')->find('foobar')->get<caret>Id()"
29+
*
2730
* @author Daniel Espendiller <[email protected]>
2831
*/
29-
public class ObjectRepositoryResultTypeProvider implements PhpTypeProvider3 {
30-
private static MethodMatcher.CallToSignature[] FIND_SIGNATURES = new MethodMatcher.CallToSignature[] {
32+
public class ObjectRepositoryResultTypeProvider implements PhpTypeProvider4 {
33+
private static final MethodMatcher.CallToSignature[] FIND_SIGNATURES = new MethodMatcher.CallToSignature[] {
3134
new MethodMatcher.CallToSignature("\\Doctrine\\Common\\Persistence\\ObjectRepository", "find"),
3235
new MethodMatcher.CallToSignature("\\Doctrine\\Common\\Persistence\\ObjectRepository", "findOneBy"),
3336
new MethodMatcher.CallToSignature("\\Doctrine\\Common\\Persistence\\ObjectRepository", "findAll"),
@@ -48,18 +51,7 @@ public char getKey() {
4851
@Nullable
4952
@Override
5053
public PhpType getType(PsiElement e) {
51-
if (!Settings.getInstance(e.getProject()).pluginEnabled) {
52-
return null;
53-
}
54-
55-
// filter out method calls without parameter
56-
// $this->get('service_name')
57-
if(!PlatformPatterns
58-
.psiElement(PhpElementTypes.METHOD_REFERENCE)
59-
.withChild(PlatformPatterns
60-
.psiElement(PhpElementTypes.PARAMETER_LIST)
61-
).accepts(e)) {
62-
54+
if (!(e instanceof MethodReference) || !Settings.getInstance(e.getProject()).pluginEnabled) {
6355
return null;
6456
}
6557

@@ -75,16 +67,6 @@ public PhpType getType(PsiElement e) {
7567
return null;
7668
}
7769

78-
// at least one parameter is necessary on some finds
79-
PsiElement[] parameters = methodRef.getParameters();
80-
if(!methodRefName.equals("findAll")) {
81-
if(parameters.length == 0) {
82-
return null;
83-
}
84-
} else if(parameters.length != 0) {
85-
return null;
86-
}
87-
8870
// we can get the repository name from the signature calls
8971
// #M#?#M#?#M#C\Foo\Bar\Controller\BarController.get?doctrine.getRepository?EntityBundle:User.find
9072
String repositorySignature = methodRef.getSignature();
@@ -105,57 +87,64 @@ public PhpType getType(PsiElement e) {
10587
return new PhpType().add("#" + this.getKey() + refSignature + TRIM_KEY + repositorySignature);
10688
}
10789

90+
@Nullable
10891
@Override
109-
public Collection<? extends PhpNamedElement> getBySignature(String expression, Set<String> visited, int depth, Project project) {
110-
// get back our original call
111-
int endIndex = expression.lastIndexOf(TRIM_KEY);
92+
public PhpType complete(String s, Project project) {
93+
int endIndex = s.lastIndexOf(TRIM_KEY);
11294
if(endIndex == -1) {
113-
return Collections.emptySet();
114-
}
115-
116-
String originalSignature = expression.substring(0, endIndex);
117-
String parameter = expression.substring(endIndex + 1);
118-
119-
// search for called method
120-
PhpIndex phpIndex = PhpIndex.getInstance(project);
121-
Collection<? extends PhpNamedElement> phpNamedElementCollections = PhpTypeProviderUtil.getTypeSignature(phpIndex, originalSignature);
122-
if(phpNamedElementCollections.size() == 0) {
123-
return Collections.emptySet();
124-
}
125-
126-
Method method = getObjectRepositoryCall(phpNamedElementCollections);
127-
if(method == null) {
128-
return Collections.emptySet();
95+
return null;
12996
}
13097

131-
// we can also pipe php references signatures and resolve them here
132-
// overwrite parameter to get string value
133-
parameter = PhpTypeProviderUtil.getResolvedParameter(phpIndex, parameter);
98+
String originalSignature = s.substring(0, endIndex);
99+
String parameter = s.substring(endIndex + 1);
100+
parameter = PhpTypeProviderUtil.getResolvedParameter(PhpIndex.getInstance(project), parameter);
134101
if(parameter == null) {
135-
return Collections.emptySet();
102+
return null;
136103
}
137104

138105
PhpClass phpClass = EntityHelper.resolveShortcutName(project, parameter);
139106
if(phpClass == null) {
140-
return Collections.emptySet();
107+
return null;
141108
}
142109

143-
String name = method.getName();
144-
if(name.equals("findAll") || name.equals("findBy")) {
145-
method.getType().add(phpClass.getFQN() + "[]");
146-
return phpNamedElementCollections;
110+
PhpIndex phpIndex = PhpIndex.getInstance(project);
111+
112+
Collection<? extends PhpNamedElement> typeSignature = PhpTypeProviderUtil.getTypeSignature(phpIndex, originalSignature);
113+
114+
// ->getRepository(SecondaryMarket::class)->findAll() => "findAll", but only if its a instance of this method;
115+
// so non Doctrine method are already filtered
116+
Set<String> resolveMethods = getObjectRepositoryCall(typeSignature).stream()
117+
.map(PhpNamedElement::getName)
118+
.collect(Collectors.toSet());
119+
120+
if (resolveMethods.isEmpty()) {
121+
return null;
147122
}
148123

149-
return PhpTypeProviderUtil.mergeSignatureResults(phpNamedElementCollections, phpClass);
124+
PhpType phpType = new PhpType();
125+
126+
resolveMethods.stream()
127+
.map(name -> name.equals("findAll") || name.equals("findBy") ? phpClass.getFQN() + "[]" : phpClass.getFQN())
128+
.collect(Collectors.toSet())
129+
.forEach(phpType::add);
130+
131+
return phpType;
132+
}
133+
134+
@Override
135+
public Collection<? extends PhpNamedElement> getBySignature(String expression, Set<String> visited, int depth, Project project) {
136+
return null;
150137
}
151138

152-
private Method getObjectRepositoryCall(Collection<? extends PhpNamedElement> phpNamedElements) {
139+
@NotNull
140+
private Collection<Method> getObjectRepositoryCall(Collection<? extends PhpNamedElement> phpNamedElements) {
141+
Collection<Method> methods = new HashSet<>();
153142
for (PhpNamedElement phpNamedElement: phpNamedElements) {
154143
if(phpNamedElement instanceof Method && PhpElementsUtil.isMethodInstanceOf((Method) phpNamedElement, FIND_SIGNATURES)) {
155-
return (Method) phpNamedElement;
144+
methods.add((Method) phpNamedElement);
156145
}
157146
}
158147

159-
return null;
148+
return methods;
160149
}
161150
}

src/main/java/fr/adrienbrault/idea/symfony2plugin/lang/ParameterLanguageInjector.java

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import com.intellij.lang.Language;
44
import com.intellij.lang.injection.MultiHostInjector;
55
import com.intellij.lang.injection.MultiHostRegistrar;
6-
import com.intellij.openapi.util.TextRange;
76
import com.intellij.psi.PsiElement;
87
import com.intellij.psi.PsiLanguageInjectionHost;
98
import com.jetbrains.php.lang.psi.elements.*;
@@ -12,6 +11,7 @@
1211
import fr.adrienbrault.idea.symfony2plugin.util.MethodMatcher;
1312
import fr.adrienbrault.idea.symfony2plugin.util.PhpElementsUtil;
1413
import org.jetbrains.annotations.NotNull;
14+
import org.jetbrains.annotations.Nullable;
1515

1616
import java.util.Collections;
1717
import java.util.List;
@@ -41,10 +41,10 @@ public class ParameterLanguageInjector implements MultiHostInjector {
4141
};
4242

4343
private final MethodLanguageInjection[] LANGUAGE_INJECTIONS = {
44-
new MethodLanguageInjection(LANGUAGE_ID_CSS, "@media all { ", " }", CSS_SELECTOR_SIGNATURES),
45-
new MethodLanguageInjection(LANGUAGE_ID_XPATH, null, null, XPATH_SIGNATURES),
46-
new MethodLanguageInjection(LANGUAGE_ID_JSON, null, null, JSON_SIGNATURES),
47-
new MethodLanguageInjection(LANGUAGE_ID_DQL, null, null, DQL_SIGNATURES),
44+
new MethodLanguageInjection(LANGUAGE_ID_CSS, "@media all { ", " }", CSS_SELECTOR_SIGNATURES),
45+
new MethodLanguageInjection(LANGUAGE_ID_XPATH, null, null, XPATH_SIGNATURES),
46+
new MethodLanguageInjection(LANGUAGE_ID_JSON, null, null, JSON_SIGNATURES),
47+
new MethodLanguageInjection(LANGUAGE_ID_DQL, null, null, DQL_SIGNATURES),
4848
};
4949

5050
public static final String LANGUAGE_ID_CSS = "CSS";
@@ -88,26 +88,23 @@ public void getLanguagesToInject(@NotNull MultiHostRegistrar registrar, @NotNull
8888
}
8989

9090
for (MethodLanguageInjection languageInjection : LANGUAGE_INJECTIONS) {
91-
Language language = languageInjection.getLanguage();
92-
if (language == null) {
93-
continue;
94-
}
9591
// $crawler->filter('...')
9692
// $em->createQuery('...')
9793
// JsonResponse::fromJsonString('...')
9894
if (parent instanceof MethodReference) {
9995
if (PhpElementsUtil.isMethodReferenceInstanceOf((MethodReference) parent, languageInjection.getSignatures())) {
100-
injectLanguage(registrar, expr, language, languageInjection);
96+
injectLanguage(registrar, expr, languageInjection);
10197
return;
10298
}
10399
}
104100
// $dql = "...";
105101
else if (parent instanceof AssignmentExpression) {
106-
if (LANGUAGE_ID_DQL.equals(language.getID())) {
102+
Language language = languageInjection.getLanguage();
103+
if (language != null && LANGUAGE_ID_DQL.equals(language.getID())) {
107104
PhpPsiElement variable = ((AssignmentExpression) parent).getVariable();
108105
if (variable instanceof Variable) {
109106
if (DQL_VARIABLE_NAME.equals(variable.getName())) {
110-
injectLanguage(registrar, expr, language, languageInjection);
107+
injectLanguage(registrar, expr, languageInjection);
111108
return;
112109
}
113110
}
@@ -117,28 +114,33 @@ else if (parent instanceof AssignmentExpression) {
117114

118115
}
119116

120-
private void injectLanguage(@NotNull MultiHostRegistrar registrar, @NotNull StringLiteralExpressionImpl element, Language language, MethodLanguageInjection languageInjection) {
117+
private void injectLanguage(@NotNull MultiHostRegistrar registrar, @NotNull StringLiteralExpressionImpl element, MethodLanguageInjection languageInjection) {
118+
Language language = languageInjection.getLanguage();
119+
if (language == null) {
120+
return;
121+
}
122+
121123
registrar.startInjecting(language)
122-
.addPlace(languageInjection.getPrefix(), languageInjection.getSuffix(), element, element.getValueRange())
123-
.doneInjecting();
124+
.addPlace(languageInjection.getPrefix(), languageInjection.getSuffix(), element, element.getValueRange())
125+
.doneInjecting();
124126
}
125127

126-
private class MethodLanguageInjection {
127-
private final Language language;
128+
private static class MethodLanguageInjection {
129+
private final String language;
128130
private final String prefix;
129131
private final String suffix;
130132
private final MethodMatcher.CallToSignature[] signatures;
131133

132-
MethodLanguageInjection(@NotNull String languageId, String prefix, String suffix, MethodMatcher.CallToSignature[] signatures) {
133-
134-
this.language = Language.findLanguageByID(languageId);
134+
MethodLanguageInjection(String languageId, String prefix, String suffix, MethodMatcher.CallToSignature[] signatures) {
135+
this.language = languageId;
135136
this.prefix = prefix;
136137
this.suffix = suffix;
137138
this.signatures = signatures;
138139
}
139140

141+
@Nullable
140142
public Language getLanguage() {
141-
return language;
143+
return Language.findLanguageByID(this.language);
142144
}
143145

144146
public String getPrefix() {

src/main/java/fr/adrienbrault/idea/symfony2plugin/routing/RouteHelper.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -393,17 +393,17 @@ public static Map<String, Route> getRoutesInsideUrlGeneratorFile(@NotNull PsiFil
393393

394394
// Symfony < 2.8
395395
// static private $declaredRoutes = array(...)
396-
for(Field field: phpClass.getFields()) {
397-
if(!field.getName().equals("declaredRoutes")) {
398-
continue;
399-
}
396+
// only "getOwnFields" is uncached and dont breaks; find* methods are cached resulting in exceptions
397+
Field[] ownFields = phpClass.getOwnFields();
398+
for (Field ownField : ownFields) {
399+
if ("declaredRoutes".equals(ownField.getName())) {
400+
PsiElement defaultValue = ownField.getDefaultValue();
401+
if(!(defaultValue instanceof ArrayCreationExpression)) {
402+
continue;
403+
}
400404

401-
PsiElement defaultValue = field.getDefaultValue();
402-
if(!(defaultValue instanceof ArrayCreationExpression)) {
403-
continue;
405+
collectRoutesOnArrayCreation(routes, (ArrayCreationExpression) defaultValue);
404406
}
405-
406-
collectRoutesOnArrayCreation(routes, (ArrayCreationExpression) defaultValue);
407407
}
408408

409409
// Symfony >= 2.8

src/main/resources/META-INF/plugin.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,13 +97,13 @@
9797
]]></description>
9898

9999
<!-- please see http://confluence.jetbrains.net/display/IDEADEV/Build+Number+Ranges for description -->
100-
<idea-version since-build="182.0"/>
100+
<idea-version since-build="201.0"/>
101101

102102
<extensions defaultExtensionNs="com.jetbrains.php">
103103
<typeProvider3 implementation="fr.adrienbrault.idea.symfony2plugin.dic.SymfonyContainerTypeProvider"/>
104104
<typeProvider3 implementation="fr.adrienbrault.idea.symfony2plugin.util.EventDispatcherTypeProvider"/>
105105
<typeProvider3 implementation="fr.adrienbrault.idea.symfony2plugin.doctrine.ObjectRepositoryTypeProvider"/>
106-
<typeProvider3 implementation="fr.adrienbrault.idea.symfony2plugin.doctrine.ObjectRepositoryResultTypeProvider"/>
106+
<typeProvider4 implementation="fr.adrienbrault.idea.symfony2plugin.doctrine.ObjectRepositoryResultTypeProvider"/>
107107
<typeProvider3 implementation="fr.adrienbrault.idea.symfony2plugin.doctrine.ObjectManagerFindTypeProvider"/>
108108
<typeProvider3 implementation="fr.adrienbrault.idea.symfony2plugin.assistant.signature.MethodSignatureTypeProvider"/>
109109
<libraryRoot id="symfony_meta" path="/symfony-meta/" runtime="false"/>

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -578,7 +578,7 @@ public void assertLineMarker(@NotNull PsiElement psiElement, @NotNull LineMarker
578578

579579
final List<PsiElement> elements = collectPsiElementsRecursive(psiElement);
580580

581-
for (LineMarkerProvider lineMarkerProvider : LineMarkerProviders.INSTANCE.allForLanguage(psiElement.getLanguage())) {
581+
for (LineMarkerProvider lineMarkerProvider : LineMarkerProviders.getInstance().allForLanguage(psiElement.getLanguage())) {
582582
Collection<LineMarkerInfo> lineMarkerInfos = new ArrayList<LineMarkerInfo>();
583583
lineMarkerProvider.collectSlowLineMarkers(elements, lineMarkerInfos);
584584

@@ -600,7 +600,7 @@ public void assertLineMarkerIsEmpty(@NotNull PsiElement psiElement) {
600600

601601
final List<PsiElement> elements = collectPsiElementsRecursive(psiElement);
602602

603-
for (LineMarkerProvider lineMarkerProvider : LineMarkerProviders.INSTANCE.allForLanguage(psiElement.getLanguage())) {
603+
for (LineMarkerProvider lineMarkerProvider : LineMarkerProviders.getInstance().allForLanguage(psiElement.getLanguage())) {
604604
Collection<LineMarkerInfo> lineMarkerInfos = new ArrayList<LineMarkerInfo>();
605605
lineMarkerProvider.collectSlowLineMarkers(elements, lineMarkerInfos);
606606

0 commit comments

Comments
 (0)