Skip to content

Commit d2f5e7d

Browse files
authored
Merge pull request #755 from bohdan-harniuk/uct-inspection-inherited-non-existent-interface
UCT-712: Developed inspection about inherited non existent interface
2 parents 09b10b0 + 358373e commit d2f5e7d

File tree

10 files changed

+176
-103
lines changed

10 files changed

+176
-103
lines changed

resources/META-INF/plugin.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,13 @@
354354
enabledByDefault="false"
355355
level="ERROR"
356356
implementationClass="com.magento.idea.magento2uct.inspections.php.existence.ImportingNonExistentInterface"/>
357+
<localInspection language="PHP" groupPath="UCT"
358+
shortName="InheritedNonExistentInterface"
359+
bundle="uct.bundle.inspection" key="inspection.displayName.InheritedNonExistentInterface"
360+
groupBundle="uct.bundle.inspection" groupKey="inspection.existence.group.name"
361+
enabledByDefault="false"
362+
level="ERROR"
363+
implementationClass="com.magento.idea.magento2uct.inspections.php.existence.InheritedNonExistentInterface"/>
357364
<!-- \UCT inspection -->
358365

359366
<internalFileTemplate name="Magento Composer JSON"/>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<html>
2+
<body>
3+
<p>[1317] The inherited interface is no longer present in the codebase.</p>
4+
<!-- tooltip end -->
5+
</body>
6+
</html>

resources/uct/bundle/inspection.properties

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ inspection.displayName.CallingDeprecatedMethod=Call @deprecated method
1515
inspection.displayName.UsingDeprecatedProperty=Using @deprecated property
1616
inspection.displayName.ImportingNonExistentClass=Importing non-existent Adobe Commerce class
1717
inspection.displayName.ImportingNonExistentInterface=Importing non-existent Adobe Commerce interface
18+
inspection.displayName.InheritedNonExistentInterface=Inherited non-existent Adobe Commerce interface
1819
customCode.warnings.deprecated.1131=[1131] Extending from @deprecated class ''{0}''
1920
customCode.warnings.deprecated.1132=[1132] Importing @deprecated class ''{0}''
2021
customCode.warnings.deprecated.1134=[1134] Using @deprecated class ''{0}''
@@ -31,3 +32,5 @@ customCode.critical.existence.1112=[1112] Imported non-existent class ''{0}''
3132
customCode.critical.existence.1112.changelog=[1112] Imported class ''{0}'' that is removed in the ''{1}''
3233
customCode.critical.existence.1312=[1312] Imported non-existent interface ''{0}''
3334
customCode.critical.existence.1312.changelog=[1312] Imported interface ''{0}'' that is removed in the ''{1}''
35+
customCode.critical.existence.1317=[1317] Inherited non-existent interface ''{0}''
36+
customCode.critical.existence.1317.changelog=[1317] Inherited interface ''{0}'' that is removed in the ''{1}''

src/com/magento/idea/magento2uct/inspections/php/ImportInspection.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ public void visitPhpUseList(final PhpUseList useList) {
4848
}
4949

