Skip to content

Commit cf47fb7

Browse files
committed
add inspection for form type as name deprecation including quickfix
1 parent 38f888d commit cf47fb7

File tree

5 files changed

+169
-0
lines changed

5 files changed

+169
-0
lines changed

META-INF/plugin.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,12 @@
545545
language="yaml"
546546
implementationClass="fr.adrienbrault.idea.symfony2plugin.intentions.yaml.YamlUnquotedColon"/>
547547

548+
<localInspection groupPath="Symfony" shortName="FormTypeAsClassConstant" displayName="Fully-qualified class name (FQCN) in form types"
549+
groupName="Form"
550+
enabledByDefault="true" level="WARNING"
551+
language="PHP"
552+
implementationClass="fr.adrienbrault.idea.symfony2plugin.codeInspection.form.FormTypeAsClassConstantInspection"/>
553+
548554
<intentionAction>
549555
<className>fr.adrienbrault.idea.symfony2plugin.intentions.php.PhpServiceIntention</className>
550556
<category>PHP</category>
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package fr.adrienbrault.idea.symfony2plugin.codeInspection.form;
2+
3+
import com.intellij.codeInspection.*;
4+
import com.intellij.openapi.project.Project;
5+
import com.intellij.psi.PsiElement;
6+
import com.intellij.psi.PsiElementVisitor;
7+
import com.intellij.psi.PsiFile;
8+
import com.intellij.util.ArrayUtil;
9+
import com.jetbrains.php.lang.psi.elements.MethodReference;
10+
import com.jetbrains.php.lang.psi.elements.StringLiteralExpression;
11+
import fr.adrienbrault.idea.symfony2plugin.Symfony2ProjectComponent;
12+
import fr.adrienbrault.idea.symfony2plugin.form.util.FormUtil;
13+
import fr.adrienbrault.idea.symfony2plugin.util.PhpElementsUtil;
14+
import org.jetbrains.annotations.Nls;
15+
import org.jetbrains.annotations.NotNull;
16+
17+
/**
18+
* @author Daniel Espendiller <daniel@espendiller.net>
19+
*/
20+
public class FormTypeAsClassConstantInspection extends LocalInspectionTool {
21+
22+
public static String MESSAGE = "Use fully-qualified class name (FQCN)";
23+
24+
@NotNull
25+
public PsiElementVisitor buildVisitor(final @NotNull ProblemsHolder holder, boolean isOnTheFly) {
26+
if(!Symfony2ProjectComponent.isEnabled(holder.getProject())) {
27+
return super.buildVisitor(holder, isOnTheFly);
28+
}
29+
30+
return new MyPsiElementVisitor(holder);
31+
}
32+
33+
private static class MyPsiElementVisitor extends PsiElementVisitor {
34+
private final ProblemsHolder holder;
35+
36+
MyPsiElementVisitor(ProblemsHolder holder) {
37+
this.holder = holder;
38+
}
39+
40+
@Override
41+
public void visitElement(PsiElement element) {
42+
if(!(element instanceof MethodReference) ||
43+
!ArrayUtil.contains(((MethodReference) element).getName(), "add", "create") ||
44+
!PhpElementsUtil.isMethodReferenceInstanceOf((MethodReference) element, "Symfony\\Component\\Form\\FormBuilderInterface")
45+
) {
46+
47+
super.visitElement(element);
48+
return;
49+
}
50+
51+
PsiElement[] parameters = ((MethodReference) element).getParameters();
52+
if(parameters.length < 2) {
53+
super.visitElement(element);
54+
return;
55+
}
56+
57+
if(!(parameters[1] instanceof StringLiteralExpression) || ((StringLiteralExpression) parameters[1]).getContents().contains("\\")) {
58+
super.visitElement(element);
59+
return;
60+
}
61+
62+
holder.registerProblem(
63+
parameters[1],
64+
MESSAGE,
65+
ProblemHighlightType.WEAK_WARNING, new MyLocalQuickFix(parameters[1])
66+
);
67+
68+
super.visitElement(element);
69+
}
70+
71+
private static class MyLocalQuickFix extends LocalQuickFixOnPsiElement {
72+
73+
MyLocalQuickFix(@NotNull PsiElement element) {
74+
super(element);
75+
}
76+
77+
@NotNull
78+
@Override
79+
public String getText() {
80+
return "Use class constant";
81+
}
82+
83+
@Nls
84+
@NotNull
85+
@Override
86+
public String getFamilyName() {
87+
return "Class constant";
88+
}
89+
90+
@Override
91+
public void invoke(@NotNull Project project, @NotNull PsiFile psiFile, @NotNull PsiElement psiElement, @NotNull PsiElement psiElement1) {
92+
if(!(getStartElement() instanceof StringLiteralExpression)) {
93+
return;
94+
}
95+
96+
try {
97+
FormUtil.replaceFormStringAliasWithClassConstant((StringLiteralExpression) getStartElement());
98+
} catch (Exception ignored) {
99+
}
100+
}
101+
}
102+
}
103+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<html>
2+
<body>
3+
Type names were deprecated use fully-qualified class name (FQCN) instead
4+
<!-- tooltip end -->
5+
</body>
6+
</html>
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package fr.adrienbrault.idea.symfony2plugin.tests.codeInspection.form;
2+
3+
import fr.adrienbrault.idea.symfony2plugin.codeInspection.form.FormTypeAsClassConstantInspection;
4+
import fr.adrienbrault.idea.symfony2plugin.tests.SymfonyLightCodeInsightFixtureTestCase;
5+
6+
import java.io.File;
7+
8+
/**
9+
* @author Daniel Espendiller <daniel@espendiller.net>
10+
* @see fr.adrienbrault.idea.symfony2plugin.codeInspection.form.FormTypeAsClassConstantInspection
11+
*/
12+
public class FormTypeAsClassConstantInspectionTest extends SymfonyLightCodeInsightFixtureTestCase {
13+
14+
public void setUp() throws Exception {
15+
super.setUp();
16+
myFixture.configureFromExistingVirtualFile(myFixture.copyFileToProject("form.php"));
17+
}
18+
19+
public String getTestDataPath() {
20+
return new File(this.getClass().getResource("fixtures").getFile()).getAbsolutePath();
21+
}
22+
23+
public void testThatFormNamesAreInspectedAsDeprecated() {
24+
assertLocalInspectionContains("my_form.php", "<?php\n" +
25+
"/** @var $builder \\Symfony\\Component\\Form\\FormBuilderInterface */\n" +
26+
"$builder->add(null, 'fo<caret>o')",
27+
FormTypeAsClassConstantInspection.MESSAGE
28+
);
29+
30+
assertLocalInspectionContains("my_form.php", "<?php\n" +
31+
"/** @var $builder \\Symfony\\Component\\Form\\FormBuilderInterface */\n" +
32+
"$builder->create(null, 'fo<caret>o')",
33+
FormTypeAsClassConstantInspection.MESSAGE
34+
);
35+
}
36+
37+
public void testThatFormNamesWithFqnAsStringNotDeprecated() {
38+
assertLocalInspectionContainsNotContains("my_form.php", "<?php\n" +
39+
"/** @var $builder \\Symfony\\Component\\Form\\FormBuilderInterface */\n" +
40+
"$builder->add(null, 'Foo\\B<caret>ar')",
41+
FormTypeAsClassConstantInspection.MESSAGE
42+
);
43+
}
44+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace Symfony\Component\Form
4+
{
5+
interface FormBuilderInterface
6+
{
7+
public function add();
8+
public function create();
9+
}
10+
}

0 commit comments

Comments
 (0)