From af5f3e98cc932836384b9ce87b069abff7f7a7d6 Mon Sep 17 00:00:00 2001 From: bohdan-harniuk Date: Thu, 17 Mar 2022 09:50:21 +0200 Subject: [PATCH 1/9] 1030: Adding configuration files support for the UCT feature --- resources/META-INF/plugin.xml | 15 +++ .../UsedDeprecatedTypeInConfig.html | 6 + .../UsedNonExistentTypeInConfig.html | 6 + resources/uct/bundle/inspection.properties | 2 + .../xml/ModuleConfigFileInspection.java | 106 ++++++++++++++++++ .../xml/UsedDeprecatedTypeInConfig.java | 46 ++++++++ .../xml/UsedNonExistentTypeInConfig.java | 46 ++++++++ .../magento2uct/packages/SupportedIssue.java | 28 +++++ .../util/php/FqnValidatorUtil.java | 53 +++++++++ .../util/php/MagentoTypeEscapeUtil.java | 21 ++++ .../versioning/VersionStateManager.java | 17 ++- .../indexes/data/ExistenceStateIndex.java | 11 ++ 12 files changed, 356 insertions(+), 1 deletion(-) create mode 100644 resources/inspectionDescriptions/UsedDeprecatedTypeInConfig.html create mode 100644 resources/inspectionDescriptions/UsedNonExistentTypeInConfig.html create mode 100644 src/com/magento/idea/magento2uct/inspections/xml/ModuleConfigFileInspection.java create mode 100644 src/com/magento/idea/magento2uct/inspections/xml/UsedDeprecatedTypeInConfig.java create mode 100644 src/com/magento/idea/magento2uct/inspections/xml/UsedNonExistentTypeInConfig.java create mode 100644 src/com/magento/idea/magento2uct/util/php/FqnValidatorUtil.java diff --git a/resources/META-INF/plugin.xml b/resources/META-INF/plugin.xml index b0cc5b59f..a909a243b 100644 --- a/resources/META-INF/plugin.xml +++ b/resources/META-INF/plugin.xml @@ -537,6 +537,21 @@ enabledByDefault="false" level="WARNING" implementationClass="com.magento.idea.magento2uct.inspections.php.api.CalledNonInterfaceMethod"/> + + + diff --git a/resources/inspectionDescriptions/UsedDeprecatedTypeInConfig.html b/resources/inspectionDescriptions/UsedDeprecatedTypeInConfig.html new file mode 100644 index 000000000..7a699ff79 --- /dev/null +++ b/resources/inspectionDescriptions/UsedDeprecatedTypeInConfig.html @@ -0,0 +1,6 @@ + + +

[1134] Using Magento 2 @deprecated type: consider using Magento Open Source|Adobe Commerce type marked as @api instead.

+ + + diff --git a/resources/inspectionDescriptions/UsedNonExistentTypeInConfig.html b/resources/inspectionDescriptions/UsedNonExistentTypeInConfig.html new file mode 100644 index 000000000..a96cb06c0 --- /dev/null +++ b/resources/inspectionDescriptions/UsedNonExistentTypeInConfig.html @@ -0,0 +1,6 @@ + + +

[1110] The used type is no longer present in the codebase.

