diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ae353ccd..f9c377d5c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,25 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0). ## 5.0.0 +### Added + +- Code generation of a Data Patch Boilerplate file [#1188](https://github.com/magento/magento2-phpstorm-plugin/pull/1188) +- Code generation of an Observer from the context menu [#1200](https://github.com/magento/magento2-phpstorm-plugin/pull/1200) +- Code generation of events.xml file [#1189](https://github.com/magento/magento2-phpstorm-plugin/pull/1189) +- Config Scope directory inspection [#1261](https://github.com/magento/magento2-phpstorm-plugin/pull/1261) + +### Changed + +- EAV attributes code generators: Added default values of the group property [#1259](https://github.com/magento/magento2-phpstorm-plugin/pull/1259) +- All code generators: Added constants visibility and class property types [#1260](https://github.com/magento/magento2-phpstorm-plugin/pull/1260) +- UCT custom coming versions [#1251](https://github.com/magento/magento2-phpstorm-plugin/pull/1251) + +### Fixed + +- Fixed wrong director(y|ies) generation for GraphQL resolver class [#1192](https://github.com/magento/magento2-phpstorm-plugin/pull/1192) +- Fixed IndexOutOfBoundsException: CreateResolverClassQuickFix.applyFix(CreateResolverClassQuickFix.java:43) [#1192](https://github.com/magento/magento2-phpstorm-plugin/pull/1192) +- Index out of range [#1239](https://github.com/magento/magento2-phpstorm-plugin/pull/1239) + ## 4.4.0 ### Added diff --git a/resources/icons/graphql.svg b/resources/icons/graphql.svg new file mode 100644 index 000000000..ffe677d5b --- /dev/null +++ b/resources/icons/graphql.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/resources/magento2/inspection.properties b/resources/magento2/inspection.properties index 7a47145af..e7596387e 100644 --- a/resources/magento2/inspection.properties +++ b/resources/magento2/inspection.properties @@ -15,7 +15,7 @@ inspection.plugin.duplicateInSameFile=The plugin name already used in this file. inspection.plugin.duplicateInOtherPlaces=The plugin name "{0}" for targeted "{1}" class is already used in the module "{2}" ({3} scope). For more details see Inspection Description. inspection.plugin.disabledPluginDoesNotExist=This plugin does not exist to be disabled. inspection.graphql.resolver.mustImplement=Class must implements any of the following interfaces: \\Magento\\Framework\\GraphQl\\Query\\ResolverInterface, \\Magento\\Framework\\GraphQl\\Query\\Resolver\\BatchResolverInterface, \\Magento\\Framework\\GraphQl\\Query\\Resolver\\BatchServiceContractResolverInterface -inspection.graphql.resolver.notExist=Resolver class do not exist +inspection.graphql.resolver.notExist=The GraphQL resolver class do not exist inspection.graphql.resolver.fix.family=Implement Resolver interface inspection.graphql.resolver.fix.title=Select one of the following interface inspection.graphql.schema.resolver.fix.family=Create GraphQL Resolver @@ -41,3 +41,6 @@ inspection.warning.method.should.have.public.access=The method "{0}" should have inspection.warning.method.should.have.public.access.fix=Change the method access inspection.displayName.ModuleScopeInspection=Module Configuration Scope Inspection inspection.config.wrong.area = The area of this config file is wrong. Please check the spelling of the parent directory, it should be equal to one of the following: adminhtml, frontend, crontab, webapi_rest, webapi_soap, graphql. +inspection.warning.class.invalidFormat=The class "{0}" has invalid format +inspection.error.graphqlResolverClass.tooShortFormat=The target GraphQL resolver class format is incorrect.\nThe fully qualified name "{0}" should contain at least 3 parts. +inspection.error.graphqlResolverClass.tooShortFormatTitle=The GraphQL resolver class format is incorrect diff --git a/src/com/magento/idea/magento2plugin/MagentoIcons.java b/src/com/magento/idea/magento2plugin/MagentoIcons.java index dc83eab99..a360d9b18 100644 --- a/src/com/magento/idea/magento2plugin/MagentoIcons.java +++ b/src/com/magento/idea/magento2plugin/MagentoIcons.java @@ -17,4 +17,5 @@ public class MagentoIcons { IconLoader.getIcon("/icons/pluginIcon16x16.svg", MagentoIcons.class); public static final Icon PLUGIN_ICON_MEDIUM = IconLoader.getIcon("/icons/pluginIcon64x64.svg", MagentoIcons.class); + public static final Icon GRAPHQL = IconLoader.getIcon("/icons/graphql.svg", MagentoIcons.class); } diff --git a/src/com/magento/idea/magento2plugin/actions/context/AbstractContextAction.java b/src/com/magento/idea/magento2plugin/actions/context/AbstractContextAction.java index 47c826a48..bf520a212 100644 --- a/src/com/magento/idea/magento2plugin/actions/context/AbstractContextAction.java +++ b/src/com/magento/idea/magento2plugin/actions/context/AbstractContextAction.java @@ -24,6 +24,7 @@ import com.magento.idea.magento2plugin.magento.packages.Package; import com.magento.idea.magento2plugin.project.Settings; import com.magento.idea.magento2plugin.util.magento.GetMagentoModuleUtil; +import javax.swing.Icon; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -51,6 +52,24 @@ public AbstractContextAction( this.moduleFile = moduleFile; } + /** + * Abstract context action constructor. + * + * @param title String + * @param description String + * @param moduleFile ModuleFileInterface + * @param icon Icon + */ + public AbstractContextAction( + final @NotNull String title, + final @NotNull String description, + final @NotNull ModuleFileInterface moduleFile, + final @Nullable Icon icon + ) { + super(title, description, icon); + this.moduleFile = moduleFile; + } + @Override @SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity"}) public void update(final @NotNull AnActionEvent event) { diff --git a/src/com/magento/idea/magento2plugin/actions/context/xml/NewGraphQLSchemaAction.java b/src/com/magento/idea/magento2plugin/actions/context/xml/NewGraphQLSchemaAction.java index 65b37bba8..6df71b95e 100644 --- a/src/com/magento/idea/magento2plugin/actions/context/xml/NewGraphQLSchemaAction.java +++ b/src/com/magento/idea/magento2plugin/actions/context/xml/NewGraphQLSchemaAction.java @@ -8,6 +8,7 @@ import com.intellij.ide.fileTemplates.actions.AttributesDefaults; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiFile; +import com.magento.idea.magento2plugin.MagentoIcons; import com.magento.idea.magento2plugin.actions.context.AbstractContextAction; import com.magento.idea.magento2plugin.magento.files.SchemaGraphQLsFile; import com.magento.idea.magento2plugin.magento.packages.ComponentType; @@ -25,7 +26,12 @@ public class NewGraphQLSchemaAction extends AbstractContextAction { * New schema.graphqls file action constructor. */ public NewGraphQLSchemaAction() { - super(ACTION_NAME, ACTION_DESCRIPTION, SchemaGraphQLsFile.getInstance()); + super( + ACTION_NAME, + ACTION_DESCRIPTION, + SchemaGraphQLsFile.getInstance(), + MagentoIcons.GRAPHQL + ); } @Override diff --git a/src/com/magento/idea/magento2plugin/actions/generation/NewGraphQlResolverAction.java b/src/com/magento/idea/magento2plugin/actions/generation/NewGraphQlResolverAction.java index 347e6b5c2..6a7f03cd8 100644 --- a/src/com/magento/idea/magento2plugin/actions/generation/NewGraphQlResolverAction.java +++ b/src/com/magento/idea/magento2plugin/actions/generation/NewGraphQlResolverAction.java @@ -23,7 +23,7 @@ public class NewGraphQlResolverAction extends AnAction { public static final String ACTION_DESCRIPTION = "Create a new Magento 2 GraphQL Resolver"; public NewGraphQlResolverAction() { - super(ACTION_NAME, ACTION_DESCRIPTION, MagentoIcons.MODULE); + super(ACTION_NAME, ACTION_DESCRIPTION, MagentoIcons.GRAPHQL); } @Override diff --git a/src/com/magento/idea/magento2plugin/actions/generation/generator/ModuleGraphQlResolverClassGenerator.java b/src/com/magento/idea/magento2plugin/actions/generation/generator/ModuleGraphQlResolverClassGenerator.java index b87da10d9..c9e734284 100644 --- a/src/com/magento/idea/magento2plugin/actions/generation/generator/ModuleGraphQlResolverClassGenerator.java +++ b/src/com/magento/idea/magento2plugin/actions/generation/generator/ModuleGraphQlResolverClassGenerator.java @@ -25,7 +25,6 @@ import com.magento.idea.magento2plugin.bundles.ValidatorBundle; import com.magento.idea.magento2plugin.indexes.ModuleIndex; import com.magento.idea.magento2plugin.magento.files.GraphQlResolverPhp; -import com.magento.idea.magento2plugin.magento.packages.File; import com.magento.idea.magento2plugin.magento.packages.MagentoPhpClass; import com.magento.idea.magento2plugin.util.GetFirstClassOfFile; import com.magento.idea.magento2plugin.util.GetPhpClassByFQN; @@ -34,6 +33,7 @@ import org.jetbrains.annotations.NotNull; public class ModuleGraphQlResolverClassGenerator extends FileGenerator { + private final GraphQlResolverFileData graphQlResolverFileData; private final Project project; private final ValidatorBundle validatorBundle; @@ -132,15 +132,15 @@ private PhpClass createGraphQlResolverClass(final String actionName) { if (parentDirectory == null) { return null; } - final String[] graphQlResolverDirectories = graphQlResolverFileData - .getGraphQlResolverDirectory().split(File.separator); - for (final String graphQlResolverDirectory: graphQlResolverDirectories) { - parentDirectory = directoryGenerator.findOrCreateSubdirectory( + final String graphQlResolverDirectory = graphQlResolverFileData + .getGraphQlResolverDirectory(); + + if (!graphQlResolverDirectory.isBlank()) { + parentDirectory = directoryGenerator.findOrCreateSubdirectories( parentDirectory, graphQlResolverDirectory ); } - final Properties attributes = getAttributes(); final PsiFile graphQlResolverFile = fileFromTemplateGenerator.generate( GraphQlResolverPhp.getInstance( diff --git a/src/com/magento/idea/magento2plugin/completion/provider/LayoutBlockCompletionContributor.java b/src/com/magento/idea/magento2plugin/completion/provider/LayoutBlockCompletionContributor.java index c01d64e1e..22be04952 100644 --- a/src/com/magento/idea/magento2plugin/completion/provider/LayoutBlockCompletionContributor.java +++ b/src/com/magento/idea/magento2plugin/completion/provider/LayoutBlockCompletionContributor.java @@ -2,36 +2,37 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + package com.magento.idea.magento2plugin.completion.provider; import com.intellij.codeInsight.completion.CompletionParameters; import com.intellij.codeInsight.completion.CompletionProvider; import com.intellij.codeInsight.completion.CompletionResultSet; import com.intellij.codeInsight.lookup.LookupElementBuilder; +import com.intellij.icons.AllIcons; import com.intellij.psi.PsiElement; import com.intellij.util.ProcessingContext; -import com.jetbrains.php.PhpIcons; import com.magento.idea.magento2plugin.indexes.LayoutIndex; import com.magento.idea.magento2plugin.stubs.indexes.BlockNameIndex; -import org.jetbrains.annotations.NotNull; - import java.util.Collection; +import org.jetbrains.annotations.NotNull; public class LayoutBlockCompletionContributor extends CompletionProvider { @Override - protected void addCompletions(@NotNull CompletionParameters parameters, - ProcessingContext context, - @NotNull CompletionResultSet result) { - PsiElement position = parameters.getPosition().getOriginalElement(); + protected void addCompletions(final @NotNull CompletionParameters parameters, + final ProcessingContext context, + final @NotNull CompletionResultSet result) { + final PsiElement position = parameters.getPosition().getOriginalElement(); if (position == null) { return; } - Collection keys = LayoutIndex.getAllKeys(BlockNameIndex.KEY, position.getProject()); - for (String key: keys) { + final Collection keys + = LayoutIndex.getAllKeys(BlockNameIndex.KEY, position.getProject()); + for (final String key: keys) { result.addElement( - LookupElementBuilder.create(key).withIcon(PhpIcons.XML_TAG_ICON) + LookupElementBuilder.create(key).withIcon(AllIcons.Nodes.Tag) ); } } diff --git a/src/com/magento/idea/magento2plugin/completion/provider/LayoutContainerCompletionContributor.java b/src/com/magento/idea/magento2plugin/completion/provider/LayoutContainerCompletionContributor.java index 3c6d6cf03..c127e968f 100644 --- a/src/com/magento/idea/magento2plugin/completion/provider/LayoutContainerCompletionContributor.java +++ b/src/com/magento/idea/magento2plugin/completion/provider/LayoutContainerCompletionContributor.java @@ -2,36 +2,37 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + package com.magento.idea.magento2plugin.completion.provider; import com.intellij.codeInsight.completion.CompletionParameters; import com.intellij.codeInsight.completion.CompletionProvider; import com.intellij.codeInsight.completion.CompletionResultSet; import com.intellij.codeInsight.lookup.LookupElementBuilder; +import com.intellij.icons.AllIcons; import com.intellij.psi.PsiElement; import com.intellij.util.ProcessingContext; -import com.jetbrains.php.PhpIcons; import com.magento.idea.magento2plugin.indexes.LayoutIndex; import com.magento.idea.magento2plugin.stubs.indexes.ContainerNameIndex; -import org.jetbrains.annotations.NotNull; - import java.util.Collection; +import org.jetbrains.annotations.NotNull; public class LayoutContainerCompletionContributor extends CompletionProvider { @Override - protected void addCompletions(@NotNull CompletionParameters parameters, - ProcessingContext context, - @NotNull CompletionResultSet result) { - PsiElement position = parameters.getPosition().getOriginalElement(); + protected void addCompletions(final @NotNull CompletionParameters parameters, + final ProcessingContext context, + final @NotNull CompletionResultSet result) { + final PsiElement position = parameters.getPosition().getOriginalElement(); if (position == null) { return; } - Collection keys = LayoutIndex.getAllKeys(ContainerNameIndex.KEY, position.getProject()); - for (String key: keys) { + final Collection keys + = LayoutIndex.getAllKeys(ContainerNameIndex.KEY, position.getProject()); + for (final String key: keys) { result.addElement( - LookupElementBuilder.create(key).withIcon(PhpIcons.XML_TAG_ICON) + LookupElementBuilder.create(key).withIcon(AllIcons.Nodes.Tag) ); } } diff --git a/src/com/magento/idea/magento2plugin/completion/provider/LayoutUpdateCompletionContributor.java b/src/com/magento/idea/magento2plugin/completion/provider/LayoutUpdateCompletionContributor.java index 071bdd3df..359534316 100644 --- a/src/com/magento/idea/magento2plugin/completion/provider/LayoutUpdateCompletionContributor.java +++ b/src/com/magento/idea/magento2plugin/completion/provider/LayoutUpdateCompletionContributor.java @@ -2,39 +2,40 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + package com.magento.idea.magento2plugin.completion.provider; import com.intellij.codeInsight.completion.CompletionParameters; import com.intellij.codeInsight.completion.CompletionProvider; import com.intellij.codeInsight.completion.CompletionResultSet; import com.intellij.codeInsight.lookup.LookupElementBuilder; +import com.intellij.icons.AllIcons; import com.intellij.psi.PsiElement; import com.intellij.psi.xml.XmlFile; import com.intellij.util.ProcessingContext; -import com.jetbrains.php.PhpIcons; import com.magento.idea.magento2plugin.indexes.LayoutIndex; +import java.util.List; import org.jetbrains.annotations.NotNull; -import java.util.List; public class LayoutUpdateCompletionContributor extends CompletionProvider { @Override - protected void addCompletions(@NotNull CompletionParameters parameters, - ProcessingContext context, - @NotNull CompletionResultSet result) { - PsiElement position = parameters.getPosition().getOriginalElement(); + protected void addCompletions(final @NotNull CompletionParameters parameters, + final ProcessingContext context, + final @NotNull CompletionResultSet result) { + final PsiElement position = parameters.getPosition().getOriginalElement(); if (position == null) { return; } - List targets = LayoutIndex.getLayoutFiles(position.getProject()); - if (targets.size() > 0) { - for (XmlFile file : targets) { + final List targets = LayoutIndex.getLayoutFiles(position.getProject()); + if (!targets.isEmpty()) { + for (final XmlFile file : targets) { result.addElement( - LookupElementBuilder + LookupElementBuilder .create(file.getVirtualFile().getNameWithoutExtension()) - .withIcon(PhpIcons.XML_TAG_ICON) + .withIcon(AllIcons.Nodes.Tag) ); } } diff --git a/src/com/magento/idea/magento2plugin/completion/provider/UiComponentCompletionProvider.java b/src/com/magento/idea/magento2plugin/completion/provider/UiComponentCompletionProvider.java index 0091aae2b..cf80246df 100644 --- a/src/com/magento/idea/magento2plugin/completion/provider/UiComponentCompletionProvider.java +++ b/src/com/magento/idea/magento2plugin/completion/provider/UiComponentCompletionProvider.java @@ -9,10 +9,10 @@ import com.intellij.codeInsight.completion.CompletionProvider; import com.intellij.codeInsight.completion.CompletionResultSet; import com.intellij.codeInsight.lookup.LookupElementBuilder; +import com.intellij.icons.AllIcons; import com.intellij.psi.PsiElement; import com.intellij.psi.xml.XmlFile; import com.intellij.util.ProcessingContext; -import com.jetbrains.php.PhpIcons; import com.magento.idea.magento2plugin.indexes.UIComponentIndex; import java.util.List; import org.jetbrains.annotations.NotNull; @@ -34,7 +34,7 @@ protected void addCompletions(@NotNull final CompletionParameters parameters, for (final XmlFile file : targets) { result.addElement(LookupElementBuilder .create(file.getVirtualFile().getNameWithoutExtension()) - .withIcon(PhpIcons.XML_TAG_ICON) + .withIcon(AllIcons.Nodes.Tag) ); } } diff --git a/src/com/magento/idea/magento2plugin/completion/provider/VirtualTypeCompletionProvider.java b/src/com/magento/idea/magento2plugin/completion/provider/VirtualTypeCompletionProvider.java index 1f16cf285..0e96a9f14 100644 --- a/src/com/magento/idea/magento2plugin/completion/provider/VirtualTypeCompletionProvider.java +++ b/src/com/magento/idea/magento2plugin/completion/provider/VirtualTypeCompletionProvider.java @@ -2,6 +2,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + package com.magento.idea.magento2plugin.completion.provider; import com.intellij.codeInsight.completion.CompletionParameters; @@ -9,35 +10,38 @@ import com.intellij.codeInsight.completion.CompletionResultSet; import com.intellij.codeInsight.completion.PlainPrefixMatcher; import com.intellij.codeInsight.lookup.LookupElementBuilder; +import com.intellij.icons.AllIcons; import com.intellij.psi.PsiElement; import com.intellij.util.ProcessingContext; -import com.jetbrains.php.PhpIcons; import com.magento.idea.magento2plugin.indexes.DiIndex; +import java.util.Collection; import org.jetbrains.annotations.NotNull; -import java.util.Collection; public class VirtualTypeCompletionProvider extends CompletionProvider { @Override - protected void addCompletions(@NotNull CompletionParameters parameters, - ProcessingContext context, - @NotNull CompletionResultSet result) { - PsiElement position = parameters.getPosition().getOriginalElement(); + protected void addCompletions(final @NotNull CompletionParameters parameters, + final ProcessingContext context, + final @NotNull CompletionResultSet result) { + final PsiElement position = parameters.getPosition().getOriginalElement(); if (position == null) { return; } - String prefix = result.getPrefixMatcher().getPrefix(); + final String prefix = result.getPrefixMatcher().getPrefix(); - DiIndex index = DiIndex.getInstance(position.getProject()); - Collection elements = index.getAllVirtualTypeElementNames(new PlainPrefixMatcher(prefix), position.getResolveScope()); + final DiIndex index = DiIndex.getInstance(position.getProject()); + final Collection elements = index.getAllVirtualTypeElementNames( + new PlainPrefixMatcher(prefix), + position.getResolveScope() + ); - for (String elementName:elements) { + for (final String elementName:elements) { result.addElement( LookupElementBuilder .create(elementName) - .withIcon(PhpIcons.CLASS_ICON) + .withIcon(AllIcons.Nodes.Class) ); } } diff --git a/src/com/magento/idea/magento2plugin/generation/php/MagentoTemplatesFactory.java b/src/com/magento/idea/magento2plugin/generation/php/MagentoTemplatesFactory.java index 83ab09dec..b9476e54f 100644 --- a/src/com/magento/idea/magento2plugin/generation/php/MagentoTemplatesFactory.java +++ b/src/com/magento/idea/magento2plugin/generation/php/MagentoTemplatesFactory.java @@ -2,6 +2,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + package com.magento.idea.magento2plugin.generation.php; import com.intellij.ide.util.projectWizard.WizardContext; @@ -9,25 +10,26 @@ import com.intellij.platform.ProjectTemplatesFactory; import com.jetbrains.php.config.generation.PhpEmptyTemplatesFactory; import icons.PhpIcons; +import javax.swing.Icon; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import javax.swing.Icon; public class MagentoTemplatesFactory extends ProjectTemplatesFactory { - public MagentoTemplatesFactory() { - } @NotNull public String[] getGroups() { return new String[]{PhpEmptyTemplatesFactory.PHP_PROJECT_TEMPLATE_GROUP}; } - public Icon getGroupIcon(String group) { - return PhpIcons.Php_icon; + public Icon getGroupIcon(final String group) { + return PhpIcons.PhpIcon; } @NotNull - public ProjectTemplate[] createTemplates(@Nullable String group, WizardContext context) { + public ProjectTemplate[] createTemplates( + final @Nullable String group, + final WizardContext context + ) { return new ProjectTemplate[]{new MagentoModuleGenerator()}; } } diff --git a/src/com/magento/idea/magento2plugin/inspections/graphqls/SchemaResolverInspection.java b/src/com/magento/idea/magento2plugin/inspections/graphqls/SchemaResolverInspection.java index 28de3bd91..2de57a155 100644 --- a/src/com/magento/idea/magento2plugin/inspections/graphqls/SchemaResolverInspection.java +++ b/src/com/magento/idea/magento2plugin/inspections/graphqls/SchemaResolverInspection.java @@ -8,12 +8,16 @@ import com.intellij.codeInspection.LocalInspectionTool; import com.intellij.codeInspection.ProblemHighlightType; import com.intellij.codeInspection.ProblemsHolder; +import com.intellij.lang.jsgraphql.psi.GraphQLNamedElement; import com.intellij.lang.jsgraphql.psi.GraphQLValue; import com.intellij.lang.jsgraphql.psi.GraphQLVisitor; +import com.intellij.psi.PsiElement; import com.jetbrains.php.lang.psi.elements.PhpClass; import com.magento.idea.magento2plugin.bundles.InspectionBundle; import com.magento.idea.magento2plugin.inspections.graphqls.fix.CreateResolverClassQuickFix; +import com.magento.idea.magento2plugin.magento.files.GraphQlResolver; import com.magento.idea.magento2plugin.util.GetPhpClassByFQN; +import com.magento.idea.magento2plugin.util.RegExUtil; import com.magento.idea.magento2plugin.util.magento.graphql.GraphQlUtil; import org.jetbrains.annotations.NotNull; @@ -21,30 +25,49 @@ public class SchemaResolverInspection extends LocalInspectionTool { private final InspectionBundle inspectionBundle = new InspectionBundle(); - @NotNull @Override - public GraphQLVisitor buildVisitor( - @NotNull final ProblemsHolder holder, + public @NotNull GraphQLVisitor buildVisitor( + final @NotNull ProblemsHolder holder, final boolean isOnTheFly ) { return new GraphQLVisitor() { @Override - public void visitValue(@NotNull final GraphQLValue element) { + public void visitValue(final @NotNull GraphQLValue element) { final String getVisitedElementValue = element.getText(); - if (getVisitedElementValue == null) { + final PsiElement parentElementValue = element.getParent(); + + if (getVisitedElementValue == null + || !(parentElementValue instanceof GraphQLNamedElement)) { return; } + final String attributeName = ((GraphQLNamedElement) parentElementValue).getName(); + if (!GraphQlResolver.CLASS_ARGUMENT.equals(attributeName)) { + return; + } final String resolverFQN = GraphQlUtil.resolverStringToPhpFQN(getVisitedElementValue); + + if (!resolverFQN.matches(RegExUtil.PhpRegex.FQN)) { + holder.registerProblem( + element, + inspectionBundle.message( + "inspection.warning.class.invalidFormat", + resolverFQN + ), + ProblemHighlightType.WARNING + ); + return; + } final GetPhpClassByFQN getPhpClassByFQN = GetPhpClassByFQN.getInstance(holder.getProject()); final PhpClass resolverClass = getPhpClassByFQN.execute(resolverFQN); + if (resolverClass == null) { holder.registerProblem( element, inspectionBundle.message( - "inspection.graphql.resolver.notExist" + "inspection.graphql.resolver.notExist" ), ProblemHighlightType.ERROR, new CreateResolverClassQuickFix()); diff --git a/src/com/magento/idea/magento2plugin/inspections/graphqls/fix/CreateResolverClassQuickFix.java b/src/com/magento/idea/magento2plugin/inspections/graphqls/fix/CreateResolverClassQuickFix.java index 57d0dca4c..44ee91b9c 100644 --- a/src/com/magento/idea/magento2plugin/inspections/graphqls/fix/CreateResolverClassQuickFix.java +++ b/src/com/magento/idea/magento2plugin/inspections/graphqls/fix/CreateResolverClassQuickFix.java @@ -14,12 +14,19 @@ import com.magento.idea.magento2plugin.actions.generation.data.GraphQlResolverFileData; import com.magento.idea.magento2plugin.actions.generation.generator.ModuleGraphQlResolverClassGenerator; import com.magento.idea.magento2plugin.bundles.InspectionBundle; +import com.magento.idea.magento2plugin.magento.packages.File; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import javax.swing.JOptionPane; import org.jetbrains.annotations.NotNull; public class CreateResolverClassQuickFix implements LocalQuickFix { + + private static final int CLASSPATH_MIN_DEPTH = 3; + + private final InspectionBundle inspectionBundle = new InspectionBundle(); + @Override public @NotNull String getFamilyName() { return new InspectionBundle().message( @@ -39,10 +46,25 @@ public void applyFix( fqnPartsList.removeIf(Strings::isNullOrEmpty); + if (fqnPartsList.size() < CLASSPATH_MIN_DEPTH) { + JOptionPane.showMessageDialog( + null, + inspectionBundle.message( + "inspection.error.graphqlResolverClass.tooShortFormat", + resolverFqn + ), + inspectionBundle.message( + "inspection.error.graphqlResolverClass.tooShortFormatTitle" + ), + JOptionPane.ERROR_MESSAGE + ); + return; + } + final int endIndex = fqnPartsList.size() - 1; final String moduleName = String.join("_", fqnPartsList.subList(0, 2)); final String resolverName = fqnPartsList.get(endIndex); - final String directory = fqnPartsList.get(2); + final String directory = String.join(File.separator, fqnPartsList.subList(2, endIndex)); final String namespace = String.join("\\", fqnPartsList.subList(0, endIndex)); final GraphQlResolverFileData graphQlResolverFileData = new GraphQlResolverFileData( diff --git a/src/com/magento/idea/magento2uct/execution/configurations/UctRunConfiguration.java b/src/com/magento/idea/magento2uct/execution/configurations/UctRunConfiguration.java index dc40ca81f..91cb841eb 100644 --- a/src/com/magento/idea/magento2uct/execution/configurations/UctRunConfiguration.java +++ b/src/com/magento/idea/magento2uct/execution/configurations/UctRunConfiguration.java @@ -5,6 +5,8 @@ package com.magento.idea.magento2uct.execution.configurations; +import static com.magento.idea.magento2uct.execution.configurations.UctSettingsEditor.MAGENTO_VERSION_PATTERN; + import com.intellij.execution.ExecutionException; import com.intellij.execution.Executor; import com.intellij.execution.RunManager; @@ -32,6 +34,7 @@ import com.magento.idea.magento2uct.settings.UctSettingsService; import com.magento.idea.magento2uct.util.UctExecutableValidatorUtil; import com.magento.idea.magento2uct.util.module.UctModulePathValidatorUtil; +import java.util.regex.Matcher; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -241,6 +244,11 @@ public boolean isNewlyCreated() { throw new ExecutionException("The coming/target version is not specified"); } + final Matcher matcher = MAGENTO_VERSION_PATTERN.matcher(getComingVersion()); + if (!matcher.find()) { + throw new ExecutionException("The coming/target version is not correct"); + } + if (getProjectRoot().isEmpty()) { throw new ExecutionException("The project root is not specified"); } @@ -255,14 +263,12 @@ public boolean isNewlyCreated() { commandSettingsBuilder.addArgument("--coming-version=" + getComingVersion()); } - commandSettingsBuilder.addArgument(getProjectRoot()); - final GeneralCommandLine commandLine = commandSettingsBuilder.createGeneralCommandLine(); if (!getModulePath().isEmpty()) { if (UctModulePathValidatorUtil.validate(getModulePath())) { - commandLine.addParameter("--module-path=".concat(getModulePath())); + commandLine.addParameter(getModulePath()); } else { throw new ExecutionException("The path to analyse is not valid"); } diff --git a/src/com/magento/idea/magento2uct/execution/configurations/UctSettingsEditor.form b/src/com/magento/idea/magento2uct/execution/configurations/UctSettingsEditor.form index a3de59bfc..1e7f0ca56 100644 --- a/src/com/magento/idea/magento2uct/execution/configurations/UctSettingsEditor.form +++ b/src/com/magento/idea/magento2uct/execution/configurations/UctSettingsEditor.form @@ -25,7 +25,9 @@ - + + + diff --git a/src/com/magento/idea/magento2uct/execution/configurations/UctSettingsEditor.java b/src/com/magento/idea/magento2uct/execution/configurations/UctSettingsEditor.java index 215bf5626..ff71c219e 100644 --- a/src/com/magento/idea/magento2uct/execution/configurations/UctSettingsEditor.java +++ b/src/com/magento/idea/magento2uct/execution/configurations/UctSettingsEditor.java @@ -29,6 +29,9 @@ import java.awt.Container; import java.net.URI; import java.net.URISyntaxException; +import java.util.Objects; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JComponent; @@ -45,6 +48,10 @@ public class UctSettingsEditor extends SettingsEditor { private static final String LEARN_MORE_URI = "https://docs.magento.com/user-guide/getting-started.html#product-editions"; private static final String LEARN_MORE_TEXT = "Learn more. "; + @SuppressWarnings("checkstyle:LineLength") + private static final String MAGENTO_VERSION_REGEX = "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$"; + public static final Pattern MAGENTO_VERSION_PATTERN + = Pattern.compile(MAGENTO_VERSION_REGEX); private final Project project; private String uctExecutablePath; @@ -126,6 +133,14 @@ protected void resetEditorFrom(final @NotNull UctRunConfiguration uctRunConfigur if (!uctRunConfiguration.getComingVersion().isEmpty()) { final String storedComingVersion = uctRunConfiguration.getComingVersion(); setSelectedValueByItsKey(comingVersion, storedComingVersion); + + if (!Objects.requireNonNull( + comingVersion.getSelectedItem()).toString().equals(storedComingVersion)) { + final ComboBoxItemData customVersion + = new ComboBoxItemData(storedComingVersion, storedComingVersion); + comingVersion.addItem(customVersion); + comingVersion.setSelectedItem(customVersion); + } } if (uctRunConfiguration.getMinIssueLevel() > 0) { @@ -148,8 +163,8 @@ protected void applyEditorTo(final @NotNull UctRunConfiguration uctRunConfigurat uctRunConfiguration.setProjectRoot(projectRoot.getComponent().getText()); uctRunConfiguration.setModulePath(modulePath.getComponent().getText()); - final ComboBoxItemData selectedComingVersion = - (ComboBoxItemData) comingVersion.getSelectedItem(); + final ComboBoxItemData selectedComingVersion + = getCorrectedSelectedItem(comingVersion.getSelectedItem()); if (selectedComingVersion == null) { uctRunConfiguration.setComingVersion(""); @@ -299,7 +314,7 @@ private String getStoredUctExecutablePath( */ @SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops") private void initializeComboboxSources() { - comingVersion.addItem(new ComboBoxItemData("", "Choose a target version")); + comingVersion.setToolTipText("Choose a target version"); for (final String version : SupportedVersion.getSupportedVersions()) { comingVersion.addItem(new ComboBoxItemData(version, version)); @@ -339,7 +354,7 @@ protected void textChanged(final @NotNull DocumentEvent event) { }); comingVersion.addItemListener(event -> { - final ComboBoxItemData selectedItem = (ComboBoxItemData) event.getItem(); + final ComboBoxItemData selectedItem = getCorrectedSelectedItem(event.getItem()); validateComingVersionField(selectedItem); }); @@ -366,13 +381,37 @@ private void validateExecutablePathField() { * @param selectedItem ComboBoxItemData */ private void validateComingVersionField(final ComboBoxItemData selectedItem) { + final Matcher matcher = MAGENTO_VERSION_PATTERN.matcher(selectedItem.getText()); + if (selectedItem != null && selectedItem.getKey().isEmpty()) { comingVersionError.setText("Please, specify target version"); + } else if (!matcher.find()) { // NOPMD + comingVersionError.setText("Please, correct target version"); } else { comingVersionError.setText(""); } } + /** + * Get existing item or select and convert custom version. + * + * @param selectedItem String|ComboBoxItemData + * @return ComboBoxItemData + */ + private ComboBoxItemData getCorrectedSelectedItem(final Object selectedItem) { + ComboBoxItemData selectedComingVersion; + + if (selectedItem instanceof ComboBoxItemData) { + selectedComingVersion = (ComboBoxItemData) selectedItem; + } else { + final String customSelectedVersion = selectedItem.toString(); + selectedComingVersion + = new ComboBoxItemData(customSelectedVersion, customSelectedVersion); + } + + return selectedComingVersion; + } + /** * Set selected combobox item by key. *