Skip to content

Commit 52cb9aa

Browse files
committed
reworked compiled container parser to support aliases extraction more safety for Symfony 3.3 private service debugger #618 #943
1 parent f218547 commit 52cb9aa

File tree

12 files changed

+324
-100
lines changed

12 files changed

+324
-100
lines changed

src/fr/adrienbrault/idea/symfony2plugin/Symfony2ProjectComponent.java

+4-9
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
import java.io.File;
2626
import java.util.ArrayList;
27-
import java.util.List;
27+
import java.util.Collection;
2828

2929
/**
3030
* @author Adrien Brault <adrien.brault@gmail.com>
@@ -100,13 +100,8 @@ public boolean isEnabled() {
100100
return Settings.getInstance(project).pluginEnabled;
101101
}
102102

103-
public List<File> getContainerFiles() {
104-
return this.getContainerFiles(true);
105-
}
106-
107-
public List<File> getContainerFiles(boolean attachSetting) {
108-
109-
List<ContainerFile> containerFiles = new ArrayList<>();
103+
public Collection<File> getContainerFiles() {
104+
Collection<ContainerFile> containerFiles = new ArrayList<>();
110105

111106
ServiceContainerLoaderParameter containerLoaderExtensionParameter = new ServiceContainerLoaderParameter(project, containerFiles);
112107
for(ServiceContainerLoader loaderExtension : SERVICE_CONTAINER_POINT_NAME.getExtensions()) {
@@ -119,7 +114,7 @@ public List<File> getContainerFiles(boolean attachSetting) {
119114
}
120115
}
121116

122-
List<File> validFiles = new ArrayList<>();
117+
Collection<File> validFiles = new ArrayList<>();
123118
for(ContainerFile containerFile : containerFiles) {
124119
if(containerFile.exists(this.project)) {
125120
validFiles.add(containerFile.getFile(this.project));

src/fr/adrienbrault/idea/symfony2plugin/config/ServiceLineMarkerProvider.java

+9-12
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,14 @@
1717
import fr.adrienbrault.idea.symfony2plugin.Symfony2InterfacesUtil;
1818
import fr.adrienbrault.idea.symfony2plugin.Symfony2ProjectComponent;
1919
import fr.adrienbrault.idea.symfony2plugin.dic.ClassServiceDefinitionTargetLazyValue;
20-
import fr.adrienbrault.idea.symfony2plugin.dic.XmlServiceParser;
2120
import fr.adrienbrault.idea.symfony2plugin.doctrine.EntityHelper;
2221
import fr.adrienbrault.idea.symfony2plugin.doctrine.metadata.util.DoctrineMetadataUtil;
2322
import fr.adrienbrault.idea.symfony2plugin.form.util.FormUtil;
2423
import fr.adrienbrault.idea.symfony2plugin.stubs.ServiceIndexUtil;
2524
import fr.adrienbrault.idea.symfony2plugin.util.PhpElementsUtil;
2625
import fr.adrienbrault.idea.symfony2plugin.util.dict.DoctrineModel;
26+
import fr.adrienbrault.idea.symfony2plugin.util.dict.ServiceUtil;
2727
import fr.adrienbrault.idea.symfony2plugin.util.resource.FileResourceUtil;
28-
import fr.adrienbrault.idea.symfony2plugin.util.service.ServiceXmlParserFactory;
2928
import org.apache.commons.lang.StringUtils;
3029
import org.jetbrains.annotations.NotNull;
3130
import org.jetbrains.annotations.Nullable;
@@ -85,14 +84,18 @@ public void collectSlowLineMarkers(@NotNull List<PsiElement> psiElements, @NotNu
8584

8685
}
8786

88-
protected void collectNavigationMarkers(@NotNull PsiElement psiElement, Collection<? super RelatedItemLineMarkerInfo> result) {
87+
/**
88+
* Dropable feature
89+
*/
90+
@Deprecated
91+
private void collectNavigationMarkers(@NotNull PsiElement psiElement, Collection<? super RelatedItemLineMarkerInfo> result) {
8992

9093
if (!(psiElement instanceof StringLiteralExpression) || !(psiElement.getContext() instanceof ParameterList)) {
9194
return;
9295
}
9396

9497
ParameterList parameterList = (ParameterList) psiElement.getContext();
95-
if (parameterList == null || !(parameterList.getContext() instanceof MethodReference)) {
98+
if (!(parameterList.getContext() instanceof MethodReference)) {
9699
return;
97100
}
98101

@@ -102,19 +105,13 @@ protected void collectNavigationMarkers(@NotNull PsiElement psiElement, Collecti
102105
}
103106

104107
String serviceId = ((StringLiteralExpression) psiElement).getContents();
105-
106-
String serviceClass = ServiceXmlParserFactory.getInstance(psiElement.getProject(), XmlServiceParser.class).getServiceMap().getMap().get(serviceId.toLowerCase());
108+
PhpClass serviceClass = ServiceUtil.getServiceClass(psiElement.getProject(), serviceId);
107109
if (null == serviceClass) {
108110
return;
109111
}
110112

111-
PsiElement[] resolveResults = PhpElementsUtil.getClassInterfacePsiElements(psiElement.getProject(), serviceClass);
112-
if(resolveResults.length == 0) {
113-
return;
114-
}
115-
116113
NavigationGutterIconBuilder<PsiElement> builder = NavigationGutterIconBuilder.create(Symfony2Icons.SERVICE_LINE_MARKER).
117-
setTargets(resolveResults).
114+
setTargets(serviceClass).
118115
setTooltipText("Navigate to service");
119116

120117
result.add(builder.createLineMarkerInfo(psiElement));
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,45 @@
11
package fr.adrienbrault.idea.symfony2plugin.dic;
22

3-
import org.jetbrains.annotations.Nullable;
3+
import fr.adrienbrault.idea.symfony2plugin.dic.container.ServiceInterface;
4+
import org.jetbrains.annotations.NotNull;
45

5-
import java.util.Collections;
6-
import java.util.HashMap;
7-
import java.util.Map;
6+
import java.util.*;
87

98
/**
9+
* @author Daniel Espendiller <daniel@espendiller.net>
1010
* @author Adrien Brault <adrien.brault@gmail.com>
1111
*/
1212
public class ServiceMap {
13+
@NotNull
14+
final private Collection<ServiceInterface> services;
1315

14-
private Map<String, String> map;
15-
private Map<String, String> publicMap;
16+
private Collection<String> ids;
1617

17-
public ServiceMap(Map<String, String> map, Map<String, String> publicMap) {
18-
this.map = Collections.unmodifiableMap(map);
19-
this.publicMap = Collections.unmodifiableMap(publicMap);
18+
ServiceMap() {
19+
this.services = Collections.unmodifiableCollection(Collections.emptyList());
2020
}
2121

22-
public ServiceMap() {
23-
this.map = new HashMap<>();
24-
this.publicMap = new HashMap<>();
22+
ServiceMap(@NotNull Collection<ServiceInterface> services) {
23+
this.services = Collections.unmodifiableCollection(services);
2524
}
2625

27-
public Map<String, String> getMap() {
28-
return map;
29-
}
30-
31-
public Map<String, String> getPublicMap() {
32-
return publicMap;
33-
}
34-
35-
@Nullable
36-
public String resolveClassName(String findValue) {
37-
38-
if(!findValue.startsWith("\\")) {
39-
findValue = "\\" + findValue;
26+
public Collection<String> getIds() {
27+
// cache value, instance cached until invalidated
28+
if(ids != null) {
29+
return ids;
4030
}
4131

42-
for (Map.Entry<String, String> entry : this.getMap().entrySet()) {
43-
if (entry.getValue().equals(findValue)) {
44-
return entry.getKey();
45-
}
46-
}
32+
Collection<String> map = new HashSet<>();
4733

48-
return null;
34+
services.forEach(service ->
35+
map.add(service.getId())
36+
);
37+
38+
return this.ids = Collections.unmodifiableCollection(map);
4939
}
5040

41+
@NotNull
42+
public Collection<ServiceInterface> getServices() {
43+
return services;
44+
}
5145
}

src/fr/adrienbrault/idea/symfony2plugin/dic/ServiceMapParser.java

+39-13
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package fr.adrienbrault.idea.symfony2plugin.dic;
22

3-
import org.apache.commons.lang.StringUtils;
3+
import fr.adrienbrault.idea.symfony2plugin.dic.container.ServiceInterface;
4+
import fr.adrienbrault.idea.symfony2plugin.dic.container.XmlService;
45
import org.w3c.dom.Document;
56
import org.w3c.dom.Element;
7+
import org.w3c.dom.Node;
68
import org.w3c.dom.NodeList;
79
import org.xml.sax.SAXException;
810

@@ -16,6 +18,7 @@
1618
import java.util.Map;
1719

1820
/**
21+
* @author Daniel Espendiller <daniel@espendiller.net>
1922
* @author Adrien Brault <adrien.brault@gmail.com>
2023
*/
2124
public class ServiceMapParser {
@@ -36,24 +39,47 @@ public ServiceMap parse(File file) throws IOException, SAXException {
3639
}
3740

3841
public ServiceMap parse(Document document) {
39-
Map<String, String> map = new HashMap<>();
40-
Map<String, String> publicMap = new HashMap<>();
41-
4242
NodeList servicesNodes = document.getElementsByTagName("service");
43+
44+
Map<String, ServiceInterface> services = new HashMap<>();
45+
Map<String, ServiceInterface> aliases = new HashMap<>();
46+
4347
for (int i = 0; i < servicesNodes.getLength(); i++) {
44-
Element node = (Element) servicesNodes.item(i);
45-
if (node.hasAttribute("class") && node.hasAttribute("id")) {
46-
map.put(node.getAttribute("id"), StringUtils.stripStart(node.getAttribute("class"), "\\"));
48+
Node node = servicesNodes.item(i);
49+
if(!(node instanceof Element)) {
50+
continue;
4751
}
48-
if (!(node.hasAttribute("public") && node.getAttribute("public").equals("false"))) {
49-
publicMap.put(node.getAttribute("id"), StringUtils.stripStart(node.getAttribute("class"), "\\"));
52+
53+
// invalid service
54+
XmlService service = XmlService.createFromXml((Element) node);
55+
if(service == null) {
56+
continue;
5057
}
51-
if (node.hasAttribute("alias") && publicMap.get(node.getAttribute("alias")) != null) {
52-
map.put(node.getAttribute("id"), map.get(node.getAttribute("alias")));
53-
publicMap.put(node.getAttribute("id"), map.get(node.getAttribute("alias")));
58+
59+
if(service.getAlias() == null) {
60+
services.put(service.getId(), service);
61+
} else {
62+
aliases.put(service.getId(), service);
5463
}
5564
}
5665

57-
return new ServiceMap(map, publicMap);
66+
// resolve alias, as xml as a fully validated stated
67+
// all alias are valid per file
68+
aliases.values().forEach(service -> {
69+
ServiceInterface serviceAlias = services.get(service.getAlias());
70+
if(serviceAlias != null) {
71+
String className = serviceAlias.getClassName();
72+
if(className != null) {
73+
XmlService v = XmlService.create(
74+
service.getId(),
75+
className,
76+
service.isPublic()
77+
);
78+
services.put(service.getId(), v);
79+
}
80+
}
81+
});
82+
83+
return new ServiceMap(services.values());
5884
}
5985
}
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package fr.adrienbrault.idea.symfony2plugin.dic;
22

33
import fr.adrienbrault.idea.symfony2plugin.util.service.AbstractServiceParser;
4+
import org.jetbrains.annotations.NotNull;
45
import org.xml.sax.SAXException;
56

67
import javax.xml.parsers.ParserConfigurationException;
@@ -12,7 +13,8 @@
1213
*/
1314
public class XmlServiceParser extends AbstractServiceParser {
1415

15-
protected ServiceMap serviceMap = new ServiceMap();
16+
@NotNull
17+
private ServiceMap serviceMap = new ServiceMap();
1618

1719
@Override
1820
public String getXPathFilter() {
@@ -21,16 +23,13 @@ public String getXPathFilter() {
2123

2224
public void parser(InputStream file) {
2325
try {
24-
// @TODO: make this one beautiful
25-
ServiceMap serviceMap1 = new ServiceMapParser().parse(file);
26-
this.serviceMap.getMap().putAll(serviceMap1.getMap());
27-
this.serviceMap.getPublicMap().putAll(serviceMap1.getPublicMap());
26+
this.serviceMap = new ServiceMapParser().parse(file);
2827
} catch (SAXException | IOException | ParserConfigurationException ignored) {
2928
}
3029
}
3130

31+
@NotNull
3232
public ServiceMap getServiceMap() {
3333
return serviceMap;
3434
}
35-
3635
}

0 commit comments

Comments
 (0)