Skip to content

Commit be7dc43

Browse files
authored
Merge pull request #752 from bohdan-harniuk/uct-inspection-non-existent-class
UCT-706: Developed existence check through VersionStateManager, added ImportingNonExistenceClass inspection
2 parents 6140228 + 0f45049 commit be7dc43

File tree

10 files changed

+270
-90
lines changed

10 files changed

+270
-90
lines changed

resources/META-INF/plugin.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,13 @@
340340
enabledByDefault="false"
341341
level="WARNING"
342342
implementationClass="com.magento.idea.magento2uct.inspections.php.deprecation.UsingDeprecatedProperty"/>
343+
<localInspection language="PHP" groupPath="UCT"
344+
shortName="ImportingNonExistentClass"
345+
bundle="uct.bundle.inspection" key="inspection.displayName.ImportingNonExistentClass"
346+
groupBundle="uct.bundle.inspection" groupKey="inspection.existence.group.name"
347+
enabledByDefault="false"
348+
level="ERROR"
349+
implementationClass="com.magento.idea.magento2uct.inspections.php.existence.ImportingNonExistentClass"/>
343350
<!-- \UCT inspection -->
344351

345352
<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>[1112] The imported class is no longer present in the codebase.</p>
4+
<!-- tooltip end -->
5+
</body>
6+
</html>