+ + + diff --git a/resources/uct/bundle/inspection.properties b/resources/uct/bundle/inspection.properties index 14dd91065..e95eb276f 100644 --- a/resources/uct/bundle/inspection.properties +++ b/resources/uct/bundle/inspection.properties @@ -38,6 +38,8 @@ inspection.displayName.ExtendedNonApiClass=Extended non Magento 2 API class inspection.displayName.InheritedNonApiInterface=Inherited non Magento 2 API interface inspection.displayName.PossibleDependencyOnImplDetails=Possible dependency on implementation details inspection.displayName.CalledNonInterfaceMethod=Called non-interface method +inspection.displayName.UsedNonExistentTypeInConfig=Used non-existent Magento 2 type in the configuration file +inspection.displayName.UsedDeprecatedTypeInConfig=Used deprecated Magento 2 type in the configuration file customCode.warnings.deprecated.1131=[1131] Extended class ''{0}'' that is @deprecated in the ''{1}'' customCode.warnings.deprecated.1132=[1132] Imported class ''{0}'' that is @deprecated in the ''{1}'' customCode.warnings.deprecated.1134=[1134] Used class ''{0}'' that is @deprecated in the ''{1}'' diff --git a/src/com/magento/idea/magento2uct/inspections/xml/ModuleConfigFileInspection.java b/src/com/magento/idea/magento2uct/inspections/xml/ModuleConfigFileInspection.java new file mode 100644 index 000000000..478229424 --- /dev/null +++ b/src/com/magento/idea/magento2uct/inspections/xml/ModuleConfigFileInspection.java @@ -0,0 +1,106 @@ +/* + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +package com.magento.idea.magento2uct.inspections.xml; + +import com.intellij.codeInspection.InspectionManager; +import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.codeInspection.XmlSuppressableInspectionTool; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.tree.IElementType; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.xml.XmlToken; +import com.intellij.psi.xml.XmlTokenType; +import com.magento.idea.magento2uct.settings.UctSettingsService; +import com.magento.idea.magento2uct.versioning.VersionStateManager; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +abstract class ModuleConfigFileInspection extends XmlSuppressableInspectionTool { + + private final String[] supportedFiles = new String[]{ + "di.xml", + "system.xml", + "events.xml", + "extension_attributes.xml", + "webapi.xml", + "communication.xml", + "queue_consumer.xml", + "crontab.xml", + "indexer.xml", + "mview.xml", + "product_types.xml", + "widget.xml", + }; + + @Override + public @Nullable ProblemDescriptor[] checkFile( + final @NotNull PsiFile file, + final @NotNull InspectionManager manager, + final boolean isOnTheFly + ) { + final Project project = file.getProject(); + final UctSettingsService settings = UctSettingsService.getInstance(project); + + if (!settings.isEnabled()) { + return getEmptyResult(); + } + + if (Arrays.stream(supportedFiles).noneMatch(name -> name.equals(file.getName()))) { + return getEmptyResult(); + } + final List allowedTokenTypes = new ArrayList<>(); + allowedTokenTypes.add(XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN); + allowedTokenTypes.add(XmlTokenType.XML_DATA_CHARACTERS); + + final List descriptors = new ArrayList<>(); + + for (final XmlToken token : PsiTreeUtil.findChildrenOfType(file, XmlToken.class)) { + if (!allowedTokenTypes.contains(token.getTokenType())) { + continue; + } + final String fqn = token.getText().trim(); + + if (!VersionStateManager.getInstance(project).isPresentInCodebase(fqn)) { + continue; + } + // Inspection logic. + doInspection(fqn, token, manager, isOnTheFly, descriptors); + } + + return descriptors.toArray(new ProblemDescriptor[0]); + } + + /** + * Implement this method to specify inspection logic. + * + * @param fqn String + * @param target PsiElement + * @param manager InspectionManager + * @param isOnTheFly boolean + * @param descriptors List[ProblemDescriptor] + */ + protected abstract void doInspection( + final @NotNull String fqn, + final @NotNull PsiElement target, + final @NotNull InspectionManager manager, + final boolean isOnTheFly, + final @NotNull List descriptors + ); + + /** + * Retrieves an empty result. + * + * @return ProblemDescriptor[] + */ + private ProblemDescriptor[] getEmptyResult() { + return new ProblemDescriptor[0]; + } +} diff --git a/src/com/magento/idea/magento2uct/inspections/xml/UsedDeprecatedTypeInConfig.java b/src/com/magento/idea/magento2uct/inspections/xml/UsedDeprecatedTypeInConfig.java new file mode 100644 index 000000000..e535afeb0 --- /dev/null +++ b/src/com/magento/idea/magento2uct/inspections/xml/UsedDeprecatedTypeInConfig.java @@ -0,0 +1,46 @@ +/* + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +package com.magento.idea.magento2uct.inspections.xml; + +import com.intellij.codeInspection.InspectionManager; +import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.codeInspection.ProblemHighlightType; +import com.intellij.psi.PsiElement; +import com.magento.idea.magento2uct.packages.SupportedIssue; +import com.magento.idea.magento2uct.versioning.VersionStateManager; +import java.util.List; +import org.jetbrains.annotations.NotNull; + +public class UsedDeprecatedTypeInConfig extends ModuleConfigFileInspection { + + @Override + protected void doInspection( + final @NotNull String fqn, + final @NotNull PsiElement target, + final @NotNull InspectionManager manager, + final boolean isOnTheFly, + final @NotNull List descriptors + ) { + if (VersionStateManager.getInstance(manager.getProject()).isDeprecated(fqn)) { + final String message = SupportedIssue.USED_DEPRECATED_TYPE_IN_CONFIG.getMessage( + fqn, + VersionStateManager.getInstance( + manager.getProject() + ).getDeprecatedInVersion(fqn) + ); + + final ProblemDescriptor descriptor = manager.createProblemDescriptor( + target, + message, + null, + ProblemHighlightType.WARNING, + isOnTheFly, + false + ); + descriptors.add(descriptor); + } + } +} diff --git a/src/com/magento/idea/magento2uct/inspections/xml/UsedNonExistentTypeInConfig.java b/src/com/magento/idea/magento2uct/inspections/xml/UsedNonExistentTypeInConfig.java new file mode 100644 index 000000000..4c3bca379 --- /dev/null +++ b/src/com/magento/idea/magento2uct/inspections/xml/UsedNonExistentTypeInConfig.java @@ -0,0 +1,46 @@ +/* + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +package com.magento.idea.magento2uct.inspections.xml; + +import com.intellij.codeInspection.InspectionManager; +import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.codeInspection.ProblemHighlightType; +import com.intellij.psi.PsiElement; +import com.magento.idea.magento2uct.packages.SupportedIssue; +import com.magento.idea.magento2uct.versioning.VersionStateManager; +import java.util.List; +import org.jetbrains.annotations.NotNull; + +public class UsedNonExistentTypeInConfig extends ModuleConfigFileInspection { + + @Override + protected void doInspection( + final @NotNull String fqn, + final @NotNull PsiElement target, + final @NotNull InspectionManager manager, + final boolean isOnTheFly, + final @NotNull List descriptors + ) { + if (!VersionStateManager.getInstance(manager.getProject()).isExists(fqn)) { + final String message = SupportedIssue.USED_NON_EXISTENT_TYPE_IN_CONFIG.getMessage( + fqn, + VersionStateManager.getInstance( + manager.getProject() + ).getRemovedInVersion(fqn) + ); + + final ProblemDescriptor descriptor = manager.createProblemDescriptor( + target, + message, + null, + ProblemHighlightType.ERROR, + isOnTheFly, + false + ); + descriptors.add(descriptor); + } + } +} diff --git a/src/com/magento/idea/magento2uct/packages/SupportedIssue.java b/src/com/magento/idea/magento2uct/packages/SupportedIssue.java index e0771622f..50a43d150 100644 --- a/src/com/magento/idea/magento2uct/packages/SupportedIssue.java +++ b/src/com/magento/idea/magento2uct/packages/SupportedIssue.java @@ -7,6 +7,7 @@ import com.intellij.codeInspection.LocalInspectionTool; import com.intellij.psi.PsiElementVisitor; +import com.jetbrains.php.lang.psi.PhpFile; import com.magento.idea.magento2uct.bundles.UctInspectionBundle; import com.magento.idea.magento2uct.inspections.UctProblemsHolder; import com.magento.idea.magento2uct.inspections.php.api.CalledNonApiMethod; @@ -45,7 +46,10 @@ import com.magento.idea.magento2uct.inspections.php.existence.UsedNonExistentConstant; import com.magento.idea.magento2uct.inspections.php.existence.UsedNonExistentProperty; import com.magento.idea.magento2uct.inspections.php.existence.UsedNonExistentType; +import com.magento.idea.magento2uct.inspections.xml.UsedDeprecatedTypeInConfig; +import com.magento.idea.magento2uct.inspections.xml.UsedNonExistentTypeInConfig; import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import org.jetbrains.annotations.Nullable; @@ -268,6 +272,18 @@ public enum SupportedIssue { IssueSeverityLevel.ERROR, "customCode.errors.api.1449", CalledNonInterfaceMethod.class + ), + USED_NON_EXISTENT_TYPE_IN_CONFIG( + 1110, + IssueSeverityLevel.CRITICAL, + "customCode.critical.existence.1110", + UsedNonExistentTypeInConfig.class + ), + USED_DEPRECATED_TYPE_IN_CONFIG( + 1134, + IssueSeverityLevel.WARNING, + "customCode.warnings.deprecated.1134", + UsedDeprecatedTypeInConfig.class ); private final int code; @@ -377,6 +393,18 @@ public static List getVisitors( return visitors; } + /** + * Get supported file types. + * + * @return List + */ + public static List> getSupportedFileTypes() { + final List> types = new ArrayList<>(); + types.add(PhpFile.class); + + return types; + } + /** * Build inspection visitor for file. * diff --git a/src/com/magento/idea/magento2uct/util/php/FqnValidatorUtil.java b/src/com/magento/idea/magento2uct/util/php/FqnValidatorUtil.java new file mode 100644 index 000000000..a7f753bf4 --- /dev/null +++ b/src/com/magento/idea/magento2uct/util/php/FqnValidatorUtil.java @@ -0,0 +1,53 @@ +/* + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +package com.magento.idea.magento2uct.util.php; + +import com.intellij.openapi.project.Project; +import com.jetbrains.php.PhpIndex; +import com.jetbrains.php.lang.psi.elements.PhpClass; +import java.util.Collection; +import java.util.regex.Matcher; +import org.jetbrains.annotations.NotNull; + +public final class FqnValidatorUtil { + + private FqnValidatorUtil() {} + + /** + * Check if provided string is a valid FQN. + * + * @param fqnCandidate String + * @param project Project + * + * @return boolean + */ + public static boolean validate( + final @NotNull String fqnCandidate, + final @NotNull Project project + ) { + String safeFqn = MagentoTypeEscapeUtil.escapeProperty(fqnCandidate); + + if (isFactoryOrProxy(safeFqn)) { + safeFqn = MagentoTypeEscapeUtil.escape(safeFqn); + } + final Collection classes = PhpIndex.getInstance(project).getAnyByFQN(safeFqn); + + return !classes.isEmpty(); + } + + /** + * Check if provided FQN is a Factory or Proxy. + * + * @param fqn String + * + * @return boolean + */ + private static boolean isFactoryOrProxy(final @NotNull String fqn) { + final Matcher matcher = MagentoTypeEscapeUtil.FACTORY_PROXY_TYPE_PATTERN.matcher(fqn); + + return matcher.find(); + } +} diff --git a/src/com/magento/idea/magento2uct/util/php/MagentoTypeEscapeUtil.java b/src/com/magento/idea/magento2uct/util/php/MagentoTypeEscapeUtil.java index ce910cea9..42802e519 100644 --- a/src/com/magento/idea/magento2uct/util/php/MagentoTypeEscapeUtil.java +++ b/src/com/magento/idea/magento2uct/util/php/MagentoTypeEscapeUtil.java @@ -15,6 +15,8 @@ public final class MagentoTypeEscapeUtil { = "(Factory|\\\\Proxy|Factory\\\\Proxy)($|\\.)"; public static final Pattern FACTORY_PROXY_TYPE_PATTERN = Pattern.compile(FACTORY_PROXY_TYPE_REGEX, Pattern.MULTILINE); + public static final String PHP_PROPERTY_REFERENCE_SEPARATOR = "::"; + public static final String JAVA_PROPERTY_REFERENCE_SEPARATOR = "."; private MagentoTypeEscapeUtil() { } @@ -43,4 +45,23 @@ private MagentoTypeEscapeUtil() { return typeFqn.equals(result) ? typeFqn : result; } + + /** + * Replace PHP property reference separator with the Intellij based separator. + * + * @param typeFqn String + * + * @return String + */ + public static @NotNull String escapeProperty(final @NotNull String typeFqn) { + if (typeFqn.contains(PHP_PROPERTY_REFERENCE_SEPARATOR) + && typeFqn.split(PHP_PROPERTY_REFERENCE_SEPARATOR).length == 1) { + return typeFqn.replace( + PHP_PROPERTY_REFERENCE_SEPARATOR, + JAVA_PROPERTY_REFERENCE_SEPARATOR + ); + } + + return typeFqn; + } } diff --git a/src/com/magento/idea/magento2uct/versioning/VersionStateManager.java b/src/com/magento/idea/magento2uct/versioning/VersionStateManager.java index aa89ea5ca..3ddf8d3cb 100644 --- a/src/com/magento/idea/magento2uct/versioning/VersionStateManager.java +++ b/src/com/magento/idea/magento2uct/versioning/VersionStateManager.java @@ -52,6 +52,19 @@ public static synchronized VersionStateManager getInstance( return instance; } + /** + * Checks if specified FQN was/is in the MBE/VBE. + * + * @param fqn String + * + * @return boolean + */ + public synchronized boolean isPresentInCodebase(final @NotNull String fqn) { + String safeFqn = MagentoTypeEscapeUtil.escapeProperty(escapeFqn(fqn)); + + return existenceStateIndex.isPresentInCodebase(safeFqn); + } + /** * Check if specified FQN exists in the deprecation index. * @@ -215,6 +228,8 @@ private void compute(final VersionStateIndex index) { * @return String */ private String escapeFqn(final @NotNull String fqn) { - return MagentoTypeEscapeUtil.escape(fqn); + return MagentoTypeEscapeUtil.escape( + fqn.trim().charAt(0) == '\\' ? fqn.trim() : '\\' + fqn.trim() + ); } } diff --git a/src/com/magento/idea/magento2uct/versioning/indexes/data/ExistenceStateIndex.java b/src/com/magento/idea/magento2uct/versioning/indexes/data/ExistenceStateIndex.java index 25d677a57..d382baccc 100644 --- a/src/com/magento/idea/magento2uct/versioning/indexes/data/ExistenceStateIndex.java +++ b/src/com/magento/idea/magento2uct/versioning/indexes/data/ExistenceStateIndex.java @@ -66,6 +66,17 @@ public synchronized boolean has(final @NotNull String fqn) { return !changelog.containsKey(fqn); } + /** + * Checks if specified FQN was/is in the MBE/VBE. + * + * @param fqn String + * + * @return boolean + */ + public synchronized boolean isPresentInCodebase(final @NotNull String fqn) { + return changelog.containsKey(fqn); + } + /** * Get version for specified FQN from prepared changelog. * From 23d1931ea38c80fbf7393d6c9bfba20fbd1cdac9 Mon Sep 17 00:00:00 2001 From: bohdan-harniuk Date: Fri, 18 Mar 2022 15:49:26 +0200 Subject: [PATCH 2/9] UCT-1030: Added config files support --- .../execution/GenerateUctReportCommand.java | 3 -- .../execution/scanner/ModuleFilesScanner.java | 9 +++-- .../inspections/UctInspectionManager.java | 39 +++++++++++-------- .../xml/ModuleConfigFileInspection.java | 24 +++++++++++- .../xml/UsedDeprecatedTypeInConfig.java | 8 ++++ .../xml/UsedNonExistentTypeInConfig.java | 8 ++++ .../magento2uct/packages/SupportedIssue.java | 2 + 7 files changed, 69 insertions(+), 24 deletions(-) diff --git a/src/com/magento/idea/magento2uct/execution/GenerateUctReportCommand.java b/src/com/magento/idea/magento2uct/execution/GenerateUctReportCommand.java index d12aec9f5..4f08468e9 100644 --- a/src/com/magento/idea/magento2uct/execution/GenerateUctReportCommand.java +++ b/src/com/magento/idea/magento2uct/execution/GenerateUctReportCommand.java @@ -135,9 +135,6 @@ public void execute() { boolean isModuleHeaderPrinted = false; for (final PsiFile psiFile : new ModuleFilesScanner(componentData)) { - if (!(psiFile instanceof PhpFile)) { - continue; - } final String filename = psiFile.getVirtualFile().getPath(); final UctInspectionManager inspectionManager = new UctInspectionManager( project diff --git a/src/com/magento/idea/magento2uct/execution/scanner/ModuleFilesScanner.java b/src/com/magento/idea/magento2uct/execution/scanner/ModuleFilesScanner.java index 1f158a173..90f703bad 100644 --- a/src/com/magento/idea/magento2uct/execution/scanner/ModuleFilesScanner.java +++ b/src/com/magento/idea/magento2uct/execution/scanner/ModuleFilesScanner.java @@ -7,8 +7,8 @@ import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiFile; -import com.jetbrains.php.lang.psi.PhpFile; import com.magento.idea.magento2uct.execution.scanner.data.ComponentData; +import com.magento.idea.magento2uct.packages.SupportedIssue; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -53,9 +53,12 @@ private List run() { */ private void collectFilesInDirectoryRecursively(final @NotNull PsiDirectory directory) { for (final PsiFile file : directory.getFiles()) { - if (file instanceof PhpFile) { - files.add(file); + if (SupportedIssue.getSupportedFileTypes().stream().noneMatch( + clazz -> clazz.isInstance(file)) + ) { + continue; } + files.add(file); } for (final PsiDirectory subDirectory : directory.getSubdirectories()) { diff --git a/src/com/magento/idea/magento2uct/inspections/UctInspectionManager.java b/src/com/magento/idea/magento2uct/inspections/UctInspectionManager.java index 093530835..2938e11ad 100644 --- a/src/com/magento/idea/magento2uct/inspections/UctInspectionManager.java +++ b/src/com/magento/idea/magento2uct/inspections/UctInspectionManager.java @@ -11,6 +11,7 @@ import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.PsiFile; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.xml.XmlFile; import com.jetbrains.php.codeInsight.PhpCodeInsightUtil; import com.jetbrains.php.lang.psi.PhpFile; import com.jetbrains.php.lang.psi.elements.AssignmentExpression; @@ -49,7 +50,9 @@ public UctInspectionManager(final @NotNull Project project) { * @return ProblemsHolder */ public @Nullable UctProblemsHolder run(final PsiFile psiFile) { - if (!(psiFile instanceof PhpFile)) { + if (SupportedIssue.getSupportedFileTypes().stream().noneMatch( + clazz -> clazz.isInstance(psiFile)) + ) { return null; } final UctProblemsHolder problemsHolder = new UctProblemsHolder( @@ -78,25 +81,29 @@ public UctInspectionManager(final @NotNull Project project) { private List collectElements(final @NotNull PsiFile psiFile) { final List elements = new LinkedList<>(); - final PhpClass phpClass = GetFirstClassOfFile.getInstance().execute((PhpFile) psiFile); + if (psiFile instanceof PhpFile) { + final PhpClass phpClass = GetFirstClassOfFile.getInstance().execute((PhpFile) psiFile); - if (phpClass != null) { - elements.add(phpClass); - final PhpPsiElement scopeForUseOperator = PhpCodeInsightUtil.findScopeForUseOperator( - phpClass - ); + if (phpClass != null) { + elements.add(phpClass); + final PhpPsiElement scopeForUseOperator = PhpCodeInsightUtil + .findScopeForUseOperator(phpClass); - if (scopeForUseOperator != null) { - elements.addAll(PhpCodeInsightUtil.collectImports(scopeForUseOperator)); + if (scopeForUseOperator != null) { + elements.addAll(PhpCodeInsightUtil.collectImports(scopeForUseOperator)); + } + elements.addAll(Arrays.asList(phpClass.getOwnFields())); } - elements.addAll(Arrays.asList(phpClass.getOwnFields())); - } - elements.addAll(PsiTreeUtil.findChildrenOfType(psiFile, ClassConstantReference.class)); - elements.addAll(PsiTreeUtil.findChildrenOfType(psiFile, MethodReference.class)); - elements.addAll(PsiTreeUtil.findChildrenOfType(psiFile, AssignmentExpression.class)); - elements.addAll(PsiTreeUtil.findChildrenOfType(psiFile, ClassReference.class)); - elements.addAll(PsiTreeUtil.findChildrenOfType(psiFile, FieldReference.class)); + elements.addAll(PsiTreeUtil.findChildrenOfType(psiFile, ClassConstantReference.class)); + elements.addAll(PsiTreeUtil.findChildrenOfType(psiFile, MethodReference.class)); + elements.addAll(PsiTreeUtil.findChildrenOfType(psiFile, AssignmentExpression.class)); + elements.addAll(PsiTreeUtil.findChildrenOfType(psiFile, ClassReference.class)); + elements.addAll(PsiTreeUtil.findChildrenOfType(psiFile, FieldReference.class)); + } else if (psiFile instanceof XmlFile) { + elements.add(psiFile); + } + return elements; } } diff --git a/src/com/magento/idea/magento2uct/inspections/xml/ModuleConfigFileInspection.java b/src/com/magento/idea/magento2uct/inspections/xml/ModuleConfigFileInspection.java index 478229424..91945ab4a 100644 --- a/src/com/magento/idea/magento2uct/inspections/xml/ModuleConfigFileInspection.java +++ b/src/com/magento/idea/magento2uct/inspections/xml/ModuleConfigFileInspection.java @@ -7,9 +7,11 @@ import com.intellij.codeInspection.InspectionManager; import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.codeInspection.ProblemsHolder; import com.intellij.codeInspection.XmlSuppressableInspectionTool; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.PsiFile; import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiTreeUtil; @@ -39,6 +41,17 @@ abstract class ModuleConfigFileInspection extends XmlSuppressableInspectionTool "product_types.xml", "widget.xml", }; + private ProblemsHolder problemsHolder; + + @Override + public @NotNull PsiElementVisitor buildVisitor( + final @NotNull ProblemsHolder holder, + final boolean isOnTheFly + ) { + problemsHolder = holder; + + return super.buildVisitor(holder, isOnTheFly); + } @Override public @Nullable ProblemDescriptor[] checkFile( @@ -48,8 +61,9 @@ abstract class ModuleConfigFileInspection extends XmlSuppressableInspectionTool ) { final Project project = file.getProject(); final UctSettingsService settings = UctSettingsService.getInstance(project); + final ProblemsHolder holder = getProblemsHolder(); - if (!settings.isEnabled()) { + if (!settings.isEnabled() || holder == null) { return getEmptyResult(); } @@ -72,7 +86,7 @@ abstract class ModuleConfigFileInspection extends XmlSuppressableInspectionTool continue; } // Inspection logic. - doInspection(fqn, token, manager, isOnTheFly, descriptors); + doInspection(fqn, token, manager, holder, isOnTheFly, descriptors); } return descriptors.toArray(new ProblemDescriptor[0]); @@ -84,6 +98,7 @@ abstract class ModuleConfigFileInspection extends XmlSuppressableInspectionTool * @param fqn String * @param target PsiElement * @param manager InspectionManager + * @param holder ProblemsHolder * @param isOnTheFly boolean * @param descriptors List[ProblemDescriptor] */ @@ -91,10 +106,15 @@ protected abstract void doInspection( final @NotNull String fqn, final @NotNull PsiElement target, final @NotNull InspectionManager manager, + final @NotNull ProblemsHolder holder, final boolean isOnTheFly, final @NotNull List descriptors ); + private @Nullable ProblemsHolder getProblemsHolder() { + return problemsHolder; + } + /** * Retrieves an empty result. * diff --git a/src/com/magento/idea/magento2uct/inspections/xml/UsedDeprecatedTypeInConfig.java b/src/com/magento/idea/magento2uct/inspections/xml/UsedDeprecatedTypeInConfig.java index e535afeb0..794a4be1c 100644 --- a/src/com/magento/idea/magento2uct/inspections/xml/UsedDeprecatedTypeInConfig.java +++ b/src/com/magento/idea/magento2uct/inspections/xml/UsedDeprecatedTypeInConfig.java @@ -8,7 +8,9 @@ import com.intellij.codeInspection.InspectionManager; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.codeInspection.ProblemHighlightType; +import com.intellij.codeInspection.ProblemsHolder; import com.intellij.psi.PsiElement; +import com.magento.idea.magento2uct.inspections.UctProblemsHolder; import com.magento.idea.magento2uct.packages.SupportedIssue; import com.magento.idea.magento2uct.versioning.VersionStateManager; import java.util.List; @@ -21,6 +23,7 @@ protected void doInspection( final @NotNull String fqn, final @NotNull PsiElement target, final @NotNull InspectionManager manager, + final @NotNull ProblemsHolder holder, final boolean isOnTheFly, final @NotNull List descriptors ) { @@ -32,6 +35,11 @@ protected void doInspection( ).getDeprecatedInVersion(fqn) ); + if (holder instanceof UctProblemsHolder) { + ((UctProblemsHolder) holder).setIssue( + SupportedIssue.USED_DEPRECATED_TYPE_IN_CONFIG + ); + } final ProblemDescriptor descriptor = manager.createProblemDescriptor( target, message, diff --git a/src/com/magento/idea/magento2uct/inspections/xml/UsedNonExistentTypeInConfig.java b/src/com/magento/idea/magento2uct/inspections/xml/UsedNonExistentTypeInConfig.java index 4c3bca379..13aaac616 100644 --- a/src/com/magento/idea/magento2uct/inspections/xml/UsedNonExistentTypeInConfig.java +++ b/src/com/magento/idea/magento2uct/inspections/xml/UsedNonExistentTypeInConfig.java @@ -8,7 +8,9 @@ import com.intellij.codeInspection.InspectionManager; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.codeInspection.ProblemHighlightType; +import com.intellij.codeInspection.ProblemsHolder; import com.intellij.psi.PsiElement; +import com.magento.idea.magento2uct.inspections.UctProblemsHolder; import com.magento.idea.magento2uct.packages.SupportedIssue; import com.magento.idea.magento2uct.versioning.VersionStateManager; import java.util.List; @@ -21,6 +23,7 @@ protected void doInspection( final @NotNull String fqn, final @NotNull PsiElement target, final @NotNull InspectionManager manager, + final @NotNull ProblemsHolder holder, final boolean isOnTheFly, final @NotNull List descriptors ) { @@ -32,6 +35,11 @@ protected void doInspection( ).getRemovedInVersion(fqn) ); + if (holder instanceof UctProblemsHolder) { + ((UctProblemsHolder) holder).setIssue( + SupportedIssue.USED_NON_EXISTENT_TYPE_IN_CONFIG + ); + } final ProblemDescriptor descriptor = manager.createProblemDescriptor( target, message, diff --git a/src/com/magento/idea/magento2uct/packages/SupportedIssue.java b/src/com/magento/idea/magento2uct/packages/SupportedIssue.java index 50a43d150..df2922715 100644 --- a/src/com/magento/idea/magento2uct/packages/SupportedIssue.java +++ b/src/com/magento/idea/magento2uct/packages/SupportedIssue.java @@ -7,6 +7,7 @@ import com.intellij.codeInspection.LocalInspectionTool; import com.intellij.psi.PsiElementVisitor; +import com.intellij.psi.xml.XmlFile; import com.jetbrains.php.lang.psi.PhpFile; import com.magento.idea.magento2uct.bundles.UctInspectionBundle; import com.magento.idea.magento2uct.inspections.UctProblemsHolder; @@ -401,6 +402,7 @@ public static List getVisitors( public static List> getSupportedFileTypes() { final List> types = new ArrayList<>(); types.add(PhpFile.class); + types.add(XmlFile.class); return types; } From bbcabf3bdd36242edb61d8b9a779072ae8056f0b Mon Sep 17 00:00:00 2001 From: bohdan-harniuk Date: Fri, 18 Mar 2022 17:39:15 +0200 Subject: [PATCH 3/9] 1030: Extended fqn escaping and references analysis --- .../inspections/UctProblemsHolder.java | 1 - .../util/php/FqnValidatorUtil.java | 53 ---------------- .../util/php/MagentoReferenceUtil.java | 63 +++++++++++++++++++ .../util/php/MagentoTypeEscapeUtil.java | 12 ++-- .../versioning/VersionStateManager.java | 6 +- .../indexes/data/ExistenceStateIndex.java | 9 ++- 6 files changed, 77 insertions(+), 67 deletions(-) delete mode 100644 src/com/magento/idea/magento2uct/util/php/FqnValidatorUtil.java create mode 100644 src/com/magento/idea/magento2uct/util/php/MagentoReferenceUtil.java diff --git a/src/com/magento/idea/magento2uct/inspections/UctProblemsHolder.java b/src/com/magento/idea/magento2uct/inspections/UctProblemsHolder.java index 0f11a8149..6f0afd2ed 100644 --- a/src/com/magento/idea/magento2uct/inspections/UctProblemsHolder.java +++ b/src/com/magento/idea/magento2uct/inspections/UctProblemsHolder.java @@ -74,7 +74,6 @@ public void registerProblem(final @NotNull ProblemDescriptor problemDescriptor) // if problem has been added successfully if (problemCount != getMyProblems().size()) { myProblemCodes.put(problemDescriptor, issue); - issue = null;//NOPMD } } diff --git a/src/com/magento/idea/magento2uct/util/php/FqnValidatorUtil.java b/src/com/magento/idea/magento2uct/util/php/FqnValidatorUtil.java deleted file mode 100644 index a7f753bf4..000000000 --- a/src/com/magento/idea/magento2uct/util/php/FqnValidatorUtil.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -package com.magento.idea.magento2uct.util.php; - -import com.intellij.openapi.project.Project; -import com.jetbrains.php.PhpIndex; -import com.jetbrains.php.lang.psi.elements.PhpClass; -import java.util.Collection; -import java.util.regex.Matcher; -import org.jetbrains.annotations.NotNull; - -public final class FqnValidatorUtil { - - private FqnValidatorUtil() {} - - /** - * Check if provided string is a valid FQN. - * - * @param fqnCandidate String - * @param project Project - * - * @return boolean - */ - public static boolean validate( - final @NotNull String fqnCandidate, - final @NotNull Project project - ) { - String safeFqn = MagentoTypeEscapeUtil.escapeProperty(fqnCandidate); - - if (isFactoryOrProxy(safeFqn)) { - safeFqn = MagentoTypeEscapeUtil.escape(safeFqn); - } - final Collection classes = PhpIndex.getInstance(project).getAnyByFQN(safeFqn); - - return !classes.isEmpty(); - } - - /** - * Check if provided FQN is a Factory or Proxy. - * - * @param fqn String - * - * @return boolean - */ - private static boolean isFactoryOrProxy(final @NotNull String fqn) { - final Matcher matcher = MagentoTypeEscapeUtil.FACTORY_PROXY_TYPE_PATTERN.matcher(fqn); - - return matcher.find(); - } -} diff --git a/src/com/magento/idea/magento2uct/util/php/MagentoReferenceUtil.java b/src/com/magento/idea/magento2uct/util/php/MagentoReferenceUtil.java new file mode 100644 index 000000000..d35c443a7 --- /dev/null +++ b/src/com/magento/idea/magento2uct/util/php/MagentoReferenceUtil.java @@ -0,0 +1,63 @@ +/* + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +package com.magento.idea.magento2uct.util.php; + +import com.intellij.openapi.util.text.StringUtil; +import org.jetbrains.annotations.NotNull; + +public final class MagentoReferenceUtil { + + public static final String PHP_REFERENCE_SEPARATOR = "::"; + + private MagentoReferenceUtil() { + } + + /** + * Check if reference looks like a PHP reference. + * + * @param referenceCandidate String + * + * @return boolean + */ + public static boolean isReference(final @NotNull String referenceCandidate) { + return referenceCandidate.contains(PHP_REFERENCE_SEPARATOR) + && referenceCandidate.split(PHP_REFERENCE_SEPARATOR).length == 2; + } + + /** + * Check if reference looks like a PHP method reference. + * + * @param referenceCandidate String + * + * @return boolean + */ + public static boolean isMethodReference(final @NotNull String referenceCandidate) { + if (isReference(referenceCandidate)) { + final String referencePart = referenceCandidate.split(PHP_REFERENCE_SEPARATOR)[1]; + + return StringUtil.isJavaIdentifier(referencePart); + } + + return false; + } + + /** + * Check if reference looks like a PHP constant reference. + * + * @param referenceCandidate String + * + * @return boolean + */ + public static boolean isConstantReference(final @NotNull String referenceCandidate) { + if (isReference(referenceCandidate)) { + final String referencePart = referenceCandidate.split(PHP_REFERENCE_SEPARATOR)[1]; + + return StringUtil.isUpperCase(referencePart); + } + + return false; + } +} diff --git a/src/com/magento/idea/magento2uct/util/php/MagentoTypeEscapeUtil.java b/src/com/magento/idea/magento2uct/util/php/MagentoTypeEscapeUtil.java index 42802e519..d938b07c8 100644 --- a/src/com/magento/idea/magento2uct/util/php/MagentoTypeEscapeUtil.java +++ b/src/com/magento/idea/magento2uct/util/php/MagentoTypeEscapeUtil.java @@ -15,8 +15,7 @@ public final class MagentoTypeEscapeUtil { = "(Factory|\\\\Proxy|Factory\\\\Proxy)($|\\.)"; public static final Pattern FACTORY_PROXY_TYPE_PATTERN = Pattern.compile(FACTORY_PROXY_TYPE_REGEX, Pattern.MULTILINE); - public static final String PHP_PROPERTY_REFERENCE_SEPARATOR = "::"; - public static final String JAVA_PROPERTY_REFERENCE_SEPARATOR = "."; + public static final String JAVA_REFERENCE_SEPARATOR = "."; private MagentoTypeEscapeUtil() { } @@ -43,7 +42,7 @@ private MagentoTypeEscapeUtil() { result = result.substring(0, begin) + result.substring(end); } - return typeFqn.equals(result) ? typeFqn : result; + return typeFqn.equals(result) ? escapeProperty(typeFqn) : escapeProperty(result); } /** @@ -54,11 +53,10 @@ private MagentoTypeEscapeUtil() { * @return String */ public static @NotNull String escapeProperty(final @NotNull String typeFqn) { - if (typeFqn.contains(PHP_PROPERTY_REFERENCE_SEPARATOR) - && typeFqn.split(PHP_PROPERTY_REFERENCE_SEPARATOR).length == 1) { + if (MagentoReferenceUtil.isReference(typeFqn)) { return typeFqn.replace( - PHP_PROPERTY_REFERENCE_SEPARATOR, - JAVA_PROPERTY_REFERENCE_SEPARATOR + MagentoReferenceUtil.PHP_REFERENCE_SEPARATOR, + JAVA_REFERENCE_SEPARATOR ); } diff --git a/src/com/magento/idea/magento2uct/versioning/VersionStateManager.java b/src/com/magento/idea/magento2uct/versioning/VersionStateManager.java index 3ddf8d3cb..f6d493177 100644 --- a/src/com/magento/idea/magento2uct/versioning/VersionStateManager.java +++ b/src/com/magento/idea/magento2uct/versioning/VersionStateManager.java @@ -17,6 +17,7 @@ import java.util.List; import org.jetbrains.annotations.NotNull; +@SuppressWarnings("PMD.AvoidSynchronizedAtMethodLevel") public final class VersionStateManager { private static VersionStateManager instance; @@ -35,7 +36,6 @@ public final class VersionStateManager { * * @return VersionStateManager */ - @SuppressWarnings("PMD.AvoidSynchronizedAtMethodLevel") public static synchronized VersionStateManager getInstance( final @NotNull Project project ) { //NOPMD @@ -60,9 +60,7 @@ public static synchronized VersionStateManager getInstance( * @return boolean */ public synchronized boolean isPresentInCodebase(final @NotNull String fqn) { - String safeFqn = MagentoTypeEscapeUtil.escapeProperty(escapeFqn(fqn)); - - return existenceStateIndex.isPresentInCodebase(safeFqn); + return existenceStateIndex.isPresentInCodebase(escapeFqn(fqn)); } /** diff --git a/src/com/magento/idea/magento2uct/versioning/indexes/data/ExistenceStateIndex.java b/src/com/magento/idea/magento2uct/versioning/indexes/data/ExistenceStateIndex.java index d382baccc..14813bf9a 100644 --- a/src/com/magento/idea/magento2uct/versioning/indexes/data/ExistenceStateIndex.java +++ b/src/com/magento/idea/magento2uct/versioning/indexes/data/ExistenceStateIndex.java @@ -16,11 +16,14 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Set; import org.jetbrains.annotations.NotNull; +@SuppressWarnings("PMD.AvoidSynchronizedAtMethodLevel") public class ExistenceStateIndex implements VersionStateIndex { private static final String RESOURCE_DIR = "existence"; @@ -28,6 +31,7 @@ public class ExistenceStateIndex implements VersionStateIndex { private final Map> versioningData; private final Map targetVersionData; private final Map changelog; + private final Set codebase; private String projectBasePath; /** @@ -37,6 +41,7 @@ public ExistenceStateIndex() { versioningData = new LinkedHashMap<>(); targetVersionData = new HashMap<>(); changelog = new HashMap<>(); + codebase = new HashSet<>(); } /** @@ -55,7 +60,6 @@ public void setProjectBasePath(final @NotNull String projectBasePath) { * * @return boolean */ - @SuppressWarnings("PMD.AvoidSynchronizedAtMethodLevel") public synchronized boolean has(final @NotNull String fqn) { groupLoadedData(); @@ -74,7 +78,7 @@ public synchronized boolean has(final @NotNull String fqn) { * @return boolean */ public synchronized boolean isPresentInCodebase(final @NotNull String fqn) { - return changelog.containsKey(fqn); + return codebase.contains(fqn); } /** @@ -198,6 +202,7 @@ private void groupLoadedData() { ); targetVersionData.putAll(gatheredData.getFirst()); changelog.putAll(gatheredData.getSecond()); + codebase.addAll(VersioningDataOperationsUtil.unionVersionData(versioningData).keySet()); } } } From c5818ecdf45cecc2514815372662884200824bb0 Mon Sep 17 00:00:00 2001 From: bohdan-harniuk Date: Sat, 19 Mar 2022 11:45:07 +0200 Subject: [PATCH 4/9] 1030: Extended xml file inspection coverage --- resources/META-INF/plugin.xml | 28 +++++++++ .../UsedDeprecatedConstantInConfig.html | 6 ++ .../UsedDeprecatedMethodInConfig.html | 6 ++ .../UsedNonExistentConstantInConfig.html | 6 ++ .../UsedNonExistentMethodInConfig.html | 6 ++ resources/uct/bundle/inspection.properties | 4 ++ .../xml/ModuleConfigFileInspection.java | 1 + .../xml/UsedDeprecatedConstantInConfig.java | 58 +++++++++++++++++++ .../xml/UsedDeprecatedMethodInConfig.java | 58 +++++++++++++++++++ .../xml/UsedDeprecatedTypeInConfig.java | 4 ++ .../xml/UsedNonExistentConstantInConfig.java | 58 +++++++++++++++++++ .../xml/UsedNonExistentMethodInConfig.java | 58 +++++++++++++++++++ .../xml/UsedNonExistentTypeInConfig.java | 4 ++ .../magento2uct/packages/SupportedIssue.java | 28 +++++++++ .../util/php/MagentoReferenceUtil.java | 5 +- 15 files changed, 328 insertions(+), 2 deletions(-) create mode 100644 resources/inspectionDescriptions/UsedDeprecatedConstantInConfig.html create mode 100644 resources/inspectionDescriptions/UsedDeprecatedMethodInConfig.html create mode 100644 resources/inspectionDescriptions/UsedNonExistentConstantInConfig.html create mode 100644 resources/inspectionDescriptions/UsedNonExistentMethodInConfig.html create mode 100644 src/com/magento/idea/magento2uct/inspections/xml/UsedDeprecatedConstantInConfig.java create mode 100644 src/com/magento/idea/magento2uct/inspections/xml/UsedDeprecatedMethodInConfig.java create mode 100644 src/com/magento/idea/magento2uct/inspections/xml/UsedNonExistentConstantInConfig.java create mode 100644 src/com/magento/idea/magento2uct/inspections/xml/UsedNonExistentMethodInConfig.java diff --git a/resources/META-INF/plugin.xml b/resources/META-INF/plugin.xml index 545ac7e40..cbe6f445f 100644 --- a/resources/META-INF/plugin.xml +++ b/resources/META-INF/plugin.xml @@ -558,6 +558,34 @@ enabledByDefault="true" level="ERROR" implementationClass="com.magento.idea.magento2uct.inspections.xml.UsedDeprecatedTypeInConfig"/> + + + + diff --git a/resources/inspectionDescriptions/UsedDeprecatedConstantInConfig.html b/resources/inspectionDescriptions/UsedDeprecatedConstantInConfig.html new file mode 100644 index 000000000..5b1db6efc --- /dev/null +++ b/resources/inspectionDescriptions/UsedDeprecatedConstantInConfig.html @@ -0,0 +1,6 @@ + + +

[1234] Using Magento 2 @deprecated constant: consider using Magento Open Source|Adobe Commerce constant marked as @api instead.

+ + + diff --git a/resources/inspectionDescriptions/UsedDeprecatedMethodInConfig.html b/resources/inspectionDescriptions/UsedDeprecatedMethodInConfig.html new file mode 100644 index 000000000..cb9b0f668 --- /dev/null +++ b/resources/inspectionDescriptions/UsedDeprecatedMethodInConfig.html @@ -0,0 +1,6 @@ + + +

[1439] Using Magento 2 @deprecated method: this method will be removed in upcoming versions. Consider relying on methods declared in API interfaces instead.

+ + + diff --git a/resources/inspectionDescriptions/UsedNonExistentConstantInConfig.html b/resources/inspectionDescriptions/UsedNonExistentConstantInConfig.html new file mode 100644 index 000000000..aaaf1516e --- /dev/null +++ b/resources/inspectionDescriptions/UsedNonExistentConstantInConfig.html @@ -0,0 +1,6 @@ + + +

[1214] The used constant is no longer present in the codebase.

+ + + diff --git a/resources/inspectionDescriptions/UsedNonExistentMethodInConfig.html b/resources/inspectionDescriptions/UsedNonExistentMethodInConfig.html new file mode 100644 index 000000000..b539bd50a --- /dev/null +++ b/resources/inspectionDescriptions/UsedNonExistentMethodInConfig.html @@ -0,0 +1,6 @@ + + +

[1410] The used method is no longer present in the codebase.

+ + + diff --git a/resources/uct/bundle/inspection.properties b/resources/uct/bundle/inspection.properties index e95eb276f..9fd84c5d9 100644 --- a/resources/uct/bundle/inspection.properties +++ b/resources/uct/bundle/inspection.properties @@ -40,6 +40,10 @@ inspection.displayName.PossibleDependencyOnImplDetails=Possible dependency on im inspection.displayName.CalledNonInterfaceMethod=Called non-interface method inspection.displayName.UsedNonExistentTypeInConfig=Used non-existent Magento 2 type in the configuration file inspection.displayName.UsedDeprecatedTypeInConfig=Used deprecated Magento 2 type in the configuration file +inspection.displayName.UsedDeprecatedConstantInConfig=Used deprecated Magento 2 constant in the configuration file +inspection.displayName.UsedDeprecatedMethodInConfig=Used deprecated Magento 2 method in the configuration file +inspection.displayName.UsedNonExistentConstantInConfig=Used non-existent Magento 2 constant in the configuration file +inspection.displayName.UsedNonExistentMethodInConfig=Used non-existent Magento 2 method in the configuration file customCode.warnings.deprecated.1131=[1131] Extended class ''{0}'' that is @deprecated in the ''{1}'' customCode.warnings.deprecated.1132=[1132] Imported class ''{0}'' that is @deprecated in the ''{1}'' customCode.warnings.deprecated.1134=[1134] Used class ''{0}'' that is @deprecated in the ''{1}'' diff --git a/src/com/magento/idea/magento2uct/inspections/xml/ModuleConfigFileInspection.java b/src/com/magento/idea/magento2uct/inspections/xml/ModuleConfigFileInspection.java index 91945ab4a..62ff42b39 100644 --- a/src/com/magento/idea/magento2uct/inspections/xml/ModuleConfigFileInspection.java +++ b/src/com/magento/idea/magento2uct/inspections/xml/ModuleConfigFileInspection.java @@ -17,6 +17,7 @@ import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.xml.XmlToken; import com.intellij.psi.xml.XmlTokenType; +import com.jetbrains.php.lang.PhpLangUtil; import com.magento.idea.magento2uct.settings.UctSettingsService; import com.magento.idea.magento2uct.versioning.VersionStateManager; import java.util.ArrayList; diff --git a/src/com/magento/idea/magento2uct/inspections/xml/UsedDeprecatedConstantInConfig.java b/src/com/magento/idea/magento2uct/inspections/xml/UsedDeprecatedConstantInConfig.java new file mode 100644 index 000000000..3a67ad75b --- /dev/null +++ b/src/com/magento/idea/magento2uct/inspections/xml/UsedDeprecatedConstantInConfig.java @@ -0,0 +1,58 @@ +/* + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +package com.magento.idea.magento2uct.inspections.xml; + +import com.intellij.codeInspection.InspectionManager; +import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.codeInspection.ProblemHighlightType; +import com.intellij.codeInspection.ProblemsHolder; +import com.intellij.psi.PsiElement; +import com.magento.idea.magento2uct.inspections.UctProblemsHolder; +import com.magento.idea.magento2uct.packages.SupportedIssue; +import com.magento.idea.magento2uct.util.php.MagentoReferenceUtil; +import com.magento.idea.magento2uct.versioning.VersionStateManager; +import java.util.List; +import org.jetbrains.annotations.NotNull; + +public class UsedDeprecatedConstantInConfig extends ModuleConfigFileInspection { + + @Override + protected void doInspection( + final @NotNull String fqn, + final @NotNull PsiElement target, + final @NotNull InspectionManager manager, + final @NotNull ProblemsHolder holder, + final boolean isOnTheFly, + final @NotNull List descriptors + ) { + if (!MagentoReferenceUtil.isConstantReference(fqn)) { + return; + } + if (VersionStateManager.getInstance(manager.getProject()).isDeprecated(fqn)) { + final String message = SupportedIssue.USED_DEPRECATED_CONSTANT_IN_CONFIG.getMessage( + fqn, + VersionStateManager.getInstance( + manager.getProject() + ).getDeprecatedInVersion(fqn) + ); + + if (holder instanceof UctProblemsHolder) { + ((UctProblemsHolder) holder).setIssue( + SupportedIssue.USED_DEPRECATED_CONSTANT_IN_CONFIG + ); + } + final ProblemDescriptor descriptor = manager.createProblemDescriptor( + target, + message, + null, + ProblemHighlightType.WARNING, + isOnTheFly, + false + ); + descriptors.add(descriptor); + } + } +} diff --git a/src/com/magento/idea/magento2uct/inspections/xml/UsedDeprecatedMethodInConfig.java b/src/com/magento/idea/magento2uct/inspections/xml/UsedDeprecatedMethodInConfig.java new file mode 100644 index 000000000..ea36967f9 --- /dev/null +++ b/src/com/magento/idea/magento2uct/inspections/xml/UsedDeprecatedMethodInConfig.java @@ -0,0 +1,58 @@ +/* + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +package com.magento.idea.magento2uct.inspections.xml; + +import com.intellij.codeInspection.InspectionManager; +import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.codeInspection.ProblemHighlightType; +import com.intellij.codeInspection.ProblemsHolder; +import com.intellij.psi.PsiElement; +import com.magento.idea.magento2uct.inspections.UctProblemsHolder; +import com.magento.idea.magento2uct.packages.SupportedIssue; +import com.magento.idea.magento2uct.util.php.MagentoReferenceUtil; +import com.magento.idea.magento2uct.versioning.VersionStateManager; +import java.util.List; +import org.jetbrains.annotations.NotNull; + +public class UsedDeprecatedMethodInConfig extends ModuleConfigFileInspection { + + @Override + protected void doInspection( + final @NotNull String fqn, + final @NotNull PsiElement target, + final @NotNull InspectionManager manager, + final @NotNull ProblemsHolder holder, + final boolean isOnTheFly, + final @NotNull List descriptors + ) { + if (!MagentoReferenceUtil.isMethodReference(fqn)) { + return; + } + if (VersionStateManager.getInstance(manager.getProject()).isDeprecated(fqn)) { + final String message = SupportedIssue.USED_DEPRECATED_METHOD_IN_CONFIG.getMessage( + fqn, + VersionStateManager.getInstance( + manager.getProject() + ).getDeprecatedInVersion(fqn) + ); + + if (holder instanceof UctProblemsHolder) { + ((UctProblemsHolder) holder).setIssue( + SupportedIssue.USED_DEPRECATED_METHOD_IN_CONFIG + ); + } + final ProblemDescriptor descriptor = manager.createProblemDescriptor( + target, + message, + null, + ProblemHighlightType.WARNING, + isOnTheFly, + false + ); + descriptors.add(descriptor); + } + } +} diff --git a/src/com/magento/idea/magento2uct/inspections/xml/UsedDeprecatedTypeInConfig.java b/src/com/magento/idea/magento2uct/inspections/xml/UsedDeprecatedTypeInConfig.java index 794a4be1c..7c10df123 100644 --- a/src/com/magento/idea/magento2uct/inspections/xml/UsedDeprecatedTypeInConfig.java +++ b/src/com/magento/idea/magento2uct/inspections/xml/UsedDeprecatedTypeInConfig.java @@ -12,6 +12,7 @@ import com.intellij.psi.PsiElement; import com.magento.idea.magento2uct.inspections.UctProblemsHolder; import com.magento.idea.magento2uct.packages.SupportedIssue; +import com.magento.idea.magento2uct.util.php.MagentoReferenceUtil; import com.magento.idea.magento2uct.versioning.VersionStateManager; import java.util.List; import org.jetbrains.annotations.NotNull; @@ -27,6 +28,9 @@ protected void doInspection( final boolean isOnTheFly, final @NotNull List descriptors ) { + if (MagentoReferenceUtil.isReference(fqn)) { + return; + } if (VersionStateManager.getInstance(manager.getProject()).isDeprecated(fqn)) { final String message = SupportedIssue.USED_DEPRECATED_TYPE_IN_CONFIG.getMessage( fqn, diff --git a/src/com/magento/idea/magento2uct/inspections/xml/UsedNonExistentConstantInConfig.java b/src/com/magento/idea/magento2uct/inspections/xml/UsedNonExistentConstantInConfig.java new file mode 100644 index 000000000..d6ce2de1a --- /dev/null +++ b/src/com/magento/idea/magento2uct/inspections/xml/UsedNonExistentConstantInConfig.java @@ -0,0 +1,58 @@ +/* + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +package com.magento.idea.magento2uct.inspections.xml; + +import com.intellij.codeInspection.InspectionManager; +import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.codeInspection.ProblemHighlightType; +import com.intellij.codeInspection.ProblemsHolder; +import com.intellij.psi.PsiElement; +import com.magento.idea.magento2uct.inspections.UctProblemsHolder; +import com.magento.idea.magento2uct.packages.SupportedIssue; +import com.magento.idea.magento2uct.util.php.MagentoReferenceUtil; +import com.magento.idea.magento2uct.versioning.VersionStateManager; +import java.util.List; +import org.jetbrains.annotations.NotNull; + +public class UsedNonExistentConstantInConfig extends ModuleConfigFileInspection { + + @Override + protected void doInspection( + final @NotNull String fqn, + final @NotNull PsiElement target, + final @NotNull InspectionManager manager, + final @NotNull ProblemsHolder holder, + final boolean isOnTheFly, + final @NotNull List descriptors + ) { + if (!MagentoReferenceUtil.isConstantReference(fqn)) { + return; + } + if (!VersionStateManager.getInstance(manager.getProject()).isExists(fqn)) { + final String message = SupportedIssue.USED_NON_EXISTENT_CONSTANT_IN_CONFIG.getMessage( + fqn, + VersionStateManager.getInstance( + manager.getProject() + ).getRemovedInVersion(fqn) + ); + + if (holder instanceof UctProblemsHolder) { + ((UctProblemsHolder) holder).setIssue( + SupportedIssue.USED_NON_EXISTENT_CONSTANT_IN_CONFIG + ); + } + final ProblemDescriptor descriptor = manager.createProblemDescriptor( + target, + message, + null, + ProblemHighlightType.ERROR, + isOnTheFly, + false + ); + descriptors.add(descriptor); + } + } +} diff --git a/src/com/magento/idea/magento2uct/inspections/xml/UsedNonExistentMethodInConfig.java b/src/com/magento/idea/magento2uct/inspections/xml/UsedNonExistentMethodInConfig.java new file mode 100644 index 000000000..40b806060 --- /dev/null +++ b/src/com/magento/idea/magento2uct/inspections/xml/UsedNonExistentMethodInConfig.java @@ -0,0 +1,58 @@ +/* + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +package com.magento.idea.magento2uct.inspections.xml; + +import com.intellij.codeInspection.InspectionManager; +import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.codeInspection.ProblemHighlightType; +import com.intellij.codeInspection.ProblemsHolder; +import com.intellij.psi.PsiElement; +import com.magento.idea.magento2uct.inspections.UctProblemsHolder; +import com.magento.idea.magento2uct.packages.SupportedIssue; +import com.magento.idea.magento2uct.util.php.MagentoReferenceUtil; +import com.magento.idea.magento2uct.versioning.VersionStateManager; +import java.util.List; +import org.jetbrains.annotations.NotNull; + +public class UsedNonExistentMethodInConfig extends ModuleConfigFileInspection { + + @Override + protected void doInspection( + final @NotNull String fqn, + final @NotNull PsiElement target, + final @NotNull InspectionManager manager, + final @NotNull ProblemsHolder holder, + final boolean isOnTheFly, + final @NotNull List descriptors + ) { + if (!MagentoReferenceUtil.isMethodReference(fqn)) { + return; + } + if (!VersionStateManager.getInstance(manager.getProject()).isExists(fqn)) { + final String message = SupportedIssue.USED_NON_EXISTENT_METHOD_IN_CONFIG.getMessage( + fqn, + VersionStateManager.getInstance( + manager.getProject() + ).getRemovedInVersion(fqn) + ); + + if (holder instanceof UctProblemsHolder) { + ((UctProblemsHolder) holder).setIssue( + SupportedIssue.USED_NON_EXISTENT_METHOD_IN_CONFIG + ); + } + final ProblemDescriptor descriptor = manager.createProblemDescriptor( + target, + message, + null, + ProblemHighlightType.ERROR, + isOnTheFly, + false + ); + descriptors.add(descriptor); + } + } +} diff --git a/src/com/magento/idea/magento2uct/inspections/xml/UsedNonExistentTypeInConfig.java b/src/com/magento/idea/magento2uct/inspections/xml/UsedNonExistentTypeInConfig.java index 13aaac616..059084ce7 100644 --- a/src/com/magento/idea/magento2uct/inspections/xml/UsedNonExistentTypeInConfig.java +++ b/src/com/magento/idea/magento2uct/inspections/xml/UsedNonExistentTypeInConfig.java @@ -12,6 +12,7 @@ import com.intellij.psi.PsiElement; import com.magento.idea.magento2uct.inspections.UctProblemsHolder; import com.magento.idea.magento2uct.packages.SupportedIssue; +import com.magento.idea.magento2uct.util.php.MagentoReferenceUtil; import com.magento.idea.magento2uct.versioning.VersionStateManager; import java.util.List; import org.jetbrains.annotations.NotNull; @@ -27,6 +28,9 @@ protected void doInspection( final boolean isOnTheFly, final @NotNull List descriptors ) { + if (MagentoReferenceUtil.isReference(fqn)) { + return; + } if (!VersionStateManager.getInstance(manager.getProject()).isExists(fqn)) { final String message = SupportedIssue.USED_NON_EXISTENT_TYPE_IN_CONFIG.getMessage( fqn, diff --git a/src/com/magento/idea/magento2uct/packages/SupportedIssue.java b/src/com/magento/idea/magento2uct/packages/SupportedIssue.java index df2922715..004d50f10 100644 --- a/src/com/magento/idea/magento2uct/packages/SupportedIssue.java +++ b/src/com/magento/idea/magento2uct/packages/SupportedIssue.java @@ -47,7 +47,11 @@ import com.magento.idea.magento2uct.inspections.php.existence.UsedNonExistentConstant; import com.magento.idea.magento2uct.inspections.php.existence.UsedNonExistentProperty; import com.magento.idea.magento2uct.inspections.php.existence.UsedNonExistentType; +import com.magento.idea.magento2uct.inspections.xml.UsedDeprecatedConstantInConfig; +import com.magento.idea.magento2uct.inspections.xml.UsedDeprecatedMethodInConfig; import com.magento.idea.magento2uct.inspections.xml.UsedDeprecatedTypeInConfig; +import com.magento.idea.magento2uct.inspections.xml.UsedNonExistentConstantInConfig; +import com.magento.idea.magento2uct.inspections.xml.UsedNonExistentMethodInConfig; import com.magento.idea.magento2uct.inspections.xml.UsedNonExistentTypeInConfig; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; @@ -285,6 +289,30 @@ public enum SupportedIssue { IssueSeverityLevel.WARNING, "customCode.warnings.deprecated.1134", UsedDeprecatedTypeInConfig.class + ), + USED_DEPRECATED_CONSTANT_IN_CONFIG( + 1234, + IssueSeverityLevel.WARNING, + "customCode.warnings.deprecated.1234", + UsedDeprecatedConstantInConfig.class + ), + USED_DEPRECATED_METHOD_IN_CONFIG( + 1439, + IssueSeverityLevel.WARNING, + "customCode.warnings.deprecated.1439", + UsedDeprecatedMethodInConfig.class + ), + USED_NON_EXISTENT_CONSTANT_IN_CONFIG( + 1214, + IssueSeverityLevel.WARNING, + "customCode.critical.existence.1214", + UsedNonExistentConstantInConfig.class + ), + USED_NON_EXISTENT_METHOD_IN_CONFIG( + 1410, + IssueSeverityLevel.WARNING, + "customCode.critical.existence.1410", + UsedNonExistentMethodInConfig.class ); private final int code; diff --git a/src/com/magento/idea/magento2uct/util/php/MagentoReferenceUtil.java b/src/com/magento/idea/magento2uct/util/php/MagentoReferenceUtil.java index d35c443a7..d01faa7a1 100644 --- a/src/com/magento/idea/magento2uct/util/php/MagentoReferenceUtil.java +++ b/src/com/magento/idea/magento2uct/util/php/MagentoReferenceUtil.java @@ -38,7 +38,8 @@ public static boolean isMethodReference(final @NotNull String referenceCandidate if (isReference(referenceCandidate)) { final String referencePart = referenceCandidate.split(PHP_REFERENCE_SEPARATOR)[1]; - return StringUtil.isJavaIdentifier(referencePart); + return StringUtil.isJavaIdentifier(referencePart) + && !isConstantReference(referenceCandidate); } return false; @@ -55,7 +56,7 @@ public static boolean isConstantReference(final @NotNull String referenceCandida if (isReference(referenceCandidate)) { final String referencePart = referenceCandidate.split(PHP_REFERENCE_SEPARATOR)[1]; - return StringUtil.isUpperCase(referencePart); + return StringUtil.isUpperCase(referencePart.replace("_", "")); } return false; From 22071d7f8c619caea2c4af1312806de2690cf6aa Mon Sep 17 00:00:00 2001 From: bohdan-harniuk Date: Sat, 19 Mar 2022 12:14:13 +0200 Subject: [PATCH 5/9] 1030: Code refactoring --- resources/META-INF/plugin.xml | 41 ++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/resources/META-INF/plugin.xml b/resources/META-INF/plugin.xml index cbe6f445f..0a16d3401 100644 --- a/resources/META-INF/plugin.xml +++ b/resources/META-INF/plugin.xml @@ -544,46 +544,47 @@ level="WARNING" implementationClass="com.magento.idea.magento2uct.inspections.php.api.CalledNonInterfaceMethod"/> - + + From 1d24a8fc797303e96c31a663b116c1097e2136cb Mon Sep 17 00:00:00 2001 From: bohdan-harniuk Date: Sat, 19 Mar 2022 12:50:03 +0200 Subject: [PATCH 6/9] 1030: Added theme xml files support --- .../xml/ModuleConfigFileInspection.java | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/com/magento/idea/magento2uct/inspections/xml/ModuleConfigFileInspection.java b/src/com/magento/idea/magento2uct/inspections/xml/ModuleConfigFileInspection.java index 62ff42b39..89e674907 100644 --- a/src/com/magento/idea/magento2uct/inspections/xml/ModuleConfigFileInspection.java +++ b/src/com/magento/idea/magento2uct/inspections/xml/ModuleConfigFileInspection.java @@ -10,6 +10,7 @@ import com.intellij.codeInspection.ProblemsHolder; import com.intellij.codeInspection.XmlSuppressableInspectionTool; import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.PsiFile; @@ -17,17 +18,20 @@ import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.xml.XmlToken; import com.intellij.psi.xml.XmlTokenType; -import com.jetbrains.php.lang.PhpLangUtil; import com.magento.idea.magento2uct.settings.UctSettingsService; import com.magento.idea.magento2uct.versioning.VersionStateManager; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.regex.Pattern; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; abstract class ModuleConfigFileInspection extends XmlSuppressableInspectionTool { + private static final String LAYOUT_FILE_REGEX = "\\/(layout|ui_component)\\/.*\\.xml"; + private static final Pattern LAYOUT_FILE_PATTERN = Pattern.compile(LAYOUT_FILE_REGEX); + private final String[] supportedFiles = new String[]{ "di.xml", "system.xml", @@ -68,7 +72,8 @@ abstract class ModuleConfigFileInspection extends XmlSuppressableInspectionTool return getEmptyResult(); } - if (Arrays.stream(supportedFiles).noneMatch(name -> name.equals(file.getName()))) { + if (Arrays.stream(supportedFiles).noneMatch(name -> name.equals(file.getName())) + && !isLayoutFile(file)) { return getEmptyResult(); } final List allowedTokenTypes = new ArrayList<>(); @@ -124,4 +129,14 @@ protected abstract void doInspection( private ProblemDescriptor[] getEmptyResult() { return new ProblemDescriptor[0]; } + + private boolean isLayoutFile(final @NotNull PsiFile file) { + final VirtualFile virtualFile = file.getVirtualFile(); + + if (virtualFile == null) { + return false; + } + + return LAYOUT_FILE_PATTERN.matcher(virtualFile.getPath()).find(); + } } From ffcea950d5438773060af17d61231bfec61a050a Mon Sep 17 00:00:00 2001 From: bohdan-harniuk Date: Sat, 19 Mar 2022 12:50:50 +0200 Subject: [PATCH 7/9] 1030: Code refactoring --- .../magento2uct/inspections/xml/ModuleConfigFileInspection.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/magento/idea/magento2uct/inspections/xml/ModuleConfigFileInspection.java b/src/com/magento/idea/magento2uct/inspections/xml/ModuleConfigFileInspection.java index 89e674907..f4d77bfad 100644 --- a/src/com/magento/idea/magento2uct/inspections/xml/ModuleConfigFileInspection.java +++ b/src/com/magento/idea/magento2uct/inspections/xml/ModuleConfigFileInspection.java @@ -32,7 +32,7 @@ abstract class ModuleConfigFileInspection extends XmlSuppressableInspectionTool private static final String LAYOUT_FILE_REGEX = "\\/(layout|ui_component)\\/.*\\.xml"; private static final Pattern LAYOUT_FILE_PATTERN = Pattern.compile(LAYOUT_FILE_REGEX); - private final String[] supportedFiles = new String[]{ + private final String[] supportedFiles = { "di.xml", "system.xml", "events.xml", From 688d5896ffb82fca2eb5f5a16345c6e3a2d3fafe Mon Sep 17 00:00:00 2001 From: bohdan-harniuk Date: Sat, 19 Mar 2022 13:06:19 +0200 Subject: [PATCH 8/9] 1030: Code refactoring --- .../idea/magento2uct/execution/GenerateUctReportCommand.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/com/magento/idea/magento2uct/execution/GenerateUctReportCommand.java b/src/com/magento/idea/magento2uct/execution/GenerateUctReportCommand.java index 4f08468e9..99a3f52c9 100644 --- a/src/com/magento/idea/magento2uct/execution/GenerateUctReportCommand.java +++ b/src/com/magento/idea/magento2uct/execution/GenerateUctReportCommand.java @@ -20,7 +20,6 @@ import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; -import com.jetbrains.php.lang.psi.PhpFile; import com.magento.idea.magento2plugin.util.magento.MagentoVersionUtil; import com.magento.idea.magento2uct.execution.output.ReportBuilder; import com.magento.idea.magento2uct.execution.output.Summary; From 334b769263ef87892956fccfc6ed214401802735 Mon Sep 17 00:00:00 2001 From: Serhii Akulov Date: Fri, 25 Mar 2022 16:22:15 +0200 Subject: [PATCH 9/9] UCT-1030: added xml files --- .../inspections/xml/ModuleConfigFileInspection.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/com/magento/idea/magento2uct/inspections/xml/ModuleConfigFileInspection.java b/src/com/magento/idea/magento2uct/inspections/xml/ModuleConfigFileInspection.java index f4d77bfad..f241e1df3 100644 --- a/src/com/magento/idea/magento2uct/inspections/xml/ModuleConfigFileInspection.java +++ b/src/com/magento/idea/magento2uct/inspections/xml/ModuleConfigFileInspection.java @@ -45,6 +45,15 @@ abstract class ModuleConfigFileInspection extends XmlSuppressableInspectionTool "mview.xml", "product_types.xml", "widget.xml", + "queue.xml", + "product_options.xml", + "export.xml", + "import.xml", + "analytics.xml", + "reports.xml", + "pdf.xml", + "cache.xml", + "validation.xml" }; private ProblemsHolder problemsHolder;