Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

split MissingServiceInspection into language implentations to reduce wall time calls #2361

Merged
merged 1 commit into from
Apr 27, 2024
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 @@ -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>
Loading