5050
for (final PhpUse use : useList.getDeclarations()) {
51+
if (use.getName().isEmpty()) {
52+
continue;
53+
}
5154
execute(project, problemsHolder, use, isInterface(use));
5255
}
5356
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* Copyright © Magento, Inc. All rights reserved.
3+
* See COPYING.txt for license details.
4+
*/
5+
6+
package com.magento.idea.magento2uct.inspections.php;
7+
8+
import com.intellij.codeInspection.ProblemsHolder;
9+
import com.intellij.openapi.project.Project;
10+
import com.intellij.psi.PsiElement;
11+
import com.intellij.psi.PsiElementVisitor;
12+
import com.jetbrains.php.lang.inspections.PhpInspection;
13+
import com.jetbrains.php.lang.psi.elements.ClassReference;
14+
import com.jetbrains.php.lang.psi.elements.PhpClass;
15+
import com.jetbrains.php.lang.psi.visitors.PhpElementVisitor;
16+
import com.magento.idea.magento2uct.packages.IssueSeverityLevel;
17+
import com.magento.idea.magento2uct.settings.UctSettingsService;
18+
import org.jetbrains.annotations.NotNull;
19+
20+
public abstract class InheritedInterfaceInspection extends PhpInspection {
21+
22+
@Override
23+
public @NotNull PsiElementVisitor buildVisitor(
24+
final @NotNull ProblemsHolder problemsHolder,
25+
final boolean isOnTheFly
26+
) {
27+
return new PhpElementVisitor() {
28+
29+
@Override
30+
public void visitPhpClass(final PhpClass clazz) {
31+
final Project project = clazz.getProject();
32+
final UctSettingsService settings = UctSettingsService.getInstance(project);
33+
34+
if (!clazz.isInterface()
35+
|| !settings.isEnabled()
36+
|| !settings.isIssueLevelSatisfiable(getSeverityLevel())
37+
) {
38+
return;
39+
}
40+
41+
for (final ClassReference ref : clazz.getExtendsList().getReferenceElements()) {
42+
final String interfaceFqn = ref.getFQN();
43+
final PsiElement interfaceClass = ref.resolve();
44+
45+
if (interfaceFqn == null || !(interfaceClass instanceof PhpClass)) {
46+
continue;
47+
}
48+
execute(project, problemsHolder, ref, interfaceFqn);
49+
}
50+
}
51+
};
52+
}
53+
54+
/**
55+
* Implement this method to specify inspection logic.
56+
*
57+
* @param project Project
58+
* @param problemsHolder ProblemsHolder
59+
* @param reference ClassReference
60+
* @param interfaceFqn String
61+
*/
62+
protected abstract void execute(
63+
final Project project,
64+
final @NotNull ProblemsHolder problemsHolder,
65+
final ClassReference reference,
66+
final String interfaceFqn
67+
);
68+
69+
/**
70+
* Implement this method to specify issue severity level for target inspection.
71+
*
72+
* @return IssueSeverityLevel
73+
*/
74+
protected abstract IssueSeverityLevel getSeverityLevel();
75+
}

src/com/magento/idea/magento2uct/inspections/php/deprecation/ImplementedDeprecatedInterface.java

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,8 @@ public void visitPhpClass(final PhpClass clazz) {
5959
}
6060
final boolean isDeprecated = VersionStateManager
6161
.getInstance(project).isDeprecated(interfaceFqn);
62-
Pair<Boolean, String> checkResult = null;
6362

