Skip to content

Commit

Permalink
Merge pull request #2270 from Haehnchen/feature/route-attribute
Browse files Browse the repository at this point in the history
support new routing class "\Symfony\Component\Routing\Attribute\Route"
  • Loading branch information
Haehnchen authored Dec 15, 2023
2 parents 16767bb + 74a8af0 commit 91bca71
Show file tree
Hide file tree
Showing 6 changed files with 25 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,6 @@
* @author Daniel Espendiller <[email protected]>
*/
public class SymfonyImplicitUsageProvider implements ImplicitUsageProvider {
private static final String[] ROUTE_ANNOTATIONS = new String[] {
"\\Symfony\\Component\\Routing\\Annotation\\Route",
"\\Sensio\\Bundle\\FrameworkExtraBundle\\Configuration\\Route"
};

@Override
public boolean isImplicitUsage(@NotNull PsiElement element) {
if (element instanceof Method method && method.getAccess() == PhpModifier.Access.PUBLIC) {
Expand Down Expand Up @@ -128,11 +123,11 @@ public boolean isImplicitWrite(@NotNull PsiElement element) {

private boolean isMethodARoute(@NotNull Method method) {
PhpDocCommentAnnotation phpDocCommentAnnotationContainer = AnnotationUtil.getPhpDocCommentAnnotationContainer(method.getDocComment());
if (phpDocCommentAnnotationContainer != null && phpDocCommentAnnotationContainer.getFirstPhpDocBlock(ROUTE_ANNOTATIONS) != null) {
if (phpDocCommentAnnotationContainer != null && phpDocCommentAnnotationContainer.getFirstPhpDocBlock(RouteHelper.ROUTE_ANNOTATIONS) != null) {
return true;
}

for (String route : ROUTE_ANNOTATIONS) {
for (String route : RouteHelper.ROUTE_ANNOTATIONS) {
Collection<@NotNull PhpAttribute> attributes = method.getAttributes(route);
if (!attributes.isEmpty()) {
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@
* @author Daniel Espendiller <[email protected]>
*/
public class RouteHelper {
public static final String[] ROUTE_ANNOTATIONS = new String[] {
"\\Symfony\\Component\\Routing\\Annotation\\Route",
"\\Sensio\\Bundle\\FrameworkExtraBundle\\Configuration\\Route",
"\\Symfony\\Component\\Routing\\Attribute\\Route"
};

private static final Key<CachedValue<Map<String, Route>>> ROUTE_CACHE = new Key<>("SYMFONY:ROUTE_CACHE");
private static final Key<CachedValue<Set<String>>> ROUTE_CONTROLLER_RESOLVED_CACHE = new Key<>("ROUTE_CONTROLLER_RESOLVED_CACHE");
Expand All @@ -72,11 +77,6 @@ public class RouteHelper {
private static final Key<CachedValue<Collection<String>>> SYMFONY_COMPILED_CACHE_ROUTES_FILES = new Key<>("SYMFONY_COMPILED_CACHE_ROUTES_FILES");
private static final Key<CachedValue<Collection<String>>> SYMFONY_COMPILED_GUESTED_FILES = new Key<>("SYMFONY_COMPILED_GUESTED_FILES");

public static Set<String> ROUTE_CLASSES = new HashSet<>(Arrays.asList(
"Sensio\\Bundle\\FrameworkExtraBundle\\Configuration\\Route",
"Symfony\\Component\\Routing\\Annotation\\Route"
));

private static final ExtensionPointName<RoutingLoader> ROUTING_LOADER = new ExtensionPointName<>(
"fr.adrienbrault.idea.symfony2plugin.extension.RoutingLoader"
);
Expand Down Expand Up @@ -1162,7 +1162,7 @@ public static Collection<PsiElement> getRouteNameTarget(@NotNull Project project
private static String getRouteNamePrefix(@NotNull PhpClass phpClass) {
PhpDocCommentAnnotation phpClassContainer = AnnotationUtil.getPhpDocCommentAnnotationContainer(phpClass.getDocComment());
if(phpClassContainer != null) {
PhpDocTagAnnotation firstPhpDocBlock = phpClassContainer.getFirstPhpDocBlock(ROUTE_CLASSES.toArray(new String[0]));
PhpDocTagAnnotation firstPhpDocBlock = phpClassContainer.getFirstPhpDocBlock(ROUTE_ANNOTATIONS);
if(firstPhpDocBlock != null) {
String name = firstPhpDocBlock.getPropertyValue("name");
if(name != null && StringUtils.isNotBlank(name)) {
Expand Down Expand Up @@ -1342,8 +1342,8 @@ private static String normalizeRouteController(@NotNull String string) {
* Support "use Symfony\Component\Routing\Annotation\Route as BaseRoute;"
*/
public static boolean isRouteClassAnnotation(@NotNull String clazz) {
String myClazz = StringUtils.stripStart(clazz, "\\");
return ROUTE_CLASSES.stream().anyMatch(s -> s.equalsIgnoreCase(myClazz));
String myClazz = "\\" + StringUtils.stripStart(clazz, "\\");
return Arrays.stream(ROUTE_ANNOTATIONS).anyMatch(s -> s.equalsIgnoreCase(myClazz));
}

private static class CompiledRoutePathFilesModificationTracker extends SimpleModificationTracker {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
public class RouteNameAnnotationCompletionProvider implements PhpAnnotationCompletionProvider {
@Override
public void getPropertyValueCompletions(AnnotationPropertyParameter annotationPropertyParameter, AnnotationCompletionProviderParameter annotationCompletionProviderParameter) {
if (!Symfony2ProjectComponent.isEnabled(annotationPropertyParameter.getProject()) || !PhpElementsUtil.isInstanceOf(annotationPropertyParameter.getPhpClass(), "\\Symfony\\Component\\Routing\\Annotation\\Route")) {
if (!Symfony2ProjectComponent.isEnabled(annotationPropertyParameter.getProject()) || !PhpElementsUtil.isInstanceOf(annotationPropertyParameter.getPhpClass(), "\\Symfony\\Component\\Routing\\Annotation\\Route", "\\Symfony\\Component\\Routing\\Annotation\\Route")) {
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
public class RouteUrlAnnotationCompletionProvider implements PhpAnnotationCompletionProvider {
@Override
public void getPropertyValueCompletions(AnnotationPropertyParameter annotationPropertyParameter, AnnotationCompletionProviderParameter annotationCompletionProviderParameter) {
if (!Symfony2ProjectComponent.isEnabled(annotationPropertyParameter.getProject()) || !PhpElementsUtil.isInstanceOf(annotationPropertyParameter.getPhpClass(), "\\Symfony\\Component\\Routing\\Annotation\\Route")) {
if (!Symfony2ProjectComponent.isEnabled(annotationPropertyParameter.getProject()) || !PhpElementsUtil.isInstanceOf(annotationPropertyParameter.getPhpClass(), "\\Symfony\\Component\\Routing\\Annotation\\Route", "\\Symfony\\Component\\Routing\\Annotation\\Route")) {
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,14 @@
import fr.adrienbrault.idea.symfony2plugin.routing.RouteHelper;
import fr.adrienbrault.idea.symfony2plugin.util.PhpElementsUtil;
import fr.adrienbrault.idea.symfony2plugin.util.yaml.YamlHelper;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.yaml.YAMLLanguage;
import org.jetbrains.yaml.psi.YAMLDocument;
import org.jetbrains.yaml.psi.YAMLKeyValue;
import org.jetbrains.yaml.psi.YAMLMapping;

import java.util.Collection;

/**
* @author Daniel Espendiller <[email protected]>
*/
Expand Down Expand Up @@ -95,14 +96,17 @@ private void visitYaml(@NotNull YAMLKeyValue yamlKeyValue) {
}

private void visitPhp(@NotNull StringLiteralExpression element) {
if (PhpElementsUtil.isAttributeNamedArgumentString(element, "\\Symfony\\Component\\Routing\\Annotation\\Route", "name")) {
if (PhpElementsUtil.isAttributeNamedArgumentString(element, "\\Symfony\\Component\\Routing\\Annotation\\Route", "name") || PhpElementsUtil.isAttributeNamedArgumentString(element, "\\Symfony\\Component\\Routing\\Attribute\\Route", "name")) {
PhpAttribute parentOfType = PsiTreeUtil.getParentOfType(element, PhpAttribute.class);
if (parentOfType.getOwner() instanceof Method method && method.getAccess().isPublic() && method.getContainingClass() != null) {
int found = 0;
String contents = element.getContents();

for (Method ownMethod : method.getContainingClass().getOwnMethods()) {
for (PhpAttribute attribute : ownMethod.getAttributes("\\Symfony\\Component\\Routing\\Annotation\\Route")) {
Collection<PhpAttribute> attributes = ownMethod.getAttributes("\\Symfony\\Component\\Routing\\Annotation\\Route");
attributes.addAll(ownMethod.getAttributes("\\Symfony\\Component\\Routing\\Attribute\\Route"));

for (PhpAttribute attribute : attributes) {
String name = PhpElementsUtil.getAttributeArgumentStringByName(attribute, "name");
if (contents.equals(name)) {
found++;
Expand All @@ -121,7 +125,7 @@ private void visitPhp(@NotNull StringLiteralExpression element) {
PhpDocTag phpDocTag = PsiTreeUtil.getParentOfType(element, PhpDocTag.class);
if (phpDocTag != null) {
PhpClass phpClass = AnnotationUtil.getAnnotationReference(phpDocTag);
if (phpClass != null && RouteHelper.ROUTE_CLASSES.contains(StringUtils.stripStart(phpClass.getFQN(), "\\"))) {
if (phpClass != null && RouteHelper.isRouteClassAnnotation(phpClass.getFQN())) {
PhpDocComment phpDocComment = PsiTreeUtil.getParentOfType(element, PhpDocComment.class);
if (phpDocComment.getNextPsiSibling() instanceof Method method && method.getAccess().isPublic() && method.getContainingClass() != null) {
int found = 0;
Expand All @@ -130,7 +134,7 @@ private void visitPhp(@NotNull StringLiteralExpression element) {
for (Method ownMethod : method.getContainingClass().getOwnMethods()) {
PhpDocCommentAnnotation phpClassContainer = AnnotationUtil.getPhpDocCommentAnnotationContainer(ownMethod.getDocComment());
if(phpClassContainer != null) {
PhpDocTagAnnotation firstPhpDocBlock = phpClassContainer.getFirstPhpDocBlock(RouteHelper.ROUTE_CLASSES.toArray(String[]::new));
PhpDocTagAnnotation firstPhpDocBlock = phpClassContainer.getFirstPhpDocBlock(RouteHelper.ROUTE_ANNOTATIONS);
if(firstPhpDocBlock != null) {
String name = firstPhpDocBlock.getPropertyValue("name");
if (contents.equals(name)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -812,6 +812,10 @@ public static boolean isInstanceOf(@NotNull PhpClass subjectClass, @NotNull Stri
return false;
}

public static boolean isInstanceOf(@NotNull PhpClass subjectClass, @NotNull String ...expectedClassAsString) {
return Arrays.stream(expectedClassAsString).anyMatch(clazz -> isInstanceOf(subjectClass, clazz));
}

/**
* @param subjectClassAsString eg DateTime
* @param expectedClass eg DateTimeInterface
Expand Down

0 comments on commit 91bca71

Please sign in to comment.