Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import com.jetbrains.php.lang.psi.elements.Parameter;
import com.jetbrains.php.lang.psi.elements.PhpClass;
import fr.adrienbrault.idea.symfony2plugin.dic.ParameterResolverConsumer;
import fr.adrienbrault.idea.symfony2plugin.dic.container.util.ServiceContainerUtil;
import fr.adrienbrault.idea.symfony2plugin.util.PhpElementsUtil;
import fr.adrienbrault.idea.symfony2plugin.util.dict.ServiceUtil;
import fr.adrienbrault.idea.symfony2plugin.util.yaml.YamlHelper;
Expand All @@ -23,8 +24,7 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.HashMap;
import java.util.Map;
import java.util.*;

/**
* @author Daniel Espendiller <daniel@espendiller.net>
Expand Down Expand Up @@ -834,4 +834,42 @@ public static boolean isXmlFileExtension(@NotNull PsiFile psiFile) {
VirtualFile virtualFile = psiFile.getVirtualFile();
return virtualFile == null || !"xml".equalsIgnoreCase(virtualFile.getExtension());
}

/**
* <prototype exclude="../src/{DependencyInjection,Entity,Tests,Kernel.php}">"
* <exclude>../foobar</exclude>"
* </prototype>"
*/
public static @NotNull Collection<PhpClass> getNamespaceResourcesClasses(@NotNull XmlTag xmlTag) {
String namespace = xmlTag.getAttributeValue("namespace");
if (StringUtils.isBlank(namespace)) {
return Collections.emptyList();
}

String resource = xmlTag.getAttributeValue("resource");
if (StringUtils.isBlank(resource)) {
return Collections.emptyList();
}

Set<String> excludes = new HashSet<>();
String exclude = xmlTag.getAttributeValue("exclude");
if (StringUtils.isNotBlank(exclude)) {
excludes.add(exclude);
}

for (XmlTag excludeTag : xmlTag.findSubTags("exclude")) {
String text = excludeTag.getValue().getText();
if (StringUtils.isNotBlank(text)) {
excludes.add(text);
}
}

return ServiceContainerUtil.getPhpClassFromResources(
xmlTag.getProject(),
namespace,
xmlTag.getContainingFile().getVirtualFile(),
List.of(resource),
excludes
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.*;
import java.util.stream.Collectors;

/**
Expand All @@ -25,11 +23,26 @@ public XmlTagAttributeValue(@NotNull XmlTag xmlTag) {
@NotNull
@Override
public Collection<String> getStringArray(@NotNull String key) {
Set<String> values = new HashSet<>();

String string = getString(key);
if (StringUtils.isNotBlank(string)) {
values.add(string);
}

// <prototype exclude="../src/{DependencyInjection,Entity,Tests,Kernel.php}">"
// <exclude>../foobar</exclude>"
// </prototype>"
if (key.equals("exclude")) {
for (XmlTag excludeTag : xmlTag.findSubTags(key)) {
String text = excludeTag.getValue().getText();
if (StringUtils.isNotBlank(text)) {
values.add(text);
}
}
}

return string != null
? Collections.singleton(string)
: Collections.emptyList();
return values;
}

@Nullable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import com.intellij.codeInsight.daemon.LineMarkerInfo;
import com.intellij.codeInsight.daemon.LineMarkerProvider;
import com.intellij.codeInsight.navigation.NavigationGutterIconBuilder;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.util.NotNullLazyValue;
import com.intellij.patterns.XmlPatterns;
import com.intellij.patterns.XmlTagPattern;
import com.intellij.psi.PsiElement;
Expand Down Expand Up @@ -46,17 +48,42 @@ public void collectSlowLineMarkers(@NotNull List<? extends PsiElement> psiElemen
continue;
}

if(!XmlHelper.getXmlTagNameLeafStartPattern().accepts(psiElement)) {
continue;
}

PsiElement xmlTag = psiElement.getParent();
if(!(xmlTag instanceof XmlTag) || !getServiceIdPattern().accepts(xmlTag)) {
if(!(xmlTag instanceof XmlTag)) {
continue;
}

if(lazyDecoratedParentServiceValues == null) {
lazyDecoratedParentServiceValues = new LazyDecoratedParentServiceValues(psiElement.getProject());
if (getServiceIdPattern().accepts(xmlTag)) {
if(lazyDecoratedParentServiceValues == null) {
lazyDecoratedParentServiceValues = new LazyDecoratedParentServiceValues(psiElement.getProject());
}

// <services><service id="foo"/></services>
visitServiceId(psiElement, (XmlTag) xmlTag, result, lazyDecoratedParentServiceValues);

continue;
}

// <services><service id="foo"/></services>
visitServiceId(psiElement, (XmlTag) xmlTag, result, lazyDecoratedParentServiceValues);
if (getPrototypeNamespacePattern().accepts(xmlTag)) {
String namespace = ((XmlTag) xmlTag).getAttributeValue("namespace");
if (StringUtils.isBlank(namespace)) {
continue;
}

String resource = ((XmlTag) xmlTag).getAttributeValue("resource");
if (StringUtils.isBlank(resource)) {
continue;
}

result.add(NavigationGutterIconBuilder.create(AllIcons.Modules.SourceRoot)
.setTargets(NotNullLazyValue.lazy(() -> XmlHelper.getNamespaceResourcesClasses((XmlTag) xmlTag)))
.setTooltipText("Navigate to class")
.createLineMarkerInfo(psiElement));
}
}
}

Expand Down Expand Up @@ -115,4 +142,14 @@ private static XmlTagPattern.Capture getServiceIdPattern() {
XmlHelper.getInsideTagPattern("services")
).inFile(XmlHelper.getXmlFilePattern());
}

/**
* <prototype namespace="App\" resource="../src/*" exclude="../src/{DependencyInjection,Entity,Tests,Kernel.php}"/>
*/
private static XmlTagPattern.Capture getPrototypeNamespacePattern() {
return XmlPatterns.xmlTag().withName("prototype")
.withChild(XmlPatterns.xmlAttribute().withName("namespace")).inside(
XmlHelper.getInsideTagPattern("services")
).inFile(XmlHelper.getXmlFilePattern());
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
package fr.adrienbrault.idea.symfony2plugin.tests.config.xml;

import com.intellij.ide.highlighter.XmlFileType;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.xml.XmlAttributeValue;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.containers.ContainerUtil;
import com.jetbrains.php.lang.psi.elements.Parameter;
import com.jetbrains.php.lang.psi.elements.PhpClass;
import com.jetbrains.php.lang.psi.elements.PhpNamedElement;
import fr.adrienbrault.idea.symfony2plugin.config.xml.XmlHelper;
import fr.adrienbrault.idea.symfony2plugin.tests.SymfonyLightCodeInsightFixtureTestCase;

import java.util.ArrayList;
import java.util.Collection;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
* @author Daniel Espendiller <daniel@espendiller.net>
Expand Down Expand Up @@ -169,4 +177,23 @@ public void testGetArgumentIndexOnArgumentCount() {
PsiElement psiElement = myFixture.getFile().findElementAt(myFixture.getCaretOffset());
assertEquals(1, XmlHelper.getArgumentIndex((XmlTag) psiElement.getParent()));
}

/**
* @see XmlHelper#getNamespaceResourcesClasses
*/
public void testGetNamespaceResourcesClasses() {
myFixture.copyFileToProject("XmlHelper.php", "src/XmlHelper.php");
VirtualFile service = myFixture.copyFileToProject("services.xml", "src/services.xml");

PsiFile file = PsiManager.getInstance(getProject()).findFile(service);

Collection<XmlTag> xmlTags = PsiTreeUtil.collectElementsOfType(file, XmlTag.class);

XmlTag xmlTag = xmlTags.stream().filter(xmlTag1 -> "prototype".equals(xmlTag1.getName())).findFirst().orElseThrow();
Collection<String> namespaceResourcesClasses = XmlHelper.getNamespaceResourcesClasses(xmlTag).stream()
.map(PhpNamedElement::getFQN)
.collect(Collectors.toSet());

assertContainsElements(namespaceResourcesClasses, "\\Foo\\Bar");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
<container>
<services>
<service id="foo.bar_factory" class="Foo\Bar"/>
<prototype namespace="Foo\" resource="../src/*"/>
</services>
</container>
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ public void testThatResourceAndExcludeAttributesAreExtractedForXml() {
assertEquals("App\\Xml\\", firstValue.getId());
assertContainsElements(firstValue.getResource(), "../src/*");
assertContainsElements(firstValue.getExclude(), "../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}");
assertContainsElements(firstValue.getExclude(), "../src/foobar");
}

public void testThatTagAreInIndexForYaml() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@

<prototype namespace="App\Xml\"
resource="../src/*"
exclude="../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}"/>
exclude="../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}">
<exclude>../src/foobar</exclude>
</prototype>

<service id="foo.tagged.xml_type" class="AppBundle\Controller\DefaultController">
<tag name="xml_type_tag"/>
Expand Down