64-
if (isDeprecated || (checkResult = InheritedDeprecatedInterface//NOPMD
65-
.checkDeprecatedParent((PhpClass) interfaceClass)).getFirst()) {
63+
if (isDeprecated) {
6664
if (problemsHolder instanceof UctProblemsHolder) {
6765
((UctProblemsHolder) problemsHolder).setReservedErrorCode(
6866
SupportedIssue.IMPLEMENTED_DEPRECATED_INTERFACE.getCode()
@@ -71,9 +69,7 @@ public void visitPhpClass(final PhpClass clazz) {
7169
problemsHolder.registerProblem(
7270
ref,
7371
SupportedIssue.IMPLEMENTED_DEPRECATED_INTERFACE.getMessage(
74-
checkResult == null
75-
? interfaceFqn
76-
: checkResult.getSecond()
72+
interfaceFqn
7773
),
7874
ProblemHighlightType.LIKE_DEPRECATED
7975
);
@@ -132,12 +128,6 @@ private Pair<Boolean, String> checkImplements(final PhpClass clazz) {
132128
.isDeprecated(interfaceFqn)) {
133129
return new Pair<>(true, interfaceFqn);
134130
}
135-
final Pair<Boolean, String> parentCheck = InheritedDeprecatedInterface
136-
.checkDeprecatedParent((PhpClass) interfaceClass);
137-
138-
if (parentCheck.getFirst()) {
139-
return parentCheck;
140-
}
141131
}
142132

143133
return new Pair<>(false, null);

src/com/magento/idea/magento2uct/inspections/php/deprecation/InheritedDeprecatedInterface.java

Lines changed: 21 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -8,108 +8,39 @@
88
import com.intellij.codeInspection.ProblemHighlightType;
99
import com.intellij.codeInspection.ProblemsHolder;
1010
import com.intellij.openapi.project.Project;
11-
import com.intellij.openapi.util.Pair;
12-
import com.intellij.psi.PsiElement;
13-
import com.intellij.psi.PsiElementVisitor;
14-
import com.jetbrains.php.lang.inspections.PhpInspection;
1511
import com.jetbrains.php.lang.psi.elements.ClassReference;
16-
import com.jetbrains.php.lang.psi.elements.PhpClass;
17-
import com.jetbrains.php.lang.psi.visitors.PhpElementVisitor;
1812
import com.magento.idea.magento2uct.inspections.UctProblemsHolder;
13+
import com.magento.idea.magento2uct.inspections.php.InheritedInterfaceInspection;
14+
import com.magento.idea.magento2uct.packages.IssueSeverityLevel;
1915
import com.magento.idea.magento2uct.packages.SupportedIssue;
20-
import com.magento.idea.magento2uct.settings.UctSettingsService;
2116
import com.magento.idea.magento2uct.versioning.VersionStateManager;
2217
import org.jetbrains.annotations.NotNull;
2318

24-
public class InheritedDeprecatedInterface extends PhpInspection {
19+
public class InheritedDeprecatedInterface extends InheritedInterfaceInspection {
2520

2621
@Override
27-
@SuppressWarnings("PMD.CognitiveComplexity")
28-
public @NotNull PsiElementVisitor buildVisitor(
22+
protected void execute(
23+
final Project project,
2924
final @NotNull ProblemsHolder problemsHolder,
30-
final boolean isOnTheFly
25+
final ClassReference reference,
26+
final String interfaceFqn
3127
) {
32-
return new PhpElementVisitor() {
33-
34-
@Override
35-
public void visitPhpClass(final PhpClass clazz) {
36-
final Project project = clazz.getProject();
37-
final UctSettingsService settings = UctSettingsService.getInstance(project);
38-
39-
if (!settings.isEnabled() || !settings.isIssueLevelSatisfiable(
40-
SupportedIssue.INHERITED_DEPRECATED_INTERFACE.getLevel())
41-
) {
42-
return;
43-
}
44-
if (!clazz.isInterface()) {
45-
return;
46-
}
47-
for (final ClassReference ref : clazz.getExtendsList().getReferenceElements()) {
48-
final String interfaceFqn = ref.getFQN();
49-
final PsiElement interfaceClass = ref.resolve();
50-
51-
if (interfaceFqn == null || !(interfaceClass instanceof PhpClass)) {
52-
continue;
53-
}
54-
Pair<Boolean, String> parentCheckResult = null;
55-
56-
if (VersionStateManager.getInstance(project).isDeprecated(interfaceFqn)//NOPMD
57-
|| (parentCheckResult = checkDeprecatedParent(
58-
(PhpClass) interfaceClass
59-
)).getFirst()) {
60-
if (problemsHolder instanceof UctProblemsHolder) {
61-
((UctProblemsHolder) problemsHolder).setReservedErrorCode(
62-
SupportedIssue.INHERITED_DEPRECATED_INTERFACE.getCode()
63-
);
64-
}
65-
problemsHolder.registerProblem(
66-
ref,
67-
SupportedIssue.INHERITED_DEPRECATED_INTERFACE.getMessage(
68-
parentCheckResult == null
69-
? interfaceFqn
70-
: parentCheckResult.getSecond()
71-
),
72-
ProblemHighlightType.LIKE_DEPRECATED
73-
);
74-
}
75-
}
76-
}
77-
};
78-
}
79-
80-
/**
81-
* Check if specified interface inherited from deprecated parent.
82-
*
83-
* @param interfaceClass PhpClass
84-
*
85-
* @return Pair[Boolean, String]
86-
*/
87-
public static Pair<Boolean, String> checkDeprecatedParent(final PhpClass interfaceClass) {
88-
if (!interfaceClass.isInterface()) {
89-
return new Pair<>(false, null);
90-
}
91-
for (final ClassReference interfaceRef
92-
: interfaceClass.getExtendsList().getReferenceElements()) {
93-
final String interfaceFqn = interfaceRef.getFQN();
94-
95-
if (interfaceFqn == null) {
96-
continue;
97-
}
98-
99-
if (VersionStateManager.getInstance(interfaceClass.getProject())
100-
.isDeprecated(interfaceFqn)) {
101-
return new Pair<>(true, interfaceFqn);
102-
}
103-
}
104-
105-
for (final PhpClass parent : interfaceClass.getImplementedInterfaces()) {
106-
final Pair<Boolean, String> checkResult = checkDeprecatedParent(parent);
107-
108-
if (checkResult.getFirst()) {
109-
return checkResult;
28+
if (VersionStateManager.getInstance(project).isDeprecated(interfaceFqn)) {
29+
if (problemsHolder instanceof UctProblemsHolder) {
30+
((UctProblemsHolder) problemsHolder).setReservedErrorCode(
31+
SupportedIssue.INHERITED_DEPRECATED_INTERFACE.getCode()
32+
);
11033
}
34+
problemsHolder.registerProblem(
35+
reference,
36+
SupportedIssue.INHERITED_DEPRECATED_INTERFACE.getMessage(interfaceFqn),
37+
ProblemHighlightType.LIKE_DEPRECATED
38+
);
11139
}
40+
}
11241

113-
return new Pair<>(false, null);
42+
@Override
43+
protected IssueSeverityLevel getSeverityLevel() {
44+
return SupportedIssue.INHERITED_DEPRECATED_INTERFACE.getLevel();
11445
}
11546
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright © Magento, Inc. All rights reserved.
3+
* See COPYING.txt for license details.
4+
*/
5+
6+
package com.magento.idea.magento2uct.inspections.php.existence;
7+
8+
import com.intellij.codeInspection.ProblemHighlightType;
9+
import com.intellij.codeInspection.ProblemsHolder;
10+
import com.intellij.openapi.project.Project;
11+
import com.jetbrains.php.lang.psi.elements.ClassReference;
12+
import com.magento.idea.magento2uct.inspections.UctProblemsHolder;
13+
import com.magento.idea.magento2uct.inspections.php.InheritedInterfaceInspection;
14+
import com.magento.idea.magento2uct.packages.IssueSeverityLevel;
15+
import com.magento.idea.magento2uct.packages.SupportedIssue;
16+
import com.magento.idea.magento2uct.versioning.VersionStateManager;
17+
import org.jetbrains.annotations.NotNull;
18+
19+
public class InheritedNonExistentInterface extends InheritedInterfaceInspection {
20+
21+
@Override
22+
protected void execute(
23+
final Project project,
24+
final @NotNull ProblemsHolder problemsHolder,
25+
final ClassReference reference,
26+
final String interfaceFqn
27+
) {
28+
if (VersionStateManager.getInstance(project).isExists(interfaceFqn)) {
29+
return;
30+
}
31+
final String removedIn = VersionStateManager.getInstance(project).getRemovedInVersion();
32+
final String message = removedIn.isEmpty()
33+
? SupportedIssue.INHERITED_NON_EXISTENT_INTERFACE.getMessage(interfaceFqn)
34+
: SupportedIssue.INHERITED_NON_EXISTENT_INTERFACE.getChangelogMessage(
35+
interfaceFqn, removedIn);
36+
37+
if (problemsHolder instanceof UctProblemsHolder) {
38+
((UctProblemsHolder) problemsHolder).setReservedErrorCode(
39+
SupportedIssue.INHERITED_NON_EXISTENT_INTERFACE.getCode()
40+
);
41+
}
42+
problemsHolder.registerProblem(reference, message, ProblemHighlightType.ERROR);
43+
}
44+
45+
@Override
46+
protected IssueSeverityLevel getSeverityLevel() {
47+
return SupportedIssue.INHERITED_NON_EXISTENT_INTERFACE.getLevel();
48+
}
49+
}

src/com/magento/idea/magento2uct/packages/SupportedIssue.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import com.magento.idea.magento2uct.inspections.php.deprecation.UsingDeprecatedProperty;
2424
import com.magento.idea.magento2uct.inspections.php.existence.ImportingNonExistentClass;
2525
import com.magento.idea.magento2uct.inspections.php.existence.ImportingNonExistentInterface;
26+
import com.magento.idea.magento2uct.inspections.php.existence.InheritedNonExistentInterface;
2627
import java.lang.reflect.InvocationTargetException;
2728
import java.util.LinkedList;
2829
import java.util.List;
@@ -115,6 +116,13 @@ public enum SupportedIssue {
115116
"customCode.critical.existence.1312",
116117
ImportingNonExistentInterface.class,
117118
"customCode.critical.existence.1312.changelog"
119+
),
120+
INHERITED_NON_EXISTENT_INTERFACE(
121+
1317,
122+
IssueSeverityLevel.CRITICAL,
123+
"customCode.critical.existence.1317",
124+
InheritedNonExistentInterface.class,
125+
"customCode.critical.existence.1317.changelog"
118126
);
119127

120128
private final int code;

src/com/magento/idea/magento2uct/versioning/indexes/data/ExistenceStateIndex.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,10 @@ public boolean has(final @NotNull String fqn) {
6666

6767
if (changelog.containsKey(fqn)) {
6868
version = changelog.get(fqn);
69+
return false;
6970
}
7071

71-
return false;
72+
return true;
7273
}
7374

7475
/**

0 commit comments

Comments
 (0)