package fr.adrienbrault.idea.symfony2plugin.routing;
import com.intellij.patterns.PlatformPatterns;
import com.intellij.psi.*;
import com.intellij.util.ProcessingContext;
import com.jetbrains.php.lang.PhpLanguage;
import com.jetbrains.php.lang.psi.elements.StringLiteralExpression;
import fr.adrienbrault.idea.symfony2plugin.Symfony2ProjectComponent;
import fr.adrienbrault.idea.symfony2plugin.util.MethodMatcher;
import fr.adrienbrault.idea.symfony2plugin.util.PsiElementUtils;
import fr.adrienbrault.idea.symfony2plugin.util.controller.ControllerReference;
import org.jetbrains.annotations.NotNull;
/**
* @author Adrien Brault <adrien.brault@gmail.com>
* @author Daniel Espendiller <daniel@espendiller.net>
*/
public class PhpRouteReferenceContributor extends PsiReferenceContributor {
public static MethodMatcher.CallToSignature[] GENERATOR_SIGNATURES = new MethodMatcher.CallToSignature[] {
new MethodMatcher.CallToSignature("\\Symfony\\Component\\Routing\\Generator\\UrlGeneratorInterface", "generate"),
new MethodMatcher.CallToSignature("\\Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller", "generateUrl"),
};
private static MethodMatcher.CallToSignature[] FORWARD_SIGNATURES = new MethodMatcher.CallToSignature[] {
new MethodMatcher.CallToSignature("\\Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller", "forward")
};
@Override
public void registerReferenceProviders(PsiReferenceRegistrar psiReferenceRegistrar) {
psiReferenceRegistrar.registerReferenceProvider(
PlatformPatterns.psiElement(StringLiteralExpression.class).withLanguage(PhpLanguage.INSTANCE),
new PsiReferenceProvider() {
@NotNull
@Override
public PsiReference[] getReferencesByElement(@NotNull PsiElement psiElement, @NotNull ProcessingContext processingContext) {
if (MethodMatcher.getMatchedSignatureWithDepth(psiElement, GENERATOR_SIGNATURES) == null) {
return new PsiReference[0];
}
return new PsiReference[]{ new RouteReference((StringLiteralExpression) psiElement) };
}
}
);
psiReferenceRegistrar.registerReferenceProvider(
PlatformPatterns.psiElement(StringLiteralExpression.class),
new PsiReferenceProvider() {
@NotNull
@Override
public PsiReference[] getReferencesByElement(@NotNull PsiElement psiElement, @NotNull ProcessingContext processingContext) {
if (MethodMatcher.getMatchedSignatureWithDepth(psiElement, FORWARD_SIGNATURES) == null) {
return new PsiReference[0];
}
return new PsiReference[]{ new ControllerReference((StringLiteralExpression) psiElement) };
}
}
);
psiReferenceRegistrar.registerReferenceProvider(
PlatformPatterns.psiElement(StringLiteralExpression.class),
new PsiReferenceProvider() {
@NotNull
@Override
public PsiReference[] getReferencesByElement(@NotNull PsiElement psiElement, @NotNull ProcessingContext processingContext) {
if(!Symfony2ProjectComponent.isEnabled(psiElement)) {
return new PsiReference[0];
}
MethodMatcher.MethodMatchParameter methodMatchParameter = new MethodMatcher.ArrayParameterMatcher(psiElement, 1)
.withSignature(GENERATOR_SIGNATURES)
.match();
if(methodMatchParameter == null) {
return new PsiReference[0];
}
String routeName = PsiElementUtils.getMethodParameterAt(methodMatchParameter.getMethodReference(), 0);
if(routeName == null) {
return new PsiReference[0];
}
return new PsiReference[]{ new RouteParameterReference((StringLiteralExpression) psiElement, routeName) };
}
}
);
}
}