Skip to content

Commit

Permalink
Merge pull request #2361 from Haehnchen/feature/service-missing-inspe…
Browse files Browse the repository at this point in the history
…ction-language

split MissingServiceInspection into language implentations to reduce wall time calls
  • Loading branch information
Haehnchen committed Apr 27, 2024
2 parents ce718b8 + 92500f3 commit 2d25b90
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,81 +17,102 @@
import fr.adrienbrault.idea.symfony2plugin.util.yaml.YamlHelper;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.yaml.YAMLLanguage;

/**
* @author Daniel Espendiller <[email protected]>
*/
public class MissingServiceInspection extends LocalInspectionTool {
public class MissingServiceInspection {

public static final String INSPECTION_MESSAGE = "Symfony: Missing Service";

@NotNull
public PsiElementVisitor buildVisitor(final @NotNull ProblemsHolder holder, boolean isOnTheFly) {
if (!Symfony2ProjectComponent.isEnabled(holder.getProject())) {
return super.buildVisitor(holder, isOnTheFly);
}
public static class PhpLocalInspectionTool extends LocalInspectionTool {
@Override
public @NotNull PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
if (!Symfony2ProjectComponent.isEnabled(holder.getProject())) {
return super.buildVisitor(holder, isOnTheFly);
}

return new MyPsiElementVisitor(holder);
}
return new PsiElementVisitor() {
private ContainerCollectionResolver.LazyServiceCollector lazyServiceCollector;

@Override
public void visitElement(@NotNull PsiElement element) {
if(element.getLanguage() == PhpLanguage.INSTANCE && element instanceof StringLiteralExpression) {
// PHP
MethodReference methodReference = PsiElementUtils.getMethodReferenceWithFirstStringParameter((StringLiteralExpression) element);
if (methodReference != null && PhpElementsUtil.isMethodReferenceInstanceOf(methodReference, ServiceContainerUtil.SERVICE_GET_SIGNATURES)) {
String serviceName = PhpElementsUtil.getFirstArgumentStringValue(methodReference);
if (StringUtils.isNotBlank(serviceName) && !hasService(serviceName)) {
holder.registerProblem(element, INSPECTION_MESSAGE, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
}
}

// #[Autowire(service: 'foobar')]
PsiElement leafText = PsiElementUtils.getTextLeafElementFromStringLiteralExpression((StringLiteralExpression) element);

boolean isAttributeLeaf = leafText != null && (
PhpElementsUtil.getAttributeNamedArgumentStringPattern(ServiceContainerUtil.AUTOWIRE_ATTRIBUTE_CLASS, "service").accepts(leafText)
|| PhpElementsUtil.getFirstAttributeStringPattern(ServiceContainerUtil.DECORATOR_ATTRIBUTE_CLASS).accepts(leafText)
);

if (isAttributeLeaf) {
String serviceName = ((StringLiteralExpression) element).getContents();
if (StringUtils.isNotBlank(serviceName) && !hasService(serviceName)) {
holder.registerProblem(element, INSPECTION_MESSAGE, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
}
}

private static class MyPsiElementVisitor extends PsiElementVisitor {
private final ProblemsHolder holder;
private ContainerCollectionResolver.LazyServiceCollector lazyServiceCollector;
}

MyPsiElementVisitor(@NotNull ProblemsHolder holder) {
this.holder = holder;
}
super.visitElement(element);
}

@Override
public void visitElement(PsiElement element) {
if(element.getLanguage() == PhpLanguage.INSTANCE && element instanceof StringLiteralExpression) {
// PHP
MethodReference methodReference = PsiElementUtils.getMethodReferenceWithFirstStringParameter((StringLiteralExpression) element);
if (methodReference != null && PhpElementsUtil.isMethodReferenceInstanceOf(methodReference, ServiceContainerUtil.SERVICE_GET_SIGNATURES)) {
String serviceName = PhpElementsUtil.getFirstArgumentStringValue(methodReference);
if (StringUtils.isNotBlank(serviceName) && !hasService(serviceName)) {
holder.registerProblem(element, INSPECTION_MESSAGE, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
private boolean hasService(@NotNull String serviceName) {
if (this.lazyServiceCollector == null) {
this.lazyServiceCollector = new ContainerCollectionResolver.LazyServiceCollector(holder.getProject());
}

return ContainerCollectionResolver.hasServiceName(lazyServiceCollector, serviceName);
}
};

// #[Autowire(service: 'foobar')]
PsiElement leafText = PsiElementUtils.getTextLeafElementFromStringLiteralExpression((StringLiteralExpression) element);
}

boolean isAttributeLeaf = leafText != null && (
PhpElementsUtil.getAttributeNamedArgumentStringPattern(ServiceContainerUtil.AUTOWIRE_ATTRIBUTE_CLASS, "service").accepts(leafText)
|| PhpElementsUtil.getFirstAttributeStringPattern(ServiceContainerUtil.DECORATOR_ATTRIBUTE_CLASS).accepts(leafText)
);
}

if (isAttributeLeaf) {
String serviceName = ((StringLiteralExpression) element).getContents();
if (StringUtils.isNotBlank(serviceName) && !hasService(serviceName)) {
holder.registerProblem(element, INSPECTION_MESSAGE, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
}
}

} else if(element.getLanguage() == YAMLLanguage.INSTANCE) {
// yaml
public static class YamlLocalInspectionTool extends LocalInspectionTool {
@Override
public @NotNull PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
if (!Symfony2ProjectComponent.isEnabled(holder.getProject())) {
return super.buildVisitor(holder, isOnTheFly);
}

return new PsiElementVisitor() {
private ContainerCollectionResolver.LazyServiceCollector lazyServiceCollector;

if (YamlElementPatternHelper.getServiceDefinition().accepts(element) && YamlElementPatternHelper.getInsideServiceKeyPattern().accepts(element)) {
String serviceName = YamlHelper.trimSpecialSyntaxServiceName(PsiElementUtils.getText(element));
@Override
public void visitElement(@NotNull PsiElement element) {
if (YamlElementPatternHelper.getServiceDefinition().accepts(element) && YamlElementPatternHelper.getInsideServiceKeyPattern().accepts(element)) {
String serviceName = YamlHelper.trimSpecialSyntaxServiceName(PsiElementUtils.getText(element));

// dont mark "@", "@?", "@@" escaping and expressions
if (serviceName.length() > 2 && !serviceName.startsWith("=") && !serviceName.startsWith("@") && !hasService(serviceName)) {
holder.registerProblem(element, INSPECTION_MESSAGE, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
// dont mark "@", "@?", "@@" escaping and expressions
if (serviceName.length() > 2 && !serviceName.startsWith("=") && !serviceName.startsWith("@") && !hasService(serviceName)) {
holder.registerProblem(element, INSPECTION_MESSAGE, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
}
}
}
}

super.visitElement(element);
}
super.visitElement(element);
}

private boolean hasService(@NotNull String serviceName) {
if (this.lazyServiceCollector == null) {
this.lazyServiceCollector = new ContainerCollectionResolver.LazyServiceCollector(holder.getProject());
}
private boolean hasService(@NotNull String serviceName) {
if (this.lazyServiceCollector == null) {
this.lazyServiceCollector = new ContainerCollectionResolver.LazyServiceCollector(holder.getProject());
}

return ContainerCollectionResolver.hasServiceName(lazyServiceCollector, serviceName);
return ContainerCollectionResolver.hasServiceName(lazyServiceCollector, serviceName);
}
};
}
}
}
14 changes: 11 additions & 3 deletions src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -472,11 +472,19 @@
language="PHP"
implementationClass="fr.adrienbrault.idea.symfony2plugin.templating.PhpTemplateMissingInspection"/>

<localInspection groupPath="Symfony" shortName="MissingService" displayName="Missing Service"
<localInspection groupPath="Symfony" shortName="MissingServiceXml" displayName="Missing Service in XML definition"
groupName="Service"
enabledByDefault="true"
level="WARNING"
implementationClass="fr.adrienbrault.idea.symfony2plugin.dic.inspection.MissingServiceInspection"/>
language="PHP"
implementationClass="fr.adrienbrault.idea.symfony2plugin.dic.inspection.MissingServiceInspection$PhpLocalInspectionTool"/>

<localInspection groupPath="Symfony" shortName="MissingServiceYaml" displayName="Missing Service in yaml definition"
groupName="Service"
enabledByDefault="true"
level="WARNING"
language="yaml"
implementationClass="fr.adrienbrault.idea.symfony2plugin.dic.inspection.MissingServiceInspection$YamlLocalInspectionTool"/>

<localInspection groupPath="Symfony" shortName="XmlServiceInstanceInspection" displayName="XML: Wrong Service Instance"
groupName="Service"
Expand Down Expand Up @@ -549,7 +557,7 @@
language="PHP"
implementationClass="fr.adrienbrault.idea.symfony2plugin.templating.inspection.TemplateExistsAnnotationPhpAttributeLocalInspection"/>

<localInspection groupPath="Symfony" shortName="RouteControllerDeprecatedInspectionXml" displayName="Deprecated Action in XML Definition"
<localInspection groupPath="Symfony" shortName="RouteControllerDeprecatedInspectionXml" displayName="Deprecated Action in XML definition"
groupName="Route"
enabledByDefault="true"
level="WARNING"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<html>
<body>
No Symfony service with given id was found. See <a href="https://symfony.com/doc/current/service_container.html?phpstorm">Symfony documentation</a> for more help
</body>
</html>

0 comments on commit 2d25b90

Please sign in to comment.