Skip to content

Commit 9426919

Browse files
authored
Merge pull request #2109 from Haehnchen/feature/duplicate-key-visit
duplicate key inspections for xml should only visits the working context
2 parents 3eb172c + 213fe9f commit 9426919

File tree

4 files changed

+78
-54
lines changed

4 files changed

+78
-54
lines changed

src/main/java/fr/adrienbrault/idea/symfony2plugin/config/xml/inspection/XmlDuplicateParameterKeyInspection.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
package fr.adrienbrault.idea.symfony2plugin.config.xml.inspection;
22

33
import com.intellij.codeInspection.ProblemsHolder;
4+
import com.intellij.psi.PsiElement;
45
import com.intellij.psi.PsiElementVisitor;
5-
import com.intellij.psi.PsiFile;
6+
import com.intellij.psi.xml.XmlAttributeValue;
67
import fr.adrienbrault.idea.symfony2plugin.Symfony2ProjectComponent;
78
import org.jetbrains.annotations.NotNull;
89

@@ -20,8 +21,12 @@ public PsiElementVisitor buildVisitor(final @NotNull ProblemsHolder holder, bool
2021

2122
return new PsiElementVisitor() {
2223
@Override
23-
public void visitFile(PsiFile file) {
24-
visitRoot(file, holder, "parameters", "parameter", "key");
24+
public void visitElement(@NotNull PsiElement element) {
25+
if (element instanceof XmlAttributeValue xmlAttributeValue) {
26+
visitRoot(xmlAttributeValue, holder, "parameters", "parameter", "key");
27+
}
28+
29+
super.visitElement(element);
2530
}
2631
};
2732
}

src/main/java/fr/adrienbrault/idea/symfony2plugin/config/xml/inspection/XmlDuplicateServiceKeyInspection.java

Lines changed: 24 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,12 @@
55
import com.intellij.codeInspection.ProblemsHolder;
66
import com.intellij.psi.PsiElement;
77
import com.intellij.psi.PsiElementVisitor;
8-
import com.intellij.psi.PsiFile;
9-
import com.intellij.psi.util.PsiTreeUtil;
108
import com.intellij.psi.xml.XmlAttribute;
119
import com.intellij.psi.xml.XmlAttributeValue;
12-
import com.intellij.psi.xml.XmlDocument;
1310
import com.intellij.psi.xml.XmlTag;
1411
import fr.adrienbrault.idea.symfony2plugin.Symfony2ProjectComponent;
15-
import org.apache.commons.lang.StringUtils;
1612
import org.jetbrains.annotations.NotNull;
1713

18-
import java.util.HashMap;
19-
import java.util.HashSet;
20-
import java.util.Map;
21-
import java.util.Set;
22-
2314
/**
2415
* @author Daniel Espendiller <daniel@espendiller.net>
2516
*/
@@ -34,59 +25,41 @@ public PsiElementVisitor buildVisitor(final @NotNull ProblemsHolder holder, bool
3425

3526
return new PsiElementVisitor() {
3627
@Override
37-
public void visitFile(PsiFile file) {
38-
visitRoot(file, holder, "services", "service", "id");
39-
super.visitFile(file);
28+
public void visitElement(@NotNull PsiElement element) {
29+
if (element instanceof XmlAttributeValue xmlAttributeValue) {
30+
visitRoot(xmlAttributeValue, holder, "services", "service", "id");
31+
}
32+
33+
super.visitElement(element);
4034
}
4135
};
4236
}
4337

44-
protected void visitRoot(PsiFile psiFile, @NotNull ProblemsHolder holder, String root, String child, String tagName) {
38+
protected void visitRoot(@NotNull XmlAttributeValue xmlAttributeValue, @NotNull ProblemsHolder holder, String root, String child, String tagName) {
39+
String value = null;
4540

46-
XmlDocument xmlDocument = PsiTreeUtil.getChildOfType(psiFile, XmlDocument.class);
47-
if(xmlDocument == null) {
48-
return;
49-
}
41+
if (xmlAttributeValue.getParent() instanceof XmlAttribute xmlAttribute && tagName.equals(xmlAttribute.getName())) {
42+
XmlTag xmlTag = xmlAttribute.getParent();
43+
if (xmlTag != null && child.equals(xmlTag.getName()) && xmlTag.getParent() instanceof XmlTag rootContextXmlTag && root.equals(rootContextXmlTag.getName())) {
44+
int found = 0;
45+
for (XmlTag parameters : rootContextXmlTag.findSubTags(child)) {
46+
String key = parameters.getAttributeValue(tagName);
5047

51-
Map<String, XmlAttribute> psiElementMap = new HashMap<>();
52-
Set<XmlAttribute> yamlKeyValues = new HashSet<>();
53-
54-
for(XmlTag xmlTag: PsiTreeUtil.getChildrenOfTypeAsList(psiFile.getFirstChild(), XmlTag.class)) {
55-
if(xmlTag.getName().equals("container")) {
56-
for(XmlTag servicesTag: xmlTag.getSubTags()) {
57-
if(servicesTag.getName().equals(root)) {
58-
for(XmlTag parameterTag: servicesTag.getSubTags()) {
59-
if(parameterTag.getName().equals(child)) {
60-
XmlAttribute keyAttr = parameterTag.getAttribute(tagName);
61-
if(keyAttr != null) {
62-
String parameterName = keyAttr.getValue();
63-
if(parameterName != null && StringUtils.isNotBlank(parameterName)) {
64-
if(psiElementMap.containsKey(parameterName)) {
65-
yamlKeyValues.add(psiElementMap.get(parameterName));
66-
yamlKeyValues.add(keyAttr);
67-
} else {
68-
psiElementMap.put(parameterName, keyAttr);
69-
}
70-
}
48+
// lazy value resolve
49+
if (value == null) {
50+
value = xmlAttributeValue.getValue();
51+
}
7152

72-
}
73-
}
74-
}
53+
if (value.equals(key)) {
54+
found++;
7555
}
76-
}
77-
}
78-
}
7956

80-
if(yamlKeyValues.size() > 0) {
81-
for(PsiElement psiElement: yamlKeyValues) {
82-
XmlAttributeValue valueElement = ((XmlAttribute) psiElement).getValueElement();
83-
if(valueElement != null) {
84-
holder.registerProblem(valueElement, "Duplicate Key", ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
57+
if (found == 2) {
58+
holder.registerProblem(xmlAttributeValue, "Symfony: Duplicate Key", ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
59+
break;
60+
}
8561
}
8662
}
8763
}
88-
8964
}
90-
91-
9265
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package fr.adrienbrault.idea.symfony2plugin.tests.config.xml;
2+
3+
import fr.adrienbrault.idea.symfony2plugin.tests.SymfonyLightCodeInsightFixtureTestCase;
4+
5+
/**
6+
* @author Daniel Espendiller <daniel@espendiller.net>
7+
* @see fr.adrienbrault.idea.symfony2plugin.config.xml.inspection.XmlDuplicateParameterKeyInspection
8+
*/
9+
public class XmlDuplicateParameterKeyInspectionTest extends SymfonyLightCodeInsightFixtureTestCase {
10+
public void testDuplicateParameterKey() {
11+
assertLocalInspectionContains("service.xml",
12+
"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" +
13+
"<container>\n" +
14+
"\n" +
15+
" <parameters>\n" +
16+
" <parameter key=\"mailer.transport\">foo</parameter>\n" +
17+
" <parameter key=\"maile<caret>r.transport\">foo1</parameter>\n" +
18+
" </parameters>\n" +
19+
"\n" +
20+
"</container>",
21+
"Symfony: Duplicate Key"
22+
);
23+
}
24+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package fr.adrienbrault.idea.symfony2plugin.tests.config.xml.inspection;
2+
3+
import fr.adrienbrault.idea.symfony2plugin.tests.SymfonyLightCodeInsightFixtureTestCase;
4+
5+
/**
6+
* @author Daniel Espendiller <daniel@espendiller.net>
7+
* @see fr.adrienbrault.idea.symfony2plugin.config.xml.inspection.XmlDuplicateServiceKeyInspection
8+
*/
9+
public class XmlDuplicateServiceKeyInspectionTest extends SymfonyLightCodeInsightFixtureTestCase {
10+
public void testDuplicateParameterKey() {
11+
assertLocalInspectionContains("service.xml","" +
12+
"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" +
13+
"<container>\n" +
14+
" <services>\n" +
15+
" <service id=\"foo<caret>bar\"/>\n" +
16+
" <service id=\"foobar\"/>\n" +
17+
" </services>\n" +
18+
"</container>",
19+
"Symfony: Duplicate Key"
20+
);
21+
}
22+
}

0 commit comments

Comments
 (0)