resources/uct/bundle/inspection.properties

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
inspection.deprecation.group.name=Deprecation Inspections
1+
inspection.deprecation.group.name=Deprecation
2+
inspection.existence.group.name=Existence
23
inspection.issues.description.link=Check https://devdocs.magento.com/upgrade-compatibility-tool/errors.html for a detailed list of Upgrade Compatibility Tool errors.
34
inspection.displayName.ExtendingDeprecatedClass=Extending from @deprecated class
45
inspection.displayName.ImportingDeprecatedClass=Importing @deprecated class
@@ -12,6 +13,7 @@ inspection.displayName.InheritedDeprecatedInterface=Inherited from @deprecated i
1213
inspection.displayName.ImplementedDeprecatedInterface=Implemented @deprecated interface
1314
inspection.displayName.CallingDeprecatedMethod=Call @deprecated method
1415
inspection.displayName.UsingDeprecatedProperty=Using @deprecated property
16+
inspection.displayName.ImportingNonExistentClass=Importing non-existent Adobe Commerce class
1517
customCode.warnings.deprecated.1131=[1131] Extending from @deprecated class ''{0}''
1618
customCode.warnings.deprecated.1132=[1132] Importing @deprecated class ''{0}''
1719
customCode.warnings.deprecated.1134=[1134] Using @deprecated class ''{0}''
@@ -24,3 +26,5 @@ customCode.warnings.deprecated.1338=[1338] Implemented @deprecated interface ''{
2426
customCode.warnings.deprecated.1439=[1439] Call @deprecated method ''{0}''
2527
customCode.warnings.deprecated.1534=[1534] Using @deprecated property ''{0}''
2628
customCode.warnings.deprecated.1535=[1535] Overriding @deprecated property ''{0}''
29+
customCode.critical.existence.1112=[1112] Imported non-existent class ''{0}''
30+
customCode.critical.existence.1112.changelog=[1112] Imported class ''{0}'' that is removed in the ''{1}''
Lines changed: 37 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* See COPYING.txt for license details.
44
*/
55

6-
package com.magento.idea.magento2uct.inspections.php.deprecation;
6+
package com.magento.idea.magento2uct.inspections.php;
77

88
import com.intellij.codeInspection.ProblemsHolder;
99
import com.intellij.openapi.project.Project;
@@ -20,33 +20,11 @@
2020
import com.magento.idea.magento2plugin.util.GetFirstClassOfFile;
2121
import com.magento.idea.magento2uct.packages.IssueSeverityLevel;
2222
import com.magento.idea.magento2uct.settings.UctSettingsService;
23-
import com.magento.idea.magento2uct.versioning.VersionStateManager;
2423
import org.jetbrains.annotations.NotNull;
2524

26-
public abstract class ImportingDeprecatedType extends PhpInspection {
27-
28-
/**
29-
* Register type specific problem.
30-
*
31-
* @param problemsHolder ProblemsHolder
32-
* @param use PhpUse
33-
* @param isInterface boolean
34-
*/
35-
protected abstract void registerProblem(
36-
final @NotNull ProblemsHolder problemsHolder,
37-
final PhpUse use,
38-
final boolean isInterface
39-
);
40-
41-
/**
42-
* Get issue severity level for concrete inspection.
43-
*
44-
* @return IssueSeverityLevel
45-
*/
46-
protected abstract IssueSeverityLevel getSeverityLevel();
25+
public abstract class ImportInspection extends PhpInspection {
4726

4827
@Override
49-
@SuppressWarnings({"PMD.CognitiveComplexity", "PMD.AvoidDeeplyNestedIfStmts"})
5028
public @NotNull PsiElementVisitor buildVisitor(
5129
final @NotNull ProblemsHolder problemsHolder,
5230
final boolean isOnTheFly
@@ -62,45 +40,57 @@ public void visitPhpUseList(final PhpUseList useList) {
6240
|| !settings.isIssueLevelSatisfiable(getSeverityLevel())) {
6341
return;
6442
}
65-
final PhpClass phpClass = getParentClass(useList);
43+
final PsiFile file = useList.getContainingFile();
44+
final PhpClass phpClass = GetFirstClassOfFile.getInstance().execute((PhpFile) file);
6645

6746
if (phpClass == null) {
6847
return;
6948
}
70-
for (final PhpUse use : useList.getDeclarations()) {
71-
if (VersionStateManager.getInstance(project).isDeprecated(use.getFQN())) {
72-
final PhpReference phpReference = use.getTargetReference();
73-
boolean isInterface = false;
74-
75-
if (phpReference != null) {
76-
final PsiElement element = phpReference.resolve();
7749

78-
if (element instanceof PhpClass
79-
&& ((PhpClass) element).isInterface()) {
80-
isInterface = true;
81-
}
82-
}
83-
registerProblem(problemsHolder, use, isInterface);
84-
}
50+
for (final PhpUse use : useList.getDeclarations()) {
51+
execute(project, problemsHolder, use, isInterface(use));
8552
}
8653
}
8754

8855
/**
89-
* Get parent class for use list.
56+
* Check if inspected use is an interface.
9057
*
91-
* @param useList PhpUseList
58+
* @param use PhpUse
9259
*
93-
* @return PhpClass
60+
* @return boolean
9461
*/
95-
private PhpClass getParentClass(final PhpUseList useList) {
96-
final PsiFile file = useList.getContainingFile();
62+
private boolean isInterface(final PhpUse use) {
63+
final PhpReference phpReference = use.getTargetReference();
9764

98-
if (!(file instanceof PhpFile)) {
99-
return null;
65+
if (phpReference != null) {
66+
final PsiElement element = phpReference.resolve();
67+
return element instanceof PhpClass && ((PhpClass) element).isInterface();
10068
}
10169

102-
return GetFirstClassOfFile.getInstance().execute((PhpFile) file);
70+
return false;
10371
}
10472
};
10573
}
74+
75+
/**
76+
* Implement this method to specify inspection logic.
77+
*
78+
* @param project Project
79+
* @param problemsHolder ProblemsHolder
80+
* @param use PhpUse
81+
* @param isInterface boolean
82+
*/
83+
protected abstract void execute(
84+
final Project project,
85+
final @NotNull ProblemsHolder problemsHolder,
86+
final PhpUse use,
87+
final boolean isInterface
88+
);
89+
90+
/**
91+
* Implement this method to specify issue severity level for target inspection.
92+
*
93+
* @return IssueSeverityLevel
94+
*/
95+
protected abstract IssueSeverityLevel getSeverityLevel();
10696
}

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

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,28 @@
77

88
import com.intellij.codeInspection.ProblemHighlightType;
99
import com.intellij.codeInspection.ProblemsHolder;
10+
import com.intellij.openapi.project.Project;
1011
import com.jetbrains.php.lang.psi.elements.PhpUse;
1112
import com.magento.idea.magento2uct.inspections.UctProblemsHolder;
13+
import com.magento.idea.magento2uct.inspections.php.ImportInspection;
1214
import com.magento.idea.magento2uct.packages.IssueSeverityLevel;
1315
import com.magento.idea.magento2uct.packages.SupportedIssue;
16+
import com.magento.idea.magento2uct.versioning.VersionStateManager;
1417
import org.jetbrains.annotations.NotNull;
1518

16-
public class ImportingDeprecatedClass extends ImportingDeprecatedType {
19+
public class ImportingDeprecatedClass extends ImportInspection {
1720

1821
@Override
19-
protected void registerProblem(
22+
protected void execute(
23+
final Project project,
2024
final @NotNull ProblemsHolder problemsHolder,
2125
final PhpUse use,
2226
final boolean isInterface
2327
) {
24-
if (!isInterface) {
28+
if (VersionStateManager.getInstance(project).isDeprecated(use.getFQN())) {
29+
if (isInterface) {
30+
return;
31+
}
2532
if (problemsHolder instanceof UctProblemsHolder) {
2633
((UctProblemsHolder) problemsHolder).setReservedErrorCode(
2734
SupportedIssue.IMPORTING_DEPRECATED_CLASS.getCode()

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

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,28 @@
77

88
import com.intellij.codeInspection.ProblemHighlightType;
99
import com.intellij.codeInspection.ProblemsHolder;
10+
import com.intellij.openapi.project.Project;
1011
import com.jetbrains.php.lang.psi.elements.PhpUse;
1112
import com.magento.idea.magento2uct.inspections.UctProblemsHolder;
13+
import com.magento.idea.magento2uct.inspections.php.ImportInspection;
1214
import com.magento.idea.magento2uct.packages.IssueSeverityLevel;
1315
import com.magento.idea.magento2uct.packages.SupportedIssue;
16+
import com.magento.idea.magento2uct.versioning.VersionStateManager;
1417
import org.jetbrains.annotations.NotNull;
1518

16-
public class ImportingDeprecatedInterface extends ImportingDeprecatedType {
19+
public class ImportingDeprecatedInterface extends ImportInspection {
1720

1821
@Override
19-
protected void registerProblem(
22+
protected void execute(
23+
final Project project,
2024
final @NotNull ProblemsHolder problemsHolder,
2125
final PhpUse use,
2226
final boolean isInterface
2327
) {
24-
if (isInterface) {
28+
if (VersionStateManager.getInstance(project).isDeprecated(use.getFQN())) {
29+
if (!isInterface) {
30+
return;
31+
}
2532
if (problemsHolder instanceof UctProblemsHolder) {
2633
((UctProblemsHolder) problemsHolder).setReservedErrorCode(
2734
SupportedIssue.IMPORTING_DEPRECATED_INTERFACE.getCode()
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
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.PhpUse;
12+
import com.magento.idea.magento2uct.inspections.UctProblemsHolder;
13+
import com.magento.idea.magento2uct.inspections.php.ImportInspection;
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 ImportingNonExistentClass extends ImportInspection {
20+
21+
@Override
22+
protected void execute(
23+
final Project project,
24+
final @NotNull ProblemsHolder problemsHolder,
25+
final PhpUse use,
26+
final boolean isInterface
27+
) {
28+
if (isInterface || VersionStateManager.getInstance(project).isExists(use.getFQN())) {
29+
return;
30+
}
31+
final String removedIn = VersionStateManager.getInstance(project).getRemovedInVersion();
32+
final String message = removedIn.isEmpty()
33+
? SupportedIssue.IMPORTED_NON_EXISTENT_CLASS.getMessage(use.getFQN())
34+
: SupportedIssue.IMPORTED_NON_EXISTENT_CLASS.getChangelogMessage(
35+
use.getFQN(), removedIn);
36+
37+
if (problemsHolder instanceof UctProblemsHolder) {
38+
((UctProblemsHolder) problemsHolder).setReservedErrorCode(
39+
SupportedIssue.IMPORTED_NON_EXISTENT_CLASS.getCode()
40+
);
41+
}
42+
problemsHolder.registerProblem(
43+
use,
44+
message,
45+
ProblemHighlightType.ERROR
46+
);
47+
}
48+
49+
@Override
50+
protected IssueSeverityLevel getSeverityLevel() {
51+
return SupportedIssue.IMPORTED_NON_EXISTENT_CLASS.getLevel();
52+
}
53+
}

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

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import com.magento.idea.magento2uct.inspections.php.deprecation.UsingDeprecatedConstant;
2222
import com.magento.idea.magento2uct.inspections.php.deprecation.UsingDeprecatedInterface;
2323
import com.magento.idea.magento2uct.inspections.php.deprecation.UsingDeprecatedProperty;
24+
import com.magento.idea.magento2uct.inspections.php.existence.ImportingNonExistentClass;
2425
import java.lang.reflect.InvocationTargetException;
2526
import java.util.LinkedList;
2627
import java.util.List;
@@ -99,11 +100,19 @@ public enum SupportedIssue {
99100
IssueSeverityLevel.WARNING,
100101
"customCode.warnings.deprecated.1534",
101102
UsingDeprecatedProperty.class
103+
),
104+
IMPORTED_NON_EXISTENT_CLASS(
105+
1112,
106+
IssueSeverityLevel.CRITICAL,
107+
"customCode.critical.existence.1112",
108+
ImportingNonExistentClass.class,
109+
"customCode.critical.existence.1112.changelog"
102110
);
103111

104112
private final int code;
105113
private final IssueSeverityLevel level;
106-
private final String messageKey;
114+
private final String message;
115+
private final String changelogMessage;
107116
private final Class<? extends LocalInspectionTool> inspectionClass;
108117
private static final UctInspectionBundle BUNDLE = new UctInspectionBundle();
109118

@@ -112,19 +121,39 @@ public enum SupportedIssue {
112121
*
113122
* @param code IssueSeverityLevel
114123
* @param level IssueSeverityLevel
115-
* @param messageKey String
124+
* @param message String
116125
* @param inspectionClass Class
117126
*/
118127
SupportedIssue(
119128
final int code,
120129
final IssueSeverityLevel level,
121-
final String messageKey,
130+
final String message,
122131
final Class<? extends LocalInspectionTool> inspectionClass
132+
) {
133+
this(code, level, message, inspectionClass, null);
134+
}
135+
136+
/**
137+
* Known issue ENUM.
138+
*
139+
* @param code IssueSeverityLevel
140+
* @param level IssueSeverityLevel
141+
* @param message String
142+
* @param inspectionClass Class
143+
* @param changelogMessage String
144+
*/
145+
SupportedIssue(
146+
final int code,
147+
final IssueSeverityLevel level,
148+
final String message,
149+
final Class<? extends LocalInspectionTool> inspectionClass,
150+
final String changelogMessage
123151
) {
124152
this.code = code;
125153
this.level = level;
126-
this.messageKey = messageKey;
154+
this.message = message;
127155
this.inspectionClass = inspectionClass;
156+
this.changelogMessage = changelogMessage;
128157
}
129158

130159
/**
@@ -153,7 +182,22 @@ public IssueSeverityLevel getLevel() {
153182
* @return String
154183
*/
155184
public String getMessage(final Object... args) {
156-
return BUNDLE.message(messageKey, args);
185+
return BUNDLE.message(message, args);
186+
}
187+
188+
/**
189+
* Get bundle message for the issue (including changelog arguments).
190+
*
191+
* @param args Object
192+
*
193+
* @return String
194+
*/
195+
public String getChangelogMessage(final Object... args) {
196+
if (changelogMessage == null) {
197+
return getMessage(args);
198+
}
199+
200+
return BUNDLE.message(changelogMessage, args);
157201
}
158202

159203
/**

0 commit comments

Comments
 (0)