From a19eb376cd38c9dc729ae0104dde252b330eedd3 Mon Sep 17 00:00:00 2001 From: Lena Orobei Date: Tue, 31 Mar 2020 19:10:46 -0500 Subject: [PATCH] Legal review update - fixed license - added required docs - fixed copyright - added issue and PR templates --- .../CODE_OF_CONDUCT.md | 0 CONTRIBUTING.md => .github/CONTRIBUTING.md | 0 .github/ISSUE_TEMPLATE.md | 33 + .github/PULL_REQUEST_TEMPLATE.md | 34 + COPYING.txt | 11 +- LICENSE.md => LICENSE.txt | 0 META-INF/plugin.xml | 2 +- README.md | 5 +- resources/META-INF/plugin.xml | 2 +- .../idea/magento2plugin/MagentoIcons.java | 2 +- .../provider/CompositeCompletionProvider.java | 2 +- .../EventNameCompletionContributor.java | 2 +- .../provider/FilePathCompletionProvider.java | 2 +- .../LayoutBlockCompletionContributor.java | 2 +- .../LayoutContainerCompletionContributor.java | 2 +- .../LayoutUpdateCompletionContributor.java | 2 +- .../ModuleNameCompletionProvider.java | 2 +- .../provider/PhpClassCompletionProvider.java | 2 +- .../PhpClassMemberCompletionProvider.java | 2 +- ...ConstructorArgumentCompletionProvider.java | 2 +- ...PhpServiceMethodCompletionContributor.java | 2 +- .../VirtualTypeCompletionProvider.java | 2 +- .../xml/XmlCompletionContributor.java | 2 +- .../idea/magento2plugin/indexes/DiIndex.java | 2 +- .../magento2plugin/indexes/EventIndex.java | 2 +- .../magento2plugin/indexes/IndexManager.java | 2 +- .../magento2plugin/indexes/LayoutIndex.java | 2 +- .../idea/magento2plugin/indexes/XmlIndex.java | 2 +- .../ClassConfigurationLineMarkerProvider.java | 2 +- .../linemarker/PluginLineMarkerProvider.java | 2 +- .../linemarker/WebApiLineMarkerProvider.java | 2 +- .../php/module/ComposerPackageModel.java | 2 +- .../php/module/ComposerPackageModelImpl.java | 2 +- .../php/module/MagentoComponent.java | 2 +- .../php/module/MagentoComponentImp.java | 2 +- .../php/module/MagentoComponentManager.java | 2 +- .../php/module/MagentoModule.java | 2 +- .../php/util/PhpPatternsHelper.java | 2 +- .../magento2plugin/php/util/PhpRegex.java | 2 +- .../project/ProjectDetector.java | 2 +- .../idea/magento2plugin/project/Settings.java | 2 +- .../magento2plugin/project/SettingsForm.form | 2 +- .../magento2plugin/project/SettingsForm.java | 2 +- .../reference/js/JsReferenceContributor.java | 2 +- .../php/PhpReferenceContributor.java | 2 +- .../provider/CompositeReferenceProvider.java | 2 +- .../EventDispatchReferenceProvider.java | 2 +- .../provider/EventNameReferenceProvider.java | 2 +- .../provider/FilePathReferenceProvider.java | 2 +- .../LayoutBlockReferenceProvider.java | 2 +- .../LayoutContainerReferenceProvider.java | 2 +- .../LayoutUpdateReferenceProvider.java | 2 +- .../provider/ModuleNameReferenceProvider.java | 2 +- .../PhpClassMemberReferenceProvider.java | 2 +- .../provider/PhpClassReferenceProvider.java | 2 +- ...pConstructorArgumentReferenceProvider.java | 2 +- .../PhpServiceMethodReferenceProvider.java | 2 +- .../VirtualTypeReferenceProvider.java | 2 +- .../xml/PolyVariantReferenceBase.java | 2 +- .../xml/XmlReferenceContributor.java | 2 +- .../stubs/indexes/BlockNameIndex.java | 2 +- .../stubs/indexes/ContainerNameIndex.java | 2 +- .../stubs/indexes/EventNameIndex.java | 2 +- .../stubs/indexes/EventObserverIndex.java | 2 +- .../stubs/indexes/LayoutDataIndexer.java | 2 +- .../stubs/indexes/ModuleNameIndex.java | 2 +- .../stubs/indexes/ModulePackageIndex.java | 2 +- .../stubs/indexes/NamedComponentIndex.java | 2 +- .../stubs/indexes/PluginIndex.java | 2 +- .../stubs/indexes/VirtualTypeIndex.java | 2 +- .../stubs/indexes/WebApiTypeIndex.java | 2 +- .../stubs/indexes/xml/PhpClassNameIndex.java | 2 +- .../idea/magento2plugin/util/RegExUtil.java | 2 +- .../idea/magento2plugin/util/VfsUtil.java | 2 +- .../util/magento/FileBasedIndexUtil.java | 2 +- .../xml/LineMarkerXmlTagDecorator.java | 2 +- .../magento2plugin/xml/XmlPsiTreeUtil.java | 2 +- transfer.patch | 9788 ----------------- 78 files changed, 144 insertions(+), 9867 deletions(-) rename CODE_OF_CONDUCT.md => .github/CODE_OF_CONDUCT.md (100%) rename CONTRIBUTING.md => .github/CONTRIBUTING.md (100%) create mode 100644 .github/ISSUE_TEMPLATE.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md rename LICENSE.md => LICENSE.txt (100%) delete mode 100644 transfer.patch diff --git a/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md similarity index 100% rename from CODE_OF_CONDUCT.md rename to .github/CODE_OF_CONDUCT.md diff --git a/CONTRIBUTING.md b/.github/CONTRIBUTING.md similarity index 100% rename from CONTRIBUTING.md rename to .github/CONTRIBUTING.md diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 000000000..ea3b45635 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,33 @@ + + +### Preconditions (*) + +1. +2. + +### Steps to reproduce (*) + +1. +2. +3. + +### Expected result (*) + +1. [Screenshots, logs or description] + +### Actual result (*) + +1. [Screenshots, logs or description] diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..fa9c34feb --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,34 @@ + + + + +### Description (*) + + +### Fixed Issues (if relevant) + +1. magento/magento2-phpstorm-plugin#: Issue title + +### Questions or comments + + +### Contribution checklist (*) + - [ ] Pull request has a meaningful description of its purpose + - [ ] All commits are accompanied by meaningful commit messages + diff --git a/COPYING.txt b/COPYING.txt index 5bd6a165b..4fc4bb744 100644 --- a/COPYING.txt +++ b/COPYING.txt @@ -1,9 +1,4 @@ -Copyright © 2015-present Dmytro Kvashnin. +Copyright © 2015-present Magento, Inc. -Each Magento source file included in this distribution is licensed under OSL 3.0 or the Magento Enterprise Edition (MEE) license. - -http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) -Please see LICENSE.txt for the full text of the OSL 3.0 license or contact license@magentocommerce.com for a copy. - -Subject to Licensee's payment of fees and compliance with the terms and conditions of the MEE License, the MEE License supersedes the OSL 3.0 license for each source file. -Please see LICENSE_EE.txt for the full text of the MEE License or visit http://magento.com/legal/terms/enterprise. +Each Magento source file included in this distribution is licensed under OSL-3.0 license +Please see LICENSE.txt for the full text of the OSL-3.0 license or visit http://opensource.org/licenses/osl-3.0.php diff --git a/LICENSE.md b/LICENSE.txt similarity index 100% rename from LICENSE.md rename to LICENSE.txt diff --git a/META-INF/plugin.xml b/META-INF/plugin.xml index 795eb465c..1deaf5bad 100644 --- a/META-INF/plugin.xml +++ b/META-INF/plugin.xml @@ -1,6 +1,6 @@ diff --git a/README.md b/README.md index 93c3a7b0d..b2aa9c53f 100644 --- a/README.md +++ b/README.md @@ -26,5 +26,8 @@ This is a plugin for Magento 2 development in the PhpStorm IDE. It is available * "Navigate to Web API configuration" reference in scope of class/interface and method ## License +Each Magento source file included in this distribution is licensed under OSL-3.0 license. -Copyright (c) 2015 Dmytro Kvashnin. See LICENSE.md for details. +Please see [LICENSE.txt](https://github.com/magento/magento2-phpstorm-plugin/blob/master/LICENSE.txt) for the full text of the [Open Software License v. 3.0 (OSL-3.0)](http://opensource.org/licenses/osl-3.0.php). + +### Join [#phpstorm-plugin](https://magentocommeng.slack.com/archives/C010C2LUCEA) channel for more details. diff --git a/resources/META-INF/plugin.xml b/resources/META-INF/plugin.xml index 79dd2ac3d..a2875854b 100644 --- a/resources/META-INF/plugin.xml +++ b/resources/META-INF/plugin.xml @@ -1,6 +1,6 @@ diff --git a/src/com/magento/idea/magento2plugin/MagentoIcons.java b/src/com/magento/idea/magento2plugin/MagentoIcons.java index 82de250f1..3be45516d 100644 --- a/src/com/magento/idea/magento2plugin/MagentoIcons.java +++ b/src/com/magento/idea/magento2plugin/MagentoIcons.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin; diff --git a/src/com/magento/idea/magento2plugin/completion/provider/CompositeCompletionProvider.java b/src/com/magento/idea/magento2plugin/completion/provider/CompositeCompletionProvider.java index f4dc6f1f8..745f6d9ed 100644 --- a/src/com/magento/idea/magento2plugin/completion/provider/CompositeCompletionProvider.java +++ b/src/com/magento/idea/magento2plugin/completion/provider/CompositeCompletionProvider.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.completion.provider; diff --git a/src/com/magento/idea/magento2plugin/completion/provider/EventNameCompletionContributor.java b/src/com/magento/idea/magento2plugin/completion/provider/EventNameCompletionContributor.java index ca6f2a032..04119b922 100644 --- a/src/com/magento/idea/magento2plugin/completion/provider/EventNameCompletionContributor.java +++ b/src/com/magento/idea/magento2plugin/completion/provider/EventNameCompletionContributor.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.completion.provider; diff --git a/src/com/magento/idea/magento2plugin/completion/provider/FilePathCompletionProvider.java b/src/com/magento/idea/magento2plugin/completion/provider/FilePathCompletionProvider.java index ff52f0586..210afb573 100644 --- a/src/com/magento/idea/magento2plugin/completion/provider/FilePathCompletionProvider.java +++ b/src/com/magento/idea/magento2plugin/completion/provider/FilePathCompletionProvider.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.completion.provider; diff --git a/src/com/magento/idea/magento2plugin/completion/provider/LayoutBlockCompletionContributor.java b/src/com/magento/idea/magento2plugin/completion/provider/LayoutBlockCompletionContributor.java index 9885fd22e..c01d64e1e 100644 --- a/src/com/magento/idea/magento2plugin/completion/provider/LayoutBlockCompletionContributor.java +++ b/src/com/magento/idea/magento2plugin/completion/provider/LayoutBlockCompletionContributor.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.completion.provider; diff --git a/src/com/magento/idea/magento2plugin/completion/provider/LayoutContainerCompletionContributor.java b/src/com/magento/idea/magento2plugin/completion/provider/LayoutContainerCompletionContributor.java index 6093efc6b..3c6d6cf03 100644 --- a/src/com/magento/idea/magento2plugin/completion/provider/LayoutContainerCompletionContributor.java +++ b/src/com/magento/idea/magento2plugin/completion/provider/LayoutContainerCompletionContributor.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.completion.provider; diff --git a/src/com/magento/idea/magento2plugin/completion/provider/LayoutUpdateCompletionContributor.java b/src/com/magento/idea/magento2plugin/completion/provider/LayoutUpdateCompletionContributor.java index 3fe032cd2..071bdd3df 100644 --- a/src/com/magento/idea/magento2plugin/completion/provider/LayoutUpdateCompletionContributor.java +++ b/src/com/magento/idea/magento2plugin/completion/provider/LayoutUpdateCompletionContributor.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.completion.provider; diff --git a/src/com/magento/idea/magento2plugin/completion/provider/ModuleNameCompletionProvider.java b/src/com/magento/idea/magento2plugin/completion/provider/ModuleNameCompletionProvider.java index fd336ca49..22e483c57 100644 --- a/src/com/magento/idea/magento2plugin/completion/provider/ModuleNameCompletionProvider.java +++ b/src/com/magento/idea/magento2plugin/completion/provider/ModuleNameCompletionProvider.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.completion.provider; diff --git a/src/com/magento/idea/magento2plugin/completion/provider/PhpClassCompletionProvider.java b/src/com/magento/idea/magento2plugin/completion/provider/PhpClassCompletionProvider.java index 568d44b9a..614d3b198 100644 --- a/src/com/magento/idea/magento2plugin/completion/provider/PhpClassCompletionProvider.java +++ b/src/com/magento/idea/magento2plugin/completion/provider/PhpClassCompletionProvider.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.completion.provider; diff --git a/src/com/magento/idea/magento2plugin/completion/provider/PhpClassMemberCompletionProvider.java b/src/com/magento/idea/magento2plugin/completion/provider/PhpClassMemberCompletionProvider.java index 46ccfa205..2a3409e9a 100644 --- a/src/com/magento/idea/magento2plugin/completion/provider/PhpClassMemberCompletionProvider.java +++ b/src/com/magento/idea/magento2plugin/completion/provider/PhpClassMemberCompletionProvider.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.completion.provider; diff --git a/src/com/magento/idea/magento2plugin/completion/provider/PhpConstructorArgumentCompletionProvider.java b/src/com/magento/idea/magento2plugin/completion/provider/PhpConstructorArgumentCompletionProvider.java index a86c9f0f0..c5e155f26 100644 --- a/src/com/magento/idea/magento2plugin/completion/provider/PhpConstructorArgumentCompletionProvider.java +++ b/src/com/magento/idea/magento2plugin/completion/provider/PhpConstructorArgumentCompletionProvider.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.completion.provider; diff --git a/src/com/magento/idea/magento2plugin/completion/provider/PhpServiceMethodCompletionContributor.java b/src/com/magento/idea/magento2plugin/completion/provider/PhpServiceMethodCompletionContributor.java index f9b67b9d1..f93f60c4a 100644 --- a/src/com/magento/idea/magento2plugin/completion/provider/PhpServiceMethodCompletionContributor.java +++ b/src/com/magento/idea/magento2plugin/completion/provider/PhpServiceMethodCompletionContributor.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.completion.provider; diff --git a/src/com/magento/idea/magento2plugin/completion/provider/VirtualTypeCompletionProvider.java b/src/com/magento/idea/magento2plugin/completion/provider/VirtualTypeCompletionProvider.java index ee547d60e..1f16cf285 100644 --- a/src/com/magento/idea/magento2plugin/completion/provider/VirtualTypeCompletionProvider.java +++ b/src/com/magento/idea/magento2plugin/completion/provider/VirtualTypeCompletionProvider.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.completion.provider; diff --git a/src/com/magento/idea/magento2plugin/completion/xml/XmlCompletionContributor.java b/src/com/magento/idea/magento2plugin/completion/xml/XmlCompletionContributor.java index 7a930dc3b..a05a7cc73 100644 --- a/src/com/magento/idea/magento2plugin/completion/xml/XmlCompletionContributor.java +++ b/src/com/magento/idea/magento2plugin/completion/xml/XmlCompletionContributor.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.completion.xml; diff --git a/src/com/magento/idea/magento2plugin/indexes/DiIndex.java b/src/com/magento/idea/magento2plugin/indexes/DiIndex.java index 94cd57aad..91370c38f 100644 --- a/src/com/magento/idea/magento2plugin/indexes/DiIndex.java +++ b/src/com/magento/idea/magento2plugin/indexes/DiIndex.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.indexes; diff --git a/src/com/magento/idea/magento2plugin/indexes/EventIndex.java b/src/com/magento/idea/magento2plugin/indexes/EventIndex.java index 2e7bc0743..181bc2f32 100644 --- a/src/com/magento/idea/magento2plugin/indexes/EventIndex.java +++ b/src/com/magento/idea/magento2plugin/indexes/EventIndex.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.indexes; diff --git a/src/com/magento/idea/magento2plugin/indexes/IndexManager.java b/src/com/magento/idea/magento2plugin/indexes/IndexManager.java index aa5577daa..d82cd8f17 100644 --- a/src/com/magento/idea/magento2plugin/indexes/IndexManager.java +++ b/src/com/magento/idea/magento2plugin/indexes/IndexManager.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.indexes; diff --git a/src/com/magento/idea/magento2plugin/indexes/LayoutIndex.java b/src/com/magento/idea/magento2plugin/indexes/LayoutIndex.java index 2d987aee7..0f0307c93 100644 --- a/src/com/magento/idea/magento2plugin/indexes/LayoutIndex.java +++ b/src/com/magento/idea/magento2plugin/indexes/LayoutIndex.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.indexes; diff --git a/src/com/magento/idea/magento2plugin/indexes/XmlIndex.java b/src/com/magento/idea/magento2plugin/indexes/XmlIndex.java index 22a0e37c7..e24fc8aac 100644 --- a/src/com/magento/idea/magento2plugin/indexes/XmlIndex.java +++ b/src/com/magento/idea/magento2plugin/indexes/XmlIndex.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.indexes; diff --git a/src/com/magento/idea/magento2plugin/php/linemarker/ClassConfigurationLineMarkerProvider.java b/src/com/magento/idea/magento2plugin/php/linemarker/ClassConfigurationLineMarkerProvider.java index 9ba39d2ff..092ed2ad4 100644 --- a/src/com/magento/idea/magento2plugin/php/linemarker/ClassConfigurationLineMarkerProvider.java +++ b/src/com/magento/idea/magento2plugin/php/linemarker/ClassConfigurationLineMarkerProvider.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.php.linemarker; diff --git a/src/com/magento/idea/magento2plugin/php/linemarker/PluginLineMarkerProvider.java b/src/com/magento/idea/magento2plugin/php/linemarker/PluginLineMarkerProvider.java index 637879bfe..67fe11738 100644 --- a/src/com/magento/idea/magento2plugin/php/linemarker/PluginLineMarkerProvider.java +++ b/src/com/magento/idea/magento2plugin/php/linemarker/PluginLineMarkerProvider.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.php.linemarker; diff --git a/src/com/magento/idea/magento2plugin/php/linemarker/WebApiLineMarkerProvider.java b/src/com/magento/idea/magento2plugin/php/linemarker/WebApiLineMarkerProvider.java index bacbeb384..4dd60b101 100644 --- a/src/com/magento/idea/magento2plugin/php/linemarker/WebApiLineMarkerProvider.java +++ b/src/com/magento/idea/magento2plugin/php/linemarker/WebApiLineMarkerProvider.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.php.linemarker; diff --git a/src/com/magento/idea/magento2plugin/php/module/ComposerPackageModel.java b/src/com/magento/idea/magento2plugin/php/module/ComposerPackageModel.java index 768066aa8..3076ff31a 100644 --- a/src/com/magento/idea/magento2plugin/php/module/ComposerPackageModel.java +++ b/src/com/magento/idea/magento2plugin/php/module/ComposerPackageModel.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.php.module; diff --git a/src/com/magento/idea/magento2plugin/php/module/ComposerPackageModelImpl.java b/src/com/magento/idea/magento2plugin/php/module/ComposerPackageModelImpl.java index e2cf2a453..fa10ea5f1 100644 --- a/src/com/magento/idea/magento2plugin/php/module/ComposerPackageModelImpl.java +++ b/src/com/magento/idea/magento2plugin/php/module/ComposerPackageModelImpl.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.php.module; diff --git a/src/com/magento/idea/magento2plugin/php/module/MagentoComponent.java b/src/com/magento/idea/magento2plugin/php/module/MagentoComponent.java index ba6d9895f..b33e4c80f 100644 --- a/src/com/magento/idea/magento2plugin/php/module/MagentoComponent.java +++ b/src/com/magento/idea/magento2plugin/php/module/MagentoComponent.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.php.module; diff --git a/src/com/magento/idea/magento2plugin/php/module/MagentoComponentImp.java b/src/com/magento/idea/magento2plugin/php/module/MagentoComponentImp.java index 503b7cace..ec4cd72ff 100644 --- a/src/com/magento/idea/magento2plugin/php/module/MagentoComponentImp.java +++ b/src/com/magento/idea/magento2plugin/php/module/MagentoComponentImp.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.php.module; diff --git a/src/com/magento/idea/magento2plugin/php/module/MagentoComponentManager.java b/src/com/magento/idea/magento2plugin/php/module/MagentoComponentManager.java index 3007238cc..c633b774c 100644 --- a/src/com/magento/idea/magento2plugin/php/module/MagentoComponentManager.java +++ b/src/com/magento/idea/magento2plugin/php/module/MagentoComponentManager.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.php.module; diff --git a/src/com/magento/idea/magento2plugin/php/module/MagentoModule.java b/src/com/magento/idea/magento2plugin/php/module/MagentoModule.java index 110dce6d3..77b3edbdd 100644 --- a/src/com/magento/idea/magento2plugin/php/module/MagentoModule.java +++ b/src/com/magento/idea/magento2plugin/php/module/MagentoModule.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.php.module; diff --git a/src/com/magento/idea/magento2plugin/php/util/PhpPatternsHelper.java b/src/com/magento/idea/magento2plugin/php/util/PhpPatternsHelper.java index f2627f5d0..409f4474f 100644 --- a/src/com/magento/idea/magento2plugin/php/util/PhpPatternsHelper.java +++ b/src/com/magento/idea/magento2plugin/php/util/PhpPatternsHelper.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.php.util; diff --git a/src/com/magento/idea/magento2plugin/php/util/PhpRegex.java b/src/com/magento/idea/magento2plugin/php/util/PhpRegex.java index 632c924a4..91ccf55a0 100644 --- a/src/com/magento/idea/magento2plugin/php/util/PhpRegex.java +++ b/src/com/magento/idea/magento2plugin/php/util/PhpRegex.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.php.util; diff --git a/src/com/magento/idea/magento2plugin/project/ProjectDetector.java b/src/com/magento/idea/magento2plugin/project/ProjectDetector.java index 8f2e86d41..586a9e608 100644 --- a/src/com/magento/idea/magento2plugin/project/ProjectDetector.java +++ b/src/com/magento/idea/magento2plugin/project/ProjectDetector.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.project; diff --git a/src/com/magento/idea/magento2plugin/project/Settings.java b/src/com/magento/idea/magento2plugin/project/Settings.java index 47b8a3262..df2291323 100644 --- a/src/com/magento/idea/magento2plugin/project/Settings.java +++ b/src/com/magento/idea/magento2plugin/project/Settings.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.project; diff --git a/src/com/magento/idea/magento2plugin/project/SettingsForm.form b/src/com/magento/idea/magento2plugin/project/SettingsForm.form index 6a596098b..70caa0737 100644 --- a/src/com/magento/idea/magento2plugin/project/SettingsForm.form +++ b/src/com/magento/idea/magento2plugin/project/SettingsForm.form @@ -1,7 +1,7 @@ diff --git a/src/com/magento/idea/magento2plugin/project/SettingsForm.java b/src/com/magento/idea/magento2plugin/project/SettingsForm.java index 4eb818305..646431bc1 100644 --- a/src/com/magento/idea/magento2plugin/project/SettingsForm.java +++ b/src/com/magento/idea/magento2plugin/project/SettingsForm.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.project; diff --git a/src/com/magento/idea/magento2plugin/reference/js/JsReferenceContributor.java b/src/com/magento/idea/magento2plugin/reference/js/JsReferenceContributor.java index 954c3cabe..787958e34 100644 --- a/src/com/magento/idea/magento2plugin/reference/js/JsReferenceContributor.java +++ b/src/com/magento/idea/magento2plugin/reference/js/JsReferenceContributor.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.reference.js; diff --git a/src/com/magento/idea/magento2plugin/reference/php/PhpReferenceContributor.java b/src/com/magento/idea/magento2plugin/reference/php/PhpReferenceContributor.java index 4099f34f3..e0525017d 100644 --- a/src/com/magento/idea/magento2plugin/reference/php/PhpReferenceContributor.java +++ b/src/com/magento/idea/magento2plugin/reference/php/PhpReferenceContributor.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.reference.php; diff --git a/src/com/magento/idea/magento2plugin/reference/provider/CompositeReferenceProvider.java b/src/com/magento/idea/magento2plugin/reference/provider/CompositeReferenceProvider.java index c2e5dd8ca..4f43f016b 100644 --- a/src/com/magento/idea/magento2plugin/reference/provider/CompositeReferenceProvider.java +++ b/src/com/magento/idea/magento2plugin/reference/provider/CompositeReferenceProvider.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.reference.provider; diff --git a/src/com/magento/idea/magento2plugin/reference/provider/EventDispatchReferenceProvider.java b/src/com/magento/idea/magento2plugin/reference/provider/EventDispatchReferenceProvider.java index 86bc9a2d3..d662093f4 100644 --- a/src/com/magento/idea/magento2plugin/reference/provider/EventDispatchReferenceProvider.java +++ b/src/com/magento/idea/magento2plugin/reference/provider/EventDispatchReferenceProvider.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.reference.provider; diff --git a/src/com/magento/idea/magento2plugin/reference/provider/EventNameReferenceProvider.java b/src/com/magento/idea/magento2plugin/reference/provider/EventNameReferenceProvider.java index bfed6cdf6..accaf980d 100644 --- a/src/com/magento/idea/magento2plugin/reference/provider/EventNameReferenceProvider.java +++ b/src/com/magento/idea/magento2plugin/reference/provider/EventNameReferenceProvider.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.reference.provider; diff --git a/src/com/magento/idea/magento2plugin/reference/provider/FilePathReferenceProvider.java b/src/com/magento/idea/magento2plugin/reference/provider/FilePathReferenceProvider.java index c877bd4ec..4d44459b8 100644 --- a/src/com/magento/idea/magento2plugin/reference/provider/FilePathReferenceProvider.java +++ b/src/com/magento/idea/magento2plugin/reference/provider/FilePathReferenceProvider.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.reference.provider; diff --git a/src/com/magento/idea/magento2plugin/reference/provider/LayoutBlockReferenceProvider.java b/src/com/magento/idea/magento2plugin/reference/provider/LayoutBlockReferenceProvider.java index 3c7d73abd..285b53d21 100644 --- a/src/com/magento/idea/magento2plugin/reference/provider/LayoutBlockReferenceProvider.java +++ b/src/com/magento/idea/magento2plugin/reference/provider/LayoutBlockReferenceProvider.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.reference.provider; diff --git a/src/com/magento/idea/magento2plugin/reference/provider/LayoutContainerReferenceProvider.java b/src/com/magento/idea/magento2plugin/reference/provider/LayoutContainerReferenceProvider.java index ebb19ae46..4843c7600 100644 --- a/src/com/magento/idea/magento2plugin/reference/provider/LayoutContainerReferenceProvider.java +++ b/src/com/magento/idea/magento2plugin/reference/provider/LayoutContainerReferenceProvider.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.reference.provider; diff --git a/src/com/magento/idea/magento2plugin/reference/provider/LayoutUpdateReferenceProvider.java b/src/com/magento/idea/magento2plugin/reference/provider/LayoutUpdateReferenceProvider.java index df1ea53d4..effe70c88 100644 --- a/src/com/magento/idea/magento2plugin/reference/provider/LayoutUpdateReferenceProvider.java +++ b/src/com/magento/idea/magento2plugin/reference/provider/LayoutUpdateReferenceProvider.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.reference.provider; diff --git a/src/com/magento/idea/magento2plugin/reference/provider/ModuleNameReferenceProvider.java b/src/com/magento/idea/magento2plugin/reference/provider/ModuleNameReferenceProvider.java index 7fcaa832b..2ee0429ec 100644 --- a/src/com/magento/idea/magento2plugin/reference/provider/ModuleNameReferenceProvider.java +++ b/src/com/magento/idea/magento2plugin/reference/provider/ModuleNameReferenceProvider.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.reference.provider; diff --git a/src/com/magento/idea/magento2plugin/reference/provider/PhpClassMemberReferenceProvider.java b/src/com/magento/idea/magento2plugin/reference/provider/PhpClassMemberReferenceProvider.java index 7323f0c0a..bf75f93c8 100644 --- a/src/com/magento/idea/magento2plugin/reference/provider/PhpClassMemberReferenceProvider.java +++ b/src/com/magento/idea/magento2plugin/reference/provider/PhpClassMemberReferenceProvider.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.reference.provider; diff --git a/src/com/magento/idea/magento2plugin/reference/provider/PhpClassReferenceProvider.java b/src/com/magento/idea/magento2plugin/reference/provider/PhpClassReferenceProvider.java index 0b4c2d08b..899c3af74 100644 --- a/src/com/magento/idea/magento2plugin/reference/provider/PhpClassReferenceProvider.java +++ b/src/com/magento/idea/magento2plugin/reference/provider/PhpClassReferenceProvider.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.reference.provider; diff --git a/src/com/magento/idea/magento2plugin/reference/provider/PhpConstructorArgumentReferenceProvider.java b/src/com/magento/idea/magento2plugin/reference/provider/PhpConstructorArgumentReferenceProvider.java index 15d389c1a..840418738 100644 --- a/src/com/magento/idea/magento2plugin/reference/provider/PhpConstructorArgumentReferenceProvider.java +++ b/src/com/magento/idea/magento2plugin/reference/provider/PhpConstructorArgumentReferenceProvider.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.reference.provider; diff --git a/src/com/magento/idea/magento2plugin/reference/provider/PhpServiceMethodReferenceProvider.java b/src/com/magento/idea/magento2plugin/reference/provider/PhpServiceMethodReferenceProvider.java index b025ab426..c3e75e531 100644 --- a/src/com/magento/idea/magento2plugin/reference/provider/PhpServiceMethodReferenceProvider.java +++ b/src/com/magento/idea/magento2plugin/reference/provider/PhpServiceMethodReferenceProvider.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.reference.provider; diff --git a/src/com/magento/idea/magento2plugin/reference/provider/VirtualTypeReferenceProvider.java b/src/com/magento/idea/magento2plugin/reference/provider/VirtualTypeReferenceProvider.java index 78ff758c9..c7e06d9b3 100644 --- a/src/com/magento/idea/magento2plugin/reference/provider/VirtualTypeReferenceProvider.java +++ b/src/com/magento/idea/magento2plugin/reference/provider/VirtualTypeReferenceProvider.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.reference.provider; diff --git a/src/com/magento/idea/magento2plugin/reference/xml/PolyVariantReferenceBase.java b/src/com/magento/idea/magento2plugin/reference/xml/PolyVariantReferenceBase.java index 3ec5d1e95..d18a0c1e3 100644 --- a/src/com/magento/idea/magento2plugin/reference/xml/PolyVariantReferenceBase.java +++ b/src/com/magento/idea/magento2plugin/reference/xml/PolyVariantReferenceBase.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.reference.xml; diff --git a/src/com/magento/idea/magento2plugin/reference/xml/XmlReferenceContributor.java b/src/com/magento/idea/magento2plugin/reference/xml/XmlReferenceContributor.java index 3d0346b08..80252bb6c 100644 --- a/src/com/magento/idea/magento2plugin/reference/xml/XmlReferenceContributor.java +++ b/src/com/magento/idea/magento2plugin/reference/xml/XmlReferenceContributor.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.reference.xml; diff --git a/src/com/magento/idea/magento2plugin/stubs/indexes/BlockNameIndex.java b/src/com/magento/idea/magento2plugin/stubs/indexes/BlockNameIndex.java index 133dc59ed..32aeef4dd 100644 --- a/src/com/magento/idea/magento2plugin/stubs/indexes/BlockNameIndex.java +++ b/src/com/magento/idea/magento2plugin/stubs/indexes/BlockNameIndex.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.stubs.indexes; diff --git a/src/com/magento/idea/magento2plugin/stubs/indexes/ContainerNameIndex.java b/src/com/magento/idea/magento2plugin/stubs/indexes/ContainerNameIndex.java index b4d41daa5..60738171f 100644 --- a/src/com/magento/idea/magento2plugin/stubs/indexes/ContainerNameIndex.java +++ b/src/com/magento/idea/magento2plugin/stubs/indexes/ContainerNameIndex.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.stubs.indexes; diff --git a/src/com/magento/idea/magento2plugin/stubs/indexes/EventNameIndex.java b/src/com/magento/idea/magento2plugin/stubs/indexes/EventNameIndex.java index 033a0aa78..80f7df03c 100644 --- a/src/com/magento/idea/magento2plugin/stubs/indexes/EventNameIndex.java +++ b/src/com/magento/idea/magento2plugin/stubs/indexes/EventNameIndex.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.stubs.indexes; diff --git a/src/com/magento/idea/magento2plugin/stubs/indexes/EventObserverIndex.java b/src/com/magento/idea/magento2plugin/stubs/indexes/EventObserverIndex.java index c91f9528f..cb0d11fd1 100644 --- a/src/com/magento/idea/magento2plugin/stubs/indexes/EventObserverIndex.java +++ b/src/com/magento/idea/magento2plugin/stubs/indexes/EventObserverIndex.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.stubs.indexes; diff --git a/src/com/magento/idea/magento2plugin/stubs/indexes/LayoutDataIndexer.java b/src/com/magento/idea/magento2plugin/stubs/indexes/LayoutDataIndexer.java index 852d98a89..e3012936a 100644 --- a/src/com/magento/idea/magento2plugin/stubs/indexes/LayoutDataIndexer.java +++ b/src/com/magento/idea/magento2plugin/stubs/indexes/LayoutDataIndexer.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.stubs.indexes; diff --git a/src/com/magento/idea/magento2plugin/stubs/indexes/ModuleNameIndex.java b/src/com/magento/idea/magento2plugin/stubs/indexes/ModuleNameIndex.java index a69c4dfcb..457863dbf 100644 --- a/src/com/magento/idea/magento2plugin/stubs/indexes/ModuleNameIndex.java +++ b/src/com/magento/idea/magento2plugin/stubs/indexes/ModuleNameIndex.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.stubs.indexes; diff --git a/src/com/magento/idea/magento2plugin/stubs/indexes/ModulePackageIndex.java b/src/com/magento/idea/magento2plugin/stubs/indexes/ModulePackageIndex.java index 94e8c0a1b..35e96d175 100644 --- a/src/com/magento/idea/magento2plugin/stubs/indexes/ModulePackageIndex.java +++ b/src/com/magento/idea/magento2plugin/stubs/indexes/ModulePackageIndex.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.stubs.indexes; diff --git a/src/com/magento/idea/magento2plugin/stubs/indexes/NamedComponentIndex.java b/src/com/magento/idea/magento2plugin/stubs/indexes/NamedComponentIndex.java index fa0eb4a1c..78d731fd1 100644 --- a/src/com/magento/idea/magento2plugin/stubs/indexes/NamedComponentIndex.java +++ b/src/com/magento/idea/magento2plugin/stubs/indexes/NamedComponentIndex.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.stubs.indexes; diff --git a/src/com/magento/idea/magento2plugin/stubs/indexes/PluginIndex.java b/src/com/magento/idea/magento2plugin/stubs/indexes/PluginIndex.java index e3c13fb07..1de5e8c5f 100644 --- a/src/com/magento/idea/magento2plugin/stubs/indexes/PluginIndex.java +++ b/src/com/magento/idea/magento2plugin/stubs/indexes/PluginIndex.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.stubs.indexes; diff --git a/src/com/magento/idea/magento2plugin/stubs/indexes/VirtualTypeIndex.java b/src/com/magento/idea/magento2plugin/stubs/indexes/VirtualTypeIndex.java index 815cc2334..c7b4ae674 100644 --- a/src/com/magento/idea/magento2plugin/stubs/indexes/VirtualTypeIndex.java +++ b/src/com/magento/idea/magento2plugin/stubs/indexes/VirtualTypeIndex.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.stubs.indexes; diff --git a/src/com/magento/idea/magento2plugin/stubs/indexes/WebApiTypeIndex.java b/src/com/magento/idea/magento2plugin/stubs/indexes/WebApiTypeIndex.java index 4f598150f..fa4fccfe4 100644 --- a/src/com/magento/idea/magento2plugin/stubs/indexes/WebApiTypeIndex.java +++ b/src/com/magento/idea/magento2plugin/stubs/indexes/WebApiTypeIndex.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.stubs.indexes; diff --git a/src/com/magento/idea/magento2plugin/stubs/indexes/xml/PhpClassNameIndex.java b/src/com/magento/idea/magento2plugin/stubs/indexes/xml/PhpClassNameIndex.java index 04ef622ea..8bc69a771 100644 --- a/src/com/magento/idea/magento2plugin/stubs/indexes/xml/PhpClassNameIndex.java +++ b/src/com/magento/idea/magento2plugin/stubs/indexes/xml/PhpClassNameIndex.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.stubs.indexes.xml; diff --git a/src/com/magento/idea/magento2plugin/util/RegExUtil.java b/src/com/magento/idea/magento2plugin/util/RegExUtil.java index 9728ed44e..0cdb4abfa 100644 --- a/src/com/magento/idea/magento2plugin/util/RegExUtil.java +++ b/src/com/magento/idea/magento2plugin/util/RegExUtil.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.util; diff --git a/src/com/magento/idea/magento2plugin/util/VfsUtil.java b/src/com/magento/idea/magento2plugin/util/VfsUtil.java index f4e75ed68..062d3f55d 100644 --- a/src/com/magento/idea/magento2plugin/util/VfsUtil.java +++ b/src/com/magento/idea/magento2plugin/util/VfsUtil.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.util; diff --git a/src/com/magento/idea/magento2plugin/util/magento/FileBasedIndexUtil.java b/src/com/magento/idea/magento2plugin/util/magento/FileBasedIndexUtil.java index 31917ad28..f88c6930d 100644 --- a/src/com/magento/idea/magento2plugin/util/magento/FileBasedIndexUtil.java +++ b/src/com/magento/idea/magento2plugin/util/magento/FileBasedIndexUtil.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.util.magento; diff --git a/src/com/magento/idea/magento2plugin/xml/LineMarkerXmlTagDecorator.java b/src/com/magento/idea/magento2plugin/xml/LineMarkerXmlTagDecorator.java index 1def7014a..fab0999c1 100644 --- a/src/com/magento/idea/magento2plugin/xml/LineMarkerXmlTagDecorator.java +++ b/src/com/magento/idea/magento2plugin/xml/LineMarkerXmlTagDecorator.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.xml; diff --git a/src/com/magento/idea/magento2plugin/xml/XmlPsiTreeUtil.java b/src/com/magento/idea/magento2plugin/xml/XmlPsiTreeUtil.java index 7f5779ab4..7308827d1 100644 --- a/src/com/magento/idea/magento2plugin/xml/XmlPsiTreeUtil.java +++ b/src/com/magento/idea/magento2plugin/xml/XmlPsiTreeUtil.java @@ -1,5 +1,5 @@ /** - * Copyright © Dmytro Kvashnin. All rights reserved. + * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ package com.magento.idea.magento2plugin.xml; diff --git a/transfer.patch b/transfer.patch deleted file mode 100644 index d0bcc2894..000000000 --- a/transfer.patch +++ /dev/null @@ -1,9788 +0,0 @@ -diff --git a/.gitignore b/.gitignore -index 031b47b..deec285 100644 ---- a/.gitignore -+++ b/.gitignore -@@ -44,4 +44,9 @@ Temporary Items - - .idea - .git --out -\ No newline at end of file -+out -+# Gradle -+.gradle -+.idea-sandbox -+build -+gradle -diff --git a/CHANGELOG.md b/CHANGELOG.md -index 3b72fe2..8e3ee87 100644 ---- a/CHANGELOG.md -+++ b/CHANGELOG.md -@@ -1,3 +1,19 @@ -+1.0.0 -+============= -+* Features: -+ * "Go to GraphQL schema" line marker in the scope of class/interface and method -+ * "Go to GraphQL resolver class" line marker in the scope of GraphQL schema type arguments -+ * RequireJS mapping support (reference navigation, completion) -+ * Plugin class methods generation -+ * Plugin declaration inspection in the scope of a Plugin Class -+ * MFTF support (reference navigation, completion) -+ * Fixed support of 2020.* versions of IDE's -+ * Create a New Magento 2 Module action -+ * Code Inspection: Duplicated Observer Usage in events XML -+ * Create a Plugin class for a class public method action -+ * Code Inspection: Warning regarding Cacheable false attribute in default XML -+ * Create a Preference for a class action -+ - 0.3.0 - ============= - * Features: -diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md -index 7f48087..f83a446 100644 ---- a/CONTRIBUTING.md -+++ b/CONTRIBUTING.md -@@ -1,13 +1,11 @@ - # Setting up development environment - - 1. Check out this repository --1. Download PhpStorm build specified in the [META-INF/plugin.xml](./META-INF/plugin.xml). Older builds can be found [here](https://confluence.jetbrains.com/display/PhpStorm/Previous+PhpStorm+Releases) --1. Create a new project in the InteliJ. The type of the project must be "InteliJ Platform Plugin". Specify a path to the PhpStorm from the previous step as SDK for this project --1. Instead of creating a project in a new directory, point it to an existing one checked out in the first step. When prompted, replace all configs --1. Revert any local modifications (which were done by the IDE during project creation) --1. Follow [these steps](http://www.jetbrains.org/intellij/sdk/docs/products/phpstorm/setting_up_environment.html) and additionally include dependency on the `javascript-openapi` --1. You may also need to install JDK 1.8 --1. To make sure that environment is configured correctly, `Run` the plugin. You should see a new instance of PhpStorm launched with the plugin installed. Make sure that plugin is enabled in PhpStorm settings and indexing is finished. Plugin features should be accessible at this point -+1. Open a folder with the project in the IntelliJ Ultimate using the `open` action button. -+1. Make sure that you on the latest develop branch (e.g 1.0.0-develop) -+1. Right-click on the `build.gradle` file, choose "Import Gradle project" -+1. When the Gradle sections appeared in the right bar, navigate there and right-click `magento-2-php-storm-plguin > Tasks -> Intellij -> runIde` -+1. Click on "Run "magento-2-php-storm-plugin" to run the plugin. You should see a new instance of IntelliJ launched with the plugin installed. Make sure that the plugin is enabled in IntelliJ settings and indexing is finished. Plugin features should be accessible at this point. - - # Plugin publication - -diff --git a/META-INF/plugin.xml b/META-INF/plugin.xml -deleted file mode 100644 -index 795eb46..0000000 ---- a/META-INF/plugin.xml -+++ /dev/null -@@ -1,85 +0,0 @@ -- -- -- com.magento.idea.magento2plugin -- Magento PhpStorm -- 0.3.0 -- Magento Inc. -- -- -- -- here -- ]]> -- -- -- -- -- -- -- -- -- com.jetbrains.php -- JavaScript -- com.intellij.modules.platform -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -diff --git a/README.md b/README.md -index 93c3a7b..4819a42 100644 ---- a/README.md -+++ b/README.md -@@ -15,7 +15,7 @@ This is a plugin for Magento 2 development in the PhpStorm IDE. It is available - 6. Check "Enable" and "OK" button. - - ## Works with --* PhpStorm >= 2017.2 -+* PhpStorm >= 2019.3.3 - * JRE >= 1.8 - - ## Features -@@ -24,6 +24,12 @@ This is a plugin for Magento 2 development in the PhpStorm IDE. It is available - * "Navigate to configuration" reference in scope of class/interface - * "Go to plugin" reference in scope of class/interface and method - * "Navigate to Web API configuration" reference in scope of class/interface and method -+* Plugin class methods generation -+* Plugin declaration inspection -+* RequireJs reference navigation and completion -+* MFTF reference navigation and completion -+* "Go to GraphQL schema" reference in scope of class/interface and method -+* "Go to GraphQL resolver class" reference in scope of GraphQL schema type arguments - - ## License - -diff --git a/build.gradle b/build.gradle -new file mode 100644 -index 0000000..93aef22 ---- /dev/null -+++ b/build.gradle -@@ -0,0 +1,38 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+ -+plugins { -+ id 'org.jetbrains.intellij' version '0.4.15' -+} -+ -+group 'com.magento.idea' -+version '1.0.0' -+ -+apply plugin: 'org.jetbrains.intellij' -+apply plugin: 'java' -+apply plugin: 'groovy' -+ -+def phpPluginVersion = System.getProperty("phpPluginVersion", "193.6494.35") -+def ideaVersion = System.getProperty("ideaVersion", "2019.3.3") -+def javaVersion = 1.8 -+ -+sourceCompatibility = javaVersion -+targetCompatibility = javaVersion -+ -+intellij { -+ version ideaVersion -+ type 'IU' -+ pluginName 'com.magento.idea.magento2plugin' -+ plugins = ["com.jetbrains.php:$phpPluginVersion", 'yaml', 'java-i18n', 'properties', 'CSS', 'JavaScriptLanguage', 'com.intellij.lang.jsgraphql:2.3.0'] -+ updateSinceUntilBuild false -+ sameSinceUntilBuild false -+ downloadSources !Boolean.valueOf(System.getenv('CI')) -+ sandboxDirectory "${project.rootDir}/.idea-sandbox" -+} -+ -+sourceSets { -+ main.java.srcDirs = ['src'] -+ main.resources.srcDirs = ['resources'] -+} -diff --git a/gradlew b/gradlew -new file mode 100755 -index 0000000..af6708f ---- /dev/null -+++ b/gradlew -@@ -0,0 +1,172 @@ -+#!/usr/bin/env sh -+ -+############################################################################## -+## -+## Gradle start up script for UN*X -+## -+############################################################################## -+ -+# Attempt to set APP_HOME -+# Resolve links: $0 may be a link -+PRG="$0" -+# Need this for relative symlinks. -+while [ -h "$PRG" ] ; do -+ ls=`ls -ld "$PRG"` -+ link=`expr "$ls" : '.*-> \(.*\)$'` -+ if expr "$link" : '/.*' > /dev/null; then -+ PRG="$link" -+ else -+ PRG=`dirname "$PRG"`"/$link" -+ fi -+done -+SAVED="`pwd`" -+cd "`dirname \"$PRG\"`/" >/dev/null -+APP_HOME="`pwd -P`" -+cd "$SAVED" >/dev/null -+ -+APP_NAME="Gradle" -+APP_BASE_NAME=`basename "$0"` -+ -+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -+DEFAULT_JVM_OPTS='"-Xmx64m"' -+ -+# Use the maximum available, or set MAX_FD != -1 to use that value. -+MAX_FD="maximum" -+ -+warn () { -+ echo "$*" -+} -+ -+die () { -+ echo -+ echo "$*" -+ echo -+ exit 1 -+} -+ -+# OS specific support (must be 'true' or 'false'). -+cygwin=false -+msys=false -+darwin=false -+nonstop=false -+case "`uname`" in -+ CYGWIN* ) -+ cygwin=true -+ ;; -+ Darwin* ) -+ darwin=true -+ ;; -+ MINGW* ) -+ msys=true -+ ;; -+ NONSTOP* ) -+ nonstop=true -+ ;; -+esac -+ -+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar -+ -+# Determine the Java command to use to start the JVM. -+if [ -n "$JAVA_HOME" ] ; then -+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then -+ # IBM's JDK on AIX uses strange locations for the executables -+ JAVACMD="$JAVA_HOME/jre/sh/java" -+ else -+ JAVACMD="$JAVA_HOME/bin/java" -+ fi -+ if [ ! -x "$JAVACMD" ] ; then -+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME -+ -+Please set the JAVA_HOME variable in your environment to match the -+location of your Java installation." -+ fi -+else -+ JAVACMD="java" -+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -+ -+Please set the JAVA_HOME variable in your environment to match the -+location of your Java installation." -+fi -+ -+# Increase the maximum file descriptors if we can. -+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then -+ MAX_FD_LIMIT=`ulimit -H -n` -+ if [ $? -eq 0 ] ; then -+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then -+ MAX_FD="$MAX_FD_LIMIT" -+ fi -+ ulimit -n $MAX_FD -+ if [ $? -ne 0 ] ; then -+ warn "Could not set maximum file descriptor limit: $MAX_FD" -+ fi -+ else -+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" -+ fi -+fi -+ -+# For Darwin, add options to specify how the application appears in the dock -+if $darwin; then -+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -+fi -+ -+# For Cygwin, switch paths to Windows format before running java -+if $cygwin ; then -+ APP_HOME=`cygpath --path --mixed "$APP_HOME"` -+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` -+ JAVACMD=`cygpath --unix "$JAVACMD"` -+ -+ # We build the pattern for arguments to be converted via cygpath -+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` -+ SEP="" -+ for dir in $ROOTDIRSRAW ; do -+ ROOTDIRS="$ROOTDIRS$SEP$dir" -+ SEP="|" -+ done -+ OURCYGPATTERN="(^($ROOTDIRS))" -+ # Add a user-defined pattern to the cygpath arguments -+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then -+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" -+ fi -+ # Now convert the arguments - kludge to limit ourselves to /bin/sh -+ i=0 -+ for arg in "$@" ; do -+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` -+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option -+ -+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition -+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` -+ else -+ eval `echo args$i`="\"$arg\"" -+ fi -+ i=$((i+1)) -+ done -+ case $i in -+ (0) set -- ;; -+ (1) set -- "$args0" ;; -+ (2) set -- "$args0" "$args1" ;; -+ (3) set -- "$args0" "$args1" "$args2" ;; -+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;; -+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; -+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; -+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; -+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; -+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; -+ esac -+fi -+ -+# Escape application args -+save () { -+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done -+ echo " " -+} -+APP_ARGS=$(save "$@") -+ -+# Collect all arguments for the java command, following the shell quoting and substitution rules -+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" -+ -+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then -+ cd "$(dirname "$0")" -+fi -+ -+exec "$JAVACMD" "$@" -diff --git a/gradlew.bat b/gradlew.bat -new file mode 100644 -index 0000000..6d57edc ---- /dev/null -+++ b/gradlew.bat -@@ -0,0 +1,84 @@ -+@if "%DEBUG%" == "" @echo off -+@rem ########################################################################## -+@rem -+@rem Gradle startup script for Windows -+@rem -+@rem ########################################################################## -+ -+@rem Set local scope for the variables with windows NT shell -+if "%OS%"=="Windows_NT" setlocal -+ -+set DIRNAME=%~dp0 -+if "%DIRNAME%" == "" set DIRNAME=. -+set APP_BASE_NAME=%~n0 -+set APP_HOME=%DIRNAME% -+ -+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -+set DEFAULT_JVM_OPTS="-Xmx64m" -+ -+@rem Find java.exe -+if defined JAVA_HOME goto findJavaFromJavaHome -+ -+set JAVA_EXE=java.exe -+%JAVA_EXE% -version >NUL 2>&1 -+if "%ERRORLEVEL%" == "0" goto init -+ -+echo. -+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -+echo. -+echo Please set the JAVA_HOME variable in your environment to match the -+echo location of your Java installation. -+ -+goto fail -+ -+:findJavaFromJavaHome -+set JAVA_HOME=%JAVA_HOME:"=% -+set JAVA_EXE=%JAVA_HOME%/bin/java.exe -+ -+if exist "%JAVA_EXE%" goto init -+ -+echo. -+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -+echo. -+echo Please set the JAVA_HOME variable in your environment to match the -+echo location of your Java installation. -+ -+goto fail -+ -+:init -+@rem Get command-line arguments, handling Windows variants -+ -+if not "%OS%" == "Windows_NT" goto win9xME_args -+ -+:win9xME_args -+@rem Slurp the command line arguments. -+set CMD_LINE_ARGS= -+set _SKIP=2 -+ -+:win9xME_args_slurp -+if "x%~1" == "x" goto execute -+ -+set CMD_LINE_ARGS=%* -+ -+:execute -+@rem Setup the command line -+ -+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar -+ -+@rem Execute Gradle -+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% -+ -+:end -+@rem End local scope for the variables with windows NT shell -+if "%ERRORLEVEL%"=="0" goto mainEnd -+ -+:fail -+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -+rem the _cmd.exe /c_ return code! -+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -+exit /b 1 -+ -+:mainEnd -+if "%OS%"=="Windows_NT" endlocal -+ -+:omega -diff --git a/magento2plugin.iml b/magento2plugin.iml -deleted file mode 100644 -index e05bb8c..0000000 ---- a/magento2plugin.iml -+++ /dev/null -@@ -1,21 +0,0 @@ -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -\ No newline at end of file -diff --git a/resources/.phpstorm.meta.php/di-autocomplete.php b/resources/.phpstorm.meta.php/di-autocomplete.php -new file mode 100644 -index 0000000..881c3ba ---- /dev/null -+++ b/resources/.phpstorm.meta.php/di-autocomplete.php -@@ -0,0 +1,6 @@ -+ '@'])); -+ override(\Magento\Framework\ObjectManagerInterface::create(0), map(['' => '@'])); -+} -\ No newline at end of file -diff --git a/resources/META-INF/plugin.xml b/resources/META-INF/plugin.xml -new file mode 100644 -index 0000000..79dd2ac ---- /dev/null -+++ b/resources/META-INF/plugin.xml -@@ -0,0 +1,151 @@ -+ -+ -+ com.magento.idea.magento2plugin -+ Magento PhpStorm -+ 1.0.0 -+ Magento Inc. -+ -+ -+ -+ here -+ ]]> -+ -+ -+ -+ -+ -+ -+ -+ -+ com.jetbrains.php -+ JavaScript -+ com.intellij.modules.platform -+ com.intellij.lang.jsgraphql -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -diff --git a/resources/META-INF/withJsGraphQl.xml b/resources/META-INF/withJsGraphQl.xml -new file mode 100644 -index 0000000..32b16a3 ---- /dev/null -+++ b/resources/META-INF/withJsGraphQl.xml -@@ -0,0 +1,7 @@ -+ -+ -+ -+ -+ -+ -+ -diff --git a/resources/fileTemplates/code/Magento Module DI Xml Plugin.xml.ft b/resources/fileTemplates/code/Magento Module DI Xml Plugin.xml.ft -new file mode 100644 -index 0000000..062b13b ---- /dev/null -+++ b/resources/fileTemplates/code/Magento Module DI Xml Plugin.xml.ft -@@ -0,0 +1,8 @@ -+#if (${TYPE}) -+ -+#end -+ -+#if (${TYPE}) -+ -+#end -\ No newline at end of file -diff --git a/resources/fileTemplates/code/Magento Module DI Xml Plugin.xml.html b/resources/fileTemplates/code/Magento Module DI Xml Plugin.xml.html -new file mode 100644 -index 0000000..0789625 ---- /dev/null -+++ b/resources/fileTemplates/code/Magento Module DI Xml Plugin.xml.html -@@ -0,0 +1,10 @@ -+ -+ -+ -+ -+ -\ No newline at end of file -diff --git a/resources/fileTemplates/code/Magento Module DI Xml Preference.xml.ft b/resources/fileTemplates/code/Magento Module DI Xml Preference.xml.ft -new file mode 100644 -index 0000000..ca2967a ---- /dev/null -+++ b/resources/fileTemplates/code/Magento Module DI Xml Preference.xml.ft -@@ -0,0 +1 @@ -+ -\ No newline at end of file -diff --git a/resources/fileTemplates/code/Magento Module DI Xml Preference.xml.html b/resources/fileTemplates/code/Magento Module DI Xml Preference.xml.html -new file mode 100644 -index 0000000..0789625 ---- /dev/null -+++ b/resources/fileTemplates/code/Magento Module DI Xml Preference.xml.html -@@ -0,0 +1,10 @@ -+ -+ -+ -+ -+ -\ No newline at end of file -diff --git a/resources/fileTemplates/code/Magento Plugin After Method.php.ft b/resources/fileTemplates/code/Magento Plugin After Method.php.ft -new file mode 100644 -index 0000000..1638512 ---- /dev/null -+++ b/resources/fileTemplates/code/Magento Plugin After Method.php.ft -@@ -0,0 +1,8 @@ -+/** -+${PARAM_DOC} -+ */ -+public function ${NAME}(${PARAM_LIST}) -+{ -+ // TODO: Implement plugin method. -+ #if (${RETURN_VARIABLES})return ${RETURN_VARIABLES}; #end -+} -diff --git a/resources/fileTemplates/code/Magento Plugin After Method.php.html b/resources/fileTemplates/code/Magento Plugin After Method.php.html -new file mode 100644 -index 0000000..c9772c9 ---- /dev/null -+++ b/resources/fileTemplates/code/Magento Plugin After Method.php.html -@@ -0,0 +1,43 @@ -+ -+ -+ -+ -+ -+ -+ -+
Magento runs all after methods following the completion of the observed method. -+ Magento requires these methods have a return value and they must have the same name as the observed method with ‘after’ as the prefix. -+
-+
-+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+
Predefined variables will take the following values:
${PARAM_DOC} PHP DocBlock for plugin function
${NAME} Name of the plugin function
${PARAM_LIST} List of plugin function parameters
${RETURN_VARIABLES} Return value for plugin function
-+ -+ -diff --git a/resources/fileTemplates/code/Magento Plugin Around Method.php.ft b/resources/fileTemplates/code/Magento Plugin Around Method.php.ft -new file mode 100644 -index 0000000..8f05a33 ---- /dev/null -+++ b/resources/fileTemplates/code/Magento Plugin Around Method.php.ft -@@ -0,0 +1,8 @@ -+/** -+${PARAM_DOC} -+ */ -+public function ${NAME}(${PARAM_LIST}) -+{ -+ // TODO: Implement plugin method. -+ return $proceed(#if(${RETURN_VARIABLES})${RETURN_VARIABLES}#end); -+} -diff --git a/resources/fileTemplates/code/Magento Plugin Around Method.php.html b/resources/fileTemplates/code/Magento Plugin Around Method.php.html -new file mode 100644 -index 0000000..a5ab1d7 ---- /dev/null -+++ b/resources/fileTemplates/code/Magento Plugin Around Method.php.html -@@ -0,0 +1,43 @@ -+ -+ -+ -+ -+ -+ -+ -+
Magento runs the code in around methods before and after their observed methods. -+ Using these methods allow you to override an observed method. Around methods must have the same name as the observed method with ‘around’ as the prefix. -+
-+
-+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+
Predefined variables will take the following values:
${PARAM_DOC} PHP DocBlock for plugin function
${NAME} Name of the plugin function
${PARAM_LIST} List of plugin function parameters
${RETURN_VARIABLES} Return value for plugin function
-+ -+ -diff --git a/resources/fileTemplates/code/Magento Plugin Before Method.php.ft b/resources/fileTemplates/code/Magento Plugin Before Method.php.ft -new file mode 100644 -index 0000000..e912262 ---- /dev/null -+++ b/resources/fileTemplates/code/Magento Plugin Before Method.php.ft -@@ -0,0 +1,10 @@ -+/** -+${PARAM_DOC} -+#if (${RETURN_VARIABLES})* @return array -+#end -+ */ -+public function ${NAME}(${PARAM_LIST}) -+{ -+ // TODO: Implement plugin method. -+ #if (${RETURN_VARIABLES})return [${RETURN_VARIABLES}]; #end -+} -diff --git a/resources/fileTemplates/code/Magento Plugin Before Method.php.html b/resources/fileTemplates/code/Magento Plugin Before Method.php.html -new file mode 100644 -index 0000000..e09fede ---- /dev/null -+++ b/resources/fileTemplates/code/Magento Plugin Before Method.php.html -@@ -0,0 +1,43 @@ -+ -+ -+ -+ -+ -+ -+ -+
Magento runs all before methods ahead of the call to an observed method. -+ These methods must have the same name as the observed method with ‘before’ as the prefix. -+
-+
-+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+
Predefined variables will take the following values:
${PARAM_DOC} PHP DocBlock for plugin function
${NAME} Name of the plugin function
${PARAM_LIST} List of plugin function parameters
${RETURN_VARIABLES} Return value for plugin function
-+ -+ -diff --git a/resources/fileTemplates/internal/Magento Module Composer.json.ft b/resources/fileTemplates/internal/Magento Module Composer.json.ft -new file mode 100644 -index 0000000..b76262d ---- /dev/null -+++ b/resources/fileTemplates/internal/Magento Module Composer.json.ft -@@ -0,0 +1,22 @@ -+{ -+ "name": "${COMPOSER_PACKAGE_NAME}", -+ "version": "${MODULE_VERSION}", -+ "description": "${MODULE_DESCRIPTION}", -+ "type": "magento2-module", -+ #if (${DEPENDENCIES}) -+ "require": { -+ ${DEPENDENCIES} -+ }, -+ #end -+ #if (${LICENSE}) -+ ${LICENSE}, -+ #end -+ "autoload": { -+ "files": [ -+ "registration.php" -+ ], -+ "psr-4": { -+ "${PACKAGE}\\\\${MODULE_NAME}\\": "" -+ } -+ } -+} -\ No newline at end of file -diff --git a/resources/fileTemplates/internal/Magento Module Composer.json.html b/resources/fileTemplates/internal/Magento Module Composer.json.html -new file mode 100644 -index 0000000..1739e68 ---- /dev/null -+++ b/resources/fileTemplates/internal/Magento Module Composer.json.html -@@ -0,0 +1,49 @@ -+ -+ -+

-+ The composer.json file determines the module's hard dependencies on other modules.
-+ It is required in a module for extensions provider vendors and it's optional for custom implementations, but it is highly recommended to use. -+

-+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+
Template's predefined variables:
${COMPOSER_PACKAGE_NAME} Module's composer name.
${MODULE_VERSION} Module's version.
${MODULE_DESCRIPTION} Short description of what the module does.
${DEPENDENCIES} A list of the module's dependencies.
${LICENSE} Module's licence.
${PACKAGE} Module's package name. Also know as Vendor name.
${MODULE_NAME} Module's name.
-+ -+ -diff --git a/resources/fileTemplates/internal/Magento Module DI Xml.xml.ft b/resources/fileTemplates/internal/Magento Module DI Xml.xml.ft -new file mode 100644 -index 0000000..5de0638 ---- /dev/null -+++ b/resources/fileTemplates/internal/Magento Module DI Xml.xml.ft -@@ -0,0 +1,3 @@ -+ -+ -+ -diff --git a/resources/fileTemplates/internal/Magento Module Registration Php.php.ft b/resources/fileTemplates/internal/Magento Module Registration Php.php.ft -new file mode 100644 -index 0000000..77b88d5 ---- /dev/null -+++ b/resources/fileTemplates/internal/Magento Module Registration Php.php.ft -@@ -0,0 +1,6 @@ -+ -+ -+ -+

-+ registration.php file is a must-have file for the Magento 2 module. Without it the module is not registered into the Magento 2 system, those the module won't work. -+

-+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+
Template's predefined variables:
${PACKAGE} Module's package name. Also know as Vendor name.
${MODULE_NAME} Module's name.
-+ -+ -diff --git a/resources/fileTemplates/internal/Magento Module Xml.xml.ft b/resources/fileTemplates/internal/Magento Module Xml.xml.ft -new file mode 100644 -index 0000000..895b817 ---- /dev/null -+++ b/resources/fileTemplates/internal/Magento Module Xml.xml.ft -@@ -0,0 +1,10 @@ -+ -+ -+ #if (${SEQUENCES}) -+ -+ ${SEQUENCES} -+ -+ #else -+ -+ #end -+ -diff --git a/resources/fileTemplates/internal/Magento Php Preference Class.php.ft b/resources/fileTemplates/internal/Magento Php Preference Class.php.ft -new file mode 100644 -index 0000000..0a7a8ae ---- /dev/null -+++ b/resources/fileTemplates/internal/Magento Php Preference Class.php.ft -@@ -0,0 +1,14 @@ -+ -+ -+ -+

-+ This inspection detects `cacheable` attribute which is set to be false in default.xml and its result to be whole site uncacheable. -+

-+

-+ Read more about caching -+

-+ -+ -diff --git a/resources/inspectionDescriptions/ObserverDeclarationInspection.html b/resources/inspectionDescriptions/ObserverDeclarationInspection.html -new file mode 100644 -index 0000000..f14b67d ---- /dev/null -+++ b/resources/inspectionDescriptions/ObserverDeclarationInspection.html -@@ -0,0 +1,23 @@ -+ -+ -+ -+ -+ -+

Observer names for events must be unique, otherwise overriding occurs. Overrides can be done by accident.

-+

-+ In case overriding is wanted, -+ -+ disable the original observer -+ -+ and give a unique name to the current observer. -+

-+

-+ Read more about Events & Observers -+

-+ -+ -\ No newline at end of file -diff --git a/resources/inspectionDescriptions/PluginInspection.html b/resources/inspectionDescriptions/PluginInspection.html -new file mode 100644 -index 0000000..e4ec88c ---- /dev/null -+++ b/resources/inspectionDescriptions/PluginInspection.html -@@ -0,0 +1,18 @@ -+ -+ -+ -+

Plugins can not be used with the following:

-+
    -+
  • Final classes
  • -+
  • Non-public methods
  • -+
  • Class methods (such as static methods)
  • -+
  • __construct
  • -+
  • Virtual types
  • -+
-+ -+ -\ No newline at end of file -diff --git a/settings.gradle b/settings.gradle -new file mode 100644 -index 0000000..3fd0692 ---- /dev/null -+++ b/settings.gradle -@@ -0,0 +1,2 @@ -+rootProject.name = 'magento2' -+ -diff --git a/src/com/magento/idea/magento2plugin/MagentoIcons.java b/src/com/magento/idea/magento2plugin/MagentoIcons.java -index ae13960..82de250 100644 ---- a/src/com/magento/idea/magento2plugin/MagentoIcons.java -+++ b/src/com/magento/idea/magento2plugin/MagentoIcons.java -@@ -13,4 +13,5 @@ import javax.swing.*; - */ - public class MagentoIcons { - public static final Icon WEB_API = IconLoader.getIcon("icons/webapi.png"); -+ public static final Icon MODULE = IconLoader.getIcon("/icons/module.png"); - } -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/CreateAPluginAction.java b/src/com/magento/idea/magento2plugin/actions/generation/CreateAPluginAction.java -new file mode 100644 -index 0000000..380ef26 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/CreateAPluginAction.java -@@ -0,0 +1,105 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation; -+ -+import com.intellij.openapi.actionSystem.AnActionEvent; -+import com.intellij.openapi.actionSystem.PlatformDataKeys; -+import com.intellij.openapi.editor.Caret; -+import com.intellij.openapi.project.DumbAwareAction; -+import com.intellij.openapi.project.Project; -+import com.intellij.openapi.util.Pair; -+import com.intellij.psi.PsiElement; -+import com.intellij.psi.PsiFile; -+import com.jetbrains.php.lang.psi.PhpFile; -+import com.jetbrains.php.lang.psi.elements.Method; -+import com.jetbrains.php.lang.psi.elements.PhpClass; -+import com.magento.idea.magento2plugin.MagentoIcons; -+import com.magento.idea.magento2plugin.actions.generation.dialog.CreateAPluginDialog; -+import com.magento.idea.magento2plugin.util.GetFirstClassOfFile; -+import com.magento.idea.magento2plugin.util.magento.plugin.IsPluginAllowedForMethod; -+import org.jetbrains.annotations.NotNull; -+import com.magento.idea.magento2plugin.project.Settings; -+ -+public class CreateAPluginAction extends DumbAwareAction { -+ public static String ACTION_NAME = "Create A Plugin..."; -+ public static String ACTION_DESCRIPTION = "Create a new Magento 2 plugin for the class"; -+ private final IsPluginAllowedForMethod isPluginAllowed; -+ private final GetFirstClassOfFile getFirstClassOfFile; -+ private Method targetMethod; -+ private PhpClass targetClass; -+ -+ public CreateAPluginAction() { -+ super(ACTION_NAME, ACTION_DESCRIPTION, MagentoIcons.MODULE); -+ this.isPluginAllowed = IsPluginAllowedForMethod.getInstance(); -+ this.getFirstClassOfFile = GetFirstClassOfFile.getInstance(); -+ } -+ -+ public void update(AnActionEvent event) { -+ targetClass = null; -+ targetMethod = null; -+ Project project = event.getData(PlatformDataKeys.PROJECT); -+ if (Settings.isEnabled(project)) { -+ Pair pair = this.findPhpClass(event); -+ PsiFile psiFile = pair.getFirst(); -+ PhpClass phpClass = pair.getSecond(); -+ targetClass = phpClass; -+ if (!(psiFile instanceof PhpFile) || phpClass.isFinal() || this.targetMethod == null) { -+ this.setStatus(event, false); -+ return; -+ } -+ } else { -+ this.setStatus(event, false); -+ return; -+ } -+ this.setStatus(event, true); -+ } -+ -+ private void setStatus(AnActionEvent event, boolean status) { -+ event.getPresentation().setVisible(status); -+ event.getPresentation().setEnabled(status); -+ } -+ -+ @Override -+ public void actionPerformed(@NotNull AnActionEvent e) { -+ CreateAPluginDialog.open(e.getProject(), this.targetMethod, this.targetClass); -+ } -+ -+ @Override -+ public boolean isDumbAware() { -+ return false; -+ } -+ -+ private Pair findPhpClass(@NotNull AnActionEvent event) { -+ PsiFile psiFile = event.getData(PlatformDataKeys.PSI_FILE); -+ -+ PhpClass phpClass = null; -+ if (psiFile instanceof PhpFile) { -+ phpClass = getFirstClassOfFile.execute((PhpFile) psiFile); -+ fetchTargetMethod(event, psiFile, phpClass); -+ } -+ -+ return Pair.create(psiFile, phpClass); -+ } -+ -+ private void fetchTargetMethod(@NotNull AnActionEvent event, PsiFile psiFile, PhpClass phpClass) { -+ Caret caret = event.getData(PlatformDataKeys.CARET); -+ if (caret == null) { -+ return; -+ } -+ int offset = caret.getOffset(); -+ PsiElement element = psiFile.findElementAt(offset); -+ if (element == null) { -+ return; -+ } -+ if (element instanceof Method && element.getParent() == phpClass && isPluginAllowed.check((Method)element)) { -+ this.targetMethod = (Method)element; -+ return; -+ } -+ PsiElement parent = element.getParent(); -+ if (parent instanceof Method && parent.getParent() == phpClass && isPluginAllowed.check((Method)parent)) { -+ this.targetMethod = (Method)parent; -+ } -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/ImportReferences/PhpClassReferenceExtractor.java b/src/com/magento/idea/magento2plugin/actions/generation/ImportReferences/PhpClassReferenceExtractor.java -new file mode 100644 -index 0000000..a8d31fa ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/ImportReferences/PhpClassReferenceExtractor.java -@@ -0,0 +1,73 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation.ImportReferences; -+ -+import com.intellij.psi.PsiElement; -+import com.jetbrains.php.lang.psi.elements.*; -+import com.jetbrains.php.lang.psi.resolve.types.PhpType; -+import com.jetbrains.php.lang.psi.visitors.PhpElementVisitor; -+import java.util.Collection; -+import org.jetbrains.annotations.NotNull; -+ -+public abstract class PhpClassReferenceExtractor { -+ private final PhpElementVisitor myCollectorVisitor = new PhpElementVisitor() { -+ public void visitPhpClass(PhpClass phpClass) { -+ PhpClassReferenceExtractor.this.processClassReference(phpClass); -+ } -+ -+ public void visitPhpParameter(Parameter parameter) { -+ PhpClassReferenceExtractor.this.processParameterReference(parameter); -+ } -+ -+ public void visitPhpReturnType(PhpReturnType returnType) { -+ PhpClassReferenceExtractor.this.processReturnTypeReference(returnType); -+ } -+ }; -+ -+ public PhpClassReferenceExtractor() { -+ } -+ -+ private void processClassReference(@NotNull PhpClass resolvedClass) { -+ String name = resolvedClass.getName(); -+ this.processReference(name, resolvedClass.getFQN(), resolvedClass); -+ } -+ -+ private void processParameterReference(@NotNull Parameter parameter) { -+ PhpType parameterType = parameter.getDeclaredType(); -+ if (parameterType.isEmpty() && !PhpType.isPrimitiveType(parameterType.toString())) { -+ return; -+ } -+ String fqn = parameterType.toString(); -+ String name = getNameFromFqn(parameterType); -+ this.processReference(name, fqn, parameter); -+ } -+ -+ public void processReturnTypeReference(PhpReturnType returnType) { -+ PhpType parameterType = returnType.getDeclaredType(); -+ if (parameterType.isEmpty() && !PhpType.isPrimitiveType(parameterType.toString())) { -+ return; -+ } -+ String fqn = parameterType.toString(); -+ String name = getNameFromFqn(parameterType); -+ this.processReference(name, fqn, returnType); -+ } -+ -+ private String getNameFromFqn(PhpType parameterType) { -+ String[] fqnArray = parameterType.toString().split("\\\\"); -+ return fqnArray[fqnArray.length - 1]; -+ } -+ -+ protected abstract void processReference(@NotNull String name, @NotNull String fqn, @NotNull PsiElement identifier); -+ -+ public void processElement(@NotNull PsiElement element) { -+ element.accept(this.myCollectorVisitor); -+ } -+ -+ public void processElements(@NotNull Collection originalElements) { -+ for (PsiElement element : originalElements) { -+ this.processElement(element); -+ } -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/ImportReferences/PhpClassReferenceResolver.java b/src/com/magento/idea/magento2plugin/actions/generation/ImportReferences/PhpClassReferenceResolver.java -new file mode 100644 -index 0000000..14fec51 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/ImportReferences/PhpClassReferenceResolver.java -@@ -0,0 +1,164 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation.ImportReferences; -+ -+import com.intellij.openapi.project.Project; -+import com.intellij.psi.PsiElement; -+import com.jetbrains.php.codeInsight.PhpCodeInsightUtil; -+import com.jetbrains.php.lang.PhpLangUtil; -+import com.jetbrains.php.lang.documentation.phpdoc.psi.PhpDocComment; -+import com.jetbrains.php.lang.documentation.phpdoc.psi.PhpDocType; -+import com.jetbrains.php.lang.lexer.PhpTokenTypes; -+import com.jetbrains.php.lang.psi.PhpPsiElementFactory; -+import com.jetbrains.php.lang.psi.PhpPsiUtil; -+import com.jetbrains.php.lang.psi.elements.ClassReference; -+import com.jetbrains.php.lang.psi.elements.PhpNamespace; -+import com.jetbrains.php.lang.psi.elements.PhpPsiElement; -+import com.jetbrains.php.lang.psi.elements.Statement; -+import com.jetbrains.php.lang.psi.resolve.types.PhpType; -+import com.jetbrains.php.refactoring.PhpAliasImporter; -+import gnu.trove.THashMap; -+import java.util.Iterator; -+import java.util.List; -+import java.util.Map; -+import java.util.Map.Entry; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+public class PhpClassReferenceResolver extends PhpClassReferenceExtractor { -+ private final PhpClassReferenceStorage myCandidatesToImportStorage = new PhpClassReferenceStorage(); -+ -+ public PhpClassReferenceResolver() { -+ } -+ -+ public void processElement(@NotNull PsiElement element) { -+ super.processElement(element); -+ } -+ -+ protected void processReference(@NotNull String name, @NotNull String fqn, @NotNull PsiElement identifier) { -+ if (!PhpType.isPrimitiveType(name)) { -+ this.myCandidatesToImportStorage.processReference(name, fqn, identifier); -+ } -+ } -+ -+ @Nullable -+ private static String alreadyImported(@NotNull PhpPsiElement scopeHolder, @NotNull Map aliases, @NotNull String fqn, @NotNull String name) { -+ boolean isSameNamespace = PhpCodeInsightUtil.isSameNamespace(scopeHolder, fqn); -+ if (isSameNamespace && PhpLangUtil.equalsClassNames(PhpLangUtil.toShortName(fqn), name)) { -+ return name; -+ } -+ boolean isNonCompound = isNonCompoundUseName(scopeHolder, fqn, name); -+ if (isNonCompound) { -+ return name; -+ } -+ Iterator entryIterator = aliases.entrySet().iterator(); -+ -+ Entry alias; -+ do { -+ if (!entryIterator.hasNext()) { -+ return null; -+ } -+ -+ alias = (Entry) entryIterator.next(); -+ } while (!PhpLangUtil.equalsClassNames((CharSequence) alias.getValue(), fqn)); -+ -+ return (String) alias.getKey(); -+ } -+ -+ public static boolean isNonCompoundUseName(@NotNull PhpPsiElement scopeHolder, @NotNull String fqn, @NotNull String name) { -+ String currentNamespaceName = scopeHolder instanceof PhpNamespace ? ((PhpNamespace)scopeHolder).getFQN() : ""; -+ return "\\".equals(currentNamespaceName) && PhpLangUtil.equalsClassNames(fqn, PhpLangUtil.toFQN(name)); -+ } -+ -+ public void importReferences(@NotNull PhpPsiElement scopeHolder, @NotNull List movedElements) { -+ Map referencesToReplace = this.importWithConflictResolve(scopeHolder); -+ if (referencesToReplace.isEmpty()) { -+ return; -+ } -+ PhpClassReferenceResolver.PhpClassReferenceRenamer renamer = new PhpClassReferenceResolver.PhpClassReferenceRenamer(scopeHolder.getProject(), referencesToReplace); -+ renamer.processElements(movedElements); -+ } -+ -+ private Map importWithConflictResolve(PhpPsiElement scopeHolder) { -+ Map aliases = PhpCodeInsightUtil.getAliasesInScope(scopeHolder); -+ Map referencesToReplace = new THashMap(); -+ boolean autoImport = PhpCodeInsightUtil.isAutoImportEnabled(scopeHolder); -+ -+ for (String name : this.myCandidatesToImportStorage.getNames()) { -+ String originalFqn = this.myCandidatesToImportStorage.getFqnByName(name); -+ assert originalFqn != null; -+ -+ String alias = alreadyImported(scopeHolder, aliases, originalFqn, name); -+ if (alias != null) { -+ if (!PhpLangUtil.equalsClassNames(name, alias)) { -+ referencesToReplace.put(name, alias); -+ } -+ } else if (!autoImport) { -+ referencesToReplace.put(name, originalFqn); -+ } else { -+ String importedFqn = aliases.get(name); -+ if (!PhpLangUtil.equalsClassNames(importedFqn, originalFqn)) { -+ if (importedFqn != null) { -+ String originalName = PhpLangUtil.toShortName(originalFqn); -+ String fqnForOriginalName = aliases.get(originalName); -+ if (fqnForOriginalName != null && !PhpLangUtil.equalsClassNames(fqnForOriginalName, originalFqn)) { -+ referencesToReplace.put(name, originalFqn); -+ } else { -+ referencesToReplace.put(name, originalName); -+ if (fqnForOriginalName == null) { -+ insertUseStatement(scopeHolder, originalName, originalFqn); -+ } -+ } -+ } else { -+ insertUseStatement(scopeHolder, name, originalFqn); -+ } -+ } -+ } -+ } -+ -+ return referencesToReplace; -+ } -+ -+ private static void insertUseStatement(PhpPsiElement scopeHolder, String name, String originalFqn) { -+ String originalName = PhpLangUtil.toShortName(originalFqn); -+ if (PhpLangUtil.equalsClassNames(originalName, name)) { -+ PhpAliasImporter.insertUseStatement(originalFqn, scopeHolder); -+ return; -+ } -+ PhpAliasImporter.insertUseStatement(originalFqn, name, scopeHolder); -+ } -+ -+ private static class PhpClassReferenceRenamer extends PhpClassReferenceExtractor { -+ private final Project myProject; -+ private final Map myRefToRename; -+ -+ private PhpClassReferenceRenamer(Project project, @NotNull Map replaceWithFqn) { -+ super(); -+ this.myProject = project; -+ this.myRefToRename = replaceWithFqn; -+ } -+ -+ protected void processReference(@NotNull String name, @NotNull String reference, @NotNull PsiElement identifier) { -+ if (this.myRefToRename.containsKey(name)) { -+ String fqn = this.myRefToRename.get(name); -+ Object newReference; -+ PsiElement oldReference; -+ if (!PhpPsiUtil.isOfType(identifier, PhpTokenTypes.IDENTIFIER) && !(identifier instanceof ClassReference)) { -+ newReference = PhpPsiElementFactory.createPhpDocType(this.myProject, fqn); -+ oldReference = PhpPsiUtil.getParentByCondition(identifier, false, PhpDocType.INSTANCEOF, PhpDocComment.INSTANCEOF); -+ } else { -+ newReference = PhpPsiElementFactory.createClassReference(this.myProject, fqn); -+ oldReference = PhpPsiUtil.getParentByCondition(identifier, false, ClassReference.INSTANCEOF, Statement.INSTANCEOF); -+ } -+ -+ assert oldReference != null; -+ -+ PsiElement added = oldReference.addRange(((PsiElement)newReference).getFirstChild(), ((PsiElement)newReference).getLastChild()); -+ oldReference.deleteChildRange(oldReference.getFirstChild(), added.getPrevSibling()); -+ } -+ } -+ } -+} -+ -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/ImportReferences/PhpClassReferenceStorage.java b/src/com/magento/idea/magento2plugin/actions/generation/ImportReferences/PhpClassReferenceStorage.java -new file mode 100644 -index 0000000..37bda18 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/ImportReferences/PhpClassReferenceStorage.java -@@ -0,0 +1,33 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation.ImportReferences; -+ -+import com.intellij.psi.PsiElement; -+import com.jetbrains.php.refactoring.importReferences.PhpClassReferenceExtractor; -+import gnu.trove.THashMap; -+import java.util.Map; -+import java.util.Set; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+public class PhpClassReferenceStorage extends PhpClassReferenceExtractor { -+ private final Map myReferences = new THashMap(); -+ -+ public PhpClassReferenceStorage() { -+ } -+ -+ protected void processReference(@NotNull String name, @NotNull String fqn, @NotNull PsiElement identifier) { -+ this.myReferences.put(name, fqn); -+ } -+ -+ @Nullable -+ public String getFqnByName(@NotNull String name) { -+ return this.myReferences.get(name); -+ } -+ -+ public Set getNames() { -+ return this.myReferences.keySet(); -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/NewModuleAction.java b/src/com/magento/idea/magento2plugin/actions/generation/NewModuleAction.java -new file mode 100644 -index 0000000..e8f1b78 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/NewModuleAction.java -@@ -0,0 +1,61 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation; -+ -+import com.intellij.ide.IdeView; -+import com.intellij.openapi.actionSystem.AnActionEvent; -+import com.intellij.openapi.actionSystem.CommonDataKeys; -+import com.intellij.openapi.actionSystem.DataContext; -+import com.intellij.openapi.actionSystem.LangDataKeys; -+import com.intellij.openapi.editor.Editor; -+import com.intellij.openapi.project.Project; -+import com.intellij.psi.PsiDirectory; -+import com.intellij.psi.PsiFile; -+import com.magento.idea.magento2plugin.MagentoIcons; -+import com.magento.idea.magento2plugin.actions.generation.dialog.NewMagentoModuleDialog; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+public class NewModuleAction extends com.intellij.openapi.actionSystem.AnAction { -+ public static String ACTION_NAME = "New Magento 2 Module"; -+ public static String ACTION_DESCRIPTION = "Create a new Magento 2 module"; -+ -+ NewModuleAction() { -+ super(ACTION_NAME, ACTION_DESCRIPTION, MagentoIcons.MODULE); -+ } -+ @Override -+ public void actionPerformed(@NotNull AnActionEvent e) { -+ DataContext dataContext = e.getDataContext(); -+ IdeView view = LangDataKeys.IDE_VIEW.getData(dataContext); -+ if (view != null) { -+ Project project = CommonDataKeys.PROJECT.getData(dataContext); -+ if (project != null) { -+ PsiDirectory initialBaseDir = view.getOrChooseDirectory(); -+ if (initialBaseDir != null) { -+ this.invoke(project, initialBaseDir, this.getFile(dataContext), view, CommonDataKeys.EDITOR.getData(dataContext)); -+ } -+ } -+ } -+ } -+ -+ public void invoke(@NotNull Project project, @NotNull PsiDirectory initialBaseDir, @Nullable PsiFile file, @Nullable IdeView view, @Nullable Editor editor) { -+ NewMagentoModuleDialog.open(project, initialBaseDir, file, view, editor); -+ } -+ -+ @Override -+ public boolean isDumbAware() { -+ return false; -+ } -+ -+ @NotNull -+ private String getActionName() { -+ return this.getTemplatePresentation().getText(); -+ } -+ -+ public PsiFile getFile(DataContext dataContext) { -+ return CommonDataKeys.PSI_FILE.getData(dataContext); -+ } -+} -+ -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/OverrideClassByAPreferenceAction.java b/src/com/magento/idea/magento2plugin/actions/generation/OverrideClassByAPreferenceAction.java -new file mode 100644 -index 0000000..103bc6c ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/OverrideClassByAPreferenceAction.java -@@ -0,0 +1,76 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation; -+ -+import com.intellij.openapi.actionSystem.AnActionEvent; -+import com.intellij.openapi.actionSystem.PlatformDataKeys; -+import com.intellij.openapi.project.DumbAwareAction; -+import com.intellij.openapi.project.Project; -+import com.intellij.openapi.util.Pair; -+import com.intellij.psi.PsiFile; -+import com.jetbrains.php.lang.psi.PhpFile; -+import com.jetbrains.php.lang.psi.elements.PhpClass; -+import com.magento.idea.magento2plugin.MagentoIcons; -+import com.magento.idea.magento2plugin.actions.generation.dialog.OverrideClassByAPreferenceDialog; -+import com.magento.idea.magento2plugin.project.Settings; -+import com.magento.idea.magento2plugin.util.GetFirstClassOfFile; -+import org.jetbrains.annotations.NotNull; -+ -+public class OverrideClassByAPreferenceAction extends DumbAwareAction { -+ public static String ACTION_NAME = "Override Class By A Preference..."; -+ public static String ACTION_DESCRIPTION = "Create a new Magento 2 preference for the class"; -+ private final GetFirstClassOfFile getFirstClassOfFile; -+ private PhpClass targetClass; -+ -+ public OverrideClassByAPreferenceAction() { -+ super(ACTION_NAME, ACTION_DESCRIPTION, MagentoIcons.MODULE); -+ this.getFirstClassOfFile = GetFirstClassOfFile.getInstance(); -+ } -+ -+ public void update(AnActionEvent event) { -+ targetClass = null; -+ Project project = event.getData(PlatformDataKeys.PROJECT); -+ if (Settings.isEnabled(project)) { -+ Pair pair = this.findPhpClass(event); -+ PsiFile psiFile = pair.getFirst(); -+ PhpClass phpClass = pair.getSecond(); -+ targetClass = phpClass; -+ if (!(psiFile instanceof PhpFile) && phpClass != null) { -+ this.setStatus(event, false); -+ return; -+ } -+ } else { -+ this.setStatus(event, false); -+ return; -+ } -+ this.setStatus(event, true); -+ } -+ -+ private void setStatus(AnActionEvent event, boolean status) { -+ event.getPresentation().setVisible(status); -+ event.getPresentation().setEnabled(status); -+ } -+ -+ @Override -+ public void actionPerformed(@NotNull AnActionEvent e) { -+ OverrideClassByAPreferenceDialog.open(e.getProject(), this.targetClass); -+ } -+ -+ @Override -+ public boolean isDumbAware() { -+ return false; -+ } -+ -+ private Pair findPhpClass(@NotNull AnActionEvent event) { -+ PsiFile psiFile = event.getData(PlatformDataKeys.PSI_FILE); -+ -+ PhpClass phpClass = null; -+ if (psiFile instanceof PhpFile) { -+ phpClass = getFirstClassOfFile.execute((PhpFile) psiFile); -+ } -+ -+ return Pair.create(psiFile, phpClass); -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/PluginGenerateAfterMethodAction.java b/src/com/magento/idea/magento2plugin/actions/generation/PluginGenerateAfterMethodAction.java -new file mode 100644 -index 0000000..d9664b5 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/PluginGenerateAfterMethodAction.java -@@ -0,0 +1,36 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation; -+ -+import com.intellij.codeInsight.CodeInsightActionHandler; -+import com.intellij.codeInsight.actions.CodeInsightAction; -+import com.intellij.openapi.editor.Editor; -+import com.intellij.openapi.project.Project; -+import com.intellij.openapi.util.Key; -+import com.intellij.psi.PsiFile; -+import com.jetbrains.php.lang.psi.elements.Method; -+import com.jetbrains.php.lang.psi.elements.PhpClass; -+import com.magento.idea.magento2plugin.actions.generation.data.code.PluginMethodData; -+import com.magento.idea.magento2plugin.actions.generation.generator.code.PluginMethodsGenerator; -+import com.magento.idea.magento2plugin.magento.files.Plugin; -+import org.jetbrains.annotations.NotNull; -+ -+public class PluginGenerateAfterMethodAction extends CodeInsightAction { -+ private final PluginGenerateMethodHandlerBase myHandler = new PluginGenerateMethodHandlerBase(Plugin.PluginType.after) { -+ protected PluginMethodData[] createPluginMethods(PhpClass currentClass, Method method, Key targetClassKey) { -+ return (new PluginMethodsGenerator(currentClass, method, targetClassKey) -+ .createPluginMethods(Plugin.PluginType.after)); -+ } -+ }; -+ -+ protected boolean isValidForFile(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file) { -+ return this.myHandler.isValidFor(editor, file); -+ } -+ -+ @NotNull -+ protected CodeInsightActionHandler getHandler() { -+ return this.myHandler; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/PluginGenerateAroundMethodAction.java b/src/com/magento/idea/magento2plugin/actions/generation/PluginGenerateAroundMethodAction.java -new file mode 100644 -index 0000000..ba3e436 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/PluginGenerateAroundMethodAction.java -@@ -0,0 +1,36 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation; -+ -+import com.intellij.codeInsight.CodeInsightActionHandler; -+import com.intellij.codeInsight.actions.CodeInsightAction; -+import com.intellij.openapi.editor.Editor; -+import com.intellij.openapi.project.Project; -+import com.intellij.openapi.util.Key; -+import com.intellij.psi.PsiFile; -+import com.jetbrains.php.lang.psi.elements.Method; -+import com.jetbrains.php.lang.psi.elements.PhpClass; -+import com.magento.idea.magento2plugin.actions.generation.data.code.PluginMethodData; -+import com.magento.idea.magento2plugin.actions.generation.generator.code.PluginMethodsGenerator; -+import com.magento.idea.magento2plugin.magento.files.Plugin; -+import org.jetbrains.annotations.NotNull; -+ -+public class PluginGenerateAroundMethodAction extends CodeInsightAction { -+ private final PluginGenerateMethodHandlerBase myHandler = new PluginGenerateMethodHandlerBase(Plugin.PluginType.around) { -+ protected PluginMethodData[] createPluginMethods(PhpClass currentClass, Method method, Key targetClassKey) { -+ return (new PluginMethodsGenerator(currentClass, method, targetClassKey) -+ .createPluginMethods(Plugin.PluginType.around)); -+ } -+ }; -+ -+ protected boolean isValidForFile(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file) { -+ return this.myHandler.isValidFor(editor, file); -+ } -+ -+ @NotNull -+ protected CodeInsightActionHandler getHandler() { -+ return this.myHandler; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/PluginGenerateBeforeMethodAction.java b/src/com/magento/idea/magento2plugin/actions/generation/PluginGenerateBeforeMethodAction.java -new file mode 100644 -index 0000000..c5aa5aa ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/PluginGenerateBeforeMethodAction.java -@@ -0,0 +1,36 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation; -+ -+import com.intellij.codeInsight.CodeInsightActionHandler; -+import com.intellij.codeInsight.actions.CodeInsightAction; -+import com.intellij.openapi.editor.Editor; -+import com.intellij.openapi.project.Project; -+import com.intellij.psi.PsiFile; -+import com.jetbrains.php.lang.psi.elements.Method; -+import com.jetbrains.php.lang.psi.elements.PhpClass; -+import com.magento.idea.magento2plugin.actions.generation.data.code.PluginMethodData; -+import com.magento.idea.magento2plugin.actions.generation.generator.code.PluginMethodsGenerator; -+import com.magento.idea.magento2plugin.magento.files.Plugin; -+import org.jetbrains.annotations.NotNull; -+import com.intellij.openapi.util.Key; -+ -+public class PluginGenerateBeforeMethodAction extends CodeInsightAction { -+ private final PluginGenerateMethodHandlerBase myHandler = new PluginGenerateMethodHandlerBase(Plugin.PluginType.before) { -+ protected PluginMethodData[] createPluginMethods(PhpClass currentClass, Method method, Key targetClassKey) { -+ return (new PluginMethodsGenerator(currentClass, method, targetClassKey) -+ .createPluginMethods(Plugin.PluginType.before)); -+ } -+ }; -+ -+ protected boolean isValidForFile(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file) { -+ return this.myHandler.isValidFor(editor, file); -+ } -+ -+ @NotNull -+ protected CodeInsightActionHandler getHandler() { -+ return this.myHandler; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/PluginGenerateMethodHandlerBase.java b/src/com/magento/idea/magento2plugin/actions/generation/PluginGenerateMethodHandlerBase.java -new file mode 100644 -index 0000000..7d3991e ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/PluginGenerateMethodHandlerBase.java -@@ -0,0 +1,255 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation; -+ -+import com.intellij.codeInsight.hint.HintManager; -+import com.intellij.ide.util.MemberChooser; -+import com.intellij.lang.LanguageCodeInsightActionHandler; -+import com.intellij.openapi.application.ApplicationManager; -+import com.intellij.openapi.editor.Editor; -+import com.intellij.openapi.project.Project; -+import com.intellij.openapi.util.Key; -+import com.intellij.psi.PsiDocumentManager; -+import com.intellij.psi.PsiElement; -+import com.intellij.psi.PsiFile; -+import com.intellij.psi.codeStyle.CodeStyleManager; -+import com.intellij.psi.tree.IElementType; -+import com.intellij.util.containers.ContainerUtil; -+import com.jetbrains.php.codeInsight.PhpCodeInsightUtil; -+import com.jetbrains.php.lang.actions.PhpNamedElementNode; -+import com.jetbrains.php.lang.lexer.PhpTokenTypes; -+import com.jetbrains.php.lang.parser.PhpElementTypes; -+import com.jetbrains.php.lang.parser.PhpStubElementTypes; -+import com.jetbrains.php.lang.psi.PhpCodeEditUtil; -+import com.jetbrains.php.lang.psi.PhpFile; -+import com.jetbrains.php.lang.psi.PhpPsiUtil; -+import com.jetbrains.php.lang.psi.elements.*; -+import java.util.*; -+import com.magento.idea.magento2plugin.actions.generation.ImportReferences.PhpClassReferenceResolver; -+import com.magento.idea.magento2plugin.actions.generation.data.code.PluginMethodData; -+import com.magento.idea.magento2plugin.actions.generation.generator.code.PluginMethodsGenerator; -+import com.magento.idea.magento2plugin.actions.generation.util.CodeStyleSettings; -+import com.magento.idea.magento2plugin.actions.generation.util.CollectInsertedMethods; -+import com.magento.idea.magento2plugin.actions.generation.util.FillTextBufferWithPluginMethods; -+import com.magento.idea.magento2plugin.magento.files.Plugin; -+import com.magento.idea.magento2plugin.util.GetPhpClassByFQN; -+import com.magento.idea.magento2plugin.util.magento.plugin.GetTargetClassNamesByPluginClassName; -+import com.magento.idea.magento2plugin.util.magento.plugin.IsPluginAllowedForMethod; -+import gnu.trove.THashSet; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+public abstract class PluginGenerateMethodHandlerBase implements LanguageCodeInsightActionHandler { -+ private CollectInsertedMethods collectInsertedMethods; -+ public String type; -+ public FillTextBufferWithPluginMethods fillTextBuffer; -+ -+ public PluginGenerateMethodHandlerBase(Plugin.PluginType type) { -+ this.type = type.toString(); -+ this.fillTextBuffer = FillTextBufferWithPluginMethods.getInstance(); -+ this.collectInsertedMethods = CollectInsertedMethods.getInstance(); -+ } -+ -+ public boolean isValidFor(Editor editor, PsiFile file) { -+ if (!(file instanceof PhpFile)) { -+ return false; -+ } -+ PhpClass phpClass = PhpCodeEditUtil.findClassAtCaret(editor, file); -+ if (phpClass == null) { -+ return false; -+ } -+ GetTargetClassNamesByPluginClassName targetClassesService = GetTargetClassNamesByPluginClassName.getInstance(editor.getProject()); -+ String currentClass = phpClass.getFQN().substring(1); -+ ArrayList targetClassNames = targetClassesService.execute(currentClass); -+ return !targetClassNames.isEmpty(); -+ } -+ -+ public void invoke(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile pluginFile) { -+ PhpFile pluginPhpFile = (PhpFile)pluginFile; -+ PhpClass pluginClass = PhpCodeEditUtil.findClassAtCaret(editor, pluginPhpFile); -+ Key targetClassKey = Key.create(PluginMethodsGenerator.originalTargetKey); -+ if (pluginClass == null) { -+ return; -+ } -+ PhpNamedElementNode[] fieldsToShow = this.targetMethods(pluginClass, targetClassKey); -+ if (fieldsToShow.length == 0) { -+ if (ApplicationManager.getApplication().isHeadlessEnvironment()) { -+ return; -+ } -+ HintManager.getInstance().showErrorHint(editor, this.getErrorMessage()); -+ return; -+ } -+ PhpNamedElementNode[] members = this.chooseMembers(fieldsToShow, true, pluginFile.getProject()); -+ if (members == null || members.length == 0) { -+ return; -+ } -+ int insertPos = getSuitableEditorPosition(editor, pluginPhpFile); -+ -+ CodeStyleSettings codeStyleSettings = new CodeStyleSettings(pluginPhpFile); -+ codeStyleSettings.adjustBeforeWrite(); -+ ApplicationManager.getApplication().runWriteAction(() -> { -+ Set insertedMethodsNames = new THashSet(); -+ PhpClassReferenceResolver resolver = new PhpClassReferenceResolver(); -+ StringBuffer textBuf = new StringBuffer(); -+ PhpPsiElement scope = PhpCodeInsightUtil.findScopeForUseOperator(pluginClass); -+ -+ for (PhpNamedElementNode member : members) { -+ PsiElement method = member.getPsiElement(); -+ PluginMethodData[] pluginMethods = this.createPluginMethods(pluginClass, (Method) method, targetClassKey); -+ fillTextBuffer.execute(targetClassKey, insertedMethodsNames, resolver, textBuf, pluginMethods); -+ } -+ -+ insertPluginMethodsToFile(project, editor, pluginFile, pluginClass, insertPos, insertedMethodsNames, resolver, textBuf, scope); -+ }); -+ codeStyleSettings.restore(); -+ } -+ -+ private void insertPluginMethodsToFile(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile pluginFile, PhpClass pluginClass, int insertPos, Set insertedMethodsNames, PhpClassReferenceResolver resolver, StringBuffer textBuf, PhpPsiElement scope) { -+ if (textBuf.length() > 0 && insertPos >= 0) { -+ editor.getDocument().insertString(insertPos, textBuf); -+ int endPos = insertPos + textBuf.length(); -+ CodeStyleManager.getInstance(project).reformatText(pluginFile, insertPos, endPos); -+ PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument()); -+ } -+ if (!insertedMethodsNames.isEmpty()) { -+ List insertedMethods = collectInsertedMethods.execute(pluginFile, pluginClass.getNameCS(), insertedMethodsNames); -+ if (scope != null && insertedMethods != null) { -+ resolver.importReferences(scope, insertedMethods); -+ } -+ } -+ } -+ -+ protected abstract PluginMethodData[] createPluginMethods(PhpClass currentClass, Method method, Key targetClassKey); -+ -+ protected String getErrorMessage() { -+ return "No methods to generate"; -+ } -+ -+ public boolean startInWriteAction() { -+ return false; -+ } -+ -+ @Nullable -+ protected PhpNamedElementNode[] chooseMembers(PhpNamedElementNode[] members, boolean allowEmptySelection, Project project) { -+ PhpNamedElementNode[] nodes = fixOrderToBeAsOriginalFiles(members).toArray(new PhpNamedElementNode[members.length]); -+ if (!ApplicationManager.getApplication().isHeadlessEnvironment()) { -+ PluginGenerateMethodHandlerBase.MyMemberChooser chooser = new PluginGenerateMethodHandlerBase.MyMemberChooser(nodes, allowEmptySelection, project); -+ chooser.setTitle("Choose Methods"); -+ chooser.setCopyJavadocVisible(false); -+ chooser.show(); -+ List list = chooser.getSelectedElements(); -+ return list == null ? null : list.toArray(new PhpNamedElementNode[0]); -+ } -+ -+ return nodes; -+ } -+ -+ @NotNull -+ protected PhpNamedElementNode[] targetMethods(@NotNull PhpClass phpClass, Key targetClassKey) { -+ TreeMap nodes = new TreeMap(); -+ -+ GetTargetClassNamesByPluginClassName targetClassesService = GetTargetClassNamesByPluginClassName.getInstance(phpClass.getProject()); -+ String currentClass = phpClass.getFQN().substring(1); -+ ArrayList targetClassNames = targetClassesService.execute(currentClass); -+ for (String targetClassName : targetClassNames) { -+ PhpClass targetClass = GetPhpClassByFQN.getInstance(phpClass.getProject()).execute(targetClassName); -+ if (targetClass.isFinal()) { -+ continue; -+ } -+ Collection methods = targetClass.getMethods(); -+ Iterator methodIterator = methods.iterator(); -+ -+ while(methodIterator.hasNext()) { -+ Method method = (Method) methodIterator.next(); -+ if (IsPluginAllowedForMethod.getInstance().check(method) && !pluginAlreadyHasMethod(phpClass, method)) { -+ method.putUserData(targetClassKey, targetClass); -+ nodes.put(method.getName(), new PhpNamedElementNode(method)); -+ } -+ } -+ } -+ PhpNamedElementNode[] targetMethods = nodes.values().toArray(new PhpNamedElementNode[0]); -+ -+ return targetMethods; -+ } -+ -+ protected boolean pluginAlreadyHasMethod(@NotNull PhpClass currentClass, @NotNull Method method) { -+ Collection currentMethods = currentClass.getMethods(); -+ String methodName = method.getName(); -+ String methodPrefix = type; -+ String methodSuffix = methodName.substring(0, 1).toUpperCase() + methodName.substring(1); -+ String pluginMethodName = methodPrefix.concat(methodSuffix); -+ for (Method currentMethod: currentMethods) { -+ if(!currentMethod.getName().equals(pluginMethodName)) { -+ continue; -+ } -+ return true; -+ } -+ return false; -+ } -+ -+ public static Collection fixOrderToBeAsOriginalFiles(PhpNamedElementNode[] selected) { -+ List newSelected = ContainerUtil.newArrayList(selected); -+ Collections.sort(newSelected, (o1, o2) -> { -+ PsiElement psiElement = o1.getPsiElement(); -+ PsiElement psiElement2 = o2.getPsiElement(); -+ PsiFile containingFile = psiElement.getContainingFile(); -+ PsiFile containingFile2 = psiElement2.getContainingFile(); -+ return containingFile == containingFile2 ? psiElement.getTextOffset() - psiElement2.getTextOffset() : containingFile.getName().compareTo(containingFile2.getName()); -+ }); -+ return newSelected; -+ } -+ -+ private static int getSuitableEditorPosition(Editor editor, PhpFile phpFile) { -+ PsiElement currElement = phpFile.findElementAt(editor.getCaretModel().getOffset()); -+ if (currElement != null) { -+ PsiElement parent = currElement.getParent(); -+ -+ for(PsiElement prevParent = currElement; parent != null && !(parent instanceof PhpFile); parent = parent.getParent()) { -+ if (isClassMember(parent)) { -+ return getNextPos(parent); -+ } -+ -+ if (parent instanceof PhpClass) { -+ while(prevParent != null) { -+ if (isClassMember(prevParent) || PhpPsiUtil.isOfType(prevParent, PhpTokenTypes.chLBRACE)) { -+ return getNextPos(prevParent); -+ } -+ -+ prevParent = prevParent.getPrevSibling(); -+ } -+ -+ for(PsiElement classChild = parent.getFirstChild(); classChild != null; classChild = classChild.getNextSibling()) { -+ if (PhpPsiUtil.isOfType(classChild, PhpTokenTypes.chLBRACE)) { -+ return getNextPos(classChild); -+ } -+ } -+ } -+ -+ prevParent = parent; -+ } -+ } -+ -+ return -1; -+ } -+ -+ private static boolean isClassMember(PsiElement element) { -+ if (element == null) { -+ return false; -+ } -+ IElementType elementType = element.getNode().getElementType(); -+ return elementType == PhpElementTypes.CLASS_FIELDS || elementType == PhpElementTypes.CLASS_CONSTANTS || elementType == PhpStubElementTypes.CLASS_METHOD; -+ } -+ -+ private static int getNextPos(PsiElement element) { -+ PsiElement next = element.getNextSibling(); -+ return next != null ? next.getTextOffset() : -1; -+ } -+ -+ private static class MyMemberChooser extends MemberChooser { -+ protected MyMemberChooser(@NotNull PhpNamedElementNode[] nodes, boolean allowEmptySelection, @NotNull Project project) { -+ super(nodes, allowEmptySelection, true, project, false); -+ } -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/data/ModuleComposerJsonData.java b/src/com/magento/idea/magento2plugin/actions/generation/data/ModuleComposerJsonData.java -new file mode 100644 -index 0000000..de032fa ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/data/ModuleComposerJsonData.java -@@ -0,0 +1,56 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation.data; -+ -+import com.intellij.psi.PsiDirectory; -+ -+public class ModuleComposerJsonData { -+ private final String packageName; -+ private final String moduleName; -+ private PsiDirectory baseDir; -+ private final String moduleDescription; -+ private final String composerPackageName; -+ private final String moduleVersion; -+ -+ public ModuleComposerJsonData( -+ String packageName, -+ String moduleName, -+ PsiDirectory baseDir, -+ String moduleDescription, -+ String composerPackageName, -+ String moduleVersion -+ ) { -+ this.packageName = packageName; -+ this.moduleName = moduleName; -+ this.baseDir = baseDir; -+ this.moduleDescription = moduleDescription; -+ this.composerPackageName = composerPackageName; -+ this.moduleVersion = moduleVersion; -+ } -+ -+ public String getPackageName() { -+ return this.packageName; -+ } -+ -+ public String getModuleName() { -+ return this.moduleName; -+ } -+ -+ public PsiDirectory getBaseDir() { -+ return this.baseDir; -+ } -+ -+ public String getModuleDescription() { -+ return this.moduleDescription; -+ } -+ -+ public String getComposerPackageName() { -+ return this.composerPackageName; -+ } -+ -+ public String getModuleVersion() { -+ return this.moduleVersion; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/data/ModuleRegistrationPhpData.java b/src/com/magento/idea/magento2plugin/actions/generation/data/ModuleRegistrationPhpData.java -new file mode 100644 -index 0000000..ae337dd ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/data/ModuleRegistrationPhpData.java -@@ -0,0 +1,35 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation.data; -+ -+import com.intellij.psi.PsiDirectory; -+ -+public class ModuleRegistrationPhpData { -+ private final String packageName; -+ private final String moduleName; -+ private PsiDirectory baseDir; -+ -+ public ModuleRegistrationPhpData( -+ String packageName, -+ String moduleName, -+ PsiDirectory baseDir -+ ) { -+ this.packageName = packageName; -+ this.moduleName = moduleName; -+ this.baseDir = baseDir; -+ } -+ -+ public String getPackageName() { -+ return this.packageName; -+ } -+ -+ public String getModuleName() { -+ return this.moduleName; -+ } -+ -+ public PsiDirectory getBaseDir() { -+ return this.baseDir; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/data/ModuleXmlData.java b/src/com/magento/idea/magento2plugin/actions/generation/data/ModuleXmlData.java -new file mode 100644 -index 0000000..dffdd0b ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/data/ModuleXmlData.java -@@ -0,0 +1,35 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation.data; -+ -+import com.intellij.psi.PsiDirectory; -+ -+public class ModuleXmlData { -+ private final String packageName; -+ private final String moduleName; -+ private PsiDirectory baseDir; -+ -+ public ModuleXmlData( -+ String packageName, -+ String moduleName, -+ PsiDirectory baseDir -+ ) { -+ this.packageName = packageName; -+ this.moduleName = moduleName; -+ this.baseDir = baseDir; -+ } -+ -+ public String getPackageName() { -+ return this.packageName; -+ } -+ -+ public String getModuleName() { -+ return this.moduleName; -+ } -+ -+ public PsiDirectory getBaseDir() { -+ return this.baseDir; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/data/PluginDiXmlData.java b/src/com/magento/idea/magento2plugin/actions/generation/data/PluginDiXmlData.java -new file mode 100644 -index 0000000..c0b02d1 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/data/PluginDiXmlData.java -@@ -0,0 +1,56 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation.data; -+ -+import com.jetbrains.php.lang.psi.elements.PhpClass; -+ -+public class PluginDiXmlData { -+ private String area; -+ private String pluginModule; -+ private PhpClass targetClass; -+ private final String sortOrder; -+ private final String pluginName; -+ private String pluginFqn; -+ -+ public PluginDiXmlData( -+ String area, -+ String pluginModule, -+ PhpClass targetClass, -+ String sortOrder, -+ String pluginName, -+ String pluginFqn -+ ) { -+ this.area = area; -+ this.pluginModule = pluginModule; -+ this.targetClass = targetClass; -+ this.sortOrder = sortOrder; -+ this.pluginName = pluginName; -+ this.pluginFqn = pluginFqn; -+ } -+ -+ public String getArea() { -+ return area; -+ } -+ -+ public String getPluginModule() { -+ return pluginModule; -+ } -+ -+ public PhpClass getTargetClass() { -+ return targetClass; -+ } -+ -+ public String getPluginName() { -+ return pluginName; -+ } -+ -+ public String getSortOrder() { -+ return sortOrder; -+ } -+ -+ public String getPluginFqn() { -+ return pluginFqn; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/data/PluginFileData.java b/src/com/magento/idea/magento2plugin/actions/generation/data/PluginFileData.java -new file mode 100644 -index 0000000..01160d1 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/data/PluginFileData.java -@@ -0,0 +1,71 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation.data; -+ -+import com.jetbrains.php.lang.psi.elements.Method; -+import com.jetbrains.php.lang.psi.elements.PhpClass; -+ -+public class PluginFileData { -+ private String pluginDirectory; -+ private String pluginClassName; -+ private String pluginType; -+ private String pluginModule; -+ private PhpClass targetClass; -+ private Method targetMethod; -+ private String pluginFqn; -+ private String namespace; -+ -+ public PluginFileData( -+ String pluginDirectory, -+ String pluginClassName, -+ String pluginType, -+ String pluginModule, -+ PhpClass targetClass, -+ Method targetMethod, -+ String pluginFqn, -+ String namespace -+ ) { -+ this.pluginDirectory = pluginDirectory; -+ this.pluginClassName = pluginClassName; -+ this.pluginType = pluginType; -+ this.pluginModule = pluginModule; -+ this.targetClass = targetClass; -+ this.targetMethod = targetMethod; -+ this.pluginFqn = pluginFqn; -+ this.namespace = namespace; -+ } -+ -+ public String getPluginClassName() { -+ return pluginClassName; -+ } -+ -+ public String getPluginDirectory() { -+ return pluginDirectory; -+ } -+ -+ public String getPluginType() { -+ return pluginType; -+ } -+ -+ public String getPluginModule() { -+ return pluginModule; -+ } -+ -+ public PhpClass getTargetClass() { -+ return targetClass; -+ } -+ -+ public Method getTargetMethod() { -+ return targetMethod; -+ } -+ -+ public String getPluginFqn() { -+ return pluginFqn; -+ } -+ -+ public String getNamespace() { -+ return namespace; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/data/PreferenceDiXmFileData.java b/src/com/magento/idea/magento2plugin/actions/generation/data/PreferenceDiXmFileData.java -new file mode 100644 -index 0000000..fefadce ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/data/PreferenceDiXmFileData.java -@@ -0,0 +1,49 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation.data; -+ -+import com.jetbrains.php.lang.psi.elements.PhpClass; -+ -+public class PreferenceDiXmFileData { -+ private String preferenceModule; -+ private PhpClass targetClass; -+ private String preferenceFqn; -+ private String namespace; -+ private String area; -+ -+ public PreferenceDiXmFileData( -+ String preferenceModule, -+ PhpClass targetClass, -+ String preferenceFqn, -+ String namespace, -+ String area -+ ) { -+ this.preferenceModule = preferenceModule; -+ this.targetClass = targetClass; -+ this.preferenceFqn = preferenceFqn; -+ this.namespace = namespace; -+ this.area = area; -+ } -+ -+ public String getPreferenceModule() { -+ return preferenceModule; -+ } -+ -+ public PhpClass getTargetClass() { -+ return targetClass; -+ } -+ -+ public String getPreferenceFqn() { -+ return preferenceFqn; -+ } -+ -+ public String getNamespace() { -+ return namespace; -+ } -+ -+ public String getArea() { -+ return area; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/data/PreferenceFileData.java b/src/com/magento/idea/magento2plugin/actions/generation/data/PreferenceFileData.java -new file mode 100644 -index 0000000..2ec66b2 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/data/PreferenceFileData.java -@@ -0,0 +1,63 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation.data; -+ -+import com.jetbrains.php.lang.psi.elements.PhpClass; -+ -+public class PreferenceFileData { -+ private String preferenceDirectory; -+ private String preferenceClassName; -+ private String preferenceModule; -+ private PhpClass targetClass; -+ private String preferenceFqn; -+ private String namespace; -+ private boolean inheritClass; -+ -+ public PreferenceFileData( -+ String preferenceDirectory, -+ String preferenceClassName, -+ String preferenceModule, -+ PhpClass targetClass, -+ String preferenceFqn, -+ String namespace, -+ boolean inheritClass -+ ) { -+ this.preferenceDirectory = preferenceDirectory; -+ this.preferenceClassName = preferenceClassName; -+ this.preferenceModule = preferenceModule; -+ this.targetClass = targetClass; -+ this.preferenceFqn = preferenceFqn; -+ this.namespace = namespace; -+ this.inheritClass = inheritClass; -+ } -+ -+ public String getPreferenceClassName() { -+ return preferenceClassName; -+ } -+ -+ public String getPreferenceDirectory() { -+ return preferenceDirectory; -+ } -+ -+ public String getPreferenceModule() { -+ return preferenceModule; -+ } -+ -+ public PhpClass getTargetClass() { -+ return targetClass; -+ } -+ -+ public String getPreferenceFqn() { -+ return preferenceFqn; -+ } -+ -+ public String getNamespace() { -+ return namespace; -+ } -+ -+ public boolean isInheritClass() { -+ return inheritClass; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/data/code/PluginMethodData.java b/src/com/magento/idea/magento2plugin/actions/generation/data/code/PluginMethodData.java -new file mode 100644 -index 0000000..44f5bc0 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/data/code/PluginMethodData.java -@@ -0,0 +1,33 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation.data.code; -+ -+import com.jetbrains.php.lang.documentation.phpdoc.psi.PhpDocComment; -+import com.jetbrains.php.lang.psi.elements.Method; -+ -+public class PluginMethodData { -+ private final PhpDocComment docComment; -+ private final Method method; -+ private final Method targetMethod; -+ -+ public PluginMethodData(Method targetMethod, PhpDocComment docComment, Method method) { -+ super(); -+ this.docComment = docComment; -+ this.method = method; -+ this.targetMethod = targetMethod; -+ } -+ -+ public PhpDocComment getDocComment() { -+ return this.docComment; -+ } -+ -+ public Method getMethod() { -+ return this.method; -+ } -+ -+ public Method getTargetMethod() { -+ return this.targetMethod; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/dialog/AbstractDialog.java b/src/com/magento/idea/magento2plugin/actions/generation/dialog/AbstractDialog.java -new file mode 100644 -index 0000000..f1bdb4d ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/dialog/AbstractDialog.java -@@ -0,0 +1,19 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation.dialog; -+ -+import javax.swing.*; -+import java.awt.*; -+ -+public abstract class AbstractDialog extends JDialog { -+ protected void pushToMiddle() { -+ Dimension dim = Toolkit.getDefaultToolkit().getScreenSize(); -+ this.setLocation(dim.width / 2 -this.getSize().width / 2, dim.height / 2 - this.getSize().height / 2); -+ } -+ -+ protected void onCancel() { -+ this.setVisible(false); -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/dialog/CreateAPluginDialog.form b/src/com/magento/idea/magento2plugin/actions/generation/dialog/CreateAPluginDialog.form -new file mode 100644 -index 0000000..d4e34fc ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/dialog/CreateAPluginDialog.form -@@ -0,0 +1,199 @@ -+ -+
-+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+
-diff --git a/src/com/magento/idea/magento2plugin/actions/generation/dialog/CreateAPluginDialog.java b/src/com/magento/idea/magento2plugin/actions/generation/dialog/CreateAPluginDialog.java -new file mode 100644 -index 0000000..ea589b7 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/dialog/CreateAPluginDialog.java -@@ -0,0 +1,180 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation.dialog; -+ -+import com.intellij.openapi.project.Project; -+import com.jetbrains.php.lang.psi.elements.Method; -+import com.jetbrains.php.lang.psi.elements.PhpClass; -+import com.magento.idea.magento2plugin.actions.generation.CreateAPluginAction; -+import com.magento.idea.magento2plugin.actions.generation.data.PluginDiXmlData; -+import com.magento.idea.magento2plugin.actions.generation.data.PluginFileData; -+import com.magento.idea.magento2plugin.actions.generation.dialog.validator.CreateAPluginDialogValidator; -+import com.magento.idea.magento2plugin.actions.generation.generator.PluginClassGenerator; -+import com.magento.idea.magento2plugin.actions.generation.generator.PluginDiXmlGenerator; -+import com.magento.idea.magento2plugin.indexes.ModuleIndex; -+import com.magento.idea.magento2plugin.magento.files.Plugin; -+import com.magento.idea.magento2plugin.magento.packages.Package; -+import com.magento.idea.magento2plugin.ui.FilteredComboBox; -+import org.jetbrains.annotations.NotNull; -+import javax.swing.*; -+import java.awt.*; -+import java.awt.event.*; -+import java.io.File; -+import java.util.List; -+ -+public class CreateAPluginDialog extends AbstractDialog { -+ @NotNull -+ private final Project project; -+ private Method targetMethod; -+ private PhpClass targetClass; -+ @NotNull -+ private final CreateAPluginDialogValidator validator; -+ private JPanel contentPane; -+ private JButton buttonOK; -+ private JButton buttonCancel; -+ private JTextField pluginClassName; -+ private JLabel pluginClassNameLabel; -+ private JTextField pluginDirectory; -+ private JLabel pluginDirectoryName; -+ private JLabel selectPluginModule; -+ private JComboBox pluginType; -+ private JLabel pluginTypeLabel; -+ private FilteredComboBox pluginModule; -+ private JComboBox pluginArea; -+ private JLabel pluginAreaLabel; -+ private JTextField pluginName; -+ private JLabel pluginNameLabel; -+ private JTextField pluginSortOrder; -+ private JLabel pluginSortOrderLabel; -+ -+ public CreateAPluginDialog(@NotNull Project project, Method targetMethod, PhpClass targetClass) { -+ this.project = project; -+ this.targetMethod = targetMethod; -+ this.targetClass = targetClass; -+ this.validator = CreateAPluginDialogValidator.getInstance(this); -+ -+ setContentPane(contentPane); -+ setModal(true); -+ getRootPane().setDefaultButton(buttonOK); -+ pushToMiddle(); -+ fillPluginTypeOptions(); -+ fillTargetAreaOptions(); -+ -+ buttonOK.addActionListener(new ActionListener() { -+ public void actionPerformed(ActionEvent e) { -+ onOK(); -+ } -+ }); -+ -+ buttonCancel.addActionListener(new ActionListener() { -+ public void actionPerformed(ActionEvent e) { -+ onCancel(); -+ } -+ }); -+ -+ setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); -+ addWindowListener(new WindowAdapter() { -+ public void windowClosing(WindowEvent e) { -+ onCancel(); -+ } -+ }); -+ -+ contentPane.registerKeyboardAction(new ActionListener() { -+ public void actionPerformed(ActionEvent e) { -+ onCancel(); -+ } -+ }, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); -+ } -+ -+ private void fillPluginTypeOptions() { -+ for (Plugin.PluginType pluginPrefixType: Plugin.PluginType.values()) { -+ pluginType.addItem(pluginPrefixType.toString()); -+ } -+ } -+ -+ private void fillTargetAreaOptions() { -+ for(Package.Areas area: Package.Areas.values()) { -+ pluginArea.addItem(area.toString()); -+ } -+ } -+ -+ private void onOK() { -+ if (!validator.validate(project)) { -+ return; -+ } -+ new PluginClassGenerator(new PluginFileData( -+ getPluginDirectory(), -+ getPluginClassName(), -+ getPluginType(), -+ getPluginModule(), -+ targetClass, -+ targetMethod, -+ getPluginClassFqn(), -+ getNamespace() -+ ), project).generate(CreateAPluginAction.ACTION_NAME, true); -+ -+ new PluginDiXmlGenerator(new PluginDiXmlData( -+ getPluginArea(), -+ getPluginModule(), -+ targetClass, -+ getPluginSortOrder(), -+ getPluginName(), -+ getPluginClassFqn() -+ ), project).generate(CreateAPluginAction.ACTION_NAME); -+ -+ this.setVisible(false); -+ } -+ -+ public String getPluginName() { -+ return this.pluginName.getText().trim(); -+ } -+ -+ public String getPluginSortOrder() { -+ return this.pluginSortOrder.getText().trim(); -+ } -+ -+ public String getPluginClassName() { -+ return this.pluginClassName.getText().trim(); -+ } -+ -+ public String getPluginDirectory() { -+ return this.pluginDirectory.getText().trim(); -+ } -+ -+ public String getPluginArea() { -+ return this.pluginArea.getSelectedItem().toString(); -+ } -+ -+ public String getPluginType() { -+ return this.pluginType.getSelectedItem().toString(); -+ } -+ -+ public String getPluginModule() { -+ return this.pluginModule.getSelectedItem().toString(); -+ } -+ -+ public static void open(@NotNull Project project, Method targetMethod, PhpClass targetClass) { -+ CreateAPluginDialog dialog = new CreateAPluginDialog(project, targetMethod, targetClass); -+ dialog.pack(); -+ dialog.setVisible(true); -+ } -+ -+ private void createUIComponents() { -+ List allModulesList = ModuleIndex.getInstance(project).getEditableModuleNames(); -+ -+ this.pluginModule = new FilteredComboBox(allModulesList); -+ } -+ -+ private String getNamespace() { -+ String targetModule = getPluginModule(); -+ String namespace = targetModule.replace(Package.VENDOR_MODULE_NAME_SEPARATOR, Package.FQN_SEPARATOR); -+ namespace = namespace.concat(Package.FQN_SEPARATOR); -+ return namespace.concat(getPluginDirectory().replace(File.separator, Package.FQN_SEPARATOR)); -+ } -+ -+ private String getPluginClassFqn() { -+ return getNamespace().concat(Package.FQN_SEPARATOR).concat(getPluginClassName()); -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/dialog/NewMagentoModuleDialog.form b/src/com/magento/idea/magento2plugin/actions/generation/dialog/NewMagentoModuleDialog.form -new file mode 100644 -index 0000000..cd3eca2 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/dialog/NewMagentoModuleDialog.form -@@ -0,0 +1,145 @@ -+ -+
-+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+
-diff --git a/src/com/magento/idea/magento2plugin/actions/generation/dialog/NewMagentoModuleDialog.java b/src/com/magento/idea/magento2plugin/actions/generation/dialog/NewMagentoModuleDialog.java -new file mode 100644 -index 0000000..c2825a2 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/dialog/NewMagentoModuleDialog.java -@@ -0,0 +1,195 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation.dialog; -+ -+import com.intellij.ide.IdeView; -+import com.intellij.openapi.editor.Editor; -+import com.intellij.openapi.project.Project; -+import com.intellij.psi.PsiDirectory; -+import com.intellij.psi.PsiFile; -+import com.magento.idea.magento2plugin.actions.generation.NewModuleAction; -+import com.magento.idea.magento2plugin.actions.generation.data.ModuleComposerJsonData; -+import com.magento.idea.magento2plugin.actions.generation.data.ModuleRegistrationPhpData; -+import com.magento.idea.magento2plugin.actions.generation.data.ModuleXmlData; -+import com.magento.idea.magento2plugin.actions.generation.dialog.validator.NewMagentoModuleDialogValidator; -+import com.magento.idea.magento2plugin.actions.generation.generator.ModuleComposerJsonGenerator; -+import com.magento.idea.magento2plugin.actions.generation.generator.ModuleRegistrationPhpGenerator; -+import com.magento.idea.magento2plugin.actions.generation.generator.ModuleXmlGenerator; -+import com.magento.idea.magento2plugin.actions.generation.generator.util.DirectoryGenerator; -+import com.magento.idea.magento2plugin.actions.generation.generator.util.FileFromTemplateGenerator; -+import com.magento.idea.magento2plugin.actions.generation.util.NavigateToCreatedFile; -+import com.magento.idea.magento2plugin.magento.packages.Package; -+import com.magento.idea.magento2plugin.util.CamelCaseToHyphen; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+import javax.swing.*; -+import java.awt.*; -+import java.awt.event.*; -+ -+public class NewMagentoModuleDialog extends AbstractDialog { -+ @NotNull -+ private final Project project; -+ @NotNull -+ private final PsiDirectory initialBaseDir; -+ @Nullable -+ private final PsiFile file; -+ @Nullable -+ private final IdeView view; -+ @Nullable -+ private final Editor editor; -+ private final DirectoryGenerator directoryGenerator; -+ private final FileFromTemplateGenerator fileFromTemplateGenerator; -+ private final NewMagentoModuleDialogValidator validator; -+ private final CamelCaseToHyphen camelCaseToHyphen; -+ private final NavigateToCreatedFile navigateToCreatedFile; -+ private JPanel contentPane; -+ private JButton buttonOK; -+ private JButton buttonCancel; -+ private JTextField packageName; -+ private JLabel packageNameLabel; -+ private JTextField moduleName; -+ private JLabel moduleNameLabel; -+ private JTextArea moduleDescription; -+ private JLabel moduleDescriptionLabel; -+ private JTextField moduleVersion; -+ private JLabel moduleVersionLabel; -+ private String detectedPackageName; -+ -+ public NewMagentoModuleDialog(@NotNull Project project, @NotNull PsiDirectory initialBaseDir, @Nullable PsiFile file, @Nullable IdeView view, @Nullable Editor editor) { -+ this.project = project; -+ this.initialBaseDir = initialBaseDir; -+ this.file = file; -+ this.view = view; -+ this.editor = editor; -+ this.directoryGenerator = DirectoryGenerator.getInstance(); -+ this.fileFromTemplateGenerator = FileFromTemplateGenerator.getInstance(project); -+ this.camelCaseToHyphen = CamelCaseToHyphen.getInstance(); -+ this.validator = NewMagentoModuleDialogValidator.getInstance(this); -+ this.navigateToCreatedFile = NavigateToCreatedFile.getInstance(); -+ detectPackageName(initialBaseDir); -+ setContentPane(contentPane); -+ setModal(true); -+ getRootPane().setDefaultButton(buttonOK); -+ pushToMiddle(); -+ -+ buttonOK.addActionListener(new ActionListener() { -+ public void actionPerformed(ActionEvent e) { -+ onOK(); -+ } -+ }); -+ -+ buttonCancel.addActionListener(new ActionListener() { -+ public void actionPerformed(ActionEvent e) { -+ onCancel(); -+ } -+ }); -+ -+ setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); -+ addWindowListener(new WindowAdapter() { -+ public void windowClosing(WindowEvent e) { -+ onCancel(); -+ } -+ }); -+ -+ contentPane.registerKeyboardAction(new ActionListener() { -+ public void actionPerformed(ActionEvent e) { -+ onCancel(); -+ } -+ }, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); -+ } -+ -+ private void detectPackageName(@NotNull PsiDirectory initialBaseDir) { -+ PsiDirectory parentDir = initialBaseDir.getParent(); -+ if (parentDir != null && parentDir.toString().endsWith(Package.PACKAGES_ROOT)) { -+ packageName.setVisible(false); -+ packageNameLabel.setVisible(false); -+ this.detectedPackageName = initialBaseDir.getName(); -+ } -+ } -+ -+ private void onOK() { -+ if (!validator.validate()) { -+ return; -+ } -+ generateFiles(); -+ this.setVisible(false); -+ } -+ -+ private void generateFiles() { -+ PsiFile composerJson = generateComposerJson(); -+ if (composerJson == null) { -+ return; -+ } -+ -+ PsiFile registrationPhp = generateRegistrationPhp(); -+ if (registrationPhp == null) { -+ return; -+ } -+ generateModuleXml(); -+ } -+ -+ private PsiFile generateComposerJson() { -+ return new ModuleComposerJsonGenerator(new ModuleComposerJsonData( -+ getPackageName(), -+ getModuleName(), -+ getBaseDir(), -+ getModuleDescription(), -+ getComposerPackageName(), -+ getModuleVersion() -+ ), project).generate(NewModuleAction.ACTION_NAME); -+ } -+ -+ private PsiFile generateRegistrationPhp() { -+ return new ModuleRegistrationPhpGenerator(new ModuleRegistrationPhpData( -+ getPackageName(), -+ getModuleName(), -+ getBaseDir() -+ ), project).generate(NewModuleAction.ACTION_NAME); -+ } -+ -+ private void generateModuleXml() { -+ new ModuleXmlGenerator(new ModuleXmlData( -+ getPackageName(), -+ getModuleName(), -+ getBaseDir() -+ ), project).generate(NewModuleAction.ACTION_NAME, true); -+ } -+ -+ private PsiDirectory getBaseDir() { -+ return detectedPackageName != null ? this.initialBaseDir.getParent() : this.initialBaseDir; -+ } -+ -+ public String getPackageName() { -+ if (detectedPackageName != null) { -+ return detectedPackageName; -+ } -+ return this.packageName.getText().trim(); -+ } -+ -+ public String getModuleName() { -+ return this.moduleName.getText().trim(); -+ } -+ -+ public String getModuleDescription() { -+ return this.moduleDescription.getText().trim(); -+ } -+ -+ public String getModuleVersion() { -+ return this.moduleVersion.getText().trim(); -+ } -+ -+ public static void open(@NotNull Project project, @NotNull PsiDirectory initialBaseDir, @Nullable PsiFile file, @Nullable IdeView view, @Nullable Editor editor) { -+ NewMagentoModuleDialog dialog = new NewMagentoModuleDialog(project, initialBaseDir, file, view, editor); -+ dialog.pack(); -+ dialog.setVisible(true); -+ } -+ -+ @NotNull -+ private String getComposerPackageName() { -+ return camelCaseToHyphen.convert(getPackageName()) -+ .concat("/") -+ .concat(camelCaseToHyphen.convert(getModuleName())); -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/dialog/OverrideClassByAPreferenceDialog.form b/src/com/magento/idea/magento2plugin/actions/generation/dialog/OverrideClassByAPreferenceDialog.form -new file mode 100644 -index 0000000..1134c12 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/dialog/OverrideClassByAPreferenceDialog.form -@@ -0,0 +1,157 @@ -+ -+
-+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+
-diff --git a/src/com/magento/idea/magento2plugin/actions/generation/dialog/OverrideClassByAPreferenceDialog.java b/src/com/magento/idea/magento2plugin/actions/generation/dialog/OverrideClassByAPreferenceDialog.java -new file mode 100644 -index 0000000..437879e ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/dialog/OverrideClassByAPreferenceDialog.java -@@ -0,0 +1,186 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation.dialog; -+ -+import com.intellij.openapi.project.Project; -+import com.intellij.psi.PsiFile; -+import com.intellij.util.ArrayUtil; -+import com.jetbrains.php.lang.psi.elements.PhpClass; -+import com.magento.idea.magento2plugin.actions.generation.OverrideClassByAPreferenceAction; -+import com.magento.idea.magento2plugin.actions.generation.data.PreferenceDiXmFileData; -+import com.magento.idea.magento2plugin.actions.generation.data.PreferenceFileData; -+import com.magento.idea.magento2plugin.actions.generation.dialog.validator.OverrideClassByAPreferenceDialogValidator; -+import com.magento.idea.magento2plugin.actions.generation.generator.PreferenceClassGenerator; -+import com.magento.idea.magento2plugin.actions.generation.generator.PreferenceDiXmlGenerator; -+import com.magento.idea.magento2plugin.indexes.ModuleIndex; -+import com.magento.idea.magento2plugin.magento.packages.Package; -+import com.magento.idea.magento2plugin.ui.FilteredComboBox; -+import org.jetbrains.annotations.NotNull; -+import javax.swing.*; -+import java.awt.event.*; -+import java.io.File; -+import java.util.List; -+ -+public class OverrideClassByAPreferenceDialog extends AbstractDialog { -+ @NotNull -+ private final Project project; -+ private PhpClass targetClass; -+ @NotNull -+ private final OverrideClassByAPreferenceDialogValidator validator; -+ private JPanel contentPane; -+ private JButton buttonOK; -+ private JButton buttonCancel; -+ private JTextField preferenceClassName; -+ private JLabel preferenceClassNameLabel; -+ private JTextField preferenceDirectory; -+ private JLabel selectPreferenceModule; -+ private FilteredComboBox preferenceModule; -+ private JComboBox preferenceArea; -+ private JLabel preferenceAreaLabel; -+ private JCheckBox inheritClass; -+ private JLabel inheritClassLabel; -+ private JLabel preferenceDirectoryLabel; -+ -+ public OverrideClassByAPreferenceDialog(@NotNull Project project, PhpClass targetClass) { -+ this.project = project; -+ this.targetClass = targetClass; -+ this.validator = OverrideClassByAPreferenceDialogValidator.getInstance(this); -+ -+ setContentPane(contentPane); -+ setModal(true); -+ getRootPane().setDefaultButton(buttonOK); -+ pushToMiddle(); -+ fillTargetAreaOptions(); -+ if (targetClass.isFinal()) { -+ inheritClass.setVisible(false); -+ inheritClassLabel.setVisible(false); -+ } -+ suggestPreferenceClassName(targetClass); -+ suggestPreferenceDirectory(targetClass); -+ -+ buttonOK.addActionListener(new ActionListener() { -+ public void actionPerformed(ActionEvent e) { -+ onOK(); -+ } -+ }); -+ -+ buttonCancel.addActionListener(new ActionListener() { -+ public void actionPerformed(ActionEvent e) { -+ onCancel(); -+ } -+ }); -+ -+ setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); -+ addWindowListener(new WindowAdapter() { -+ public void windowClosing(WindowEvent e) { -+ onCancel(); -+ } -+ }); -+ -+ contentPane.registerKeyboardAction(new ActionListener() { -+ public void actionPerformed(ActionEvent e) { -+ onCancel(); -+ } -+ }, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); -+ } -+ -+ private void suggestPreferenceDirectory(PhpClass targetClass) { -+ String[] fqnParts = targetClass.getPresentableFQN().split("\\\\"); -+ if (fqnParts.length != 0) { -+ fqnParts = ArrayUtil.remove(fqnParts, fqnParts.length - 1); -+ } -+ if (fqnParts[1] != null) { -+ fqnParts = ArrayUtil.remove(fqnParts, 1); -+ } -+ if (fqnParts[0] != null) { -+ fqnParts = ArrayUtil.remove(fqnParts, 0); -+ } -+ String suggestedDirectory = String.join(File.separator, fqnParts); -+ preferenceDirectory.setText(suggestedDirectory); -+ } -+ -+ private void suggestPreferenceClassName(PhpClass targetClass) { -+ preferenceClassName.setText(targetClass.getName()); -+ } -+ -+ private void fillTargetAreaOptions() { -+ for(Package.Areas area: Package.Areas.values()) { -+ preferenceArea.addItem(area.toString()); -+ } -+ } -+ -+ private void onOK() { -+ if (!validator.validate(project)) { -+ return; -+ } -+ PsiFile diXml = new PreferenceDiXmlGenerator(new PreferenceDiXmFileData( -+ getPreferenceModule(), -+ targetClass, -+ getPreferenceClassFqn(), -+ getNamespace(), -+ getPreferenceArea() -+ ), project).generate(OverrideClassByAPreferenceAction.ACTION_NAME); -+ if (diXml == null) { -+ JOptionPane.showMessageDialog(null, "Preference already declared in the target module!", "Error", JOptionPane.ERROR_MESSAGE); -+ return; -+ } -+ -+ new PreferenceClassGenerator(new PreferenceFileData( -+ getPreferenceDirectory(), -+ getPreferenceClassName(), -+ getPreferenceModule(), -+ targetClass, -+ getPreferenceClassFqn(), -+ getNamespace(), -+ isInheritClass() -+ ), project).generate(OverrideClassByAPreferenceAction.ACTION_NAME, true); -+ -+ -+ this.setVisible(false); -+ } -+ -+ public String getPreferenceClassName() { -+ return this.preferenceClassName.getText().trim(); -+ } -+ -+ public String getPreferenceDirectory() { -+ return this.preferenceDirectory.getText().trim(); -+ } -+ -+ public String getPreferenceArea() { -+ return this.preferenceArea.getSelectedItem().toString(); -+ } -+ -+ public String getPreferenceModule() { -+ return this.preferenceModule.getSelectedItem().toString(); -+ } -+ -+ public boolean isInheritClass() { -+ return this.inheritClass.isSelected(); -+ } -+ -+ public static void open(@NotNull Project project, PhpClass targetClass) { -+ OverrideClassByAPreferenceDialog dialog = new OverrideClassByAPreferenceDialog(project, targetClass); -+ dialog.pack(); -+ dialog.setVisible(true); -+ } -+ -+ private void createUIComponents() { -+ List allModulesList = ModuleIndex.getInstance(project).getEditableModuleNames(); -+ -+ this.preferenceModule = new FilteredComboBox(allModulesList); -+ } -+ -+ private String getNamespace() { -+ String targetModule = getPreferenceModule(); -+ String namespace = targetModule.replace(Package.VENDOR_MODULE_NAME_SEPARATOR, Package.FQN_SEPARATOR); -+ namespace = namespace.concat(Package.FQN_SEPARATOR); -+ return namespace.concat(getPreferenceDirectory().replace(File.separator, Package.FQN_SEPARATOR)); -+ } -+ -+ private String getPreferenceClassFqn() { -+ return getNamespace().concat(Package.FQN_SEPARATOR).concat(getPreferenceClassName()); -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/dialog/validator/CreateAPluginDialogValidator.java b/src/com/magento/idea/magento2plugin/actions/generation/dialog/validator/CreateAPluginDialogValidator.java -new file mode 100644 -index 0000000..bc70a8c ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/dialog/validator/CreateAPluginDialogValidator.java -@@ -0,0 +1,92 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation.dialog.validator; -+ -+import com.intellij.openapi.project.Project; -+import com.magento.idea.magento2plugin.actions.generation.dialog.CreateAPluginDialog; -+import com.magento.idea.magento2plugin.indexes.ModuleIndex; -+import com.magento.idea.magento2plugin.util.Regex; -+import javax.swing.*; -+import java.util.List; -+ -+public class CreateAPluginDialogValidator { -+ private static CreateAPluginDialogValidator INSTANCE = null; -+ private CreateAPluginDialog dialog; -+ -+ public static CreateAPluginDialogValidator getInstance(CreateAPluginDialog dialog) { -+ if (null == INSTANCE) { -+ INSTANCE = new CreateAPluginDialogValidator(); -+ } -+ INSTANCE.dialog = dialog; -+ return INSTANCE; -+ } -+ -+ public boolean validate(Project project) -+ { -+ String errorTitle = "Error"; -+ String pluginClassName = dialog.getPluginClassName(); -+ if (pluginClassName.length() == 0) { -+ JOptionPane.showMessageDialog(null, "Plugin Class Name must not be empty.", errorTitle, JOptionPane.ERROR_MESSAGE); -+ return false; -+ } -+ -+ if (!pluginClassName.matches(Regex.ALPHANUMERIC)) { -+ JOptionPane.showMessageDialog(null, "Plugin Class Name must contain letters and numbers only.", errorTitle, JOptionPane.ERROR_MESSAGE); -+ return false; -+ } -+ -+ if (!Character.isUpperCase(pluginClassName.charAt(0)) && !Character.isDigit(pluginClassName.charAt(0))) { -+ JOptionPane.showMessageDialog(null, "Plugin Class Name must start from a number or a capital letter", errorTitle, JOptionPane.ERROR_MESSAGE); -+ return false; -+ } -+ -+ String pluginDirectory = dialog.getPluginDirectory(); -+ if (pluginDirectory.length() == 0) { -+ JOptionPane.showMessageDialog(null, "Plugin Directory must not be empty.", errorTitle, JOptionPane.ERROR_MESSAGE); -+ return false; -+ } -+ -+ if (!pluginDirectory.matches(Regex.DIRECTORY)) { -+ JOptionPane.showMessageDialog(null, "Plugin Directory is not valid.", errorTitle, JOptionPane.ERROR_MESSAGE); -+ return false; -+ } -+ -+ String pluginName = dialog.getPluginName(); -+ if (pluginName.length() == 0) { -+ JOptionPane.showMessageDialog(null, "Plugin Name must not be empty.", errorTitle, JOptionPane.ERROR_MESSAGE); -+ return false; -+ } -+ -+ if (!pluginName.matches(Regex.IDENTIFIER)) { -+ JOptionPane.showMessageDialog(null, "Plugin Name must contain letters, numbers, dashes, and underscores only.", errorTitle, JOptionPane.ERROR_MESSAGE); -+ return false; -+ } -+ -+ String sortOrder = dialog.getPluginSortOrder(); -+ if (sortOrder.length() == 0) { -+ JOptionPane.showMessageDialog(null, "Sort Order must not be empty.", errorTitle, JOptionPane.ERROR_MESSAGE); -+ return false; -+ } -+ -+ if (!sortOrder.matches(Regex.NUMERIC)) { -+ JOptionPane.showMessageDialog(null, "Sort Order must contain numbers only.", errorTitle, JOptionPane.ERROR_MESSAGE); -+ return false; -+ } -+ -+ String pluginModule = dialog.getPluginModule(); -+ if (pluginModule.length() == 0) { -+ JOptionPane.showMessageDialog(null, "Plugin Module must not be empty.", errorTitle, JOptionPane.ERROR_MESSAGE); -+ return false; -+ } -+ -+ List allModulesList = ModuleIndex.getInstance(project).getEditableModuleNames(); -+ if (!allModulesList.contains(pluginModule)) { -+ JOptionPane.showMessageDialog(null, "No such module '".concat(pluginModule).concat("'."), errorTitle, JOptionPane.ERROR_MESSAGE); -+ return false; -+ } -+ -+ return true; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/dialog/validator/NewMagentoModuleDialogValidator.java b/src/com/magento/idea/magento2plugin/actions/generation/dialog/validator/NewMagentoModuleDialogValidator.java -new file mode 100644 -index 0000000..16d64a9 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/dialog/validator/NewMagentoModuleDialogValidator.java -@@ -0,0 +1,70 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation.dialog.validator; -+ -+import com.magento.idea.magento2plugin.actions.generation.dialog.NewMagentoModuleDialog; -+import com.magento.idea.magento2plugin.util.Regex; -+import javax.swing.*; -+ -+public class NewMagentoModuleDialogValidator { -+ private static NewMagentoModuleDialogValidator INSTANCE = null; -+ private NewMagentoModuleDialog dialog; -+ -+ public static NewMagentoModuleDialogValidator getInstance(NewMagentoModuleDialog dialog) { -+ if (null == INSTANCE) { -+ INSTANCE = new NewMagentoModuleDialogValidator(); -+ } -+ INSTANCE.dialog = dialog; -+ return INSTANCE; -+ } -+ -+ public boolean validate() -+ { -+ String errorTitle = "Error"; -+ String packageName = dialog.getPackageName(); -+ if (packageName.length() == 0) { -+ JOptionPane.showMessageDialog(null, "Package Name must not be empty.", errorTitle, JOptionPane.ERROR_MESSAGE); -+ return false; -+ } -+ -+ if (!packageName.matches(Regex.ALPHANUMERIC)) { -+ JOptionPane.showMessageDialog(null, "Package Name must contain letters and numbers only.", errorTitle, JOptionPane.ERROR_MESSAGE); -+ return false; -+ } -+ -+ if (!Character.isUpperCase(packageName.charAt(0)) && !Character.isDigit(packageName.charAt(0))) { -+ JOptionPane.showMessageDialog(null, "Package Name must start from a number or a capital letter", errorTitle, JOptionPane.ERROR_MESSAGE); -+ return false; -+ } -+ -+ String moduleName = dialog.getModuleName(); -+ if (moduleName.length() == 0) { -+ JOptionPane.showMessageDialog(null, "Module Name must not be empty.", errorTitle, JOptionPane.ERROR_MESSAGE); -+ return false; -+ } -+ -+ if (!moduleName.matches(Regex.ALPHANUMERIC)) { -+ JOptionPane.showMessageDialog(null, "Module Name must contain letters and numbers only.", errorTitle, JOptionPane.ERROR_MESSAGE); -+ return false; -+ } -+ -+ if (!Character.isUpperCase(moduleName.charAt(0)) && !Character.isDigit(moduleName.charAt(0))) { -+ JOptionPane.showMessageDialog(null, "Module Name must start from a number or a capital letter", errorTitle, JOptionPane.ERROR_MESSAGE); -+ return false; -+ } -+ -+ if (dialog.getModuleVersion().length() == 0) { -+ JOptionPane.showMessageDialog(null, "Module Version must not be empty.", errorTitle, JOptionPane.ERROR_MESSAGE); -+ return false; -+ } -+ -+ if (dialog.getModuleDescription().length() == 0) { -+ JOptionPane.showMessageDialog(null, "Module Version must not be empty.", errorTitle, JOptionPane.ERROR_MESSAGE); -+ return false; -+ } -+ -+ return true; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/dialog/validator/OverrideClassByAPreferenceDialogValidator.java b/src/com/magento/idea/magento2plugin/actions/generation/dialog/validator/OverrideClassByAPreferenceDialogValidator.java -new file mode 100644 -index 0000000..1d3a2f9 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/dialog/validator/OverrideClassByAPreferenceDialogValidator.java -@@ -0,0 +1,70 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation.dialog.validator; -+ -+import com.intellij.openapi.project.Project; -+import com.magento.idea.magento2plugin.actions.generation.dialog.OverrideClassByAPreferenceDialog; -+import com.magento.idea.magento2plugin.indexes.ModuleIndex; -+import com.magento.idea.magento2plugin.util.Regex; -+import javax.swing.*; -+import java.util.List; -+ -+public class OverrideClassByAPreferenceDialogValidator { -+ private static OverrideClassByAPreferenceDialogValidator INSTANCE = null; -+ private OverrideClassByAPreferenceDialog dialog; -+ -+ public static OverrideClassByAPreferenceDialogValidator getInstance(OverrideClassByAPreferenceDialog dialog) { -+ if (null == INSTANCE) { -+ INSTANCE = new OverrideClassByAPreferenceDialogValidator(); -+ } -+ INSTANCE.dialog = dialog; -+ return INSTANCE; -+ } -+ -+ public boolean validate(Project project) -+ { -+ String errorTitle = "Error"; -+ String preferenceClassName = dialog.getPreferenceClassName(); -+ if (preferenceClassName.length() == 0) { -+ JOptionPane.showMessageDialog(null, "Preference Class Name must not be empty.", errorTitle, JOptionPane.ERROR_MESSAGE); -+ return false; -+ } -+ -+ if (!preferenceClassName.matches(Regex.ALPHANUMERIC)) { -+ JOptionPane.showMessageDialog(null, "Preference Class Name must contain letters and numbers only.", errorTitle, JOptionPane.ERROR_MESSAGE); -+ return false; -+ } -+ -+ if (!Character.isUpperCase(preferenceClassName.charAt(0)) && !Character.isDigit(preferenceClassName.charAt(0))) { -+ JOptionPane.showMessageDialog(null, "Preference Class Name must start from a number or a capital letter", errorTitle, JOptionPane.ERROR_MESSAGE); -+ return false; -+ } -+ -+ String preferenceDirectory = dialog.getPreferenceDirectory(); -+ if (preferenceDirectory.length() == 0) { -+ JOptionPane.showMessageDialog(null, "Preference Directory must not be empty.", errorTitle, JOptionPane.ERROR_MESSAGE); -+ return false; -+ } -+ -+ if (!preferenceDirectory.matches(Regex.DIRECTORY)) { -+ JOptionPane.showMessageDialog(null, "Preference Directory is not valid.", errorTitle, JOptionPane.ERROR_MESSAGE); -+ return false; -+ } -+ -+ String preferenceModule = dialog.getPreferenceModule(); -+ if (preferenceModule.length() == 0) { -+ JOptionPane.showMessageDialog(null, "Preference Module must not be empty.", errorTitle, JOptionPane.ERROR_MESSAGE); -+ return false; -+ } -+ -+ List allModulesList = ModuleIndex.getInstance(project).getEditableModuleNames(); -+ if (!allModulesList.contains(preferenceModule)) { -+ JOptionPane.showMessageDialog(null, "No such module '".concat(preferenceModule).concat("'."), errorTitle, JOptionPane.ERROR_MESSAGE); -+ return false; -+ } -+ -+ return true; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/generator/FileGenerator.java b/src/com/magento/idea/magento2plugin/actions/generation/generator/FileGenerator.java -new file mode 100644 -index 0000000..eea7758 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/generator/FileGenerator.java -@@ -0,0 +1,39 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation.generator; -+ -+import com.intellij.openapi.project.Project; -+import com.intellij.psi.PsiFile; -+import com.magento.idea.magento2plugin.actions.generation.util.NavigateToCreatedFile; -+import java.util.Properties; -+ -+public abstract class FileGenerator { -+ private final Project project; -+ private final NavigateToCreatedFile navigateToCreatedFile; -+ -+ public FileGenerator(Project project) -+ { -+ this.project = project; -+ this.navigateToCreatedFile = NavigateToCreatedFile.getInstance(); -+ } -+ -+ public abstract PsiFile generate(String actionName); -+ -+ public PsiFile generate(String actionName, boolean openFile) { -+ PsiFile file = this.generate(actionName); -+ if (file != null) { -+ navigateToCreatedFile.navigate(project, file); -+ } -+ return file; -+ } -+ -+ protected Properties getAttributes() { -+ Properties attributes = new Properties(); -+ this.fillAttributes(attributes); -+ return attributes; -+ } -+ -+ protected abstract void fillAttributes(Properties attributes); -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/generator/ModuleComposerJsonGenerator.java b/src/com/magento/idea/magento2plugin/actions/generation/generator/ModuleComposerJsonGenerator.java -new file mode 100644 -index 0000000..34d1fbe ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/generator/ModuleComposerJsonGenerator.java -@@ -0,0 +1,42 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation.generator; -+ -+import com.intellij.openapi.project.Project; -+import com.intellij.psi.PsiFile; -+import com.magento.idea.magento2plugin.actions.generation.data.ModuleComposerJsonData; -+import com.magento.idea.magento2plugin.actions.generation.generator.data.ModuleDirectoriesData; -+import com.magento.idea.magento2plugin.actions.generation.generator.util.DirectoryGenerator; -+import com.magento.idea.magento2plugin.actions.generation.generator.util.FileFromTemplateGenerator; -+import com.magento.idea.magento2plugin.magento.files.ComposerJson; -+import org.jetbrains.annotations.NotNull; -+import java.util.Properties; -+ -+public class ModuleComposerJsonGenerator extends FileGenerator { -+ -+ private final ModuleComposerJsonData moduleComposerJsonData; -+ private final FileFromTemplateGenerator fileFromTemplateGenerator; -+ private final DirectoryGenerator directoryGenerator; -+ -+ public ModuleComposerJsonGenerator(@NotNull ModuleComposerJsonData moduleComposerJsonData, Project project) { -+ super(project); -+ this.moduleComposerJsonData = moduleComposerJsonData; -+ this.fileFromTemplateGenerator = FileFromTemplateGenerator.getInstance(project); -+ this.directoryGenerator = DirectoryGenerator.getInstance(); -+ } -+ -+ public PsiFile generate(String actionName) { -+ ModuleDirectoriesData moduleDirectoriesData = directoryGenerator.createOrFindModuleDirectories(moduleComposerJsonData.getPackageName(), moduleComposerJsonData.getModuleName(), moduleComposerJsonData.getBaseDir()); -+ return fileFromTemplateGenerator.generate(ComposerJson.getInstance(), getAttributes(), moduleDirectoriesData.getModuleDirectory(), actionName); -+ } -+ -+ protected void fillAttributes(Properties attributes) { -+ attributes.setProperty("PACKAGE", moduleComposerJsonData.getPackageName()); -+ attributes.setProperty("MODULE_NAME", moduleComposerJsonData.getModuleName()); -+ attributes.setProperty("MODULE_DESCRIPTION", moduleComposerJsonData.getModuleDescription()); -+ attributes.setProperty("COMPOSER_PACKAGE_NAME", moduleComposerJsonData.getComposerPackageName()); -+ attributes.setProperty("MODULE_VERSION", moduleComposerJsonData.getModuleVersion()); -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/generator/ModuleRegistrationPhpGenerator.java b/src/com/magento/idea/magento2plugin/actions/generation/generator/ModuleRegistrationPhpGenerator.java -new file mode 100644 -index 0000000..18fa5cc ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/generator/ModuleRegistrationPhpGenerator.java -@@ -0,0 +1,39 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation.generator; -+ -+import com.intellij.openapi.project.Project; -+import com.intellij.psi.PsiFile; -+import com.magento.idea.magento2plugin.actions.generation.data.ModuleRegistrationPhpData; -+import com.magento.idea.magento2plugin.actions.generation.generator.data.ModuleDirectoriesData; -+import com.magento.idea.magento2plugin.actions.generation.generator.util.DirectoryGenerator; -+import com.magento.idea.magento2plugin.actions.generation.generator.util.FileFromTemplateGenerator; -+import com.magento.idea.magento2plugin.magento.files.RegistrationPhp; -+import org.jetbrains.annotations.NotNull; -+import java.util.Properties; -+ -+public class ModuleRegistrationPhpGenerator extends FileGenerator { -+ -+ private final ModuleRegistrationPhpData moduleRegistrationPhpData; -+ private final FileFromTemplateGenerator fileFromTemplateGenerator; -+ private final DirectoryGenerator directoryGenerator; -+ -+ public ModuleRegistrationPhpGenerator(@NotNull ModuleRegistrationPhpData moduleRegistrationPhpData, Project project) { -+ super(project); -+ this.moduleRegistrationPhpData = moduleRegistrationPhpData; -+ this.fileFromTemplateGenerator = FileFromTemplateGenerator.getInstance(project); -+ this.directoryGenerator = DirectoryGenerator.getInstance(); -+ } -+ -+ public PsiFile generate(String actionName) { -+ ModuleDirectoriesData moduleDirectoriesData = directoryGenerator.createOrFindModuleDirectories(moduleRegistrationPhpData.getPackageName(), moduleRegistrationPhpData.getModuleName(), moduleRegistrationPhpData.getBaseDir()); -+ return fileFromTemplateGenerator.generate(RegistrationPhp.getInstance(), getAttributes(), moduleDirectoriesData.getModuleDirectory(), actionName); -+ } -+ -+ protected void fillAttributes(Properties attributes) { -+ attributes.setProperty("PACKAGE", moduleRegistrationPhpData.getPackageName()); -+ attributes.setProperty("MODULE_NAME", moduleRegistrationPhpData.getModuleName()); -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/generator/ModuleXmlGenerator.java b/src/com/magento/idea/magento2plugin/actions/generation/generator/ModuleXmlGenerator.java -new file mode 100644 -index 0000000..ba5f039 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/generator/ModuleXmlGenerator.java -@@ -0,0 +1,40 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation.generator; -+ -+import com.intellij.openapi.project.Project; -+import com.intellij.psi.PsiFile; -+import com.magento.idea.magento2plugin.actions.generation.data.ModuleXmlData; -+import com.magento.idea.magento2plugin.actions.generation.generator.data.ModuleDirectoriesData; -+import com.magento.idea.magento2plugin.actions.generation.generator.util.DirectoryGenerator; -+import com.magento.idea.magento2plugin.actions.generation.generator.util.FileFromTemplateGenerator; -+import com.magento.idea.magento2plugin.magento.files.ModuleXml; -+import org.jetbrains.annotations.NotNull; -+import java.util.Properties; -+ -+public class ModuleXmlGenerator extends FileGenerator { -+ -+ private final ModuleXmlData moduleXmlData; -+ private final FileFromTemplateGenerator fileFromTemplateGenerator; -+ private final DirectoryGenerator directoryGenerator; -+ -+ public ModuleXmlGenerator(@NotNull ModuleXmlData moduleXmlData, Project project) { -+ super(project); -+ this.moduleXmlData = moduleXmlData; -+ this.fileFromTemplateGenerator = FileFromTemplateGenerator.getInstance(project); -+ this.directoryGenerator = DirectoryGenerator.getInstance(); -+ } -+ -+ @Override -+ public PsiFile generate(String actionName) { -+ ModuleDirectoriesData moduleDirectoriesData = directoryGenerator.createOrFindModuleDirectories(moduleXmlData.getPackageName(), moduleXmlData.getModuleName(), moduleXmlData.getBaseDir()); -+ return fileFromTemplateGenerator.generate(ModuleXml.getInstance(), getAttributes(), moduleDirectoriesData.getModuleEtcDirectory(), actionName); -+ } -+ -+ protected void fillAttributes(Properties attributes) { -+ attributes.setProperty("PACKAGE", moduleXmlData.getPackageName()); -+ attributes.setProperty("MODULE_NAME", moduleXmlData.getModuleName()); -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/generator/PluginClassGenerator.java b/src/com/magento/idea/magento2plugin/actions/generation/generator/PluginClassGenerator.java -new file mode 100644 -index 0000000..46fca0c ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/generator/PluginClassGenerator.java -@@ -0,0 +1,174 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation.generator; -+ -+import com.intellij.openapi.command.WriteCommandAction; -+import com.intellij.openapi.editor.Document; -+import com.intellij.openapi.project.Project; -+import com.intellij.openapi.util.Key; -+import com.intellij.psi.PsiDirectory; -+import com.intellij.psi.PsiDocumentManager; -+import com.intellij.psi.PsiElement; -+import com.intellij.psi.PsiFile; -+import com.intellij.psi.codeStyle.CodeStyleManager; -+import com.intellij.psi.impl.source.tree.LeafPsiElement; -+import com.intellij.psi.util.PsiTreeUtil; -+import com.jetbrains.php.codeInsight.PhpCodeInsightUtil; -+import com.jetbrains.php.lang.psi.PhpFile; -+import com.jetbrains.php.lang.psi.elements.Method; -+import com.jetbrains.php.lang.psi.elements.PhpClass; -+import com.jetbrains.php.lang.psi.elements.PhpPsiElement; -+import com.magento.idea.magento2plugin.actions.generation.ImportReferences.PhpClassReferenceResolver; -+import com.magento.idea.magento2plugin.actions.generation.data.PluginFileData; -+import com.magento.idea.magento2plugin.actions.generation.data.code.PluginMethodData; -+import com.magento.idea.magento2plugin.actions.generation.generator.code.PluginMethodsGenerator; -+import com.magento.idea.magento2plugin.actions.generation.generator.util.DirectoryGenerator; -+import com.magento.idea.magento2plugin.actions.generation.generator.util.FileFromTemplateGenerator; -+import com.magento.idea.magento2plugin.actions.generation.util.CodeStyleSettings; -+import com.magento.idea.magento2plugin.actions.generation.util.CollectInsertedMethods; -+import com.magento.idea.magento2plugin.actions.generation.util.FillTextBufferWithPluginMethods; -+import com.magento.idea.magento2plugin.indexes.ModuleIndex; -+import com.magento.idea.magento2plugin.magento.files.Plugin; -+import com.magento.idea.magento2plugin.magento.packages.MagentoPhpClass; -+import com.magento.idea.magento2plugin.util.GetFirstClassOfFile; -+import com.magento.idea.magento2plugin.util.GetPhpClassByFQN; -+import gnu.trove.THashSet; -+import org.jetbrains.annotations.NotNull; -+import javax.swing.*; -+import java.io.File; -+import java.util.Collection; -+import java.util.List; -+import java.util.Properties; -+import java.util.Set; -+ -+public class PluginClassGenerator extends FileGenerator { -+ private PluginFileData pluginFileData; -+ private Project project; -+ private final FillTextBufferWithPluginMethods fillTextBuffer; -+ private final CollectInsertedMethods collectInsertedMethods; -+ private final DirectoryGenerator directoryGenerator; -+ private final FileFromTemplateGenerator fileFromTemplateGenerator; -+ private final GetFirstClassOfFile getFirstClassOfFile; -+ -+ public PluginClassGenerator(@NotNull PluginFileData pluginFileData, Project project) { -+ super(project); -+ this.directoryGenerator = DirectoryGenerator.getInstance(); -+ this.fileFromTemplateGenerator = FileFromTemplateGenerator.getInstance(project); -+ this.getFirstClassOfFile = GetFirstClassOfFile.getInstance(); -+ this.fillTextBuffer = FillTextBufferWithPluginMethods.getInstance(); -+ this.collectInsertedMethods = CollectInsertedMethods.getInstance(); -+ this.pluginFileData = pluginFileData; -+ this.project = project; -+ } -+ -+ public PsiFile generate(String actionName) -+ { -+ final PsiFile[] pluginFile = {null}; -+ WriteCommandAction.runWriteCommandAction(project, () -> { -+ PhpClass pluginClass = GetPhpClassByFQN.getInstance(project).execute(pluginFileData.getPluginFqn()); -+ if (pluginClass == null) { -+ pluginClass = createPluginClass(actionName); -+ } -+ if (pluginClass == null) { -+ JOptionPane.showMessageDialog(null, "Plugin Class cant be created!", "Error", JOptionPane.ERROR_MESSAGE); -+ return; -+ } -+ -+ Key targetClassKey = Key.create(PluginMethodsGenerator.originalTargetKey); -+ Method targetMethod = pluginFileData.getTargetMethod(); -+ targetMethod.putUserData(targetClassKey, pluginFileData.getTargetClass()); -+ PluginMethodsGenerator pluginGenerator = new PluginMethodsGenerator(pluginClass, targetMethod, targetClassKey); -+ -+ PluginMethodData[] pluginMethodData = pluginGenerator.createPluginMethods(getPluginType()); -+ if (checkIfMethodExist(pluginClass, pluginMethodData)){ -+ JOptionPane.showMessageDialog(null, "Plugin method already exist!", "Error", JOptionPane.ERROR_MESSAGE); -+ return; -+ } -+ -+ Set insertedMethodsNames = new THashSet(); -+ PhpClassReferenceResolver resolver = new PhpClassReferenceResolver(); -+ StringBuffer textBuf = new StringBuffer(); -+ -+ fillTextBuffer.execute(targetClassKey, insertedMethodsNames, resolver, textBuf, pluginMethodData); -+ -+ pluginFile[0] = pluginClass.getContainingFile(); -+ CodeStyleSettings codeStyleSettings = new CodeStyleSettings((PhpFile) pluginFile[0]); -+ codeStyleSettings.adjustBeforeWrite(); -+ -+ int insertPos = getInsertPos(pluginClass); -+ PhpPsiElement scope = PhpCodeInsightUtil.findScopeForUseOperator(pluginClass); -+ -+ if (textBuf.length() > 0 && insertPos >= 0) { -+ PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(project); -+ Document document = psiDocumentManager.getDocument(pluginFile[0]); -+ document.insertString(insertPos, textBuf); -+ int endPos = insertPos + textBuf.length() + 1; -+ CodeStyleManager.getInstance(project).reformatText(pluginFile[0], insertPos, endPos); -+ psiDocumentManager.commitDocument(document); -+ } -+ if (!insertedMethodsNames.isEmpty()) { -+ List insertedMethods = collectInsertedMethods.execute(pluginFile[0], pluginClass.getNameCS(), insertedMethodsNames); -+ if (scope != null && insertedMethods != null) { -+ resolver.importReferences(scope, insertedMethods); -+ } -+ } -+ codeStyleSettings.restore(); -+ }); -+ return pluginFile[0]; -+ } -+ -+ private boolean checkIfMethodExist(PhpClass pluginClass, PluginMethodData[] pluginMethodData) { -+ Collection currentPluginMethods = pluginClass.getMethods(); -+ for (Method currentPluginMethod: currentPluginMethods) { -+ for (PluginMethodData pluginMethod: pluginMethodData) { -+ if (!pluginMethod.getMethod().getName().equals(currentPluginMethod.getName())){ -+ continue; -+ } -+ return true; -+ } -+ } -+ return false; -+ } -+ -+ private PhpClass createPluginClass(String actionName) { -+ PsiDirectory parentDirectory = ModuleIndex.getInstance(project).getModuleDirectoryByModuleName(getPluginModule()); -+ String[] pluginDirectories = pluginFileData.getPluginDirectory().split(File.separator); -+ for (String pluginDirectory: pluginDirectories) { -+ parentDirectory = directoryGenerator.findOrCreateSubdirectory(parentDirectory, pluginDirectory); -+ } -+ -+ Properties attributes = getAttributes(); -+ PsiFile pluginFile = fileFromTemplateGenerator.generate(Plugin.getInstance(pluginFileData.getPluginClassName()), attributes, parentDirectory, actionName); -+ if (pluginFile == null) { -+ return null; -+ } -+ return getFirstClassOfFile.execute((PhpFile) pluginFile); -+ } -+ -+ protected void fillAttributes(Properties attributes) { -+ attributes.setProperty("NAME", pluginFileData.getPluginClassName()); -+ attributes.setProperty("NAMESPACE", pluginFileData.getNamespace()); -+ } -+ -+ public Plugin.PluginType getPluginType() { -+ return Plugin.getPluginTypeByString(pluginFileData.getPluginType()); -+ } -+ -+ public String getPluginModule() { -+ return pluginFileData.getPluginModule(); -+ } -+ -+ private int getInsertPos(PhpClass pluginClass) { -+ int insertPos = -1; -+ LeafPsiElement[] leafElements = PsiTreeUtil.getChildrenOfType(pluginClass, LeafPsiElement.class); -+ for (LeafPsiElement leafPsiElement: leafElements) { -+ if (!leafPsiElement.getText().equals(MagentoPhpClass.CLOSING_TAG)) { -+ continue; -+ } -+ insertPos = leafPsiElement.getTextOffset(); -+ } -+ return insertPos; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/generator/PluginDiXmlGenerator.java b/src/com/magento/idea/magento2plugin/actions/generation/generator/PluginDiXmlGenerator.java -new file mode 100644 -index 0000000..25d68fb ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/generator/PluginDiXmlGenerator.java -@@ -0,0 +1,128 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation.generator; -+ -+import com.intellij.openapi.command.WriteCommandAction; -+import com.intellij.openapi.editor.Document; -+import com.intellij.openapi.project.Project; -+import com.intellij.psi.PsiDocumentManager; -+import com.intellij.psi.PsiFile; -+import com.intellij.psi.codeStyle.CodeStyleManager; -+import com.intellij.psi.util.PsiTreeUtil; -+import com.intellij.psi.xml.*; -+import com.jetbrains.php.lang.PhpLangUtil; -+import com.magento.idea.magento2plugin.actions.generation.data.PluginDiXmlData; -+import com.magento.idea.magento2plugin.actions.generation.generator.util.FindOrCreateDiXml; -+import com.magento.idea.magento2plugin.actions.generation.generator.util.GetCodeTemplate; -+import com.magento.idea.magento2plugin.actions.generation.generator.util.XmlFilePositionUtil; -+import com.magento.idea.magento2plugin.magento.files.ModuleDiXml; -+import com.magento.idea.magento2plugin.xml.XmlPsiTreeUtil; -+import org.jetbrains.annotations.NotNull; -+import java.io.IOException; -+import java.util.*; -+ -+public class PluginDiXmlGenerator extends FileGenerator { -+ private final GetCodeTemplate getCodeTemplate; -+ private final FindOrCreateDiXml findOrCreateDiXml; -+ private final XmlFilePositionUtil positionUtil; -+ private PluginDiXmlData pluginFileData; -+ private Project project; -+ private boolean isTypeDeclared; -+ -+ public PluginDiXmlGenerator(@NotNull PluginDiXmlData pluginFileData, Project project) { -+ super(project); -+ this.pluginFileData = pluginFileData; -+ this.project = project; -+ this.getCodeTemplate = GetCodeTemplate.getInstance(project); -+ this.findOrCreateDiXml = FindOrCreateDiXml.getInstance(project); -+ this.positionUtil = XmlFilePositionUtil.getInstance(); -+ } -+ -+ public PsiFile generate(String actionName) -+ { -+ PsiFile diXmlFile = findOrCreateDiXml.execute(actionName, pluginFileData.getPluginModule(), pluginFileData.getArea()); -+ XmlAttributeValue typeAttributeValue = getTypeAttributeValue((XmlFile) diXmlFile); -+ boolean isPluginDeclared = false; -+ this.isTypeDeclared = false; -+ if (typeAttributeValue != null) { -+ this.isTypeDeclared = true; -+ isPluginDeclared = isPluginDeclared(typeAttributeValue); -+ } -+ if (isPluginDeclared) { -+ return null; -+ } -+ WriteCommandAction.runWriteCommandAction(project, () -> { -+ StringBuffer textBuf = new StringBuffer(); -+ try { -+ textBuf.append(getCodeTemplate.execute(ModuleDiXml.TEMPLATE_PLUGIN, getAttributes())); -+ } catch (IOException e) { -+ e.printStackTrace(); -+ return; -+ } -+ -+ int insertPos = isTypeDeclared -+ ? positionUtil.getEndPositionOfTag(PsiTreeUtil.getParentOfType(typeAttributeValue, XmlTag.class)) -+ : positionUtil.getRootInsertPosition((XmlFile) diXmlFile); -+ if (textBuf.length() > 0 && insertPos >= 0) { -+ PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(project); -+ Document document = psiDocumentManager.getDocument(diXmlFile); -+ document.insertString(insertPos, textBuf); -+ int endPos = insertPos + textBuf.length() + 1; -+ CodeStyleManager.getInstance(project).reformatText(diXmlFile, insertPos, endPos); -+ psiDocumentManager.commitDocument(document); -+ } -+ }); -+ -+ return diXmlFile; -+ } -+ -+ private boolean isPluginDeclared(XmlAttributeValue typeAttributeValue) { -+ XmlTag xmlTag = PsiTreeUtil.getParentOfType(typeAttributeValue, XmlTag.class); -+ XmlTag[] xmlTags = PsiTreeUtil.getChildrenOfType(xmlTag, XmlTag.class); -+ if (xmlTags == null) { -+ return false; -+ } -+ for (XmlTag child: xmlTags) { -+ if (!child.getName().equals(ModuleDiXml.PLUGIN_TAG_NAME)) { -+ continue; -+ } -+ XmlAttribute[] xmlAttributes = PsiTreeUtil.getChildrenOfType(child, XmlAttribute.class); -+ for (XmlAttribute xmlAttribute: xmlAttributes) { -+ if (!xmlAttribute.getName().equals(ModuleDiXml.PLUGIN_TYPE_ATTRIBUTE)) { -+ continue; -+ } -+ String declaredClass = PhpLangUtil.toPresentableFQN(xmlAttribute.getValue()); -+ if (declaredClass.equals(pluginFileData.getPluginFqn())) { -+ return true; -+ } -+ } -+ } -+ -+ return false; -+ } -+ -+ private XmlAttributeValue getTypeAttributeValue(XmlFile diXml) { -+ Collection pluginTypes = XmlPsiTreeUtil.findAttributeValueElements(diXml, ModuleDiXml.PLUGIN_TYPE_TAG, ModuleDiXml.PLUGIN_TYPE_ATTR_NAME); -+ String pluginClassFqn = pluginFileData.getTargetClass().getPresentableFQN(); -+ for (XmlAttributeValue pluginType: pluginTypes) { -+ if (!PhpLangUtil.toPresentableFQN(pluginType.getValue()).equals(pluginClassFqn)) { -+ continue; -+ } -+ return pluginType; -+ } -+ -+ return null; -+ } -+ -+ protected void fillAttributes(Properties attributes) { -+ if (!isTypeDeclared) { -+ attributes.setProperty("TYPE", pluginFileData.getTargetClass().getPresentableFQN()); -+ } -+ attributes.setProperty("NAME", pluginFileData.getPluginName()); -+ attributes.setProperty("PLUGIN_TYPE", pluginFileData.getPluginFqn()); -+ attributes.setProperty("PLUGIN_NAME", pluginFileData.getPluginName()); -+ attributes.setProperty("SORT_ORDER", pluginFileData.getSortOrder()); -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/generator/PreferenceClassGenerator.java b/src/com/magento/idea/magento2plugin/actions/generation/generator/PreferenceClassGenerator.java -new file mode 100644 -index 0000000..fb5893c ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/generator/PreferenceClassGenerator.java -@@ -0,0 +1,87 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation.generator; -+ -+import com.intellij.openapi.project.Project; -+import com.intellij.psi.PsiDirectory; -+import com.intellij.psi.PsiFile; -+import com.jetbrains.php.lang.psi.PhpFile; -+import com.jetbrains.php.lang.psi.elements.PhpClass; -+import com.magento.idea.magento2plugin.actions.generation.data.PreferenceFileData; -+import com.magento.idea.magento2plugin.actions.generation.generator.util.DirectoryGenerator; -+import com.magento.idea.magento2plugin.actions.generation.generator.util.FileFromTemplateGenerator; -+import com.magento.idea.magento2plugin.indexes.ModuleIndex; -+import com.magento.idea.magento2plugin.magento.files.PhpPreference; -+import com.magento.idea.magento2plugin.util.GetFirstClassOfFile; -+import com.magento.idea.magento2plugin.util.GetPhpClassByFQN; -+import org.jetbrains.annotations.NotNull; -+import javax.swing.*; -+import java.io.File; -+import java.util.Properties; -+ -+public class PreferenceClassGenerator extends FileGenerator { -+ private PreferenceFileData preferenceFileData; -+ private Project project; -+ private final DirectoryGenerator directoryGenerator; -+ private final FileFromTemplateGenerator fileFromTemplateGenerator; -+ private final GetFirstClassOfFile getFirstClassOfFile; -+ -+ public PreferenceClassGenerator(@NotNull PreferenceFileData preferenceFileData, Project project) { -+ super(project); -+ this.directoryGenerator = DirectoryGenerator.getInstance(); -+ this.fileFromTemplateGenerator = FileFromTemplateGenerator.getInstance(project); -+ this.getFirstClassOfFile = GetFirstClassOfFile.getInstance(); -+ this.preferenceFileData = preferenceFileData; -+ this.project = project; -+ } -+ -+ public PsiFile generate(String actionName) { -+ PhpClass pluginClass = GetPhpClassByFQN.getInstance(project).execute(preferenceFileData.getPreferenceFqn()); -+ if (pluginClass == null) { -+ pluginClass = createPluginClass(actionName); -+ } -+ if (pluginClass == null) { -+ JOptionPane.showMessageDialog(null, "Preference Class cant be created!", "Error", JOptionPane.ERROR_MESSAGE); -+ return null; -+ } -+ -+ return pluginClass.getContainingFile(); -+ } -+ -+ private PhpClass createPluginClass(String actionName) { -+ PsiDirectory parentDirectory = ModuleIndex.getInstance(project).getModuleDirectoryByModuleName(getPreferenceModule()); -+ String[] pluginDirectories = preferenceFileData.getPreferenceDirectory().split(File.separator); -+ for (String pluginDirectory: pluginDirectories) { -+ parentDirectory = directoryGenerator.findOrCreateSubdirectory(parentDirectory, pluginDirectory); -+ } -+ -+ Properties attributes = getAttributes(); -+ PsiFile pluginFile = fileFromTemplateGenerator.generate(PhpPreference.getInstance(preferenceFileData.getPreferenceClassName()), attributes, parentDirectory, actionName); -+ if (pluginFile == null) { -+ return null; -+ } -+ return getFirstClassOfFile.execute((PhpFile) pluginFile); -+ } -+ -+ protected void fillAttributes(Properties attributes) { -+ String preferenceClassName = preferenceFileData.getPreferenceClassName(); -+ attributes.setProperty("NAME", preferenceFileData.getPreferenceClassName()); -+ attributes.setProperty("NAMESPACE", preferenceFileData.getNamespace()); -+ if (!preferenceFileData.isInheritClass()) { -+ return; -+ } -+ String parentClassName = preferenceFileData.getTargetClass().getName(); -+ if (!parentClassName.equals(preferenceClassName)) { -+ attributes.setProperty("USE", preferenceFileData.getTargetClass().getPresentableFQN()); -+ attributes.setProperty("EXTENDS", parentClassName); -+ return; -+ } -+ attributes.setProperty("EXTENDS", preferenceFileData.getTargetClass().getFQN()); -+ } -+ -+ public String getPreferenceModule() { -+ return preferenceFileData.getPreferenceModule(); -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/generator/PreferenceDiXmlGenerator.java b/src/com/magento/idea/magento2plugin/actions/generation/generator/PreferenceDiXmlGenerator.java -new file mode 100644 -index 0000000..addf516 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/generator/PreferenceDiXmlGenerator.java -@@ -0,0 +1,89 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation.generator; -+ -+import com.intellij.openapi.command.WriteCommandAction; -+import com.intellij.openapi.editor.Document; -+import com.intellij.openapi.project.Project; -+import com.intellij.psi.PsiDocumentManager; -+import com.intellij.psi.PsiFile; -+import com.intellij.psi.codeStyle.CodeStyleManager; -+import com.intellij.psi.xml.*; -+import com.jetbrains.php.lang.PhpLangUtil; -+import com.magento.idea.magento2plugin.actions.generation.data.PreferenceDiXmFileData; -+import com.magento.idea.magento2plugin.actions.generation.generator.util.FindOrCreateDiXml; -+import com.magento.idea.magento2plugin.actions.generation.generator.util.GetCodeTemplate; -+import com.magento.idea.magento2plugin.actions.generation.generator.util.XmlFilePositionUtil; -+import com.magento.idea.magento2plugin.magento.files.ModuleDiXml; -+import com.magento.idea.magento2plugin.xml.XmlPsiTreeUtil; -+import org.jetbrains.annotations.NotNull; -+import java.io.IOException; -+import java.util.Collection; -+import java.util.Properties; -+ -+public class PreferenceDiXmlGenerator extends FileGenerator { -+ private final GetCodeTemplate getCodeTemplate; -+ private final FindOrCreateDiXml findOrCreateDiXml; -+ private final XmlFilePositionUtil positionUtil; -+ private PreferenceDiXmFileData preferenceDiXmFileData; -+ private Project project; -+ -+ public PreferenceDiXmlGenerator(@NotNull PreferenceDiXmFileData preferenceDiXmFileData, Project project) { -+ super(project); -+ this.preferenceDiXmFileData = preferenceDiXmFileData; -+ this.project = project; -+ this.getCodeTemplate = GetCodeTemplate.getInstance(project); -+ this.findOrCreateDiXml = FindOrCreateDiXml.getInstance(project); -+ this.positionUtil = XmlFilePositionUtil.getInstance(); -+ } -+ -+ public PsiFile generate(String actionName) -+ { -+ PsiFile diXmlFile = findOrCreateDiXml.execute(actionName, preferenceDiXmFileData.getPreferenceModule(), preferenceDiXmFileData.getArea()); -+ boolean isPreferenceDeclared = getTypeAttributeValue((XmlFile) diXmlFile); -+ if (isPreferenceDeclared) { -+ return null; -+ } -+ WriteCommandAction.runWriteCommandAction(project, () -> { -+ StringBuffer textBuf = new StringBuffer(); -+ try { -+ textBuf.append(getCodeTemplate.execute(ModuleDiXml.TEMPLATE_PREFERENCE, getAttributes())); -+ } catch (IOException e) { -+ e.printStackTrace(); -+ return; -+ } -+ -+ int insertPos = positionUtil.getRootInsertPosition((XmlFile) diXmlFile); -+ if (textBuf.length() > 0 && insertPos >= 0) { -+ PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(project); -+ Document document = psiDocumentManager.getDocument(diXmlFile); -+ document.insertString(insertPos, textBuf); -+ int endPos = insertPos + textBuf.length() + 1; -+ CodeStyleManager.getInstance(project).reformatText(diXmlFile, insertPos, endPos); -+ psiDocumentManager.commitDocument(document); -+ } -+ }); -+ -+ return diXmlFile; -+ } -+ -+ private boolean getTypeAttributeValue(XmlFile diXml) { -+ Collection preferences = XmlPsiTreeUtil.findAttributeValueElements(diXml, ModuleDiXml.PREFERENCE_TAG_NAME, ModuleDiXml.PREFERENCE_ATTR_FOR); -+ String pluginClassFqn = preferenceDiXmFileData.getTargetClass().getPresentableFQN(); -+ for (XmlAttributeValue preference: preferences) { -+ if (!PhpLangUtil.toPresentableFQN(preference.getValue()).equals(pluginClassFqn)) { -+ continue; -+ } -+ return true; -+ } -+ -+ return false; -+ } -+ -+ protected void fillAttributes(Properties attributes) { -+ attributes.setProperty("FOR", preferenceDiXmFileData.getTargetClass().getPresentableFQN()); -+ attributes.setProperty("TYPE", preferenceDiXmFileData.getPreferenceFqn()); -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/generator/code/PluginMethodsGenerator.java b/src/com/magento/idea/magento2plugin/actions/generation/generator/code/PluginMethodsGenerator.java -new file mode 100644 -index 0000000..59d6ff2 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/generator/code/PluginMethodsGenerator.java -@@ -0,0 +1,317 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation.generator.code; -+ -+import com.intellij.openapi.project.Project; -+import com.intellij.openapi.util.Key; -+import com.intellij.openapi.util.text.StringUtil; -+import com.intellij.psi.PsiElement; -+import com.jetbrains.php.codeInsight.PhpCodeInsightUtil; -+import com.jetbrains.php.config.PhpLanguageFeature; -+import com.jetbrains.php.lang.PhpCodeUtil; -+import com.jetbrains.php.lang.documentation.phpdoc.PhpDocUtil; -+import com.jetbrains.php.lang.documentation.phpdoc.psi.PhpDocComment; -+import com.jetbrains.php.lang.psi.elements.*; -+import com.jetbrains.php.lang.psi.resolve.types.PhpType; -+import com.magento.idea.magento2plugin.actions.generation.data.code.PluginMethodData; -+import com.magento.idea.magento2plugin.magento.files.Plugin; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+import java.util.*; -+import java.util.regex.Pattern; -+ -+public class PluginMethodsGenerator { -+ public static String originalTargetKey = "original.target"; -+ @NotNull -+ private final PhpClass pluginClass; -+ @NotNull -+ private final Method myMethod; -+ @NotNull -+ private final PhpClass myTargetClass; -+ -+ public PluginMethodsGenerator(@NotNull PhpClass pluginClass, @NotNull Method method, Key targetClassKey) { -+ super(); -+ this.pluginClass = pluginClass; -+ this.myMethod = method; -+ this.myTargetClass = (PhpClass)Objects.requireNonNull(method.getUserData(targetClassKey)); -+ } -+ -+ @NotNull -+ public PluginMethodData[] createPluginMethods(@NotNull Plugin.PluginType type) { -+ List pluginMethods = new ArrayList(); -+ String templateName = Plugin.getMethodTemplateByPluginType(type); -+ PhpClass currentClass = this.pluginClass; -+ if (currentClass != null) { -+ Properties attributes = this.getAccessMethodAttributes(PhpCodeInsightUtil.findScopeForUseOperator(this.myMethod), type); -+ String methodTemplate = PhpCodeUtil.getCodeTemplate(templateName, attributes, this.pluginClass.getProject()); -+ PhpClass dummyClass = PhpCodeUtil.createClassFromMethodTemplate(currentClass, currentClass.getProject(), methodTemplate); -+ if (dummyClass != null) { -+ PhpDocComment currDocComment = null; -+ -+ for(PsiElement child = dummyClass.getFirstChild(); child != null; child = child.getNextSibling()) { -+ if (child instanceof PhpDocComment) { -+ currDocComment = (PhpDocComment)child; -+ } else if (child instanceof Method) { -+ pluginMethods.add(new PluginMethodData(myMethod, currDocComment, (Method)child)); -+ currDocComment = null; -+ } -+ } -+ } -+ } -+ -+ return pluginMethods.toArray(new PluginMethodData[0]); -+ } -+ -+ private Properties getAccessMethodAttributes(@Nullable PhpPsiElement scopeForUseOperator, @NotNull Plugin.PluginType type) { -+ Properties attributes = new Properties(); -+ String typeHint = this.fillAttributes(scopeForUseOperator, attributes, type); -+ this.addTypeHintsAndReturnType(attributes, typeHint); -+ return attributes; -+ } -+ -+ @NotNull -+ private String fillAttributes(@Nullable PhpPsiElement scopeForUseOperator, Properties attributes, @NotNull Plugin.PluginType type) { -+ String fieldName = this.myMethod.getName(); -+ String methodSuffix = fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1); -+ String pluginMethodName = type.toString().concat(methodSuffix); -+ -+ attributes.setProperty("NAME", pluginMethodName); -+ PhpReturnType targetMethodReturnType = myMethod.getReturnType(); -+ String typeHint = ""; -+ if (targetMethodReturnType != null) { -+ typeHint = targetMethodReturnType.getText(); -+ } -+ Collection parameters = new ArrayList(); -+ parameters.add(myTargetClass); -+ parameters.addAll(Arrays.asList(myMethod.getParameters())); -+ attributes.setProperty("PARAM_DOC", this.getParameterDoc(parameters, type, scopeForUseOperator.getProject())); -+ attributes.setProperty("PARAM_LIST", this.getParameterList(parameters, type)); -+ String returnVariables = this.getReturnVariables(type); -+ if (returnVariables != null) { -+ attributes.setProperty("RETURN_VARIABLES", returnVariables); -+ } -+ -+ return typeHint; -+ } -+ -+ private void addTypeHintsAndReturnType(Properties attributes, String typeHint) { -+ Project project = this.pluginClass.getProject(); -+ if (PhpLanguageFeature.SCALAR_TYPE_HINTS.isSupported(project) && isDocTypeConvertable(typeHint)) { -+ attributes.setProperty("SCALAR_TYPE_HINT", convertDocTypeToHint(project, typeHint)); -+ } -+ -+ boolean hasFeatureVoid = PhpLanguageFeature.RETURN_VOID.isSupported(project); -+ if (hasFeatureVoid) { -+ attributes.setProperty("VOID_RETURN_TYPE", "void"); -+ } -+ -+ if (PhpLanguageFeature.RETURN_TYPES.isSupported(project) && isDocTypeConvertable(typeHint)) { -+ attributes.setProperty("RETURN_TYPE", convertDocTypeToHint(project, typeHint)); -+ } -+ -+ } -+ -+ private static boolean isDocTypeConvertable(String typeHint) { -+ return !typeHint.equalsIgnoreCase("mixed") && !typeHint.equalsIgnoreCase("static") && !typeHint.equalsIgnoreCase("true") && !typeHint.equalsIgnoreCase("false") && !typeHint.equalsIgnoreCase("null") && (!typeHint.contains("|") || typeWithNull(typeHint)); -+ } -+ -+ private static boolean typeWithNull(String typeHint) { -+ return typeHint.split(Pattern.quote("|")).length == 2 && StringUtil.toUpperCase(typeHint).contains("NULL"); -+ } -+ -+ private static String convertNullableType(Project project, String typeHint) { -+ String[] split = typeHint.split(Pattern.quote("|")); -+ boolean hasNullableTypeFeature = PhpLanguageFeature.NULLABLES.isSupported(project); -+ return split[0].equalsIgnoreCase("null") ? (hasNullableTypeFeature ? "?" : "") + split[1] : (hasNullableTypeFeature ? "?" : "") + split[0]; -+ } -+ -+ @NotNull -+ private static String convertDocTypeToHint(Project project, String typeHint) { -+ String hint = typeHint.contains("[]") ? "array" : typeHint; -+ hint = hint.contains("boolean") ? "bool" : hint; -+ if (typeWithNull(typeHint)) { -+ hint = convertNullableType(project, hint); -+ } -+ -+ return hint; -+ } -+ -+ private String getParameterDoc(Collection parameters, @NotNull Plugin.PluginType type, Project project) { -+ StringBuilder sb = new StringBuilder(); -+ PhpReturnType returnType = myMethod.getReturnType(); -+ -+ PhpNamedElement element; -+ int i = 0; -+ for(Iterator iterator = parameters.iterator(); iterator.hasNext(); i++) { -+ element = (PhpNamedElement)iterator.next(); -+ -+ if (sb.length() > 0) { -+ sb.append("\n"); -+ } -+ -+ sb.append("* @param "); -+ String typeStr = PhpDocUtil.getTypePresentation(project, element.getType(), PhpCodeInsightUtil.findScopeForUseOperator(element)); -+ -+ if (!typeStr.isEmpty()) { -+ sb.append(typeStr).append(' '); -+ } -+ String paramName = element.getName(); -+ if (i == 0) { -+ paramName = "subject"; -+ } -+ sb.append('$').append(paramName); -+ -+ if (type.equals(Plugin.PluginType.around) && i == 0) { -+ sb.append("\n* @param callable $proceed"); -+ } -+ if (type.equals(Plugin.PluginType.after) && i == 0) { -+ if (returnType != null) { -+ if (returnType.getText().equals("void")) { -+ sb.append("\n* @param null $result"); -+ } else { -+ sb.append("\n* @param ").append(returnType.getText()).append(" $result"); -+ } -+ } else { -+ sb.append("\n* @param $result"); -+ } -+ } -+ } -+ -+ if (!type.equals(Plugin.PluginType.before) && returnType != null) { -+ if (returnType.getText().equals("void")) { -+ sb.append("\n* @return void"); -+ } else { -+ sb.append("\n* @return ").append(returnType.getText()); -+ } -+ } -+ return sb.toString(); -+ } -+ -+ protected String getParameterList(Collection parameters, @NotNull Plugin.PluginType type) { -+ StringBuilder buf = new StringBuilder(); -+ PhpReturnType returnType = myMethod.getReturnType(); -+ Iterator iterator = parameters.iterator(); -+ -+ Integer i = 0; -+ while(iterator.hasNext()) { -+ PhpNamedElement element = (PhpNamedElement)iterator.next(); -+ if (i != 0) { -+ buf.append(','); -+ } -+ -+ if (element instanceof Parameter) { -+ buf.append(PhpCodeUtil.paramToString(element)); -+ } else { -+ String typeHint = this.getTypeHint(element); -+ if (typeHint != null && !typeHint.isEmpty()) { -+ buf.append(typeHint).append(' '); -+ } -+ -+ String paramName = element.getName(); -+ if (i == 0) { -+ paramName = "subject"; -+ } -+ buf.append("$").append(paramName); -+ } -+ if (type.equals(Plugin.PluginType.after) && i == 0){ -+ if (returnType != null && !returnType.getText().equals("void")) { -+ buf.append(", ").append(returnType.getText()).append(" $result"); -+ } else { -+ buf.append(", $result"); -+ } -+ } -+ if (type.equals(Plugin.PluginType.around) && i == 0){ -+ buf.append(", callable $proceed"); -+ } -+ i++; -+ } -+ -+ return buf.toString(); -+ } -+ -+ protected String getReturnVariables(@NotNull Plugin.PluginType type) { -+ StringBuilder buf = new StringBuilder(); -+ if (type.equals(Plugin.PluginType.after)) { -+ return buf.append("$result").toString(); -+ } -+ Parameter[] parameters = myMethod.getParameters(); -+ if (parameters.length == 0) { -+ return null; -+ } -+ boolean isFirst = true; -+ -+ for (Parameter parameter: parameters) { -+ if (isFirst) { -+ isFirst = false; -+ } else { -+ buf.append(", "); -+ } -+ -+ String paramName = parameter.getName(); -+ buf.append("$").append(paramName); -+ } -+ -+ return buf.toString(); -+ } -+ -+ @Nullable -+ private String getTypeHint(@NotNull PhpNamedElement element) { -+ PhpType filedType = element.getType().global(this.pluginClass.getProject()); -+ Set typeStrings = filedType.getTypes(); -+ String typeString = null; -+ if (typeStrings.size() == 1) { -+ typeString = this.convertTypeToString(element, typeStrings); -+ } -+ -+ if (typeStrings.size() == 2) { -+ PhpType filteredNullType = filterNullCaseInsensitive(filedType); -+ if (filteredNullType.getTypes().size() == 1) { -+ if (PhpLanguageFeature.NULLABLES.isSupported(element.getProject())) { -+ typeString = "?" + this.convertTypeToString(element, filteredNullType.getTypes()); -+ } else { -+ typeString = this.convertTypeToString(element, filteredNullType.getTypes()); -+ } -+ } -+ } -+ -+ return typeString; -+ } -+ -+ @Nullable -+ private String convertTypeToString(@NotNull PhpNamedElement element, Set typeStrings) { -+ String simpleType = typeStrings.iterator().next(); -+ simpleType = StringUtil.trimStart(simpleType, "\\"); -+ if (!PhpType.isPrimitiveType(simpleType) || PhpLanguageFeature.SCALAR_TYPE_HINTS.isSupported(element.getProject()) || "array".equalsIgnoreCase(simpleType) || "callable".equalsIgnoreCase(simpleType)) { -+ String typeString = simpleType.endsWith("]") ? "array" : this.getFieldTypeString(element, filterNullCaseInsensitive(element.getType())); -+ if (!typeString.isEmpty()) { -+ return typeString; -+ } -+ } -+ -+ return null; -+ } -+ -+ private String getFieldTypeString(PhpNamedElement element, @NotNull PhpType type) { -+ return PhpDocUtil.getTypePresentation(this.pluginClass.getProject(), type, PhpCodeInsightUtil.findScopeForUseOperator(element)); -+ } -+ -+ private static PhpType filterNullCaseInsensitive(PhpType filedType) { -+ if (filedType.getTypes().isEmpty()) { -+ return PhpType.EMPTY; -+ } else { -+ PhpType phpType = new PhpType(); -+ Iterator iterator = filedType.getTypes().iterator(); -+ -+ while(iterator.hasNext()) { -+ String type = (String)iterator.next(); -+ if (!type.equalsIgnoreCase("\\null")) { -+ phpType.add(type); -+ } -+ } -+ -+ return phpType; -+ } -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/generator/data/ModuleDirectoriesData.java b/src/com/magento/idea/magento2plugin/actions/generation/generator/data/ModuleDirectoriesData.java -new file mode 100644 -index 0000000..1b02cde ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/generator/data/ModuleDirectoriesData.java -@@ -0,0 +1,30 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation.generator.data; -+ -+import com.intellij.psi.PsiDirectory; -+import org.jetbrains.annotations.NotNull; -+ -+public class ModuleDirectoriesData { -+ @NotNull -+ private final PsiDirectory moduleDirectory; -+ @NotNull -+ private final PsiDirectory moduleEtc; -+ -+ public ModuleDirectoriesData(@NotNull PsiDirectory moduleDirectory, @NotNull PsiDirectory moduleEtc) { -+ this.moduleDirectory = moduleDirectory; -+ this.moduleEtc = moduleEtc; -+ } -+ -+ @NotNull -+ public PsiDirectory getModuleDirectory() { -+ return moduleDirectory; -+ } -+ -+ @NotNull -+ public PsiDirectory getModuleEtcDirectory() { -+ return moduleEtc; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/generator/util/DirectoryGenerator.java b/src/com/magento/idea/magento2plugin/actions/generation/generator/util/DirectoryGenerator.java -new file mode 100644 -index 0000000..065114c ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/generator/util/DirectoryGenerator.java -@@ -0,0 +1,34 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation.generator.util; -+ -+import com.intellij.openapi.application.WriteAction; -+import com.intellij.psi.PsiDirectory; -+import com.magento.idea.magento2plugin.actions.generation.generator.data.ModuleDirectoriesData; -+import com.magento.idea.magento2plugin.magento.packages.Package; -+import org.jetbrains.annotations.NotNull; -+ -+public class DirectoryGenerator { -+ private static DirectoryGenerator INSTANCE = null; -+ -+ public static DirectoryGenerator getInstance() { -+ if (null == INSTANCE) { -+ INSTANCE = new DirectoryGenerator(); -+ } -+ return INSTANCE; -+ } -+ -+ public ModuleDirectoriesData createOrFindModuleDirectories(@NotNull String packageName, @NotNull String moduleName, @NotNull PsiDirectory baseDirectory){ -+ PsiDirectory packageDirectory = findOrCreateSubdirectory(baseDirectory, packageName); -+ PsiDirectory moduleDirectory = findOrCreateSubdirectory(packageDirectory, moduleName); -+ PsiDirectory moduleEtcDirectory = findOrCreateSubdirectory(moduleDirectory, Package.MODULE_BASE_AREA_DIR); -+ return new ModuleDirectoriesData(moduleDirectory, moduleEtcDirectory); -+ } -+ -+ public PsiDirectory findOrCreateSubdirectory(@NotNull PsiDirectory parent, @NotNull String subdirName) { -+ final PsiDirectory sub = parent.findSubdirectory(subdirName); -+ return sub == null ? WriteAction.compute(() -> parent.createSubdirectory(subdirName)) : sub; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/generator/util/FileFromTemplateGenerator.java b/src/com/magento/idea/magento2plugin/actions/generation/generator/util/FileFromTemplateGenerator.java -new file mode 100644 -index 0000000..80bdd87 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/generator/util/FileFromTemplateGenerator.java -@@ -0,0 +1,121 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation.generator.util; -+ -+import com.intellij.ide.fileTemplates.DefaultTemplatePropertiesProvider; -+import com.intellij.ide.fileTemplates.FileTemplate; -+import com.intellij.ide.fileTemplates.FileTemplateManager; -+import com.intellij.lang.Language; -+import com.intellij.openapi.application.ApplicationManager; -+import com.intellij.openapi.command.CommandProcessor; -+import com.intellij.openapi.project.Project; -+import com.intellij.openapi.ui.Messages; -+import com.intellij.openapi.util.Ref; -+import com.intellij.openapi.util.text.StringUtil; -+import com.intellij.psi.PsiDirectory; -+import com.intellij.psi.PsiElement; -+import com.intellij.psi.PsiFile; -+import com.intellij.psi.PsiFileFactory; -+import com.intellij.psi.codeStyle.CodeStyleManager; -+import com.intellij.util.IncorrectOperationException; -+import com.magento.idea.magento2plugin.magento.files.ModuleFileInterface; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+import java.io.File; -+import java.io.IOException; -+import java.util.Iterator; -+import java.util.List; -+import java.util.Properties; -+ -+public class FileFromTemplateGenerator { -+ private static FileFromTemplateGenerator INSTANCE = null; -+ private Project project; -+ -+ public static FileFromTemplateGenerator getInstance(Project project) { -+ if (null == INSTANCE) { -+ INSTANCE = new FileFromTemplateGenerator(); -+ } -+ INSTANCE.project = project; -+ return INSTANCE; -+ } -+ -+ @Nullable -+ public PsiFile generate(@NotNull ModuleFileInterface moduleFile, @NotNull Properties attributes, @NotNull PsiDirectory baseDir, @NotNull String actionName) { -+ Ref fileRef = new Ref(null); -+ Ref exceptionRef = new Ref(null); -+ String filePath = baseDir.getText().concat("/").concat(moduleFile.getFileName()); -+ CommandProcessor.getInstance().executeCommand(project, () -> { -+ Runnable run = () -> { -+ try { -+ PsiFile file = createFile(moduleFile, filePath, baseDir, attributes); -+ if (file != null) { -+ fileRef.set(file); -+ } -+ } catch (IncorrectOperationException | IOException var9) { -+ exceptionRef.set(var9.getMessage()); -+ } -+ }; -+ ApplicationManager.getApplication().runWriteAction(run); -+ }, actionName, null); -+ if (!exceptionRef.isNull()) { -+ Messages.showErrorDialog(exceptionRef.get(), actionName); -+ return null; -+ } else { -+ return fileRef.get(); -+ } -+ } -+ -+ @Nullable -+ private PsiFile createFile(@NotNull ModuleFileInterface moduleFile, @NotNull String filePath, @NotNull PsiDirectory baseDir, @NotNull Properties attributes) throws IOException, IncorrectOperationException { -+ List path = StringUtil.split(filePath.replace(File.separator, "/"), "/"); -+ String fileName = path.get(path.size() - 1); -+ PsiFile fileTemplate = createFileFromTemplate(getTemplateManager(), baseDir, moduleFile.getTemplate(), attributes, fileName, moduleFile.getLanguage()); -+ if (fileTemplate == null) { -+ throw new IncorrectOperationException("Template not found!"); -+ } else { -+ PsiElement file; -+ -+ file = baseDir.add(fileTemplate); -+ if (file instanceof PsiFile) { -+ return (PsiFile)file; -+ } else { -+ return null; -+ } -+ } -+ } -+ -+ public PsiFile createFileFromTemplate(@NotNull FileTemplateManager templateManager, @NotNull PsiDirectory directory, @NotNull String templateName, @NotNull Properties properties, @NotNull String fileName, @NotNull Language language) throws IOException { -+ FileTemplate fileTemplate = templateManager.getInternalTemplate(templateName); -+ fillDefaultProperties(templateManager, properties, directory); -+ String fileTemplateText = fileTemplate.getText(properties); -+ PsiFile file = PsiFileFactory.getInstance(project).createFileFromText(fileName, language, fileTemplateText, true, false); -+ if (fileTemplate.isReformatCode()) { -+ CodeStyleManager.getInstance(project).reformat(file); -+ } -+ -+ return file; -+ } -+ -+ public void fillDefaultProperties(@NotNull FileTemplateManager templateManager, @NotNull Properties props, @NotNull PsiDirectory directory) { -+ Properties hardCodedProperties = templateManager.getDefaultProperties(); -+ Iterator iterator = hardCodedProperties.keySet().iterator(); -+ -+ while(iterator.hasNext()) { -+ Object propertyKey = iterator.next(); -+ props.setProperty((String)propertyKey, hardCodedProperties.getProperty((String)propertyKey)); -+ } -+ -+ iterator = DefaultTemplatePropertiesProvider.EP_NAME.getExtensionList().iterator(); -+ -+ while(iterator.hasNext()) { -+ DefaultTemplatePropertiesProvider provider = (DefaultTemplatePropertiesProvider)iterator.next(); -+ provider.fillProperties(directory, props); -+ } -+ } -+ -+ public FileTemplateManager getTemplateManager() { -+ return FileTemplateManager.getInstance(project); -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/generator/util/FindOrCreateDiXml.java b/src/com/magento/idea/magento2plugin/actions/generation/generator/util/FindOrCreateDiXml.java -new file mode 100644 -index 0000000..f3c8237 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/generator/util/FindOrCreateDiXml.java -@@ -0,0 +1,62 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation.generator.util; -+ -+import com.intellij.openapi.project.Project; -+import com.intellij.psi.PsiDirectory; -+import com.intellij.psi.PsiFile; -+import com.magento.idea.magento2plugin.indexes.ModuleIndex; -+import com.magento.idea.magento2plugin.magento.files.ModuleDiXml; -+import com.magento.idea.magento2plugin.magento.packages.Package; -+import com.magento.idea.magento2plugin.util.magento.FileBasedIndexUtil; -+import java.util.ArrayList; -+import java.util.Properties; -+ -+public class FindOrCreateDiXml { -+ private static FindOrCreateDiXml INSTANCE = null; -+ private Project project; -+ -+ public static FindOrCreateDiXml getInstance(Project project) { -+ if (null == INSTANCE) { -+ INSTANCE = new FindOrCreateDiXml(project); -+ } -+ -+ return INSTANCE; -+ } -+ -+ FindOrCreateDiXml(Project project) { -+ this.project = project; -+ } -+ -+ public PsiFile execute(String actionName, String moduleName, String area) { -+ DirectoryGenerator directoryGenerator = DirectoryGenerator.getInstance(); -+ FileFromTemplateGenerator fileFromTemplateGenerator = FileFromTemplateGenerator.getInstance(project); -+ -+ PsiDirectory parentDirectory = ModuleIndex.getInstance(project).getModuleDirectoryByModuleName(moduleName); -+ ArrayList fileDirectories = new ArrayList<>(); -+ fileDirectories.add(Package.MODULE_BASE_AREA_DIR); -+ if (!getArea(area).equals(Package.Areas.base)) { -+ fileDirectories.add(getArea(area).toString()); -+ } -+ for (String fileDirectory: fileDirectories) { -+ parentDirectory = directoryGenerator.findOrCreateSubdirectory(parentDirectory, fileDirectory); -+ } -+ ModuleDiXml moduleDiXml = new ModuleDiXml(); -+ PsiFile diXml = FileBasedIndexUtil.findModuleConfigFile( -+ moduleDiXml.getFileName(), -+ getArea(area), -+ moduleName, -+ project -+ ); -+ if (diXml == null) { -+ diXml = fileFromTemplateGenerator.generate(moduleDiXml, new Properties(), parentDirectory, actionName); -+ } -+ return diXml; -+ } -+ -+ private Package.Areas getArea(String area) { -+ return Package.getAreaByString(area); -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/generator/util/GetCodeTemplate.java b/src/com/magento/idea/magento2plugin/actions/generation/generator/util/GetCodeTemplate.java -new file mode 100644 -index 0000000..cfa1983 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/generator/util/GetCodeTemplate.java -@@ -0,0 +1,33 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation.generator.util; -+ -+import com.intellij.ide.fileTemplates.FileTemplate; -+import com.intellij.ide.fileTemplates.FileTemplateManager; -+import com.intellij.openapi.project.Project; -+import java.io.IOException; -+import java.util.Properties; -+ -+public class GetCodeTemplate { -+ private static GetCodeTemplate INSTANCE = null; -+ private Project project; -+ -+ public static GetCodeTemplate getInstance(Project project) { -+ if (null == INSTANCE) { -+ INSTANCE = new GetCodeTemplate(project); -+ } -+ -+ return INSTANCE; -+ } -+ -+ GetCodeTemplate (Project project) { -+ this.project = project; -+ } -+ -+ public String execute(String templateName, Properties properties) throws IOException { -+ FileTemplate fileTemplate = FileTemplateManager.getInstance(project).getCodeTemplate(templateName); -+ return fileTemplate.getText(properties); -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/generator/util/XmlFilePositionUtil.java b/src/com/magento/idea/magento2plugin/actions/generation/generator/util/XmlFilePositionUtil.java -new file mode 100644 -index 0000000..2998155 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/generator/util/XmlFilePositionUtil.java -@@ -0,0 +1,41 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation.generator.util; -+ -+import com.intellij.psi.PsiElement; -+import com.intellij.psi.xml.XmlFile; -+import com.intellij.psi.xml.XmlTag; -+import com.intellij.psi.xml.XmlTokenType; -+import com.intellij.xml.util.XmlUtil; -+ -+public class XmlFilePositionUtil { -+ private static XmlFilePositionUtil INSTANCE = null; -+ -+ public static XmlFilePositionUtil getInstance() { -+ if (null == INSTANCE) { -+ INSTANCE = new XmlFilePositionUtil(); -+ } -+ -+ return INSTANCE; -+ } -+ -+ public int getRootInsertPosition(XmlFile xmlFile) { -+ int insertPos = -1; -+ XmlTag rootTag = xmlFile.getRootTag(); -+ if (rootTag == null) { -+ return insertPos; -+ } -+ return getEndPositionOfTag(rootTag); -+ } -+ -+ public int getEndPositionOfTag(XmlTag tag) { -+ PsiElement tagEnd = XmlUtil.getTokenOfType(tag, XmlTokenType.XML_END_TAG_START); -+ if (tagEnd == null) { -+ return -1; -+ } -+ -+ return tagEnd.getTextOffset(); -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/util/CodeStyleSettings.java b/src/com/magento/idea/magento2plugin/actions/generation/util/CodeStyleSettings.java -new file mode 100644 -index 0000000..d9a517f ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/util/CodeStyleSettings.java -@@ -0,0 +1,34 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation.util; -+ -+import com.intellij.application.options.CodeStyle; -+import com.intellij.psi.codeStyle.CommonCodeStyleSettings; -+import com.jetbrains.php.lang.PhpLanguage; -+import com.jetbrains.php.lang.psi.PhpFile; -+ -+public class CodeStyleSettings { -+ private PhpFile phpFile; -+ private boolean currLineBreaks; -+ private int currBlankLines; -+ private CommonCodeStyleSettings settings; -+ -+ public CodeStyleSettings(PhpFile phpFile){ -+ this.phpFile = phpFile; -+ this.settings = CodeStyle.getLanguageSettings(this.phpFile, PhpLanguage.INSTANCE); -+ } -+ -+ public void adjustBeforeWrite() { -+ this.currLineBreaks = settings.KEEP_LINE_BREAKS; -+ this.currBlankLines = settings.KEEP_BLANK_LINES_IN_CODE; -+ settings.KEEP_LINE_BREAKS = false; -+ settings.KEEP_BLANK_LINES_IN_CODE = 0; -+ }; -+ -+ public void restore() { -+ settings.KEEP_LINE_BREAKS = currLineBreaks; -+ settings.KEEP_BLANK_LINES_IN_CODE = currBlankLines; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/util/CollectInsertedMethods.java b/src/com/magento/idea/magento2plugin/actions/generation/util/CollectInsertedMethods.java -new file mode 100644 -index 0000000..566549a ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/util/CollectInsertedMethods.java -@@ -0,0 +1,51 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation.util; -+ -+import com.intellij.psi.PsiElement; -+import com.intellij.psi.PsiFile; -+import com.jetbrains.php.lang.PhpLangUtil; -+import com.jetbrains.php.lang.psi.PhpFile; -+import com.jetbrains.php.lang.psi.PhpPsiUtil; -+import com.jetbrains.php.lang.psi.elements.Method; -+import com.jetbrains.php.lang.psi.elements.PhpClass; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+import java.util.ArrayList; -+import java.util.List; -+import java.util.Set; -+ -+public class CollectInsertedMethods { -+ private static CollectInsertedMethods INSTANCE = null; -+ -+ public static CollectInsertedMethods getInstance() { -+ if (null == INSTANCE) { -+ INSTANCE = new CollectInsertedMethods(); -+ } -+ return INSTANCE; -+ } -+ -+ @Nullable -+ public List execute(@NotNull PsiFile file, @NotNull CharSequence className, @NotNull Set methodNames) { -+ if (!(file instanceof PhpFile)) { -+ return null; -+ } -+ PhpClass phpClass = PhpPsiUtil.findClass((PhpFile) file, (aClass) -> PhpLangUtil.equalsClassNames(aClass.getNameCS(), className)); -+ if (phpClass == null) { -+ return null; -+ } else { -+ List insertedMethods = new ArrayList(); -+ Method[] ownMethods = phpClass.getOwnMethods(); -+ -+ for (Method method : ownMethods) { -+ if (methodNames.contains(method.getNameCS())) { -+ insertedMethods.add(method); -+ } -+ } -+ -+ return insertedMethods; -+ } -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/util/FillTextBufferWithPluginMethods.java b/src/com/magento/idea/magento2plugin/actions/generation/util/FillTextBufferWithPluginMethods.java -new file mode 100644 -index 0000000..12d1d9b ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/util/FillTextBufferWithPluginMethods.java -@@ -0,0 +1,53 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation.util; -+ -+import com.intellij.openapi.util.Key; -+import com.intellij.psi.PsiElement; -+import com.jetbrains.php.lang.documentation.phpdoc.psi.PhpDocComment; -+import com.jetbrains.php.lang.psi.elements.Method; -+import com.jetbrains.php.lang.psi.elements.Parameter; -+import com.jetbrains.php.lang.psi.elements.PhpReturnType; -+import com.magento.idea.magento2plugin.actions.generation.ImportReferences.PhpClassReferenceResolver; -+import com.magento.idea.magento2plugin.actions.generation.data.code.PluginMethodData; -+import org.jetbrains.annotations.NotNull; -+import java.util.ArrayList; -+import java.util.Arrays; -+import java.util.Collection; -+import java.util.Set; -+ -+public class FillTextBufferWithPluginMethods { -+ private static FillTextBufferWithPluginMethods INSTANCE = null; -+ -+ public static FillTextBufferWithPluginMethods getInstance() { -+ if (null == INSTANCE) { -+ INSTANCE = new FillTextBufferWithPluginMethods(); -+ } -+ return INSTANCE; -+ } -+ -+ public void execute(@NotNull Key targetClassKey, Set insertedMethodsNames, @NotNull PhpClassReferenceResolver resolver, @NotNull StringBuffer textBuf, @NotNull PluginMethodData[] pluginMethods) { -+ for (PluginMethodData pluginMethod : pluginMethods) { -+ insertedMethodsNames.add(pluginMethod.getMethod().getName()); -+ PhpDocComment comment = pluginMethod.getDocComment(); -+ if (comment != null) { -+ textBuf.append(comment.getText()); -+ } -+ Method targetMethod = pluginMethod.getTargetMethod(); -+ Parameter[] parameters = targetMethod.getParameters(); -+ Collection processElements = new ArrayList<>(Arrays.asList(parameters)); -+ resolver.processElements(processElements); -+ PsiElement targetClass = (PsiElement) pluginMethod.getTargetMethod().getUserData(targetClassKey); -+ resolver.processElement(targetClass); -+ PhpReturnType returnType = targetMethod.getReturnType(); -+ if (returnType != null) { -+ resolver.processElement(returnType); -+ } -+ -+ textBuf.append('\n'); -+ textBuf.append(pluginMethod.getMethod().getText()); -+ } -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/actions/generation/util/NavigateToCreatedFile.java b/src/com/magento/idea/magento2plugin/actions/generation/util/NavigateToCreatedFile.java -new file mode 100644 -index 0000000..f90a8c4 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/actions/generation/util/NavigateToCreatedFile.java -@@ -0,0 +1,30 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.actions.generation.util; -+ -+import com.intellij.ide.util.PsiNavigationSupport; -+import com.intellij.openapi.project.Project; -+import com.intellij.openapi.vfs.VirtualFile; -+import com.intellij.psi.PsiFile; -+import org.jetbrains.annotations.NotNull; -+ -+public class NavigateToCreatedFile { -+ private static NavigateToCreatedFile INSTANCE = null; -+ -+ public static NavigateToCreatedFile getInstance() { -+ if (null == INSTANCE) { -+ INSTANCE = new NavigateToCreatedFile(); -+ } -+ return INSTANCE; -+ } -+ -+ public void navigate(@NotNull Project project, @NotNull PsiFile createdFile) { -+ VirtualFile virtualFile = createdFile.getVirtualFile(); -+ if (virtualFile == null) { -+ return; -+ } -+ PsiNavigationSupport.getInstance().createNavigatable(project, virtualFile, -1).navigate(false); -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/completion/provider/RequireJsMappingCompletionProvider.java b/src/com/magento/idea/magento2plugin/completion/provider/RequireJsMappingCompletionProvider.java -new file mode 100644 -index 0000000..96a9a66 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/completion/provider/RequireJsMappingCompletionProvider.java -@@ -0,0 +1,44 @@ -+/* -+ * 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.lang.javascript.JavaScriptFileType; -+import com.intellij.psi.PsiElement; -+import com.intellij.util.ProcessingContext; -+import com.intellij.util.indexing.FileBasedIndex; -+import com.magento.idea.magento2plugin.stubs.indexes.js.RequireJsIndex; -+import org.jetbrains.annotations.NotNull; -+import java.util.Collection; -+ -+public class RequireJsMappingCompletionProvider extends CompletionProvider { -+ -+ @Override -+ protected void addCompletions(@NotNull CompletionParameters parameters, -+ ProcessingContext context, -+ @NotNull CompletionResultSet result) { -+ PsiElement position = parameters.getPosition().getOriginalElement(); -+ if (position == null) { -+ return; -+ } -+ String prefix = result.getPrefixMatcher().getPrefix(); -+ -+ Collection requireJsKeys -+ = FileBasedIndex.getInstance().getAllKeys(RequireJsIndex.KEY, position.getProject()); -+ -+ requireJsKeys.removeIf(m -> !m.startsWith(prefix)); -+ JavaScriptFileType jsFileType = new JavaScriptFileType(); -+ for (String requireJsKey : requireJsKeys) { -+ result.addElement( -+ LookupElementBuilder -+ .create(requireJsKey) -+ .withIcon(jsFileType.getIcon()) -+ ); -+ } -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/completion/provider/mftf/ActionGroupCompletionProvider.java b/src/com/magento/idea/magento2plugin/completion/provider/mftf/ActionGroupCompletionProvider.java -new file mode 100644 -index 0000000..add108d ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/completion/provider/mftf/ActionGroupCompletionProvider.java -@@ -0,0 +1,35 @@ -+package com.magento.idea.magento2plugin.completion.provider.mftf; -+ -+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.psi.PsiElement; -+import com.intellij.util.ProcessingContext; -+import com.intellij.util.indexing.FileBasedIndex; -+import com.magento.idea.magento2plugin.stubs.indexes.mftf.ActionGroupIndex; -+import org.jetbrains.annotations.NotNull; -+ -+import java.util.Collection; -+ -+public class ActionGroupCompletionProvider extends CompletionProvider { -+ -+ @Override -+ protected void addCompletions(@NotNull CompletionParameters parameters, -+ ProcessingContext context, -+ @NotNull CompletionResultSet result) -+ { -+ PsiElement position = parameters.getPosition().getOriginalElement(); -+ -+ if (position == null) { -+ return; -+ } -+ -+ Collection selectorNames -+ = FileBasedIndex.getInstance().getAllKeys(ActionGroupIndex.KEY, position.getProject()); -+ -+ for (String selectorName: selectorNames) { -+ result.addElement(LookupElementBuilder.create(selectorName)); -+ } -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/completion/provider/mftf/DataCompletionProvider.java b/src/com/magento/idea/magento2plugin/completion/provider/mftf/DataCompletionProvider.java -new file mode 100644 -index 0000000..3879942 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/completion/provider/mftf/DataCompletionProvider.java -@@ -0,0 +1,35 @@ -+package com.magento.idea.magento2plugin.completion.provider.mftf; -+ -+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.psi.PsiElement; -+import com.intellij.util.ProcessingContext; -+import com.intellij.util.indexing.FileBasedIndex; -+import com.magento.idea.magento2plugin.stubs.indexes.mftf.DataIndex; -+import org.jetbrains.annotations.NotNull; -+ -+import java.util.Collection; -+ -+public class DataCompletionProvider extends CompletionProvider { -+ -+ @Override -+ protected void addCompletions(@NotNull CompletionParameters parameters, -+ ProcessingContext context, -+ @NotNull CompletionResultSet result) -+ { -+ PsiElement position = parameters.getPosition().getOriginalElement(); -+ -+ if (position == null) { -+ return; -+ } -+ -+ Collection selectorNames -+ = FileBasedIndex.getInstance().getAllKeys(DataIndex.KEY, position.getProject()); -+ -+ for (String selectorName: selectorNames) { -+ result.addElement(LookupElementBuilder.create(selectorName)); -+ } -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/completion/provider/mftf/SelectorCompletionProvider.java b/src/com/magento/idea/magento2plugin/completion/provider/mftf/SelectorCompletionProvider.java -new file mode 100644 -index 0000000..bd58d96 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/completion/provider/mftf/SelectorCompletionProvider.java -@@ -0,0 +1,35 @@ -+package com.magento.idea.magento2plugin.completion.provider.mftf; -+ -+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.psi.PsiElement; -+import com.intellij.util.ProcessingContext; -+import com.intellij.util.indexing.FileBasedIndex; -+import com.magento.idea.magento2plugin.stubs.indexes.mftf.SectionIndex; -+import org.jetbrains.annotations.NotNull; -+ -+import java.util.Collection; -+ -+public class SelectorCompletionProvider extends CompletionProvider { -+ -+ @Override -+ protected void addCompletions(@NotNull CompletionParameters parameters, -+ ProcessingContext context, -+ @NotNull CompletionResultSet result) -+ { -+ PsiElement position = parameters.getPosition().getOriginalElement(); -+ -+ if (position == null) { -+ return; -+ } -+ -+ Collection selectorNames -+ = FileBasedIndex.getInstance().getAllKeys(SectionIndex.KEY, position.getProject()); -+ -+ for (String selectorName: selectorNames) { -+ result.addElement(LookupElementBuilder.create(selectorName)); -+ } -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/completion/xml/XmlCompletionContributor.java b/src/com/magento/idea/magento2plugin/completion/xml/XmlCompletionContributor.java -index c1a5ff1..7a930dc 100644 ---- a/src/com/magento/idea/magento2plugin/completion/xml/XmlCompletionContributor.java -+++ b/src/com/magento/idea/magento2plugin/completion/xml/XmlCompletionContributor.java -@@ -9,6 +9,7 @@ import com.intellij.codeInsight.completion.CompletionType; - import com.intellij.patterns.XmlPatterns; - import com.intellij.psi.xml.XmlTokenType; - import com.magento.idea.magento2plugin.completion.provider.*; -+import com.magento.idea.magento2plugin.completion.provider.mftf.*; - - import static com.intellij.patterns.PlatformPatterns.psiElement; - import static com.intellij.patterns.StandardPatterns.string; -@@ -105,5 +106,65 @@ public class XmlCompletionContributor extends CompletionContributor { - ).inFile(xmlFile().withName(string().endsWith("events.xml"))), - new EventNameCompletionContributor() - ); -+ -+ extend(CompletionType.BASIC, psiElement(XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN) -+ .inside(XmlPatterns.xmlAttributeValue().withParent( -+ XmlPatterns.xmlAttribute().withName("component") -+ )), -+ new RequireJsMappingCompletionProvider() -+ ); -+ -+ extend(CompletionType.BASIC, psiElement(XmlTokenType.XML_DATA_CHARACTERS) -+ .withParent(XmlPatterns.xmlText().withParent( -+ XmlPatterns.xmlTag().withName("item").withChild( -+ XmlPatterns.xmlAttribute().withValue(string().matches("component")) -+ ).withChild( -+ XmlPatterns.xmlAttribute().withName("name") -+ ) -+ ) -+ ), -+ new RequireJsMappingCompletionProvider() -+ ); -+ -+ // mftf selector completion contributor -+ extend(CompletionType.BASIC, -+ psiElement(XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN) -+ .inside(XmlPatterns.xmlAttribute()) -+ .inFile(xmlFile().withName(string().endsWith("Test.xml"))), -+ new SelectorCompletionProvider() -+ ); -+ -+ // mftf action group completion contributor -+ extend( -+ CompletionType.BASIC, -+ psiElement(XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN) -+ .inside( -+ XmlPatterns.xmlAttribute().withName(string().oneOf("ref", "extends")) -+ .withParent(XmlPatterns.xmlTag().withName("actionGroup") -+ ) -+ ), -+ new ActionGroupCompletionProvider() -+ ); -+ -+ // mftf data entity completion contributor -+ extend( -+ CompletionType.BASIC, -+ psiElement(XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN) -+ .inside(XmlPatterns.xmlAttribute().withName(string().oneOf("entity", "value", "userInput", "url")) -+ ), -+ new DataCompletionProvider() -+ ); -+ -+ // Data entity/extends completion contributor -+ extend( -+ CompletionType.BASIC, -+ psiElement(XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN) -+ .inside( -+ XmlPatterns.xmlAttribute().withName("extends") -+ .withParent(XmlPatterns.xmlTag().withName("entity") -+ ) -+ ), -+ new DataCompletionProvider() -+ ); - } - } -diff --git a/src/com/magento/idea/magento2plugin/graphql/linemarker/GraphQlResolverClassLineMarkerProvider.java b/src/com/magento/idea/magento2plugin/graphql/linemarker/GraphQlResolverClassLineMarkerProvider.java -new file mode 100644 -index 0000000..104ab3e ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/graphql/linemarker/GraphQlResolverClassLineMarkerProvider.java -@@ -0,0 +1,94 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.graphql.linemarker; -+ -+import com.intellij.codeInsight.daemon.LineMarkerInfo; -+import com.intellij.codeInsight.daemon.LineMarkerProvider; -+import com.intellij.codeInsight.navigation.NavigationGutterIconBuilder; -+import com.intellij.lang.jsgraphql.psi.GraphQLArgument; -+import com.intellij.lang.jsgraphql.psi.GraphQLStringValue; -+import com.intellij.openapi.project.Project; -+import com.intellij.psi.PsiElement; -+import com.intellij.psi.util.PsiTreeUtil; -+import com.jetbrains.php.PhpIcons; -+import com.jetbrains.php.PhpIndex; -+import com.jetbrains.php.lang.psi.elements.PhpClass; -+import com.magento.idea.magento2plugin.project.Settings; -+import com.magento.idea.magento2plugin.util.magento.graphql.GraphQlUtil; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+import java.util.*; -+ -+public class GraphQlResolverClassLineMarkerProvider implements LineMarkerProvider { -+ @Nullable -+ @Override -+ public LineMarkerInfo getLineMarkerInfo(@NotNull PsiElement psiElement) { -+ return null; -+ } -+ -+ @Override -+ public void collectSlowLineMarkers(@NotNull List psiElements, @NotNull Collection collection) { -+ if (psiElements.size() > 0) { -+ if (!Settings.isEnabled(psiElements.get(0).getProject())) { -+ return; -+ } -+ } -+ -+ for (PsiElement psiElement : psiElements) { -+ if (psiElement instanceof GraphQLArgument) { -+ Collection results; -+ -+ GraphQlResolverClassCollector collector = new GraphQlResolverClassCollector(); -+ results = collector.getGraphQLResolverClasses((GraphQLArgument) psiElement); -+ GraphQLStringValue argumentStringValue = GraphQlUtil.fetchResolverQuotedStringFromArgument(psiElement); -+ if (argumentStringValue == null) { -+ continue; -+ } -+ -+ if (results.size() > 0 ) { -+ collection.add(NavigationGutterIconBuilder -+ .create(PhpIcons.CLASS) -+ .setTargets(results) -+ .setTooltipText("Navigate to class") -+ .createLineMarkerInfo(PsiTreeUtil.getDeepestLast(argumentStringValue)) -+ ); -+ } -+ } -+ } -+ } -+ -+ private static class GraphQlResolverClassCollector { -+ -+ private HashMap> routesCache = new HashMap<>(); -+ -+ -+ Collection getGraphQLResolverClasses(@NotNull GraphQLArgument graphQLArgument) { -+ List graphQLResolverClasses = new ArrayList<>(); -+ GraphQLStringValue argumentStringValue = GraphQlUtil.fetchResolverQuotedStringFromArgument(graphQLArgument); -+ if (argumentStringValue == null) { -+ return graphQLResolverClasses; -+ } -+ -+ graphQLResolverClasses.addAll(getUsages(argumentStringValue)); -+ -+ return graphQLResolverClasses; -+ } -+ -+ Collection getUsages(@NotNull GraphQLStringValue graphQLStringValue) { -+ String phpClassFQN = GraphQlUtil.resolverStringToPhpFQN(graphQLStringValue.getText()); -+ if (!routesCache.containsKey(phpClassFQN)) { -+ -+ Collection phpClasses = extractClasses(phpClassFQN, graphQLStringValue.getProject()); -+ routesCache.put(phpClassFQN, phpClasses); -+ } -+ return routesCache.get(phpClassFQN); -+ } -+ -+ Collection extractClasses(@NotNull String phpClassFQN, Project project) { -+ PhpIndex phpIndex = PhpIndex.getInstance(project); -+ return phpIndex.getClassesByFQN(phpClassFQN); -+ } -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/indexes/IndexManager.java b/src/com/magento/idea/magento2plugin/indexes/IndexManager.java -index e20c4a6..aa5577d 100644 ---- a/src/com/magento/idea/magento2plugin/indexes/IndexManager.java -+++ b/src/com/magento/idea/magento2plugin/indexes/IndexManager.java -@@ -7,6 +7,10 @@ package com.magento.idea.magento2plugin.indexes; - import com.intellij.util.indexing.FileBasedIndexImpl; - import com.intellij.util.indexing.ID; - import com.magento.idea.magento2plugin.stubs.indexes.*; -+import com.magento.idea.magento2plugin.stubs.indexes.js.MagentoLibJsIndex; -+import com.magento.idea.magento2plugin.stubs.indexes.js.RequireJsIndex; -+import com.magento.idea.magento2plugin.stubs.indexes.graphql.GraphQlResolverIndex; -+import com.magento.idea.magento2plugin.stubs.indexes.mftf.*; - import com.magento.idea.magento2plugin.stubs.indexes.xml.PhpClassNameIndex; - - /** -@@ -29,7 +33,18 @@ public class IndexManager { - // webapi - WebApiTypeIndex.KEY, - ModuleNameIndex.KEY, -- PhpClassNameIndex.KEY -+ PhpClassNameIndex.KEY, -+ //require_js -+ RequireJsIndex.KEY, -+ MagentoLibJsIndex.KEY, -+ // mftf -+ ActionGroupIndex.KEY, -+ DataIndex.KEY, -+ PageIndex.KEY, -+ SectionIndex.KEY, -+ StepKeyIndex.KEY, -+ //graphql -+ GraphQlResolverIndex.KEY - }; - - for (ID id: indexIds) { -diff --git a/src/com/magento/idea/magento2plugin/indexes/JsIndex.java b/src/com/magento/idea/magento2plugin/indexes/JsIndex.java -new file mode 100644 -index 0000000..c4e4442 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/indexes/JsIndex.java -@@ -0,0 +1,118 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.indexes; -+ -+import com.intellij.openapi.project.Project; -+import com.intellij.openapi.vfs.VirtualFile; -+import com.intellij.psi.PsiElement; -+import com.intellij.psi.PsiManager; -+import com.intellij.psi.PsiReference; -+import com.intellij.psi.search.GlobalSearchScope; -+import com.intellij.util.indexing.FileBasedIndex; -+import com.magento.idea.magento2plugin.reference.xml.PolyVariantReferenceBase; -+import com.magento.idea.magento2plugin.stubs.indexes.js.RequireJsIndex; -+import com.magento.idea.magento2plugin.reference.provider.util.GetAllSubFilesOfVirtualFileUtil; -+import com.magento.idea.magento2plugin.reference.provider.util.GetFilePathUtil; -+import com.magento.idea.magento2plugin.reference.provider.util.GetModuleNameUtil; -+import com.magento.idea.magento2plugin.reference.provider.util.GetModuleSourceFilesUtil; -+import org.jetbrains.annotations.NotNull; -+import java.util.ArrayList; -+import java.util.Collection; -+import java.util.List; -+ -+public class JsIndex { -+ -+ private static JsIndex INSTANCE; -+ -+ private JsIndex() { -+ } -+ -+ public static JsIndex getInstance() { -+ if (null == INSTANCE) { -+ INSTANCE = new JsIndex(); -+ } -+ return INSTANCE; -+ } -+ -+ public PsiReference[] getRequireJsPreferences(@NotNull PsiElement element, final GlobalSearchScope scope) { -+ String originalValue = element.getText(); -+ String jsKey = originalValue -+ .replace("'", "") -+ .replace("\"", ""); -+ -+ Collection values = -+ FileBasedIndex.getInstance().getValues(RequireJsIndex.KEY, jsKey, scope); -+ PsiManager psiManager = PsiManager.getInstance(element.getProject()); -+ -+ List targets = new ArrayList<>(); -+ if (values.isEmpty()) { -+ Collection files = LibJsIndex.getInstance().getLibJsFiles(jsKey, element.getProject()); -+ convertVirtualFilesToPsiElements(psiManager, targets, jsKey, files); -+ } else { -+ for (String value : values) { -+ String filePath = GetFilePathUtil.getInstance().execute(value); -+ if (null == filePath) { -+ continue; -+ } -+ Collection files = getJsFilesByPath(value, element.getProject()); -+ -+ convertVirtualFilesToPsiElements(psiManager, targets, filePath, files); -+ } -+ } -+ -+ if (targets.isEmpty()) { -+ return PsiReference.EMPTY_ARRAY; -+ } -+ -+ return new PsiReference[] { -+ new PolyVariantReferenceBase(element, targets) -+ }; -+ } -+ -+ private void convertVirtualFilesToPsiElements(PsiManager psiManager, List targets, String filePath, Collection files) { -+ for (VirtualFile file : files) { -+ String fileUrl = file.getUrl(); -+ if (!fileUrl.contains(filePath)) { -+ return; -+ } -+ -+ PsiElement psiElement = psiManager.findFile(file); -+ if (null != psiElement) { -+ targets.add(psiElement); -+ } -+ } -+ } -+ -+ private Collection getJsFilesByPath(@NotNull String filePath, @NotNull Project project) -+ { -+ Collection virtualFiles = new ArrayList<>(); -+ Collection files = new ArrayList<>(); -+ -+ String fileName = filePath.substring(filePath.lastIndexOf("/") + 1).concat(".js").replace("'", ""); -+ String moduleName = GetModuleNameUtil.getInstance().execute(filePath); -+ if (moduleName == null) { -+ virtualFiles.addAll(LibJsIndex.getInstance().getLibJsFiles(filePath, project)); -+ } else { -+ virtualFiles.addAll(GetModuleSourceFilesUtil.getInstance().execute(filePath, project)); -+ } -+ if (!virtualFiles.isEmpty()) { -+ for (VirtualFile virtualFile : virtualFiles) { -+ Collection vfChildren = GetAllSubFilesOfVirtualFileUtil. -+ getInstance().execute(virtualFile); -+ if (null != vfChildren) { -+ vfChildren.removeIf(file -> { -+ if (!file.isDirectory()) { -+ String name = file.getName(); -+ return !name.equals(fileName); -+ } -+ return true; -+ }); -+ files.addAll(vfChildren); -+ } -+ } -+ } -+ return files; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/indexes/LibJsIndex.java b/src/com/magento/idea/magento2plugin/indexes/LibJsIndex.java -new file mode 100644 -index 0000000..2b378bb ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/indexes/LibJsIndex.java -@@ -0,0 +1,36 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.indexes; -+ -+import com.intellij.openapi.project.Project; -+import com.intellij.openapi.vfs.VirtualFile; -+import com.intellij.psi.search.GlobalSearchScope; -+import com.intellij.util.indexing.FileBasedIndex; -+import com.magento.idea.magento2plugin.stubs.indexes.js.MagentoLibJsIndex; -+import org.jetbrains.annotations.NotNull; -+import java.util.Collection; -+ -+public class LibJsIndex { -+ -+ private static LibJsIndex INSTANCE; -+ -+ private LibJsIndex() { -+ } -+ -+ public static LibJsIndex getInstance() { -+ if (null == INSTANCE) { -+ INSTANCE = new LibJsIndex(); -+ } -+ return INSTANCE; -+ } -+ -+ public Collection getLibJsFiles(@NotNull String filePath, @NotNull Project project) { -+ return FileBasedIndex.getInstance() -+ .getContainingFiles(MagentoLibJsIndex.KEY, -+ filePath.replace("'", ""), -+ GlobalSearchScope.allScope(project) -+ ); -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/indexes/ModuleIndex.java b/src/com/magento/idea/magento2plugin/indexes/ModuleIndex.java -new file mode 100644 -index 0000000..b82ea70 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/indexes/ModuleIndex.java -@@ -0,0 +1,77 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.indexes; -+ -+import com.intellij.openapi.project.Project; -+import com.intellij.openapi.vfs.VirtualFile; -+import com.intellij.psi.PsiDirectory; -+import com.intellij.psi.PsiManager; -+import com.intellij.psi.search.GlobalSearchScope; -+import com.intellij.util.indexing.FileBasedIndex; -+import com.jetbrains.php.lang.PhpFileType; -+import com.magento.idea.magento2plugin.magento.packages.Package; -+import com.magento.idea.magento2plugin.stubs.indexes.ModuleNameIndex; -+import com.magento.idea.magento2plugin.util.RegExUtil; -+import java.util.ArrayList; -+import java.util.Collection; -+import java.util.Collections; -+import java.util.List; -+ -+public class ModuleIndex { -+ -+ private static ModuleIndex INSTANCE; -+ -+ private Project project; -+ -+ private ModuleIndex() { -+ } -+ -+ public static ModuleIndex getInstance(final Project project) { -+ if (null == INSTANCE) { -+ INSTANCE = new ModuleIndex(); -+ } -+ INSTANCE.project = project; -+ -+ return INSTANCE; -+ } -+ -+ public List getEditableModuleNames() { -+ FileBasedIndex index = FileBasedIndex -+ .getInstance(); -+ List allModulesList = new ArrayList<>(); -+ Collection allModules = index.getAllKeys(ModuleNameIndex.KEY, project); -+ for (String moduleName : allModules) { -+ if (!moduleName.matches(RegExUtil.Magento.MODULE_NAME)) { -+ continue; -+ } -+ Collection files = index.getContainingFiles(ModuleNameIndex.KEY, moduleName, GlobalSearchScope.getScopeRestrictedByFileTypes( -+ GlobalSearchScope.allScope(project), -+ PhpFileType.INSTANCE -+ )); -+ if (files.isEmpty()) { -+ continue; -+ } -+ VirtualFile virtualFile = files.iterator().next(); -+ if (virtualFile.getPath().contains(Package.VENDOR)) { -+ continue; -+ } -+ -+ allModulesList.add(moduleName); -+ } -+ Collections.sort(allModulesList); -+ return allModulesList; -+ } -+ -+ public PsiDirectory getModuleDirectoryByModuleName(String moduleName) { -+ FileBasedIndex index = FileBasedIndex -+ .getInstance(); -+ Collection files = index.getContainingFiles(ModuleNameIndex.KEY, moduleName, GlobalSearchScope.getScopeRestrictedByFileTypes( -+ GlobalSearchScope.allScope(project), -+ PhpFileType.INSTANCE -+ )); -+ VirtualFile virtualFile = files.iterator().next(); -+ return PsiManager.getInstance(project).findDirectory(virtualFile.getParent()); -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/inspections/php/PluginInspection.java b/src/com/magento/idea/magento2plugin/inspections/php/PluginInspection.java -new file mode 100644 -index 0000000..183eced ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/inspections/php/PluginInspection.java -@@ -0,0 +1,280 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.inspections.php; -+ -+import com.intellij.codeInspection.ProblemDescriptor; -+import com.intellij.codeInspection.ProblemHighlightType; -+import com.intellij.codeInspection.ProblemsHolder; -+import com.intellij.psi.PsiElement; -+import com.intellij.psi.PsiElementVisitor; -+import com.jetbrains.php.PhpBundle; -+import com.jetbrains.php.PhpClassHierarchyUtils; -+import com.jetbrains.php.PhpIndex; -+import com.jetbrains.php.lang.PhpLangUtil; -+import com.jetbrains.php.lang.inspections.PhpInspection; -+import com.jetbrains.php.lang.psi.elements.Method; -+import com.jetbrains.php.lang.psi.elements.Parameter; -+import com.jetbrains.php.lang.psi.elements.PhpClass; -+import com.jetbrains.php.lang.psi.visitors.PhpElementVisitor; -+import com.magento.idea.magento2plugin.inspections.php.util.PhpClassImplementsInterfaceUtil; -+import com.magento.idea.magento2plugin.magento.files.Plugin; -+import com.magento.idea.magento2plugin.util.GetPhpClassByFQN; -+import com.magento.idea.magento2plugin.util.magento.plugin.GetTargetClassNamesByPluginClassName; -+import org.jetbrains.annotations.NotNull; -+import java.util.*; -+ -+public class PluginInspection extends PhpInspection { -+ -+ @NotNull -+ @Override -+ public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder problemsHolder, boolean b) { -+ return new PhpElementVisitor() { -+ private static final String pluginOnNotPublicMethodProblemDescription = "You can't declare a plugin for a not public method"; -+ private static final String pluginOnFinalClassProblemDescription = "You can't declare a plugin for a final class!"; -+ private static final String pluginOnFinalMethodProblemDescription = "You can't declare a plugin for a final method!"; -+ private static final String pluginOnStaticMethodProblemDescription = "You can't declare a plugin for a static method!"; -+ private static final String pluginOnConstructorMethodProblemDescription = "You can't declare a plugin for a __construct method!"; -+ private static final String redundantParameterProblemDescription = "Redundant parameter"; -+ private static final String possibleTypeIncompatibilityProblemDescription = "Possible type incompatibility. Consider changing the parameter according to the target method."; -+ private final Integer beforePluginExtraParamsStart = 2; -+ private final Integer afterAndAroundPluginExtraParamsStart = 3; -+ -+ private String getPluginPrefix(Method pluginMethod) { -+ String pluginMethodName = pluginMethod.getName(); -+ if (pluginMethodName.startsWith(Plugin.PluginType.around.toString())) { -+ return Plugin.PluginType.around.toString(); -+ } -+ if (pluginMethodName.startsWith(Plugin.PluginType.before.toString())) { -+ return Plugin.PluginType.before.toString(); -+ } -+ if (pluginMethodName.startsWith(Plugin.PluginType.after.toString())) { -+ return Plugin.PluginType.after.toString(); -+ } -+ -+ return null; -+ } -+ -+ public void visitPhpMethod(Method pluginMethod) { -+ String pluginPrefix = getPluginPrefix(pluginMethod); -+ if (pluginPrefix == null) { -+ return; -+ } -+ -+ PsiElement parentClass = pluginMethod.getParent(); -+ if (!(parentClass instanceof PhpClass)) { -+ return; -+ } -+ PsiElement currentClassNameIdentifier = ((PhpClass) parentClass).getNameIdentifier(); -+ String currentClass = ((PhpClass) parentClass).getFQN().substring(1); -+ GetTargetClassNamesByPluginClassName targetClassesService = GetTargetClassNamesByPluginClassName.getInstance(problemsHolder.getProject()); -+ ArrayList targetClassNames = targetClassesService.execute(currentClass); -+ PhpIndex phpIndex = PhpIndex.getInstance(problemsHolder.getProject()); -+ -+ for (String targetClassName : targetClassNames) { -+ -+ PhpClass target = GetPhpClassByFQN.getInstance(problemsHolder.getProject()).execute(targetClassName); -+ if (target == null) { -+ return; -+ } -+ checkTargetClass(currentClassNameIdentifier, target); -+ -+ String targetClassMethodName = getTargetMethodName(pluginMethod, pluginPrefix); -+ if (targetClassMethodName == null) { -+ return; -+ } -+ Method targetMethod = target.findMethodByName(targetClassMethodName); -+ if (targetMethod == null) { -+ return; -+ } -+ checkTargetMethod(pluginMethod, targetClassMethodName, targetMethod); -+ checkParametersCompatibility(pluginMethod, pluginPrefix, phpIndex, targetClassName, targetMethod); -+ } -+ } -+ -+ private void checkTargetClass(PsiElement currentClassNameIdentifier, PhpClass target) { -+ if (target.isFinal()) { -+ ProblemDescriptor[] currentResults = problemsHolder.getResultsArray(); -+ int finalClassProblems = getFinalClassProblems(currentResults); -+ if (finalClassProblems == 0) { -+ problemsHolder.registerProblem(currentClassNameIdentifier, pluginOnFinalClassProblemDescription, ProblemHighlightType.ERROR); -+ } -+ } -+ } -+ -+ private void checkTargetMethod(Method pluginMethod, String targetClassMethodName, Method targetMethod) { -+ if (targetClassMethodName.equals(Plugin.constructMethodName)) { -+ problemsHolder.registerProblem(pluginMethod.getNameIdentifier(), pluginOnConstructorMethodProblemDescription, ProblemHighlightType.ERROR); -+ } -+ if (targetMethod.isFinal()) { -+ problemsHolder.registerProblem(pluginMethod.getNameIdentifier(), pluginOnFinalMethodProblemDescription, ProblemHighlightType.ERROR); -+ } -+ if (targetMethod.isStatic()) { -+ problemsHolder.registerProblem(pluginMethod.getNameIdentifier(), pluginOnStaticMethodProblemDescription, ProblemHighlightType.ERROR); -+ } -+ if (!targetMethod.getAccess().toString().equals(Plugin.publicAccess)) { -+ problemsHolder.registerProblem(pluginMethod.getNameIdentifier(), pluginOnNotPublicMethodProblemDescription, ProblemHighlightType.ERROR); -+ } -+ } -+ -+ private void checkParametersCompatibility(Method pluginMethod, String pluginPrefix, PhpIndex phpIndex, String targetClassName, Method targetMethod) { -+ Parameter[] targetMethodParameters = targetMethod.getParameters(); -+ Parameter[] pluginMethodParameters = pluginMethod.getParameters(); -+ -+ int index = 0; -+ for (Parameter pluginMethodParameter : pluginMethodParameters) { -+ index++; -+ String declaredType = pluginMethodParameter.getDeclaredType().toString(); -+ -+ if (index == 1) { -+ String targetClassFqn = "\\".concat(targetClassName); -+ if (!checkTypeIncompatibility(targetClassFqn, declaredType, phpIndex)) { -+ problemsHolder.registerProblem(pluginMethodParameter, PhpBundle.message("inspection.wrong_param_type", new Object[]{declaredType, targetClassFqn}), ProblemHighlightType.ERROR); -+ } -+ if (!checkPossibleTypeIncompatibility(targetClassFqn, declaredType, phpIndex)) { -+ problemsHolder.registerProblem(pluginMethodParameter, possibleTypeIncompatibilityProblemDescription, ProblemHighlightType.WEAK_WARNING); -+ } -+ continue; -+ } -+ if (index == 2 && pluginPrefix.equals(Plugin.PluginType.around.toString())) { -+ if (!checkTypeIncompatibility("callable", declaredType, phpIndex)) { -+ problemsHolder.registerProblem(pluginMethodParameter, PhpBundle.message("inspection.wrong_param_type", new Object[]{declaredType, "callable"}), ProblemHighlightType.ERROR); -+ } -+ continue; -+ } -+ if (index == 2 && pluginPrefix.equals(Plugin.PluginType.after.toString()) && -+ !targetMethod.getDeclaredType().toString().equals("void")) { -+ if (declaredType.isEmpty() || targetMethod.getDeclaredType().toString().isEmpty()) { -+ continue; -+ } -+ if (!checkTypeIncompatibility(targetMethod.getDeclaredType().toString(), declaredType, phpIndex)) { -+ problemsHolder.registerProblem(pluginMethodParameter, PhpBundle.message("inspection.wrong_param_type", new Object[]{declaredType, targetMethod.getDeclaredType().toString()}), ProblemHighlightType.ERROR); -+ } -+ if (!checkPossibleTypeIncompatibility(targetMethod.getDeclaredType().toString(), declaredType, phpIndex)) { -+ problemsHolder.registerProblem(pluginMethodParameter, possibleTypeIncompatibilityProblemDescription, ProblemHighlightType.WEAK_WARNING); -+ } -+ continue; -+ } -+ if (index == 2 && pluginPrefix.equals(Plugin.PluginType.after.toString()) && -+ targetMethod.getDeclaredType().toString().equals("void")) { -+ if (declaredType.isEmpty()) { -+ continue; -+ } -+ if (!declaredType.equals("null")) { -+ problemsHolder.registerProblem(pluginMethodParameter, PhpBundle.message("inspection.wrong_param_type", new Object[]{declaredType, "null"}), ProblemHighlightType.ERROR); -+ } -+ continue; -+ } -+ int targetParameterKey = index - (pluginPrefix.equals(Plugin.PluginType.before.toString()) ? -+ beforePluginExtraParamsStart : -+ afterAndAroundPluginExtraParamsStart); -+ if (targetMethodParameters.length <= targetParameterKey) { -+ problemsHolder.registerProblem(pluginMethodParameter, redundantParameterProblemDescription, ProblemHighlightType.ERROR); -+ continue; -+ } -+ Parameter targetMethodParameter = targetMethodParameters[targetParameterKey]; -+ String targetMethodParameterDeclaredType = targetMethodParameter.getDeclaredType().toString(); -+ -+ if (!checkTypeIncompatibility(targetMethodParameterDeclaredType, declaredType, phpIndex)) { -+ problemsHolder.registerProblem(pluginMethodParameter, PhpBundle.message("inspection.wrong_param_type", new Object[]{declaredType, targetMethodParameterDeclaredType}), ProblemHighlightType.ERROR); -+ } -+ if (!checkPossibleTypeIncompatibility(targetMethodParameterDeclaredType, declaredType, phpIndex)) { -+ problemsHolder.registerProblem(pluginMethodParameter, possibleTypeIncompatibilityProblemDescription, ProblemHighlightType.WEAK_WARNING); -+ } -+ } -+ } -+ -+ -+ -+ private String getTargetMethodName(Method pluginMethod, String pluginPrefix) { -+ String pluginMethodName = pluginMethod.getName(); -+ String targetClassMethodName = pluginMethodName. -+ replace(pluginPrefix, ""); -+ char firstCharOfTargetName = targetClassMethodName.charAt(0); -+ int charType = Character.getType(firstCharOfTargetName); -+ if (charType == Character.LOWERCASE_LETTER) { -+ return null; -+ } -+ return Character.toLowerCase(firstCharOfTargetName) + targetClassMethodName.substring(1); -+ } -+ -+ private int getFinalClassProblems(ProblemDescriptor[] currentResults) { -+ int finalClassProblems = 0; -+ for (ProblemDescriptor currentProblem : currentResults) { -+ if (currentProblem.getDescriptionTemplate().equals(pluginOnFinalClassProblemDescription)) { -+ finalClassProblems++; -+ } -+ } -+ return finalClassProblems; -+ } -+ -+ -+ private boolean checkTypeIncompatibility(String targetType, String declaredType, PhpIndex phpIndex) { -+ if (targetType.isEmpty() || declaredType.isEmpty()) { -+ return true; -+ } -+ -+ if (declaredType.equals(targetType)) { -+ return true; -+ } -+ -+ boolean isDeclaredTypeClass = PhpLangUtil.isFqn(declaredType); -+ boolean isTargetTypeClass = PhpLangUtil.isFqn(targetType); -+ if (!isTargetTypeClass && isDeclaredTypeClass) { -+ return false; -+ } -+ -+ GetPhpClassByFQN getPhpClassByFQN = GetPhpClassByFQN.getInstance(problemsHolder.getProject()); -+ PhpClass targetClass = getPhpClassByFQN.execute(targetType); -+ PhpClass declaredClass = getPhpClassByFQN.execute(declaredType); -+ if (targetClass == null || declaredClass == null) { -+ return false; -+ } -+ -+ if (declaredClass.isInterface() && PhpClassImplementsInterfaceUtil.execute(declaredClass, targetClass)) { -+ return true; -+ } -+ -+ if (PhpClassHierarchyUtils.classesEqual(targetClass, declaredClass)) { -+ return true; -+ } -+ -+ if (PhpClassHierarchyUtils.isSuperClass(targetClass, declaredClass, false)) { -+ return true; -+ } -+ -+ if (targetClass.isInterface() && PhpClassImplementsInterfaceUtil.execute(targetClass, declaredClass)) { -+ return true; -+ } -+ -+ if (PhpClassHierarchyUtils.isSuperClass(declaredClass, targetClass, false)) { -+ return true; -+ } -+ -+ return false; -+ } -+ -+ private boolean checkPossibleTypeIncompatibility(String targetType, String declaredType, PhpIndex phpIndex) { -+ if (targetType.isEmpty() || declaredType.isEmpty()) { -+ return true; -+ } -+ -+ GetPhpClassByFQN getPhpClassByFQN = GetPhpClassByFQN.getInstance(problemsHolder.getProject()); -+ PhpClass targetClass = getPhpClassByFQN.execute(targetType); -+ PhpClass declaredClass = getPhpClassByFQN.execute(declaredType); -+ if (targetClass == null || declaredClass == null) { -+ return true; -+ } -+ if (PhpClassHierarchyUtils.isSuperClass(declaredClass, targetClass, false)) { -+ return false; -+ } -+ if (targetClass.isInterface() && PhpClassImplementsInterfaceUtil.execute(targetClass, declaredClass)) { -+ return false; -+ } -+ -+ return true; -+ } -+ }; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/inspections/php/util/PhpClassImplementsInterfaceUtil.java b/src/com/magento/idea/magento2plugin/inspections/php/util/PhpClassImplementsInterfaceUtil.java -new file mode 100644 -index 0000000..48b9f60 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/inspections/php/util/PhpClassImplementsInterfaceUtil.java -@@ -0,0 +1,29 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.inspections.php.util; -+ -+import com.jetbrains.php.lang.psi.elements.PhpClass; -+import org.jetbrains.annotations.NotNull; -+ -+public class PhpClassImplementsInterfaceUtil { -+ -+ public static boolean execute(@NotNull PhpClass interfaceClass, @NotNull PhpClass subClass) { -+ if (!interfaceClass.isInterface()) { -+ return false; -+ } -+ PhpClass[] interfaces = subClass.getImplementedInterfaces(); -+ if (interfaces.length == 0) { -+ return false; -+ } -+ for (PhpClass targetInterfaceClass: interfaces) { -+ if (!targetInterfaceClass.getFQN().equals(interfaceClass.getFQN())) { -+ continue; -+ } -+ return true; -+ } -+ -+ return false; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/inspections/xml/CacheableFalseInDefaultLayoutInspection.java b/src/com/magento/idea/magento2plugin/inspections/xml/CacheableFalseInDefaultLayoutInspection.java -new file mode 100644 -index 0000000..f99f431 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/inspections/xml/CacheableFalseInDefaultLayoutInspection.java -@@ -0,0 +1,40 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.inspections.xml; -+ -+import com.intellij.codeInspection.ProblemHighlightType; -+import com.intellij.codeInspection.ProblemsHolder; -+import com.intellij.codeInspection.XmlSuppressableInspectionTool; -+import com.intellij.psi.PsiElementVisitor; -+import com.intellij.psi.XmlElementVisitor; -+import com.intellij.psi.xml.XmlAttribute; -+import com.magento.idea.magento2plugin.inspections.xml.fix.XmlRemoveCacheableAttributeQuickFix; -+import com.magento.idea.magento2plugin.magento.files.LayoutXml; -+import org.jetbrains.annotations.NotNull; -+ -+public class CacheableFalseInDefaultLayoutInspection extends XmlSuppressableInspectionTool { -+ @NotNull -+ @Override -+ public PsiElementVisitor buildVisitor(final @NotNull ProblemsHolder holder, final boolean isOnTheFly) { -+ return new XmlElementVisitor() { -+ private static final String CacheDisableProblemDescription = "Cacheable false attribute on the default layout will disable cache site-wide"; -+ @Override -+ public void visitXmlAttribute(XmlAttribute attribute) { -+ String fileName = holder.getFile().getName(); -+ if (!fileName.equals(LayoutXml.DefaultFileName)) return; -+ final String text = attribute.getValue(); -+ final String attributeName = attribute.getName(); -+ if (!attributeName.equals(LayoutXml.CacheableAttributeName)) return; -+ if (!attribute.getParent().getName().equals(LayoutXml.BlockAttributeTagName)) return; -+ if (text == null) return; -+ if (text.equals(LayoutXml.CacheableAttributeFalseValue)) { -+ holder.registerProblem(attribute, CacheDisableProblemDescription, -+ ProblemHighlightType.WARNING, -+ new XmlRemoveCacheableAttributeQuickFix()); -+ } -+ } -+ }; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/inspections/xml/ObserverDeclarationInspection.java b/src/com/magento/idea/magento2plugin/inspections/xml/ObserverDeclarationInspection.java -new file mode 100644 -index 0000000..e953ff8 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/inspections/xml/ObserverDeclarationInspection.java -@@ -0,0 +1,271 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+ -+package com.magento.idea.magento2plugin.inspections.xml; -+ -+import com.intellij.codeInspection.ProblemHighlightType; -+import com.intellij.codeInspection.ProblemsHolder; -+import com.intellij.ide.highlighter.XmlFileType; -+import com.intellij.openapi.vfs.VirtualFile; -+import com.intellij.psi.*; -+import com.intellij.psi.search.GlobalSearchScope; -+import com.intellij.psi.util.PsiTreeUtil; -+import com.intellij.psi.xml.XmlAttribute; -+import com.intellij.psi.xml.XmlAttributeValue; -+import com.intellij.psi.xml.XmlDocument; -+import com.intellij.psi.xml.XmlTag; -+import com.jetbrains.php.lang.inspections.PhpInspection; -+import com.magento.idea.magento2plugin.indexes.EventIndex; -+import com.magento.idea.magento2plugin.magento.files.ModuleXml; -+import com.magento.idea.magento2plugin.magento.packages.Package; -+import org.jetbrains.annotations.NotNull; -+import java.net.MalformedURLException; -+import java.net.URL; -+import java.util.*; -+ -+import com.intellij.openapi.vfs.VfsUtil; -+import org.jetbrains.annotations.Nullable; -+ -+public class ObserverDeclarationInspection extends PhpInspection { -+ -+ @NotNull -+ @Override -+ public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder problemsHolder, boolean b) { -+ return new XmlElementVisitor() { -+ private final String moduleXmlFileName = ModuleXml.getInstance().getFileName(); -+ private static final String eventsXmlFileName = "events.xml"; -+ private static final String duplicatedObserverNameSameFileProblemDescription = "The observer name already used in this file. For more details see Inspection Description."; -+ private static final String duplicatedObserverNameProblemDescription = -+ "The observer name \"%s\" for event \"%s\" is already used in the module \"%s\" (%s scope). For more details see Inspection Description."; -+ private HashMap loadedFileHash = new HashMap<>(); -+ private final ProblemHighlightType errorSeverity = ProblemHighlightType.WARNING; -+ -+ @Override -+ public void visitFile(PsiFile file) { -+ if (!file.getName().equals(eventsXmlFileName)) { -+ return; -+ } -+ -+ XmlTag[] xmlTags = getFileXmlTags(file); -+ EventIndex eventIndex = EventIndex.getInstance(file.getProject()); -+ -+ if (xmlTags == null) { -+ return; -+ } -+ -+ HashMap targetObserversHash = new HashMap<>(); -+ -+ for (XmlTag eventXmlTag: xmlTags) { -+ HashMap eventProblems = new HashMap<>(); -+ if (!eventXmlTag.getName().equals("event")) { -+ continue; -+ } -+ -+ XmlAttribute eventNameAttribute = eventXmlTag.getAttribute("name"); -+ -+ String eventNameAttributeValue = eventNameAttribute.getValue(); -+ if (eventNameAttributeValue == null) { -+ continue; -+ } -+ -+ List targetObservers = fetchObserverTagsFromEventTag(eventXmlTag); -+ -+ for (XmlTag observerXmlTag: targetObservers) { -+ XmlAttribute observerNameAttribute = observerXmlTag.getAttribute("name"); -+ XmlAttribute observerDisabledAttribute = observerXmlTag.getAttribute("disabled"); -+ -+ if (observerNameAttribute == null || (observerDisabledAttribute != null && observerDisabledAttribute.getValue().equals("true"))) { -+ continue; -+ } -+ -+ String observerName = observerNameAttribute.getValue(); -+ String observerKey = eventNameAttributeValue.concat("_").concat(observerName); -+ if (targetObserversHash.containsKey(observerKey)) { -+ problemsHolder.registerProblem( -+ observerNameAttribute.getValueElement(), -+ duplicatedObserverNameSameFileProblemDescription, -+ errorSeverity -+ ); -+ } -+ targetObserversHash.put(observerKey, observerXmlTag); -+ -+ List> modulesWithSameObserverName = fetchModuleNamesWhereSameObserverNameUsed(eventNameAttributeValue, observerName, eventIndex, file); -+ for (HashMap moduleEntry: modulesWithSameObserverName) { -+ Map.Entry module = moduleEntry.entrySet().iterator().next(); -+ String moduleName = module.getKey(); -+ String scope = module.getValue(); -+ String problemKey = observerKey.concat("_").concat(moduleName).concat("_").concat(scope); -+ if (!eventProblems.containsKey(problemKey)){ -+ problemsHolder.registerProblem( -+ observerNameAttribute.getValueElement(), -+ String.format( -+ duplicatedObserverNameProblemDescription, -+ observerName, -+ eventNameAttributeValue, -+ moduleName, -+ scope -+ ), -+ errorSeverity -+ ); -+ eventProblems.put(problemKey, observerXmlTag); -+ } -+ } -+ } -+ } -+ } -+ -+ private List> fetchModuleNamesWhereSameObserverNameUsed(String eventNameAttributeValue, String observerName, EventIndex eventIndex, PsiFile file) { -+ List> modulesName = new ArrayList<>(); -+ String currentFileDirectory = file.getContainingDirectory().toString(); -+ String currentFileFullPath = currentFileDirectory.concat("/").concat(file.getName()); -+ -+ Collection indexedEvents = eventIndex.getEventElements(eventNameAttributeValue, GlobalSearchScope.getScopeRestrictedByFileTypes( -+ GlobalSearchScope.allScope(file.getProject()), -+ XmlFileType.INSTANCE -+ )); -+ -+ for (PsiElement indexedEvent: indexedEvents) { -+ PsiFile indexedAttributeParent = PsiTreeUtil.getTopmostParentOfType(indexedEvent, PsiFile.class); -+ if (indexedAttributeParent == null) { -+ continue; -+ } -+ -+ String indexedEventAttributeValue = ((XmlAttributeValue) indexedEvent).getValue(); -+ if (!indexedEventAttributeValue.equals(eventNameAttributeValue)) { -+ continue; -+ } -+ -+ String indexedFileDirectory = indexedAttributeParent.getContainingDirectory().toString(); -+ String indexedFileFullPath = indexedFileDirectory.concat("/").concat(indexedAttributeParent.getName()); -+ if (indexedFileFullPath.equals(currentFileFullPath)) { -+ continue; -+ } -+ -+ String scope = getAreaFromFileDirectory(indexedAttributeParent); -+ -+ List indexObserversTags = fetchObserverTagsFromEventTag((XmlTag) indexedEvent.getParent().getParent()); -+ for (XmlTag indexObserversTag: indexObserversTags) { -+ XmlAttribute indexedObserverNameAttribute = indexObserversTag.getAttribute("name"); -+ if (indexedObserverNameAttribute == null) { -+ continue; -+ } -+ if (!observerName.equals(indexedObserverNameAttribute.getValue())){ -+ continue; -+ } -+ addModuleNameWhereSameObserverUsed(modulesName, indexedAttributeParent, scope); -+ } -+ } -+ -+ return modulesName; -+ } -+ -+ private List fetchObserverTagsFromEventTag(XmlTag eventXmlTag) { -+ List result = new ArrayList<>(); -+ XmlTag[] observerXmlTags = PsiTreeUtil.getChildrenOfType(eventXmlTag, XmlTag.class); -+ if (observerXmlTags == null) { -+ return result; -+ } -+ -+ for (XmlTag observerXmlTag: observerXmlTags) { -+ if (!observerXmlTag.getName().equals("observer")) { -+ continue; -+ } -+ -+ result.add(observerXmlTag); -+ } -+ -+ return result; -+ } -+ -+ private void addModuleNameWhereSameObserverUsed(List> modulesName, PsiFile indexedFile, String scope) { -+ XmlTag moduleDeclarationTag = getModuleDeclarationTagByConfigFile(indexedFile); -+ if (moduleDeclarationTag == null) return; -+ -+ if (!moduleDeclarationTag.getName().equals("module")) { -+ return; -+ } -+ XmlAttribute moduleNameAttribute = moduleDeclarationTag.getAttribute("name"); -+ if (moduleNameAttribute == null) { -+ return; -+ } -+ -+ HashMap moduleEntry = new HashMap<>(); -+ -+ moduleEntry.put(moduleNameAttribute.getValue(), scope); -+ modulesName.add(moduleEntry); -+ } -+ -+ @Nullable -+ private XmlTag getModuleDeclarationTagByConfigFile(PsiFile file) { -+ String fileDirectory = file.getContainingDirectory().toString(); -+ String fileArea = file.getContainingDirectory().getName(); -+ String moduleXmlFilePath = getModuleXmlFilePathByConfigFileDirectory(fileDirectory, fileArea); -+ -+ VirtualFile virtualFile = getFileByPath(moduleXmlFilePath); -+ if (virtualFile == null) return null; -+ -+ PsiFile moduleDeclarationFile = PsiManager.getInstance(file.getProject()).findFile(virtualFile); -+ XmlTag[] moduleDeclarationTags = getFileXmlTags(moduleDeclarationFile); -+ if (moduleDeclarationTags == null) { -+ return null; -+ } -+ return moduleDeclarationTags[0]; -+ } -+ -+ @Nullable -+ private VirtualFile getFileByPath(String moduleXmlFilePath) { -+ if (loadedFileHash.containsKey(moduleXmlFilePath)) { -+ return loadedFileHash.get(moduleXmlFilePath); -+ } -+ VirtualFile virtualFile; -+ try { -+ virtualFile = VfsUtil.findFileByURL(new URL(moduleXmlFilePath)); -+ } catch (MalformedURLException e) { -+ return null; -+ } -+ if (virtualFile == null) { -+ return null; -+ } -+ loadedFileHash.put(moduleXmlFilePath, virtualFile); -+ return virtualFile; -+ } -+ -+ private String getModuleXmlFilePathByConfigFileDirectory(String fileDirectory, String fileArea) { -+ String moduleXmlFile = fileDirectory.replace(fileArea, "").concat(moduleXmlFileName); -+ if (fileDirectory.endsWith("etc")) { -+ moduleXmlFile = fileDirectory.concat("/").concat(moduleXmlFileName); -+ } -+ return moduleXmlFile.replace("PsiDirectory:", "file:"); -+ } -+ -+ @Nullable -+ private XmlTag[] getFileXmlTags(PsiFile file) { -+ XmlDocument xmlDocument = PsiTreeUtil.getChildOfType(file, XmlDocument.class); -+ XmlTag xmlRootTag = PsiTreeUtil.getChildOfType(xmlDocument, XmlTag.class); -+ return PsiTreeUtil.getChildrenOfType(xmlRootTag, XmlTag.class); -+ } -+ -+ private String getAreaFromFileDirectory(@NotNull PsiFile file) { -+ if (file.getParent() == null) { -+ return ""; -+ } -+ -+ String areaFromFileDirectory = file.getParent().getName(); -+ -+ if (areaFromFileDirectory.equals(Package.MODULE_BASE_AREA_DIR)) { -+ return Package.Areas.base.toString(); -+ } -+ -+ for (Package.Areas area: Package.Areas.values()) { -+ if (area.toString().equals(areaFromFileDirectory)) { -+ return area.toString(); -+ } -+ } -+ -+ return ""; -+ } -+ }; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/inspections/xml/fix/XmlRemoveCacheableAttributeQuickFix.java b/src/com/magento/idea/magento2plugin/inspections/xml/fix/XmlRemoveCacheableAttributeQuickFix.java -new file mode 100644 -index 0000000..6b74347 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/inspections/xml/fix/XmlRemoveCacheableAttributeQuickFix.java -@@ -0,0 +1,23 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.inspections.xml.fix; -+ -+import com.intellij.codeInspection.LocalQuickFix; -+import com.intellij.codeInspection.ProblemDescriptor; -+import com.intellij.openapi.project.Project; -+import org.jetbrains.annotations.NotNull; -+ -+public class XmlRemoveCacheableAttributeQuickFix implements LocalQuickFix { -+ @NotNull -+ @Override -+ public String getFamilyName() { -+ return "Remove cacheable attribute"; -+ } -+ -+ @Override -+ public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { -+ descriptor.getPsiElement().delete(); -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/magento/files/ComposerJson.java b/src/com/magento/idea/magento2plugin/magento/files/ComposerJson.java -new file mode 100644 -index 0000000..98b05a2 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/magento/files/ComposerJson.java -@@ -0,0 +1,36 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.magento.files; -+ -+import com.intellij.json.JsonLanguage; -+import com.intellij.lang.Language; -+ -+public class ComposerJson implements ModuleFileInterface { -+ public static String FILE_NAME = "composer.json"; -+ public static String TEMPLATE = "Magento Module Composer"; -+ private static ComposerJson INSTANCE = null; -+ -+ public static ComposerJson getInstance() { -+ if (null == INSTANCE) { -+ INSTANCE = new ComposerJson(); -+ } -+ return INSTANCE; -+ } -+ -+ @Override -+ public String getFileName() { -+ return FILE_NAME; -+ } -+ -+ @Override -+ public String getTemplate() { -+ return TEMPLATE; -+ } -+ -+ @Override -+ public Language getLanguage() { -+ return JsonLanguage.INSTANCE; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/magento/files/LayoutXml.java b/src/com/magento/idea/magento2plugin/magento/files/LayoutXml.java -new file mode 100644 -index 0000000..647e2ce ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/magento/files/LayoutXml.java -@@ -0,0 +1,12 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.magento.files; -+ -+public class LayoutXml { -+ public static String DefaultFileName = "default.xml"; -+ public static String CacheableAttributeName = "cacheable"; -+ public static String CacheableAttributeFalseValue = "false"; -+ public static String BlockAttributeTagName = "block"; -+} -diff --git a/src/com/magento/idea/magento2plugin/magento/files/ModuleDiXml.java b/src/com/magento/idea/magento2plugin/magento/files/ModuleDiXml.java -new file mode 100644 -index 0000000..6dfc1c8 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/magento/files/ModuleDiXml.java -@@ -0,0 +1,49 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.magento.files; -+ -+import com.intellij.lang.Language; -+import com.intellij.lang.xml.XMLLanguage; -+ -+public class ModuleDiXml implements ModuleFileInterface { -+ public static String FILE_NAME = "di.xml"; -+ public static String TEMPLATE = "Magento Module DI Xml"; -+ -+ //code templates -+ public static String TEMPLATE_PLUGIN = "Magento Module DI Xml Plugin"; -+ public static String TEMPLATE_PREFERENCE = "Magento Module DI Xml Preference"; -+ -+ //tags -+ public static String PLUGIN_TYPE_TAG = "type"; -+ public static String PLUGIN_TYPE_ATTRIBUTE = "type"; -+ public static String PLUGIN_TAG_NAME = "plugin"; -+ public static String PLUGIN_TYPE_ATTR_NAME = "name"; -+ public static String PREFERENCE_TAG_NAME = "preference"; -+ public static String PREFERENCE_ATTR_FOR = "for"; -+ -+ private static ModuleDiXml INSTANCE = null; -+ -+ public static ModuleDiXml getInstance() { -+ if (null == INSTANCE) { -+ INSTANCE = new ModuleDiXml(); -+ } -+ return INSTANCE; -+ } -+ -+ @Override -+ public String getFileName() { -+ return FILE_NAME; -+ } -+ -+ @Override -+ public String getTemplate() { -+ return TEMPLATE; -+ } -+ -+ @Override -+ public Language getLanguage() { -+ return XMLLanguage.INSTANCE; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/magento/files/ModuleFileInterface.java b/src/com/magento/idea/magento2plugin/magento/files/ModuleFileInterface.java -new file mode 100644 -index 0000000..918e3b0 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/magento/files/ModuleFileInterface.java -@@ -0,0 +1,13 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.magento.files; -+ -+import com.intellij.lang.Language; -+ -+public interface ModuleFileInterface { -+ public String getFileName(); -+ public String getTemplate(); -+ public Language getLanguage(); -+} -diff --git a/src/com/magento/idea/magento2plugin/magento/files/ModuleXml.java b/src/com/magento/idea/magento2plugin/magento/files/ModuleXml.java -new file mode 100644 -index 0000000..9da3070 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/magento/files/ModuleXml.java -@@ -0,0 +1,36 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.magento.files; -+ -+import com.intellij.lang.Language; -+import com.intellij.lang.xml.XMLLanguage; -+ -+public class ModuleXml implements ModuleFileInterface { -+ public static String FILE_NAME = "module.xml"; -+ public static String TEMPLATE = "Magento Module Xml"; -+ private static ModuleXml INSTANCE = null; -+ -+ public static ModuleXml getInstance() { -+ if (null == INSTANCE) { -+ INSTANCE = new ModuleXml(); -+ } -+ return INSTANCE; -+ } -+ -+ @Override -+ public String getFileName() { -+ return FILE_NAME; -+ } -+ -+ @Override -+ public String getTemplate() { -+ return TEMPLATE; -+ } -+ -+ @Override -+ public Language getLanguage() { -+ return XMLLanguage.INSTANCE; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/magento/files/PhpPreference.java b/src/com/magento/idea/magento2plugin/magento/files/PhpPreference.java -new file mode 100644 -index 0000000..eade2bc ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/magento/files/PhpPreference.java -@@ -0,0 +1,42 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.magento.files; -+ -+import com.intellij.lang.Language; -+import com.jetbrains.php.lang.PhpLanguage; -+ -+public class PhpPreference implements ModuleFileInterface { -+ public static String TEMPLATE = "Magento Php Preference Class"; -+ -+ private static PhpPreference INSTANCE = null; -+ private String fileName; -+ -+ public static PhpPreference getInstance(String className) { -+ if (null == INSTANCE) { -+ INSTANCE = new PhpPreference(); -+ } -+ INSTANCE.setFileName(className.concat(".php")); -+ return INSTANCE; -+ } -+ -+ @Override -+ public String getFileName() { -+ return this.fileName; -+ } -+ -+ @Override -+ public String getTemplate() { -+ return TEMPLATE; -+ } -+ -+ @Override -+ public Language getLanguage() { -+ return PhpLanguage.INSTANCE; -+ } -+ -+ private void setFileName(String filename) { -+ this.fileName = filename; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/magento/files/Plugin.java b/src/com/magento/idea/magento2plugin/magento/files/Plugin.java -new file mode 100644 -index 0000000..61f0ff4 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/magento/files/Plugin.java -@@ -0,0 +1,83 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.magento.files; -+ -+import com.intellij.lang.Language; -+import com.jetbrains.php.lang.PhpLanguage; -+ -+public class Plugin implements ModuleFileInterface { -+ public static String TEMPLATE = "PHP Class"; -+ public static final String BEFORE_METHOD_TEMPLATE_NAME = "Magento Plugin Before Method"; -+ public static final String AROUND_METHOD_TEMPLATE_NAME = "Magento Plugin Around Method"; -+ public static final String AFTER_METHOD_TEMPLATE_NAME = "Magento Plugin After Method"; -+ -+ public static enum PluginType { -+ before, -+ after, -+ around -+ } -+ -+ //forbidden target method -+ public static final String constructMethodName = "__construct"; -+ -+ //allowed methods access type -+ public static final String publicAccess = "public"; -+ -+ private static Plugin INSTANCE = null; -+ private String fileName; -+ -+ public static Plugin getInstance(String className) { -+ if (null == INSTANCE) { -+ INSTANCE = new Plugin(); -+ } -+ INSTANCE.setFileName(className.concat(".php")); -+ return INSTANCE; -+ } -+ -+ @Override -+ public String getFileName() { -+ return this.fileName; -+ } -+ -+ @Override -+ public String getTemplate() { -+ return TEMPLATE; -+ } -+ -+ @Override -+ public Language getLanguage() { -+ return PhpLanguage.INSTANCE; -+ } -+ -+ private void setFileName(String filename) { -+ this.fileName = filename; -+ }; -+ -+ public static String getMethodTemplateByPluginType(PluginType pluginType) -+ { -+ if (pluginType.equals(PluginType.after)) { -+ return AFTER_METHOD_TEMPLATE_NAME; -+ } -+ if (pluginType.equals(PluginType.before)) { -+ return BEFORE_METHOD_TEMPLATE_NAME; -+ } -+ if (pluginType.equals(PluginType.around)) { -+ return AROUND_METHOD_TEMPLATE_NAME; -+ } -+ return null; -+ } -+ -+ public static Plugin.PluginType getPluginTypeByString(String string) -+ { -+ for (Plugin.PluginType pluginType: Plugin.PluginType.values()) { -+ if (!pluginType.toString().equals(string)) -+ { -+ continue; -+ } -+ return pluginType; -+ } -+ return null; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/magento/files/RegistrationPhp.java b/src/com/magento/idea/magento2plugin/magento/files/RegistrationPhp.java -new file mode 100644 -index 0000000..715599d ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/magento/files/RegistrationPhp.java -@@ -0,0 +1,36 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.magento.files; -+ -+import com.intellij.lang.Language; -+import com.jetbrains.php.lang.PhpLanguage; -+ -+public class RegistrationPhp implements ModuleFileInterface { -+ public static String FILE_NAME = "registration.php"; -+ public static String TEMPLATE = "Magento Module Registration Php"; -+ private static RegistrationPhp INSTANCE = null; -+ -+ public static RegistrationPhp getInstance() { -+ if (null == INSTANCE) { -+ INSTANCE = new RegistrationPhp(); -+ } -+ return INSTANCE; -+ } -+ -+ @Override -+ public String getFileName() { -+ return FILE_NAME; -+ } -+ -+ @Override -+ public String getTemplate() { -+ return TEMPLATE; -+ } -+ -+ @Override -+ public Language getLanguage() { -+ return PhpLanguage.INSTANCE; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/magento/packages/MagentoPhpClass.java b/src/com/magento/idea/magento2plugin/magento/packages/MagentoPhpClass.java -new file mode 100644 -index 0000000..bf58853 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/magento/packages/MagentoPhpClass.java -@@ -0,0 +1,9 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.magento.packages; -+ -+public class MagentoPhpClass { -+ public static String CLOSING_TAG = "}"; -+} -diff --git a/src/com/magento/idea/magento2plugin/magento/packages/Package.java b/src/com/magento/idea/magento2plugin/magento/packages/Package.java -new file mode 100644 -index 0000000..ac37b3f ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/magento/packages/Package.java -@@ -0,0 +1,37 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.magento.packages; -+ -+import com.magento.idea.magento2plugin.magento.files.Plugin; -+ -+public class Package { -+ public static String PACKAGES_ROOT = "app/code"; -+ public static String VENDOR = "vendor"; -+ public static String MODULE_BASE_AREA_DIR = "etc"; -+ public static String VENDOR_MODULE_NAME_SEPARATOR = "_"; -+ public static String FQN_SEPARATOR = "\\"; -+ -+ public static enum Areas { -+ base, -+ adminhtml, -+ frontend, -+ crontab, -+ webapi_rest, -+ webapi_soap, -+ graphql -+ } -+ -+ public static Package.Areas getAreaByString(String string) -+ { -+ for (Package.Areas areas: Package.Areas.values()) { -+ if (!areas.toString().equals(string)) -+ { -+ continue; -+ } -+ return areas; -+ } -+ return null; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/php/linemarker/GraphQlResolverUsageLineMarkerProvider.java b/src/com/magento/idea/magento2plugin/php/linemarker/GraphQlResolverUsageLineMarkerProvider.java -new file mode 100644 -index 0000000..885e60a ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/php/linemarker/GraphQlResolverUsageLineMarkerProvider.java -@@ -0,0 +1,97 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.php.linemarker; -+ -+import com.intellij.codeInsight.daemon.LineMarkerInfo; -+import com.intellij.codeInsight.daemon.LineMarkerProvider; -+import com.intellij.codeInsight.navigation.NavigationGutterIconBuilder; -+import com.intellij.lang.jsgraphql.GraphQLIcons; -+import com.intellij.lang.jsgraphql.psi.GraphQLQuotedString; -+import com.intellij.psi.PsiElement; -+import com.intellij.psi.util.PsiTreeUtil; -+import com.jetbrains.php.lang.psi.elements.PhpClass; -+import com.magento.idea.magento2plugin.project.Settings; -+import com.magento.idea.magento2plugin.stubs.indexes.graphql.GraphQlResolverIndex; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+import java.util.ArrayList; -+import java.util.Collection; -+import java.util.HashMap; -+import java.util.List; -+ -+public class GraphQlResolverUsageLineMarkerProvider implements LineMarkerProvider { -+ @Nullable -+ @Override -+ public LineMarkerInfo getLineMarkerInfo(@NotNull PsiElement psiElement) { -+ return null; -+ } -+ -+ @Override -+ public void collectSlowLineMarkers(@NotNull List psiElements, @NotNull Collection collection) { -+ if (psiElements.size() > 0) { -+ if (!Settings.isEnabled(psiElements.get(0).getProject())) { -+ return; -+ } -+ } -+ -+ for (PsiElement psiElement : psiElements) { -+ if (psiElement instanceof PhpClass) { -+ List results; -+ -+ if (!isResolver((PhpClass) psiElement)) { -+ return; -+ } -+ GraphQlUsagesCollector collector = new GraphQlUsagesCollector(); -+ results = collector.getGraphQLUsages((PhpClass) psiElement); -+ -+ if (results.size() > 0 ) { -+ collection.add(NavigationGutterIconBuilder -+ .create(GraphQLIcons.FILE) -+ .setTargets(results) -+ .setTooltipText("Navigate to schema") -+ .createLineMarkerInfo(PsiTreeUtil.getDeepestFirst(psiElement)) -+ ); -+ } -+ } -+ } -+ } -+ -+ private boolean isResolver(PhpClass psiElement) { -+ PhpClass[] implementedInterfaces = psiElement.getImplementedInterfaces(); -+ for (PhpClass implementedInterface: implementedInterfaces) { -+ if (!implementedInterface.getFQN().equals("\\Magento\\Framework\\GraphQl\\Query\\ResolverInterface")) { -+ continue; -+ } -+ return true; -+ } -+ return false; -+ } -+ -+ private static class GraphQlUsagesCollector { -+ -+ private HashMap> graphQlCache = new HashMap<>(); -+ -+ List getGraphQLUsages(@NotNull PhpClass phpClass) { -+ List graphQLQuotedStrings = new ArrayList<>(); -+ -+ graphQLQuotedStrings.addAll(getUsages(phpClass)); -+ -+ return graphQLQuotedStrings; -+ } -+ -+ List getUsages(@NotNull PhpClass phpClass) { -+ String phpClassFQN = phpClass.getFQN(); -+ if (!graphQlCache.containsKey(phpClassFQN)) { -+ List graphQLStringValues = extractGraphQLQuotesStringsForClass(phpClass); -+ graphQlCache.put(phpClassFQN, graphQLStringValues); -+ } -+ return graphQlCache.get(phpClassFQN); -+ } -+ -+ List extractGraphQLQuotesStringsForClass(@NotNull PhpClass phpClass) { -+ return GraphQlResolverIndex.getGraphQLUsages(phpClass); -+ } -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/project/ProjectDetector.java b/src/com/magento/idea/magento2plugin/project/ProjectDetector.java -index 182632c..8f2e86d 100644 ---- a/src/com/magento/idea/magento2plugin/project/ProjectDetector.java -+++ b/src/com/magento/idea/magento2plugin/project/ProjectDetector.java -@@ -29,23 +29,23 @@ import javax.swing.event.HyperlinkEvent; - - public class ProjectDetector implements DirectoryProjectConfigurator { - @Override -- public void configureProject(Project project, @NotNull VirtualFile virtualFile, Ref ref) { -+ public void configureProject(@NotNull Project project, @NotNull VirtualFile baseDir, @NotNull Ref moduleRef, boolean newProject) { - StartupManager.getInstance(project).runWhenProjectIsInitialized(() -> { - DumbService.getInstance(project).smartInvokeLater(() -> { - if (null == VfsUtil.findRelativeFile(project.getBaseDir(), "app", "etc", "di.xml")) { - return; - } - Notification notification = new Notification("Magento", "Magento", -- "Enable Magento support for this project?", -- NotificationType.INFORMATION, new NotificationListener.Adapter() { -- @Override -- public void hyperlinkActivated(@NotNull Notification notification, @NotNull HyperlinkEvent event) { -- Settings.getInstance(project).pluginEnabled = true; -- IndexManager.manualReindex(); -- MagentoComponentManager.getInstance(project).flushModules(); -- notification.expire(); -- } -+ "Enable Magento support for this project?", -+ NotificationType.INFORMATION, new NotificationListener.Adapter() { -+ @Override -+ public void hyperlinkActivated(@NotNull Notification notification, @NotNull HyperlinkEvent event) { -+ Settings.getInstance(project).pluginEnabled = true; -+ IndexManager.manualReindex(); -+ MagentoComponentManager.getInstance(project).flushModules(); -+ notification.expire(); - } -+ } - ); - Notifications.Bus.notify(notification, project); - }); -diff --git a/src/com/magento/idea/magento2plugin/reference/js/JsReferenceContributor.java b/src/com/magento/idea/magento2plugin/reference/js/JsReferenceContributor.java -index 138b699..954c3ca 100644 ---- a/src/com/magento/idea/magento2plugin/reference/js/JsReferenceContributor.java -+++ b/src/com/magento/idea/magento2plugin/reference/js/JsReferenceContributor.java -@@ -8,6 +8,7 @@ import com.intellij.lang.javascript.patterns.JSPatterns; - import com.intellij.psi.*; - import com.magento.idea.magento2plugin.reference.provider.FilePathReferenceProvider; - import com.magento.idea.magento2plugin.reference.provider.ModuleNameReferenceProvider; -+import com.magento.idea.magento2plugin.reference.provider.RequireJsPreferenceReferenceProvider; - import com.magento.idea.magento2plugin.util.RegExUtil; - import org.jetbrains.annotations.NotNull; - -@@ -26,5 +27,10 @@ public class JsReferenceContributor extends PsiReferenceContributor { - JSPatterns.jsLiteralExpression().withText(string().matches(".*\\W" + RegExUtil.FILE_PATH + ".*")), - new FilePathReferenceProvider() - ); -+ -+ registrar.registerReferenceProvider( -+ JSPatterns.jsLiteralExpression().withText(string().matches(".*\\W" + RegExUtil.FILE_PATH + ".*")), -+ new RequireJsPreferenceReferenceProvider() -+ ); - } - } -diff --git a/src/com/magento/idea/magento2plugin/reference/provider/FilePathReferenceProvider.java b/src/com/magento/idea/magento2plugin/reference/provider/FilePathReferenceProvider.java -index c2a01a1..c877bd4 100644 ---- a/src/com/magento/idea/magento2plugin/reference/provider/FilePathReferenceProvider.java -+++ b/src/com/magento/idea/magento2plugin/reference/provider/FilePathReferenceProvider.java -@@ -10,17 +10,14 @@ import com.intellij.psi.*; - import com.intellij.psi.search.FilenameIndex; - import com.intellij.psi.search.GlobalSearchScope; - import com.intellij.util.ProcessingContext; --import com.intellij.util.indexing.FileBasedIndex; --import com.jetbrains.php.lang.PhpFileType; -+import com.magento.idea.magento2plugin.reference.provider.util.GetAllSubFilesOfVirtualFileUtil; -+import com.magento.idea.magento2plugin.reference.provider.util.GetFilePathUtil; -+import com.magento.idea.magento2plugin.reference.provider.util.GetModuleNameUtil; -+import com.magento.idea.magento2plugin.reference.provider.util.GetModuleSourceFilesUtil; - import com.magento.idea.magento2plugin.reference.xml.PolyVariantReferenceBase; --import com.magento.idea.magento2plugin.stubs.indexes.ModuleNameIndex; - import gnu.trove.THashMap; - import org.jetbrains.annotations.NotNull; -- - import java.util.*; --import java.util.function.BiConsumer; --import java.util.regex.Matcher; --import java.util.regex.Pattern; - - public class FilePathReferenceProvider extends PsiReferenceProvider { - -@@ -32,7 +29,7 @@ public class FilePathReferenceProvider extends PsiReferenceProvider { - - String origValue = element.getText(); - -- String filePath = getFilePath(element); -+ String filePath = GetFilePathUtil.getInstance().execute(origValue); - if (null == filePath) { - return PsiReference.EMPTY_ARRAY; - } -@@ -110,7 +107,7 @@ public class FilePathReferenceProvider extends PsiReferenceProvider { - { - Collection files = new ArrayList<>(); - -- String filePath = getFilePath(element); -+ String filePath = GetFilePathUtil.getInstance().execute(element.getText()); - if (null == filePath) { - return files; - } -@@ -127,7 +124,7 @@ public class FilePathReferenceProvider extends PsiReferenceProvider { - files.removeIf(f -> !f.getPath().endsWith(filePath)); - - // filter by module -- Collection vfs = getModuleSourceFiles(element); -+ Collection vfs = GetModuleSourceFilesUtil.getInstance().execute(element.getText(), element.getProject()); - if (null != vfs) { - files.removeIf(f -> { - for (VirtualFile vf : vfs) { -@@ -140,10 +137,11 @@ public class FilePathReferenceProvider extends PsiReferenceProvider { - } - } else if (isModuleNamePresent(element)) { - // extension absent -- Collection vfs = getModuleSourceFiles(element); -+ Collection vfs = GetModuleSourceFilesUtil.getInstance().execute(element.getText(), element.getProject()); - if (null != vfs) { - for (VirtualFile vf : vfs) { -- Collection vfChildren = getAllSubFiles(vf); -+ Collection vfChildren = GetAllSubFilesOfVirtualFileUtil. -+ getInstance().execute(vf); - if (null != vfChildren) { - vfChildren.removeIf(f -> { - if (!f.isDirectory()) { -@@ -163,77 +161,8 @@ public class FilePathReferenceProvider extends PsiReferenceProvider { - return files; - } - -- private Collection getModuleFile(@NotNull PsiElement element) -- { -- String moduleName = getModuleName(element); -- if (null == moduleName || moduleName.isEmpty()) { -- return null; -- } -- return FileBasedIndex.getInstance() -- .getContainingFiles(ModuleNameIndex.KEY, moduleName, -- GlobalSearchScope.getScopeRestrictedByFileTypes( -- GlobalSearchScope.allScope(element.getProject()), -- PhpFileType.INSTANCE -- ) -- ); -- } -- -- private Collection getModuleSourceFiles(@NotNull PsiElement element) -- { -- Collection virtualFiles = getModuleFile(element); -- if (null == virtualFiles) { -- return null; -- } -- virtualFiles.removeIf(vf -> !(vf != null && vf.getParent() != null)); -- Collection sourceVfs = new ArrayList<>(); -- for (VirtualFile vf : virtualFiles) { -- sourceVfs.add(vf.getParent()); -- } -- return sourceVfs; -- } -- -- private String getFilePath(@NotNull PsiElement element) -- { -- String value = element.getText(); -- String moduleName = getModuleName(element); -- if (null != moduleName && value.contains(moduleName)) { -- value = value.replace(moduleName, ""); -- } -- -- Pattern pattern = Pattern.compile("\\W?(([\\w-]+/)*[\\w\\.-]+)"); -- Matcher matcher = pattern.matcher(value); -- if (!matcher.find()) { -- return null; -- } -- -- return matcher.group(1); -- } -- -- private String getModuleName(@NotNull PsiElement element) -- { -- Pattern pattern = Pattern.compile("(([A-Z][a-zA-Z0-9]+)_([A-Z][a-zA-Z0-9]+))"); -- Matcher matcher = pattern.matcher(element.getText()); -- return matcher.find() ? matcher.group(1) : null; -- } -- - private boolean isModuleNamePresent(@NotNull PsiElement element) - { -- return getModuleName(element) != null; -- } -- -- private Collection getAllSubFiles(VirtualFile virtualFile) -- { -- Collection list = new ArrayList<>(); -- -- VfsUtilCore.visitChildrenRecursively(virtualFile, new VirtualFileVisitor() { -- @Override -- public boolean visitFile(@NotNull VirtualFile file) { -- if (!file.isDirectory()) { -- list.add(file); -- } -- return super.visitFile(file); -- } -- }); -- return list; -+ return GetModuleNameUtil.getInstance().execute(element.getText()) != null; - } - } -diff --git a/src/com/magento/idea/magento2plugin/reference/provider/RequireJsPreferenceReferenceProvider.java b/src/com/magento/idea/magento2plugin/reference/provider/RequireJsPreferenceReferenceProvider.java -new file mode 100644 -index 0000000..2cd2c13 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/reference/provider/RequireJsPreferenceReferenceProvider.java -@@ -0,0 +1,22 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.reference.provider; -+ -+import com.intellij.psi.PsiElement; -+import com.intellij.psi.PsiReference; -+import com.intellij.psi.PsiReferenceProvider; -+import com.intellij.util.ProcessingContext; -+import com.magento.idea.magento2plugin.indexes.JsIndex; -+import org.jetbrains.annotations.NotNull; -+ -+public class RequireJsPreferenceReferenceProvider extends PsiReferenceProvider { -+ -+ @NotNull -+ @Override -+ public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) { -+ JsIndex index = JsIndex.getInstance(); -+ return index.getRequireJsPreferences(element, element.getResolveScope()); -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/reference/provider/mftf/ActionGroupReferenceProvider.java b/src/com/magento/idea/magento2plugin/reference/provider/mftf/ActionGroupReferenceProvider.java -new file mode 100644 -index 0000000..8bb794f ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/reference/provider/mftf/ActionGroupReferenceProvider.java -@@ -0,0 +1,74 @@ -+package com.magento.idea.magento2plugin.reference.provider.mftf; -+ -+import com.intellij.ide.highlighter.XmlFileType; -+import com.intellij.openapi.util.TextRange; -+import com.intellij.openapi.util.text.StringUtil; -+import com.intellij.openapi.vfs.VfsUtilCore; -+import com.intellij.openapi.vfs.VirtualFile; -+import com.intellij.openapi.vfs.VirtualFileManager; -+import com.intellij.openapi.vfs.VirtualFileVisitor; -+import com.intellij.psi.*; -+import com.intellij.psi.search.FilenameIndex; -+import com.intellij.psi.search.GlobalSearchScope; -+import com.intellij.psi.util.PsiTreeUtil; -+import com.intellij.psi.xml.*; -+import com.intellij.util.ProcessingContext; -+import com.intellij.util.indexing.FileBasedIndex; -+import com.jetbrains.php.lang.PhpFileType; -+import com.jetbrains.php.lang.psi.PhpFile; -+import com.magento.idea.magento2plugin.reference.xml.PolyVariantReferenceBase; -+import com.magento.idea.magento2plugin.stubs.indexes.mftf.ActionGroupIndex; -+import com.magento.idea.magento2plugin.xml.XmlPsiTreeUtil; -+import gnu.trove.THashMap; -+import org.jetbrains.annotations.NotNull; -+ -+import java.util.ArrayList; -+import java.util.Collection; -+import java.util.List; -+import java.util.Map; -+import java.util.regex.Matcher; -+import java.util.regex.Pattern; -+ -+public class ActionGroupReferenceProvider extends PsiReferenceProvider { -+ -+ @NotNull -+ @Override -+ public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) { -+ List psiReferences = new ArrayList<>(); -+ -+ String origValue = StringUtil.unquoteString(element.getText()); -+ -+ Collection containingFiles = FileBasedIndex.getInstance() -+ .getContainingFiles( -+ ActionGroupIndex.KEY, -+ origValue, -+ GlobalSearchScope.getScopeRestrictedByFileTypes( -+ GlobalSearchScope.allScope(element.getProject()), -+ XmlFileType.INSTANCE -+ ) -+ ); -+ -+ PsiManager psiManager = PsiManager.getInstance(element.getProject()); -+ -+ List psiElements = new ArrayList<>(); -+ -+ for (VirtualFile virtualFile: containingFiles) { -+ XmlFile xmlFile = (XmlFile) psiManager.findFile(virtualFile); -+ -+ if (xmlFile == null) { -+ continue; -+ } -+ -+ Collection valueElements = XmlPsiTreeUtil -+ .findAttributeValueElements(xmlFile, "actionGroup", "name", origValue); -+ -+ psiElements.addAll(valueElements); -+ } -+ -+ if (psiElements.size() > 0) { -+ psiReferences.add(new PolyVariantReferenceBase(element, psiElements)); -+ } -+ -+ return psiReferences.toArray(new PsiReference[psiReferences.size()]); -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/reference/provider/mftf/DataReferenceProvider.java b/src/com/magento/idea/magento2plugin/reference/provider/mftf/DataReferenceProvider.java -new file mode 100644 -index 0000000..dafa829 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/reference/provider/mftf/DataReferenceProvider.java -@@ -0,0 +1,106 @@ -+package com.magento.idea.magento2plugin.reference.provider.mftf; -+ -+import com.intellij.ide.highlighter.XmlFileType; -+import com.intellij.openapi.util.text.StringUtil; -+import com.intellij.openapi.vfs.VirtualFile; -+import com.intellij.psi.PsiElement; -+import com.intellij.psi.PsiManager; -+import com.intellij.psi.PsiReference; -+import com.intellij.psi.PsiReferenceProvider; -+import com.intellij.psi.search.GlobalSearchScope; -+import com.intellij.psi.xml.XmlAttribute; -+import com.intellij.psi.xml.XmlAttributeValue; -+import com.intellij.psi.xml.XmlFile; -+import com.intellij.psi.xml.XmlTag; -+import com.intellij.util.ProcessingContext; -+import com.intellij.util.indexing.FileBasedIndex; -+import com.magento.idea.magento2plugin.reference.xml.PolyVariantReferenceBase; -+import com.magento.idea.magento2plugin.stubs.indexes.mftf.DataIndex; -+import com.magento.idea.magento2plugin.xml.XmlPsiTreeUtil; -+import org.jetbrains.annotations.NotNull; -+ -+import java.util.ArrayList; -+import java.util.Collection; -+import java.util.List; -+ -+ -+public class DataReferenceProvider extends PsiReferenceProvider { -+ -+ @NotNull -+ @Override -+ public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) { -+ List psiReferences = new ArrayList<>(); -+ -+ String origValue = StringUtil.unquoteString(element.getText()); -+ String modifiedValue = origValue.replaceAll("\\{{2}([_A-Za-z0-9.]+)(\\([^}]+\\))?\\}{2}", "$1").toString(); -+ -+ Collection containingFiles = FileBasedIndex.getInstance() -+ .getContainingFiles( -+ DataIndex.KEY, -+ modifiedValue, -+ GlobalSearchScope.getScopeRestrictedByFileTypes( -+ GlobalSearchScope.allScope(element.getProject()), -+ XmlFileType.INSTANCE -+ ) -+ ); -+ -+ PsiManager psiManager = PsiManager.getInstance(element.getProject()); -+ -+ List psiElements = new ArrayList<>(); -+ -+ for (VirtualFile virtualFile: containingFiles) { -+ XmlFile xmlFile = (XmlFile) psiManager.findFile(virtualFile); -+ -+ if (xmlFile == null) { -+ continue; -+ } -+ -+ if (!modifiedValue.contains(".")) { -+ Collection valueElements = XmlPsiTreeUtil -+ .findAttributeValueElements(xmlFile, "entity", "name", modifiedValue); -+ -+ psiElements.addAll(valueElements); -+ continue; -+ } -+ -+ -+ String[] parts = modifiedValue.split("\\."); -+ String entityName = parts[0]; -+ String dataName = parts[1]; -+ -+ XmlTag rootTag = xmlFile.getRootTag(); -+ -+ for (XmlTag entityTag: rootTag.findSubTags("entity")) { -+ if (entityTag == null) { -+ continue; -+ } -+ -+ XmlAttribute entityNameAttribute = entityTag.getAttribute("name"); -+ -+ if (entityNameAttribute == null || -+ entityNameAttribute.getValueElement() == null || -+ !entityNameAttribute.getValueElement().getValue().equals(entityName) -+ ) { -+ continue; -+ } -+ -+ for (XmlTag dataTag: entityTag.findSubTags("data")) { -+ XmlAttribute keyNameAttribute = dataTag.getAttribute("key"); -+ -+ if (keyNameAttribute != null && -+ keyNameAttribute.getValueElement() != null && -+ keyNameAttribute.getValueElement().getValue().equals(dataName) -+ ) { -+ psiElements.add(keyNameAttribute.getValueElement()); -+ } -+ } -+ } -+ } -+ -+ if (psiElements.size() > 0) { -+ psiReferences.add(new PolyVariantReferenceBase(element, psiElements)); -+ } -+ -+ return psiReferences.toArray(new PsiReference[psiReferences.size()]); -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/reference/provider/mftf/PageReferenceProvider.java b/src/com/magento/idea/magento2plugin/reference/provider/mftf/PageReferenceProvider.java -new file mode 100644 -index 0000000..3ac6927 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/reference/provider/mftf/PageReferenceProvider.java -@@ -0,0 +1,69 @@ -+package com.magento.idea.magento2plugin.reference.provider.mftf; -+ -+import com.intellij.ide.highlighter.XmlFileType; -+import com.intellij.openapi.util.text.StringUtil; -+import com.intellij.openapi.vfs.VirtualFile; -+import com.intellij.psi.PsiElement; -+import com.intellij.psi.PsiManager; -+import com.intellij.psi.PsiReference; -+import com.intellij.psi.PsiReferenceProvider; -+import com.intellij.psi.search.GlobalSearchScope; -+import com.intellij.psi.xml.XmlAttributeValue; -+import com.intellij.psi.xml.XmlFile; -+import com.intellij.util.ProcessingContext; -+import com.intellij.util.indexing.FileBasedIndex; -+import com.magento.idea.magento2plugin.reference.xml.PolyVariantReferenceBase; -+import com.magento.idea.magento2plugin.stubs.indexes.mftf.ActionGroupIndex; -+import com.magento.idea.magento2plugin.stubs.indexes.mftf.PageIndex; -+import com.magento.idea.magento2plugin.xml.XmlPsiTreeUtil; -+import org.jetbrains.annotations.NotNull; -+import sun.jvm.hotspot.debugger.Page; -+ -+import java.util.ArrayList; -+import java.util.Collection; -+import java.util.List; -+ -+public class PageReferenceProvider extends PsiReferenceProvider { -+ -+ @NotNull -+ @Override -+ public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) { -+ List psiReferences = new ArrayList<>(); -+ -+ String origValue = StringUtil.unquoteString(element.getText()); -+ String modifiedValue = origValue.replaceAll("\\{{2}([_A-Za-z0-9]+)([^}]+)?\\}{2}", "$1").toString(); -+ -+ Collection containingFiles = FileBasedIndex.getInstance() -+ .getContainingFiles( -+ PageIndex.KEY, -+ modifiedValue, -+ GlobalSearchScope.getScopeRestrictedByFileTypes( -+ GlobalSearchScope.allScope(element.getProject()), -+ XmlFileType.INSTANCE -+ ) -+ ); -+ -+ PsiManager psiManager = PsiManager.getInstance(element.getProject()); -+ -+ List psiElements = new ArrayList<>(); -+ -+ for (VirtualFile virtualFile: containingFiles) { -+ XmlFile xmlFile = (XmlFile) psiManager.findFile(virtualFile); -+ -+ if (xmlFile == null) { -+ continue; -+ } -+ -+ Collection valueElements = XmlPsiTreeUtil -+ .findAttributeValueElements(xmlFile, "page", "name", modifiedValue); -+ -+ psiElements.addAll(valueElements); -+ } -+ -+ if (psiElements.size() > 0) { -+ psiReferences.add(new PolyVariantReferenceBase(element, psiElements)); -+ } -+ -+ return psiReferences.toArray(new PsiReference[psiReferences.size()]); -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/reference/provider/mftf/SectionReferenceProvider.java b/src/com/magento/idea/magento2plugin/reference/provider/mftf/SectionReferenceProvider.java -new file mode 100644 -index 0000000..48286b9 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/reference/provider/mftf/SectionReferenceProvider.java -@@ -0,0 +1,103 @@ -+package com.magento.idea.magento2plugin.reference.provider.mftf; -+ -+import com.intellij.ide.highlighter.XmlFileType; -+import com.intellij.openapi.util.text.StringUtil; -+import com.intellij.openapi.vfs.VirtualFile; -+import com.intellij.psi.*; -+import com.intellij.psi.search.GlobalSearchScope; -+import com.intellij.psi.xml.*; -+import com.intellij.util.ProcessingContext; -+import com.intellij.util.indexing.FileBasedIndex; -+import com.magento.idea.magento2plugin.reference.xml.PolyVariantReferenceBase; -+import com.magento.idea.magento2plugin.stubs.indexes.mftf.SectionIndex; -+import org.jetbrains.annotations.NotNull; -+ -+import java.util.ArrayList; -+import java.util.Collection; -+import java.util.List; -+ -+public class SectionReferenceProvider extends PsiReferenceProvider { -+ -+ @NotNull -+ @Override -+ public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) { -+ List psiReferences = new ArrayList<>(); -+ -+ String origValue = StringUtil.unquoteString(element.getText()); -+ String modifiedValue = origValue.replaceAll(".*\\{{2}([_A-Za-z0-9.]+)(\\([^}]+\\))?\\}{2}.*", "$1").toString(); -+ -+ Collection containingFiles = FileBasedIndex.getInstance() -+ .getContainingFiles( -+ SectionIndex.KEY, -+ modifiedValue, -+ GlobalSearchScope.getScopeRestrictedByFileTypes( -+ GlobalSearchScope.allScope(element.getProject()), -+ XmlFileType.INSTANCE -+ ) -+ ); -+ -+ PsiManager psiManager = PsiManager.getInstance(element.getProject()); -+ -+ List psiElements = new ArrayList<>(); -+ -+ for (VirtualFile virtualFile: containingFiles) { -+ XmlFile xmlFile = (XmlFile) psiManager.findFile(virtualFile); -+ -+ if (xmlFile == null) { -+ continue; -+ } -+ -+ String[] parts = modifiedValue.split("\\."); -+ -+ String sectionName = parts[0]; -+ String elementName; -+ -+ boolean isSectionNameOnly = parts.length == 1; -+ -+ if (isSectionNameOnly) { -+ elementName = ""; -+ } else { -+ elementName = parts[1]; -+ } -+ -+ XmlTag rootTag = xmlFile.getRootTag(); -+ -+ for (XmlTag sectionTag: rootTag.findSubTags("section")) { -+ if (sectionTag == null) { -+ continue; -+ } -+ -+ XmlAttribute sectionNameAttribute = sectionTag.getAttribute("name"); -+ -+ if (sectionNameAttribute == null || -+ sectionNameAttribute.getValueElement() == null || -+ !sectionNameAttribute.getValueElement().getValue().equals(sectionName) -+ ) { -+ continue; -+ } -+ -+ if (isSectionNameOnly) { -+ psiElements.add(sectionNameAttribute.getValueElement()); -+ continue; -+ } -+ -+ for (XmlTag elementTag: sectionTag.findSubTags("element")) { -+ XmlAttribute elementNameAttribute = elementTag.getAttribute("name"); -+ -+ if (elementNameAttribute != null && -+ elementNameAttribute.getValueElement() != null && -+ elementNameAttribute.getValueElement().getValue().equals(elementName) -+ ) { -+ psiElements.add(elementNameAttribute.getValueElement()); -+ } -+ } -+ } -+ } -+ -+ if (psiElements.size() > 0) { -+ psiReferences.add(new PolyVariantReferenceBase(element, psiElements)); -+ } -+ -+ return psiReferences.toArray(new PsiReference[psiReferences.size()]); -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/reference/provider/mftf/VariableToStepKeyProvider.java b/src/com/magento/idea/magento2plugin/reference/provider/mftf/VariableToStepKeyProvider.java -new file mode 100644 -index 0000000..a3708da ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/reference/provider/mftf/VariableToStepKeyProvider.java -@@ -0,0 +1,65 @@ -+package com.magento.idea.magento2plugin.reference.provider.mftf; -+ -+import com.intellij.openapi.util.text.StringUtil; -+import com.intellij.psi.PsiElement; -+import com.intellij.psi.PsiReference; -+import com.intellij.psi.PsiReferenceProvider; -+import com.intellij.psi.xml.XmlAttribute; -+import com.intellij.psi.xml.XmlFile; -+import com.intellij.psi.xml.XmlTag; -+import com.intellij.util.ProcessingContext; -+import com.magento.idea.magento2plugin.reference.xml.PolyVariantReferenceBase; -+import org.jetbrains.annotations.NotNull; -+ -+import java.util.ArrayList; -+import java.util.List; -+ -+public class VariableToStepKeyProvider extends PsiReferenceProvider { -+ -+ @NotNull -+ @Override -+ public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) { -+ List psiReferences = new ArrayList<>(); -+ -+ String origValue = StringUtil.unquoteString(element.getText()); -+ -+ String modifiedValue = origValue.replaceAll("\\$", "").toString(); -+ -+ XmlFile xmlFile = (XmlFile) element.getContainingFile(); -+ XmlTag xmlRootTag = xmlFile.getRootTag(); -+ -+ for (XmlTag childTag : xmlRootTag.getSubTags()) { -+ if (childTag.getAttributeValue("name") == null || -+ childTag.getAttributeValue("name").isEmpty() -+ ) { -+ continue; -+ } -+ -+ addAttributeValue( -+ childTag, -+ element, -+ modifiedValue, -+ psiReferences -+ ); -+ } -+ -+ return psiReferences.toArray(new PsiReference[psiReferences.size()]); -+ } -+ -+ private void addAttributeValue(XmlTag parentTag, PsiElement element, String valueToMatch, List psiReferences) { -+ for (XmlTag childTag: parentTag.getSubTags()) { -+ List psiElements = new ArrayList<>(); -+ XmlAttribute stepKeyAttribute = childTag.getAttribute("stepKey"); -+ -+ if (stepKeyAttribute != null && -+ stepKeyAttribute.getValueElement() != null && -+ stepKeyAttribute.getValueElement().getValue().equals(valueToMatch) -+ ) { -+ psiElements.add(stepKeyAttribute.getValueElement()); -+ psiReferences.add(new PolyVariantReferenceBase(element, psiElements)); -+ } -+ -+ addAttributeValue(childTag, element, valueToMatch, psiReferences); -+ } -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/reference/provider/util/GetAllSubFilesOfVirtualFileUtil.java b/src/com/magento/idea/magento2plugin/reference/provider/util/GetAllSubFilesOfVirtualFileUtil.java -new file mode 100644 -index 0000000..3c0e9fe ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/reference/provider/util/GetAllSubFilesOfVirtualFileUtil.java -@@ -0,0 +1,40 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.reference.provider.util; -+ -+import com.intellij.openapi.vfs.VfsUtilCore; -+import com.intellij.openapi.vfs.VirtualFile; -+import com.intellij.openapi.vfs.VirtualFileVisitor; -+import org.jetbrains.annotations.NotNull; -+import java.util.ArrayList; -+import java.util.Collection; -+ -+public class GetAllSubFilesOfVirtualFileUtil { -+ -+ private static GetAllSubFilesOfVirtualFileUtil INSTANCE; -+ -+ public static GetAllSubFilesOfVirtualFileUtil getInstance() { -+ if (null == INSTANCE) { -+ INSTANCE = new GetAllSubFilesOfVirtualFileUtil(); -+ } -+ return INSTANCE; -+ } -+ -+ public Collection execute(VirtualFile virtualFile) -+ { -+ Collection list = new ArrayList<>(); -+ -+ VfsUtilCore.visitChildrenRecursively(virtualFile, new VirtualFileVisitor() { -+ @Override -+ public boolean visitFile(@NotNull VirtualFile file) { -+ if (!file.isDirectory()) { -+ list.add(file); -+ } -+ return super.visitFile(file); -+ } -+ }); -+ return list; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/reference/provider/util/GetFilePathUtil.java b/src/com/magento/idea/magento2plugin/reference/provider/util/GetFilePathUtil.java -new file mode 100644 -index 0000000..35e631b ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/reference/provider/util/GetFilePathUtil.java -@@ -0,0 +1,37 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.reference.provider.util; -+ -+import org.jetbrains.annotations.NotNull; -+import java.util.regex.Matcher; -+import java.util.regex.Pattern; -+ -+public class GetFilePathUtil { -+ -+ private static GetFilePathUtil INSTANCE; -+ -+ public static GetFilePathUtil getInstance() { -+ if (null == INSTANCE) { -+ INSTANCE = new GetFilePathUtil(); -+ } -+ return INSTANCE; -+ } -+ -+ public String execute(@NotNull String value) -+ { -+ String moduleName = GetModuleNameUtil.getInstance().execute(value); -+ if (null != moduleName && value.contains(moduleName)) { -+ value = value.replace(moduleName, ""); -+ } -+ -+ Pattern pattern = Pattern.compile("\\W?(([\\w-]+/)*[\\w\\.-]+)"); -+ Matcher matcher = pattern.matcher(value); -+ if (!matcher.find()) { -+ return null; -+ } -+ -+ return matcher.group(1); -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/reference/provider/util/GetModuleFileUtil.java b/src/com/magento/idea/magento2plugin/reference/provider/util/GetModuleFileUtil.java -new file mode 100644 -index 0000000..41850b4 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/reference/provider/util/GetModuleFileUtil.java -@@ -0,0 +1,41 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.reference.provider.util; -+ -+import com.intellij.openapi.project.Project; -+import com.intellij.openapi.vfs.VirtualFile; -+import com.intellij.psi.search.GlobalSearchScope; -+import com.intellij.util.indexing.FileBasedIndex; -+import com.jetbrains.php.lang.PhpFileType; -+import com.magento.idea.magento2plugin.stubs.indexes.ModuleNameIndex; -+import org.jetbrains.annotations.NotNull; -+import java.util.Collection; -+ -+public class GetModuleFileUtil { -+ -+ private static GetModuleFileUtil INSTANCE; -+ -+ public static GetModuleFileUtil getInstance() { -+ if (null == INSTANCE) { -+ INSTANCE = new GetModuleFileUtil(); -+ } -+ return INSTANCE; -+ } -+ -+ public Collection execute(@NotNull String fileName, Project project) -+ { -+ String moduleName = GetModuleNameUtil.getInstance().execute(fileName); -+ if (null == moduleName || moduleName.isEmpty()) { -+ return null; -+ } -+ return FileBasedIndex.getInstance() -+ .getContainingFiles(ModuleNameIndex.KEY, moduleName, -+ GlobalSearchScope.getScopeRestrictedByFileTypes( -+ GlobalSearchScope.allScope(project), -+ PhpFileType.INSTANCE -+ ) -+ ); -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/reference/provider/util/GetModuleNameUtil.java b/src/com/magento/idea/magento2plugin/reference/provider/util/GetModuleNameUtil.java -new file mode 100644 -index 0000000..eb807f4 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/reference/provider/util/GetModuleNameUtil.java -@@ -0,0 +1,28 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.reference.provider.util; -+ -+import org.jetbrains.annotations.NotNull; -+import java.util.regex.Matcher; -+import java.util.regex.Pattern; -+ -+public class GetModuleNameUtil { -+ -+ private static GetModuleNameUtil INSTANCE; -+ -+ public static GetModuleNameUtil getInstance() { -+ if (null == INSTANCE) { -+ INSTANCE = new GetModuleNameUtil(); -+ } -+ return INSTANCE; -+ } -+ -+ public String execute(@NotNull String fileName) -+ { -+ Pattern pattern = Pattern.compile("(([A-Z][a-zA-Z0-9]+)_([A-Z][a-zA-Z0-9]+))"); -+ Matcher matcher = pattern.matcher(fileName); -+ return matcher.find() ? matcher.group(1) : null; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/reference/provider/util/GetModuleSourceFilesUtil.java b/src/com/magento/idea/magento2plugin/reference/provider/util/GetModuleSourceFilesUtil.java -new file mode 100644 -index 0000000..2f25967 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/reference/provider/util/GetModuleSourceFilesUtil.java -@@ -0,0 +1,40 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.reference.provider.util; -+ -+import com.intellij.openapi.project.Project; -+import com.intellij.openapi.vfs.VirtualFile; -+import org.jetbrains.annotations.NotNull; -+import java.util.ArrayList; -+import java.util.Collection; -+ -+public class GetModuleSourceFilesUtil { -+ -+ private static GetModuleSourceFilesUtil INSTANCE; -+ -+ public static GetModuleSourceFilesUtil getInstance() { -+ if (null == INSTANCE) { -+ INSTANCE = new GetModuleSourceFilesUtil(); -+ } -+ return INSTANCE; -+ } -+ -+ public Collection execute(@NotNull String fileName, Project project) -+ { -+ Collection virtualFiles = GetModuleFileUtil.getInstance().execute( -+ fileName, -+ project -+ ); -+ if (null == virtualFiles) { -+ return null; -+ } -+ virtualFiles.removeIf(vf -> !(vf != null && vf.getParent() != null)); -+ Collection sourceVfs = new ArrayList<>(); -+ for (VirtualFile vf : virtualFiles) { -+ sourceVfs.add(vf.getParent()); -+ } -+ return sourceVfs; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/reference/xml/XmlReferenceContributor.java b/src/com/magento/idea/magento2plugin/reference/xml/XmlReferenceContributor.java -index 650712e..3d0346b 100644 ---- a/src/com/magento/idea/magento2plugin/reference/xml/XmlReferenceContributor.java -+++ b/src/com/magento/idea/magento2plugin/reference/xml/XmlReferenceContributor.java -@@ -10,10 +10,10 @@ import com.intellij.psi.PsiReferenceRegistrar; - import com.intellij.psi.xml.XmlTokenType; - import com.magento.idea.magento2plugin.php.util.PhpRegex; - import com.magento.idea.magento2plugin.reference.provider.*; -+import com.magento.idea.magento2plugin.reference.provider.mftf.*; - import org.jetbrains.annotations.NotNull; - --import static com.intellij.patterns.XmlPatterns.string; --import static com.intellij.patterns.XmlPatterns.xmlFile; -+import static com.intellij.patterns.XmlPatterns.*; - - public class XmlReferenceContributor extends PsiReferenceContributor { - -@@ -156,5 +156,87 @@ public class XmlReferenceContributor extends PsiReferenceContributor { - new FilePathReferenceProvider() - ) - ); -+ -+ // -+ registrar.registerReferenceProvider( -+ XmlPatterns.xmlAttributeValue().withValue(string().matches(".*\\{\\{[^\\}]+\\}\\}.*")), -+ new CompositeReferenceProvider( -+ new DataReferenceProvider(), -+ new PageReferenceProvider(), -+ new SectionReferenceProvider() -+ ) -+ ); -+ -+ // -+ registrar.registerReferenceProvider( -+ XmlPatterns.xmlAttributeValue().withParent(XmlPatterns.xmlAttribute().withName(string().oneOf("entity", "value", "userInput", "url"))), -+ new CompositeReferenceProvider( -+ new DataReferenceProvider(), -+ new SectionReferenceProvider() -+ ) -+ ); -+ -+ // -+ registrar.registerReferenceProvider( -+ XmlPatterns.xmlAttributeValue().withParent(XmlPatterns.xmlAttribute().withName("ref") -+ .withParent(XmlPatterns.xmlTag().withName("actionGroup"))), -+ new CompositeReferenceProvider( -+ new ActionGroupReferenceProvider() -+ ) -+ ); -+ -+ // <*Result type="variable">$someVariableReferenceToStepKey -+ registrar.registerReferenceProvider( -+ XmlPatterns.psiElement(XmlTokenType.XML_DATA_CHARACTERS).withParent( -+ XmlPatterns.xmlText().withParent( -+ XmlPatterns.xmlTag().withChild( -+ XmlPatterns.xmlAttribute().withName("type") -+ ) -+ ) -+ ), -+ new CompositeReferenceProvider( -+ new VariableToStepKeyProvider() -+ ) -+ ); -+ -+ // -+ registrar.registerReferenceProvider( -+ XmlPatterns.xmlAttributeValue().withParent(XmlPatterns.xmlAttribute().withName("extends") -+ .withParent(XmlPatterns.xmlTag().withName("actionGroup"))), -+ new CompositeReferenceProvider( -+ new ActionGroupReferenceProvider() -+ ) -+ ); -+ -+ // -+ registrar.registerReferenceProvider( -+ XmlPatterns.xmlAttributeValue().withParent(XmlPatterns.xmlAttribute().withName("extends") -+ .withParent(XmlPatterns.xmlTag().withName("entity"))), -+ new CompositeReferenceProvider( -+ new DataReferenceProvider() -+ ) -+ ); -+ -+ // -+ registrar.registerReferenceProvider( -+ XmlPatterns.xmlAttributeValue().withParent( -+ XmlPatterns.xmlAttribute().withName("component") -+ ), -+ new RequireJsPreferenceReferenceProvider() -+ ); -+ -+ // requireJsMappingKey -+ registrar.registerReferenceProvider( -+ XmlPatterns.psiElement(XmlTokenType.XML_DATA_CHARACTERS).withParent( -+ XmlPatterns.xmlText().withParent( -+ XmlPatterns.xmlTag().withName("item").withChild( -+ XmlPatterns.xmlAttribute().withValue(string().matches("component")) -+ ).withChild( -+ XmlPatterns.xmlAttribute().withName("name") -+ ) -+ ) -+ ), -+ new RequireJsPreferenceReferenceProvider() -+ ); - } - } -diff --git a/src/com/magento/idea/magento2plugin/stubs/indexes/graphql/GraphQlResolverIndex.java b/src/com/magento/idea/magento2plugin/stubs/indexes/graphql/GraphQlResolverIndex.java -new file mode 100644 -index 0000000..e3dd7ff ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/stubs/indexes/graphql/GraphQlResolverIndex.java -@@ -0,0 +1,168 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.stubs.indexes.graphql; -+ -+import com.intellij.lang.jsgraphql.GraphQLFileType; -+import com.intellij.lang.jsgraphql.psi.*; -+import com.intellij.openapi.vfs.VirtualFile; -+import com.intellij.psi.PsiElement; -+import com.intellij.psi.PsiManager; -+import com.intellij.psi.search.GlobalSearchScope; -+import com.intellij.util.indexing.*; -+import com.intellij.util.io.EnumeratorStringDescriptor; -+import com.intellij.util.io.KeyDescriptor; -+import com.jetbrains.php.lang.psi.elements.PhpClass; -+import com.magento.idea.magento2plugin.util.magento.graphql.GraphQlUtil; -+import org.jetbrains.annotations.NotNull; -+import java.util.*; -+ -+public class GraphQlResolverIndex extends ScalarIndexExtension { -+ public static final ID KEY -+ = ID.create("com.magento.idea.magento2plugin.stubs.indexes.resolver_usages"); -+ -+ @NotNull -+ @Override -+ public ID getName() { -+ return KEY; -+ } -+ -+ @NotNull -+ @Override -+ public DataIndexer getIndexer() { -+ return inputData -> { -+ Map map = new HashMap<>(); -+ -+ GraphQLFile graphQLFile = (GraphQLFile) inputData.getPsiFile(); -+ PsiElement[] children = graphQLFile.getChildren(); -+ for (PsiElement child : children) { -+ if (!(child instanceof GraphQLObjectTypeDefinition) && !(child instanceof GraphQLInterfaceTypeDefinition)) { -+ continue; -+ } -+ PsiElement[] objectChildren = child.getChildren(); -+ for (PsiElement objectChild : objectChildren) { -+ if (!(objectChild instanceof GraphQLFieldsDefinition)) { -+ continue; -+ } -+ PsiElement[] fieldsChildren = objectChild.getChildren(); -+ for (PsiElement fieldsChild : fieldsChildren) { -+ if (!(fieldsChild instanceof GraphQLFieldDefinition)) { -+ continue; -+ } -+ PsiElement[] fieldChildren = fieldsChild.getChildren(); -+ for (PsiElement fieldChild : fieldChildren) { -+ if (!(fieldChild instanceof GraphQLDirective)) { -+ continue; -+ } -+ if (!fieldChild.getText().startsWith("@resolver")) { -+ continue; -+ } -+ -+ PsiElement[] directiveChildren = fieldChild.getChildren(); -+ -+ for (PsiElement directiveChild : directiveChildren) { -+ if (!(directiveChild instanceof GraphQLArguments)) { -+ continue; -+ } -+ -+ PsiElement[] argumentsChildren = directiveChild.getChildren(); -+ for (PsiElement argumentsChild : argumentsChildren) { -+ if (!(argumentsChild instanceof GraphQLArgument)) { -+ continue; -+ } -+ -+ PsiElement argumentStringValue = GraphQlUtil.fetchResolverQuotedStringFromArgument(argumentsChild); -+ if (argumentStringValue == null) continue; -+ -+ String resolverFQN = argumentStringValue.getText(); -+ if (resolverFQN == null) { -+ return null; -+ } -+ -+ resolverFQN = GraphQlUtil.resolverStringToPhpFQN(resolverFQN); -+ -+ map.put(resolverFQN, null); -+ } -+ } -+ } -+ } -+ } -+ } -+ -+ return map; -+ }; -+ } -+ -+ @NotNull -+ @Override -+ public KeyDescriptor getKeyDescriptor() { -+ return new EnumeratorStringDescriptor(); -+ } -+ -+ @NotNull -+ @Override -+ public FileBasedIndex.InputFilter getInputFilter() { -+ return virtualFile -> (virtualFile.getFileType() == GraphQLFileType.INSTANCE -+ && virtualFile.getName().equals("schema.graphqls")); -+ } -+ -+ @Override -+ public boolean dependsOnFileContent() { -+ return true; -+ } -+ -+ @Override -+ public int getVersion() { -+ return 1; -+ } -+ -+ -+ public static List getGraphQLUsages(@NotNull PhpClass phpClass) { -+ List quotedStrings = new ArrayList<>(); -+ -+ String classFqn = phpClass.getFQN(); -+ Collection containingFiles = FileBasedIndex -+ .getInstance().getContainingFiles(KEY, classFqn, GlobalSearchScope.allScope(phpClass.getProject())); -+ -+ PsiManager psiManager = PsiManager.getInstance(phpClass.getProject()); -+ for (VirtualFile virtualFile : containingFiles) { -+ GraphQLFile file = (GraphQLFile) psiManager.findFile(virtualFile); -+ if (file == null) { -+ continue; -+ } -+ PsiElement[] children = file.getChildren(); -+ findMatchingQuotedString(children, classFqn, quotedStrings); -+ } -+ return quotedStrings; -+ } -+ -+ private static PsiElement findMatchingQuotedString(PsiElement[] psiElements, String classFqn, List quotedStrings) { -+ for (PsiElement element: psiElements) { -+ if (!(element instanceof GraphQLArgument) && element.getChildren().length == 0) { -+ continue; -+ } -+ if (!(element instanceof GraphQLArgument) && element.getChildren().length != 0) { -+ findMatchingQuotedString(element.getChildren(), classFqn, quotedStrings); -+ continue; -+ } -+ -+ PsiElement argumentStringValue = GraphQlUtil.fetchResolverQuotedStringFromArgument(element); -+ if (argumentStringValue == null) continue; -+ -+ String resolverFQN = argumentStringValue.getText(); -+ if (resolverFQN == null) { -+ return null; -+ } -+ -+ resolverFQN = GraphQlUtil.resolverStringToPhpFQN(resolverFQN); -+ -+ if (!resolverFQN.equals(classFqn)) { -+ continue; -+ } -+ -+ quotedStrings.add((GraphQLQuotedString) argumentStringValue.getFirstChild()); -+ } -+ return null; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/stubs/indexes/js/MagentoLibJsIndex.java b/src/com/magento/idea/magento2plugin/stubs/indexes/js/MagentoLibJsIndex.java -new file mode 100644 -index 0000000..f0bba2a ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/stubs/indexes/js/MagentoLibJsIndex.java -@@ -0,0 +1,70 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.stubs.indexes.js; -+ -+import com.intellij.lang.javascript.JavaScriptFileType; -+import com.intellij.openapi.vfs.VirtualFile; -+import com.intellij.util.indexing.*; -+import com.intellij.util.io.EnumeratorStringDescriptor; -+import com.intellij.util.io.KeyDescriptor; -+import org.jetbrains.annotations.NotNull; -+ -+import java.util.HashMap; -+import java.util.Map; -+ -+public class MagentoLibJsIndex extends ScalarIndexExtension { -+ public static final ID KEY = -+ ID.create("com.magento.idea.magento2plugin.stubs.indexes.magento_lib"); -+ -+ @NotNull -+ @Override -+ public ID getName() { -+ return KEY; -+ } -+ -+ @NotNull -+ @Override -+ public DataIndexer getIndexer() { -+ return inputData -> { -+ Map map = new HashMap<>(); -+ String libPath = inputData.getProject().getBasePath() + "/lib/web/"; -+ VirtualFile file = inputData.getFile(); -+ -+ if (!file.getPath().contains(libPath)){ -+ return map; -+ } -+ -+ String key = file.getPath().replace(libPath, ""); -+ key = key.substring(0, key.lastIndexOf('.')); -+ map.put(key, null); -+ -+ return map; -+ }; -+ } -+ -+ @NotNull -+ @Override -+ public KeyDescriptor getKeyDescriptor() { -+ return new EnumeratorStringDescriptor(); -+ } -+ -+ @NotNull -+ @Override -+ public FileBasedIndex.InputFilter getInputFilter() { -+ return virtualFile -> ( -+ virtualFile.getFileType().equals(JavaScriptFileType.INSTANCE) && virtualFile.getPath().contains("lib/web") -+ ); -+ } -+ -+ @Override -+ public boolean dependsOnFileContent() { -+ return true; -+ } -+ -+ @Override -+ public int getVersion() { -+ return 1; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/stubs/indexes/js/RequireJsIndex.java b/src/com/magento/idea/magento2plugin/stubs/indexes/js/RequireJsIndex.java -new file mode 100644 -index 0000000..4fd74fc ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/stubs/indexes/js/RequireJsIndex.java -@@ -0,0 +1,129 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.stubs.indexes.js; -+ -+import com.intellij.lang.javascript.JavaScriptFileType; -+import com.intellij.lang.javascript.psi.*; -+import com.intellij.psi.PsiElement; -+import com.intellij.psi.util.PsiTreeUtil; -+import com.intellij.util.indexing.*; -+import com.intellij.util.io.DataExternalizer; -+import com.intellij.util.io.EnumeratorStringDescriptor; -+import com.intellij.util.io.KeyDescriptor; -+import org.jetbrains.annotations.NotNull; -+import java.util.HashMap; -+import java.util.Map; -+ -+public class RequireJsIndex extends FileBasedIndexExtension { -+ public static final ID KEY = -+ ID.create("com.magento.idea.magento2plugin.stubs.indexes.require_js"); -+ -+ @NotNull -+ @Override -+ public ID getName() { -+ return KEY; -+ } -+ -+ @NotNull -+ @Override -+ public DataIndexer getIndexer() { -+ return inputData -> { -+ Map map = new HashMap<>(); -+ JSFile jsFile = (JSFile)inputData.getPsiFile(); -+ -+ JSVarStatement jsVarStatement = PsiTreeUtil.getChildOfType(jsFile, JSVarStatement.class); -+ if (jsVarStatement == null) { -+ return map; -+ } -+ JSVariable[] jsVariableList = jsVarStatement.getVariables(); -+ for (JSVariable jsVariable : jsVariableList) { -+ String name = jsVariable.getName(); -+ if (name.equals("config")) { -+ JSObjectLiteralExpression config = PsiTreeUtil.getChildOfType(jsVariable, JSObjectLiteralExpression.class); -+ if (config == null) { -+ return map; -+ } -+ parseConfigMap(map, config); -+ -+ JSProperty pathsMap = config.findProperty("paths"); -+ if (pathsMap == null) { -+ return map; -+ } -+ JSObjectLiteralExpression[] pathGroupsWrappers = PsiTreeUtil.getChildrenOfType(pathsMap, JSObjectLiteralExpression.class); -+ for (JSObjectLiteralExpression pathGroupsWrapper : pathGroupsWrappers) { -+ JSProperty[] allConfigs = pathGroupsWrapper.getProperties(); -+ for (JSProperty mapping : allConfigs) { -+ String nameConfig = mapping.getName(); -+ JSExpression value = mapping.getValue(); -+ if (value == null) { -+ continue; -+ } -+ String valueConfig = value.getText(); -+ map.put(nameConfig, valueConfig); -+ } -+ } -+ } -+ } -+ -+ return map; -+ }; -+ } -+ -+ private void parseConfigMap(Map map, JSObjectLiteralExpression config) { -+ JSProperty configMap = config.findProperty("map"); -+ if (configMap == null) { -+ return; -+ } -+ -+ JSObjectLiteralExpression[] configGroupsWrappers = PsiTreeUtil.getChildrenOfType(configMap, JSObjectLiteralExpression.class); -+ for (JSObjectLiteralExpression configGroupsWrapper : configGroupsWrappers) { -+ PsiElement[] configGroups = configGroupsWrapper.getChildren(); -+ -+ for (PsiElement configGroup : configGroups) { -+ JSObjectLiteralExpression mappingWrapper = PsiTreeUtil.getChildOfType(configGroup, JSObjectLiteralExpression.class); -+ JSProperty[] allConfigs = mappingWrapper.getProperties(); -+ -+ for (JSProperty mapping : allConfigs) { -+ String nameConfig = mapping.getName(); -+ JSExpression value = mapping.getValue(); -+ if (value == null) { -+ continue; -+ } -+ String valueConfig = value.getText(); -+ map.put(nameConfig, valueConfig); -+ } -+ } -+ } -+ } -+ -+ @NotNull -+ @Override -+ public KeyDescriptor getKeyDescriptor() { -+ return new EnumeratorStringDescriptor(); -+ } -+ -+ @NotNull -+ @Override -+ public FileBasedIndex.InputFilter getInputFilter() { -+ return virtualFile -> ( -+ virtualFile.getFileType().equals(JavaScriptFileType.INSTANCE) && virtualFile.getName().equals("requirejs-config.js") -+ ); -+ } -+ -+ @Override -+ public boolean dependsOnFileContent() { -+ return true; -+ } -+ -+ @Override -+ public int getVersion() { -+ return 1; -+ } -+ -+ @NotNull -+ public DataExternalizer getValueExternalizer() { -+ return EnumeratorStringDescriptor.INSTANCE; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/stubs/indexes/mftf/ActionGroupIndex.java b/src/com/magento/idea/magento2plugin/stubs/indexes/mftf/ActionGroupIndex.java -new file mode 100644 -index 0000000..3990b0a ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/stubs/indexes/mftf/ActionGroupIndex.java -@@ -0,0 +1,108 @@ -+package com.magento.idea.magento2plugin.stubs.indexes.mftf; -+ -+import com.intellij.ide.highlighter.XmlFileType; -+import com.intellij.psi.PsiFile; -+import com.intellij.psi.util.PsiTreeUtil; -+import com.intellij.psi.xml.XmlDocument; -+import com.intellij.psi.xml.XmlFile; -+import com.intellij.psi.xml.XmlTag; -+import com.intellij.util.indexing.*; -+import com.intellij.util.io.DataExternalizer; -+import com.intellij.util.io.EnumeratorStringDescriptor; -+import com.intellij.util.io.KeyDescriptor; -+import com.magento.idea.magento2plugin.project.Settings; -+import gnu.trove.THashMap; -+import org.jetbrains.annotations.NotNull; -+ -+import java.util.Map; -+ -+public class ActionGroupIndex extends FileBasedIndexExtension { -+ public static final ID KEY = ID.create( -+ "com.magento.idea.magento2plugin.stubs.indexes.mftf.action_group_index" -+ ); -+ -+ private final KeyDescriptor myKeyDescriptor = new EnumeratorStringDescriptor(); -+ -+ @NotNull -+ @Override -+ public DataIndexer getIndexer() { -+ return inputData -> { -+ Map map = new THashMap<>(); -+ PsiFile psiFile = inputData.getPsiFile(); -+ -+ if (!Settings.isEnabled(psiFile.getProject())) { -+ return map; -+ } -+ -+ if (!(psiFile instanceof XmlFile)) { -+ return map; -+ } -+ -+ XmlDocument xmlDocument = ((XmlFile) psiFile).getDocument(); -+ -+ if (xmlDocument == null) { -+ return map; -+ } -+ -+ XmlTag xmlRootTag = xmlDocument.getRootTag(); -+ -+ if (xmlRootTag == null || !xmlRootTag.getName().equals("actionGroups")) { -+ return map; -+ } -+ -+ XmlTag xmlTags[] = PsiTreeUtil.getChildrenOfType(psiFile.getFirstChild(), XmlTag.class); -+ -+ if (xmlTags == null) { -+ return map; -+ } -+ -+ for (XmlTag actionGroupTag : xmlRootTag.findSubTags("actionGroup")) { -+ String name = actionGroupTag.getAttributeValue("name"); -+ -+ if (name == null || name.isEmpty()) { -+ continue; -+ } -+ -+ map.put(name, name); -+ } -+ -+ return map; -+ }; -+ } -+ -+ @NotNull -+ @Override -+ public ID getName() { -+ return KEY; -+ } -+ -+ @NotNull -+ @Override -+ public KeyDescriptor getKeyDescriptor() { -+ return this.myKeyDescriptor; -+ } -+ -+ @NotNull -+ public DataExternalizer getValueExternalizer() { -+ return EnumeratorStringDescriptor.INSTANCE; -+ } -+ -+ @NotNull -+ @Override -+ public FileBasedIndex.InputFilter getInputFilter() { -+ return file -> -+ file.getFileType() == XmlFileType.INSTANCE && -+ file.getPath().contains("Test/Mftf/ActionGroup") -+ ; -+ } -+ -+ @Override -+ public boolean dependsOnFileContent() { -+ return true; -+ } -+ -+ @Override -+ public int getVersion() { -+ return 1; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/stubs/indexes/mftf/DataIndex.java b/src/com/magento/idea/magento2plugin/stubs/indexes/mftf/DataIndex.java -new file mode 100644 -index 0000000..c5c1a8e ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/stubs/indexes/mftf/DataIndex.java -@@ -0,0 +1,119 @@ -+package com.magento.idea.magento2plugin.stubs.indexes.mftf; -+ -+import com.intellij.ide.highlighter.XmlFileType; -+import com.intellij.psi.PsiFile; -+import com.intellij.psi.util.PsiTreeUtil; -+import com.intellij.psi.xml.XmlDocument; -+import com.intellij.psi.xml.XmlFile; -+import com.intellij.psi.xml.XmlTag; -+import com.intellij.util.indexing.*; -+import com.intellij.util.io.DataExternalizer; -+import com.intellij.util.io.EnumeratorStringDescriptor; -+import com.intellij.util.io.KeyDescriptor; -+import com.magento.idea.magento2plugin.project.Settings; -+import gnu.trove.THashMap; -+import org.jetbrains.annotations.NotNull; -+ -+import java.util.Map; -+ -+public class DataIndex extends FileBasedIndexExtension { -+ public static final ID KEY = ID.create( -+ "com.magento.idea.magento2plugin.stubs.indexes.mftf.data_index" -+ ); -+ -+ private final KeyDescriptor myKeyDescriptor = new EnumeratorStringDescriptor(); -+ -+ @NotNull -+ @Override -+ public DataIndexer getIndexer() { -+ return inputData -> { -+ Map map = new THashMap<>(); -+ PsiFile psiFile = inputData.getPsiFile(); -+ -+ if (!Settings.isEnabled(psiFile.getProject())) { -+ return map; -+ } -+ -+ if (!(psiFile instanceof XmlFile)) { -+ return map; -+ } -+ -+ XmlDocument xmlDocument = ((XmlFile) psiFile).getDocument(); -+ -+ if (xmlDocument == null) { -+ return map; -+ } -+ -+ XmlTag xmlRootTag = xmlDocument.getRootTag(); -+ -+ if (xmlRootTag == null || !xmlRootTag.getName().equals("entities")) { -+ return map; -+ } -+ -+ XmlTag xmlTags[] = PsiTreeUtil.getChildrenOfType(psiFile.getFirstChild(), XmlTag.class); -+ -+ if (xmlTags == null) { -+ return map; -+ } -+ -+ for (XmlTag entityTag : xmlRootTag.findSubTags("entity")) { -+ String entityName = entityTag.getAttributeValue("name"); -+ -+ if (entityName == null || entityName.isEmpty()) { -+ continue; -+ } -+ -+ map.put(entityName, entityName); -+ -+ for (XmlTag dataTag : entityTag.findSubTags("data")) { -+ String key = dataTag.getAttributeValue("key"); -+ String value = dataTag.getText(); -+ -+ if (key == null || key.isEmpty() || value == null || value.isEmpty()) { -+ continue; -+ } -+ -+ map.put(entityName + "." + key, value); -+ } -+ } -+ -+ return map; -+ }; -+ } -+ -+ @NotNull -+ @Override -+ public ID getName() { -+ return KEY; -+ } -+ -+ @NotNull -+ @Override -+ public KeyDescriptor getKeyDescriptor() { -+ return this.myKeyDescriptor; -+ } -+ -+ @NotNull -+ public DataExternalizer getValueExternalizer() { -+ return EnumeratorStringDescriptor.INSTANCE; -+ } -+ -+ @NotNull -+ @Override -+ public FileBasedIndex.InputFilter getInputFilter() { -+ return file -> -+ file.getFileType() == XmlFileType.INSTANCE && -+ file.getPath().contains("Test/Mftf/Data") -+ ; -+ } -+ -+ @Override -+ public boolean dependsOnFileContent() { -+ return true; -+ } -+ -+ @Override -+ public int getVersion() { -+ return 1; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/stubs/indexes/mftf/PageIndex.java b/src/com/magento/idea/magento2plugin/stubs/indexes/mftf/PageIndex.java -new file mode 100644 -index 0000000..ed6d0d9 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/stubs/indexes/mftf/PageIndex.java -@@ -0,0 +1,108 @@ -+package com.magento.idea.magento2plugin.stubs.indexes.mftf; -+ -+import com.intellij.ide.highlighter.XmlFileType; -+import com.intellij.psi.PsiFile; -+import com.intellij.psi.util.PsiTreeUtil; -+import com.intellij.psi.xml.XmlDocument; -+import com.intellij.psi.xml.XmlFile; -+import com.intellij.psi.xml.XmlTag; -+import com.intellij.util.indexing.*; -+import com.intellij.util.io.DataExternalizer; -+import com.intellij.util.io.EnumeratorStringDescriptor; -+import com.intellij.util.io.KeyDescriptor; -+import com.magento.idea.magento2plugin.project.Settings; -+import gnu.trove.THashMap; -+import org.jetbrains.annotations.NotNull; -+ -+import java.util.Map; -+ -+public class PageIndex extends FileBasedIndexExtension { -+ public static final ID KEY = ID.create( -+ "com.magento.idea.magento2plugin.stubs.indexes.mftf.page_index" -+ ); -+ -+ private final KeyDescriptor myKeyDescriptor = new EnumeratorStringDescriptor(); -+ -+ @NotNull -+ @Override -+ public DataIndexer getIndexer() { -+ return inputData -> { -+ Map map = new THashMap<>(); -+ PsiFile psiFile = inputData.getPsiFile(); -+ -+ if (!Settings.isEnabled(psiFile.getProject())) { -+ return map; -+ } -+ -+ if (!(psiFile instanceof XmlFile)) { -+ return map; -+ } -+ -+ XmlDocument xmlDocument = ((XmlFile) psiFile).getDocument(); -+ -+ if (xmlDocument == null) { -+ return map; -+ } -+ -+ XmlTag xmlRootTag = xmlDocument.getRootTag(); -+ -+ if (xmlRootTag == null || !xmlRootTag.getName().equals("pages")) { -+ return map; -+ } -+ -+ XmlTag xmlTags[] = PsiTreeUtil.getChildrenOfType(psiFile.getFirstChild(), XmlTag.class); -+ -+ if (xmlTags == null) { -+ return map; -+ } -+ -+ for (XmlTag pageTag : xmlRootTag.findSubTags("page")) { -+ String name = pageTag.getAttributeValue("name"); -+ -+ if (name == null || name.isEmpty()) { -+ continue; -+ } -+ -+ map.put(name, name); -+ } -+ -+ return map; -+ }; -+ } -+ -+ @NotNull -+ @Override -+ public ID getName() { -+ return KEY; -+ } -+ -+ @NotNull -+ @Override -+ public KeyDescriptor getKeyDescriptor() { -+ return this.myKeyDescriptor; -+ } -+ -+ @NotNull -+ public DataExternalizer getValueExternalizer() { -+ return EnumeratorStringDescriptor.INSTANCE; -+ } -+ -+ @NotNull -+ @Override -+ public FileBasedIndex.InputFilter getInputFilter() { -+ return file -> -+ file.getFileType() == XmlFileType.INSTANCE && -+ file.getPath().contains("Test/Mftf/Page") -+ ; -+ } -+ -+ @Override -+ public boolean dependsOnFileContent() { -+ return true; -+ } -+ -+ @Override -+ public int getVersion() { -+ return 1; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/stubs/indexes/mftf/SectionIndex.java b/src/com/magento/idea/magento2plugin/stubs/indexes/mftf/SectionIndex.java -new file mode 100644 -index 0000000..bd42d0f ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/stubs/indexes/mftf/SectionIndex.java -@@ -0,0 +1,119 @@ -+package com.magento.idea.magento2plugin.stubs.indexes.mftf; -+ -+import com.intellij.ide.highlighter.XmlFileType; -+import com.intellij.psi.PsiFile; -+import com.intellij.psi.util.PsiTreeUtil; -+import com.intellij.psi.xml.XmlDocument; -+import com.intellij.psi.xml.XmlFile; -+import com.intellij.psi.xml.XmlTag; -+import com.intellij.util.indexing.*; -+import com.intellij.util.io.DataExternalizer; -+import com.intellij.util.io.EnumeratorStringDescriptor; -+import com.intellij.util.io.KeyDescriptor; -+import com.magento.idea.magento2plugin.project.Settings; -+import gnu.trove.THashMap; -+import org.jetbrains.annotations.NotNull; -+ -+import java.util.Map; -+ -+public class SectionIndex extends FileBasedIndexExtension { -+ public static final ID KEY = ID.create( -+ "com.magento.idea.magento2plugin.stubs.indexes.mftf.selector_index" -+ ); -+ -+ private final KeyDescriptor myKeyDescriptor = new EnumeratorStringDescriptor(); -+ -+ @NotNull -+ @Override -+ public DataIndexer getIndexer() { -+ return inputData -> { -+ Map map = new THashMap<>(); -+ PsiFile psiFile = inputData.getPsiFile(); -+ -+ if (!Settings.isEnabled(psiFile.getProject())) { -+ return map; -+ } -+ -+ if (!(psiFile instanceof XmlFile)) { -+ return map; -+ } -+ -+ XmlDocument xmlDocument = ((XmlFile) psiFile).getDocument(); -+ -+ if (xmlDocument == null) { -+ return map; -+ } -+ -+ XmlTag xmlRootTag = xmlDocument.getRootTag(); -+ -+ if (xmlRootTag == null || !xmlRootTag.getName().equals("sections")) { -+ return map; -+ } -+ -+ XmlTag xmlTags[] = PsiTreeUtil.getChildrenOfType(psiFile.getFirstChild(), XmlTag.class); -+ -+ if (xmlTags == null) { -+ return map; -+ } -+ -+ for (XmlTag sectionTag : xmlRootTag.findSubTags("section")) { -+ String section = sectionTag.getAttributeValue("name"); -+ -+ if (section == null || section.isEmpty()) { -+ continue; -+ } -+ -+ map.put(section, section); -+ -+ for (XmlTag elementTag : sectionTag.findSubTags("element")) { -+ String element = elementTag.getAttributeValue("name"); -+ String selector = elementTag.getAttributeValue("selector"); -+ -+ if (element == null || element.isEmpty() || selector == null || selector.isEmpty()) { -+ continue; -+ } -+ -+ map.put(section + "." + element, selector); -+ } -+ } -+ -+ return map; -+ }; -+ } -+ -+ @NotNull -+ @Override -+ public ID getName() { -+ return KEY; -+ } -+ -+ @NotNull -+ @Override -+ public KeyDescriptor getKeyDescriptor() { -+ return this.myKeyDescriptor; -+ } -+ -+ @NotNull -+ public DataExternalizer getValueExternalizer() { -+ return EnumeratorStringDescriptor.INSTANCE; -+ } -+ -+ @NotNull -+ @Override -+ public FileBasedIndex.InputFilter getInputFilter() { -+ return file -> -+ file.getFileType() == XmlFileType.INSTANCE && -+ file.getPath().contains("Test/Mftf/Section") -+ ; -+ } -+ -+ @Override -+ public boolean dependsOnFileContent() { -+ return true; -+ } -+ -+ @Override -+ public int getVersion() { -+ return 1; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/stubs/indexes/mftf/StepKeyIndex.java b/src/com/magento/idea/magento2plugin/stubs/indexes/mftf/StepKeyIndex.java -new file mode 100644 -index 0000000..aafd29c ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/stubs/indexes/mftf/StepKeyIndex.java -@@ -0,0 +1,127 @@ -+package com.magento.idea.magento2plugin.stubs.indexes.mftf; -+ -+import com.intellij.ide.highlighter.XmlFileType; -+import com.intellij.psi.PsiFile; -+import com.intellij.psi.util.PsiTreeUtil; -+import com.intellij.psi.xml.XmlDocument; -+import com.intellij.psi.xml.XmlFile; -+import com.intellij.psi.xml.XmlTag; -+import com.intellij.util.indexing.*; -+import com.intellij.util.io.DataExternalizer; -+import com.intellij.util.io.EnumeratorStringDescriptor; -+import com.intellij.util.io.KeyDescriptor; -+import com.magento.idea.magento2plugin.project.Settings; -+import gnu.trove.THashMap; -+import org.jetbrains.annotations.NotNull; -+ -+import java.util.Map; -+ -+public class StepKeyIndex extends FileBasedIndexExtension { -+ public static final ID KEY = ID.create( -+ "com.magento.idea.magento2plugin.stubs.indexes.mftf.step_key_index" -+ ); -+ -+ private final KeyDescriptor myKeyDescriptor = new EnumeratorStringDescriptor(); -+ -+ @NotNull -+ @Override -+ public DataIndexer getIndexer() { -+ return inputData -> { -+ Map map = new THashMap<>(); -+ PsiFile psiFile = inputData.getPsiFile(); -+ -+ if (!Settings.isEnabled(psiFile.getProject())) { -+ return map; -+ } -+ -+ if (!(psiFile instanceof XmlFile)) { -+ return map; -+ } -+ -+ XmlDocument xmlDocument = ((XmlFile) psiFile).getDocument(); -+ -+ if (xmlDocument == null) { -+ return map; -+ } -+ -+ XmlTag xmlRootTag = xmlDocument.getRootTag(); -+ -+ if (xmlRootTag == null || !xmlRootTag.getName().equals("tests")) { -+ return map; -+ } -+ -+ XmlTag xmlTags[] = PsiTreeUtil.getChildrenOfType(psiFile.getFirstChild(), XmlTag.class); -+ -+ if (xmlTags == null) { -+ return map; -+ } -+ -+ for (XmlTag childTag : xmlRootTag.getSubTags()) { -+ if (childTag.getAttributeValue("name") == null || -+ childTag.getAttributeValue("name").isEmpty() -+ ) { -+ continue; -+ } -+ -+ fillResultMap( -+ childTag.getName() + "." + childTag.getAttributeValue("name"), -+ childTag, -+ map -+ ); -+ } -+ -+ return map; -+ }; -+ } -+ -+ private void fillResultMap(String namespacePrefix, XmlTag parentTag, Map resultMap) { -+ for (XmlTag childTag: parentTag.getSubTags()) { -+ if (childTag.getAttributeValue("stepKey") == null || -+ childTag.getAttributeValue("stepKey").isEmpty() -+ ) { -+ continue; -+ } -+ -+ String stepKeyReference = childTag.getAttributeValue("stepKey"); -+ -+ resultMap.put(namespacePrefix + "." + stepKeyReference, stepKeyReference); -+ fillResultMap(namespacePrefix, childTag, resultMap); -+ } -+ } -+ -+ @NotNull -+ @Override -+ public ID getName() { -+ return KEY; -+ } -+ -+ @NotNull -+ @Override -+ public KeyDescriptor getKeyDescriptor() { -+ return this.myKeyDescriptor; -+ } -+ -+ @NotNull -+ public DataExternalizer getValueExternalizer() { -+ return EnumeratorStringDescriptor.INSTANCE; -+ } -+ -+ @NotNull -+ @Override -+ public FileBasedIndex.InputFilter getInputFilter() { -+ return file -> -+ file.getFileType() == XmlFileType.INSTANCE && -+ file.getPath().contains("Test/Mftf") -+ ; -+ } -+ -+ @Override -+ public boolean dependsOnFileContent() { -+ return true; -+ } -+ -+ @Override -+ public int getVersion() { -+ return 1; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/ui/FilteredComboBox.java b/src/com/magento/idea/magento2plugin/ui/FilteredComboBox.java -new file mode 100644 -index 0000000..347711e ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/ui/FilteredComboBox.java -@@ -0,0 +1,62 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.ui; -+ -+import java.awt.event.KeyAdapter; -+import java.awt.event.KeyEvent; -+import java.util.ArrayList; -+import java.util.List; -+import javax.swing.DefaultComboBoxModel; -+import javax.swing.JComboBox; -+import javax.swing.JTextField; -+import javax.swing.SwingUtilities; -+ -+public class FilteredComboBox extends JComboBox { -+ private List entries; -+ -+ public List getEntries() { -+ return entries; -+ } -+ -+ public FilteredComboBox(List entries) { -+ super(entries.toArray()); -+ this.entries = entries; -+ this.setEditable(true); -+ -+ final JTextField textfield = -+ (JTextField) this.getEditor().getEditorComponent(); -+ -+ textfield.addKeyListener(new KeyAdapter() { -+ public void keyReleased(KeyEvent ke) { -+ SwingUtilities.invokeLater(new Runnable() { -+ public void run() { -+ comboFilter(textfield.getText()); -+ } -+ }); -+ } -+ }); -+ -+ } -+ -+ public void comboFilter(String enteredText) { -+ List entriesFiltered = new ArrayList(); -+ -+ for (String entry : getEntries()) { -+ if (entry.toLowerCase().contains(enteredText.toLowerCase())) { -+ entriesFiltered.add(entry); -+ } -+ } -+ -+ if (entriesFiltered.size() > 0) { -+ this.setModel( -+ new DefaultComboBoxModel( -+ entriesFiltered.toArray())); -+ this.setSelectedItem(enteredText); -+ this.showPopup(); -+ } else { -+ this.hidePopup(); -+ } -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/util/CamelCaseToHyphen.java b/src/com/magento/idea/magento2plugin/util/CamelCaseToHyphen.java -new file mode 100644 -index 0000000..7ee209d ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/util/CamelCaseToHyphen.java -@@ -0,0 +1,31 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.util; -+ -+import java.lang.*; -+import java.util.regex.Matcher; -+import java.util.regex.Pattern; -+ -+public class CamelCaseToHyphen { -+ private static CamelCaseToHyphen INSTANCE = null; -+ public static CamelCaseToHyphen getInstance() { -+ if (null == INSTANCE) { -+ INSTANCE = new CamelCaseToHyphen(); -+ } -+ return INSTANCE; -+ } -+ -+ public String convert(String string) { -+ String regex = "(?=[A-Z][a-z])"; -+ String subst = "-"; -+ -+ Pattern pattern = Pattern.compile(regex); -+ Matcher matcher = pattern.matcher(string); -+ -+ String result = matcher.replaceAll(subst); -+ -+ return result.toLowerCase().substring(1); -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/util/GetFirstClassOfFile.java b/src/com/magento/idea/magento2plugin/util/GetFirstClassOfFile.java -new file mode 100644 -index 0000000..1d308b9 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/util/GetFirstClassOfFile.java -@@ -0,0 +1,28 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.util; -+ -+import com.intellij.psi.util.PsiTreeUtil; -+import com.jetbrains.php.lang.psi.PhpFile; -+import com.jetbrains.php.lang.psi.elements.PhpClass; -+import org.jetbrains.annotations.Nullable; -+import java.util.Collection; -+ -+public class GetFirstClassOfFile { -+ private static GetFirstClassOfFile INSTANCE = null; -+ -+ public static GetFirstClassOfFile getInstance() { -+ if (null == INSTANCE) { -+ INSTANCE = new GetFirstClassOfFile(); -+ } -+ return INSTANCE; -+ } -+ -+ @Nullable -+ public PhpClass execute(PhpFile phpFile) { -+ Collection phpClasses = PsiTreeUtil.collectElementsOfType(phpFile, PhpClass.class); -+ return phpClasses.size() == 0 ? null : phpClasses.iterator().next(); -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/util/GetPhpClassByFQN.java b/src/com/magento/idea/magento2plugin/util/GetPhpClassByFQN.java -new file mode 100644 -index 0000000..12b04a4 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/util/GetPhpClassByFQN.java -@@ -0,0 +1,37 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.util; -+ -+import com.intellij.openapi.project.Project; -+import com.jetbrains.php.PhpIndex; -+import com.jetbrains.php.lang.psi.elements.PhpClass; -+ -+import java.util.Collection; -+ -+public class GetPhpClassByFQN { -+ private static GetPhpClassByFQN INSTANCE = null; -+ private Project project; -+ -+ public static GetPhpClassByFQN getInstance(Project project) { -+ if (null == INSTANCE) { -+ INSTANCE = new GetPhpClassByFQN(); -+ } -+ INSTANCE.project = project; -+ return INSTANCE; -+ } -+ -+ public PhpClass execute(String targetClassName) { -+ PhpIndex phpIndex = PhpIndex.getInstance(project); -+ Collection interfaces = phpIndex.getInterfacesByFQN(targetClassName); -+ if (!interfaces.isEmpty()) { -+ return interfaces.iterator().next(); -+ } -+ Collection classes = phpIndex.getClassesByFQN(targetClassName); -+ if (classes.isEmpty()) { -+ return null; -+ } -+ return classes.iterator().next(); -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/util/Regex.java b/src/com/magento/idea/magento2plugin/util/Regex.java -new file mode 100644 -index 0000000..7566edf ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/util/Regex.java -@@ -0,0 +1,20 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.util; -+ -+public class Regex { -+ -+ public static final String ALPHANUMERIC -+ = "[a-zA-Z0-9]*"; -+ -+ public static final String NUMERIC -+ = "[0-9]*"; -+ -+ public static final String IDENTIFIER -+ = "[a-zA-Z0-9_\\-]*"; -+ -+ public static final String DIRECTORY -+ = "^(?!\\/)[a-zA-Z0-9\\/]*[^\\/]$"; -+} -diff --git a/src/com/magento/idea/magento2plugin/util/magento/FileBasedIndexUtil.java b/src/com/magento/idea/magento2plugin/util/magento/FileBasedIndexUtil.java -index cb12b37..31917ad 100644 ---- a/src/com/magento/idea/magento2plugin/util/magento/FileBasedIndexUtil.java -+++ b/src/com/magento/idea/magento2plugin/util/magento/FileBasedIndexUtil.java -@@ -6,12 +6,16 @@ package com.magento.idea.magento2plugin.util.magento; - - import com.intellij.openapi.project.Project; - import com.intellij.openapi.vfs.VirtualFile; -+import com.intellij.psi.PsiFile; -+import com.intellij.psi.PsiManager; - import com.intellij.psi.search.GlobalSearchScope; - import com.intellij.util.indexing.FileBasedIndex; - import com.jetbrains.php.lang.PhpFileType; -+import com.magento.idea.magento2plugin.magento.packages.Package; - import com.magento.idea.magento2plugin.stubs.indexes.ModuleNameIndex; - import com.magento.idea.magento2plugin.util.RegExUtil; - -+import java.io.File; - import java.util.ArrayList; - import java.util.Collection; - import java.util.regex.Matcher; -@@ -43,6 +47,40 @@ public class FileBasedIndexUtil { - return viewVfs; - } - -+ public static PsiFile findModuleConfigFile(String virtualFieName, Package.Areas area, String moduleName, Project project) -+ { -+ Pattern pattern = Pattern.compile(RegExUtil.Magento.MODULE_NAME); -+ Matcher matcher = pattern.matcher(moduleName); -+ if (!matcher.find()) { -+ return null; -+ } -+ -+ Collection moduleVfs = -+ FileBasedIndex.getInstance().getContainingFiles(ModuleNameIndex.KEY, moduleName, -+ GlobalSearchScope.getScopeRestrictedByFileTypes( -+ GlobalSearchScope.allScope(project), -+ PhpFileType.INSTANCE -+ ) -+ ); -+ if (moduleVfs.isEmpty()) { -+ return null; -+ } -+ -+ VirtualFile moduleVf = moduleVfs.iterator().next(); -+ -+ String relativePath = File.separator.concat(Package.MODULE_BASE_AREA_DIR).concat(File.separator); -+ if (!area.equals(Package.Areas.base)) { -+ relativePath = relativePath.concat(area.toString()).concat(File.separator); -+ } -+ relativePath = relativePath.concat(virtualFieName); -+ -+ VirtualFile configFile = moduleVf.getParent().findFileByRelativePath(relativePath); -+ if (configFile == null) { -+ return null; -+ } -+ return PsiManager.getInstance(project).findFile(configFile); -+ } -+ - public static Collection findViewVfsByModuleVf(VirtualFile moduleVf, Project project) - { - Collection viewVfs = new ArrayList<>(); -diff --git a/src/com/magento/idea/magento2plugin/util/magento/graphql/GraphQlUtil.java b/src/com/magento/idea/magento2plugin/util/magento/graphql/GraphQlUtil.java -new file mode 100644 -index 0000000..65918f0 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/util/magento/graphql/GraphQlUtil.java -@@ -0,0 +1,43 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.util.magento.graphql; -+ -+import com.intellij.lang.jsgraphql.psi.GraphQLStringValue; -+import com.intellij.psi.PsiElement; -+import org.jetbrains.annotations.NotNull; -+import org.jetbrains.annotations.Nullable; -+ -+public class GraphQlUtil { -+ -+ @NotNull -+ public static String resolverStringToPhpFQN(String resolverFQN) { -+ resolverFQN = resolverFQN.replace("\\\\", "\\").replace("\"",""); -+ if (!resolverFQN.startsWith("\\")) { -+ resolverFQN = "\\".concat(resolverFQN); -+ } -+ return resolverFQN; -+ } -+ -+ @Nullable -+ public static GraphQLStringValue fetchResolverQuotedStringFromArgument(PsiElement argument) { -+ PsiElement[] argumentChildren = argument.getChildren(); -+ -+ if (argumentChildren.length < 2) { -+ return null; -+ } -+ PsiElement argumentIdentifier = argumentChildren[0]; -+ if (!(argumentChildren[1] instanceof GraphQLStringValue)) { -+ return null; -+ } -+ -+ GraphQLStringValue argumentStringValue = (GraphQLStringValue) argumentChildren[1]; -+ -+ if (!argumentIdentifier.getText().equals("class")) { -+ return null; -+ } -+ -+ return argumentStringValue; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/util/magento/plugin/GetTargetClassNamesByPluginClassName.java b/src/com/magento/idea/magento2plugin/util/magento/plugin/GetTargetClassNamesByPluginClassName.java -new file mode 100644 -index 0000000..da70223 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/util/magento/plugin/GetTargetClassNamesByPluginClassName.java -@@ -0,0 +1,55 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.util.magento.plugin; -+ -+import com.intellij.openapi.project.Project; -+import com.intellij.psi.search.GlobalSearchScope; -+import com.intellij.util.indexing.FileBasedIndex; -+import com.magento.idea.magento2plugin.stubs.indexes.PluginIndex; -+ -+import java.util.ArrayList; -+import java.util.Collection; -+import java.util.List; -+import java.util.Set; -+ -+/** -+ * Returns all targets class names for the plugin -+ */ -+public class GetTargetClassNamesByPluginClassName { -+ private static GetTargetClassNamesByPluginClassName INSTANCE = null; -+ private Project project; -+ -+ public static GetTargetClassNamesByPluginClassName getInstance(Project project) { -+ if (null == INSTANCE) { -+ INSTANCE = new GetTargetClassNamesByPluginClassName(); -+ } -+ INSTANCE.project = project; -+ return INSTANCE; -+ } -+ -+ public ArrayList execute(String currentClassName) { -+ ArrayList targetClassNames = new ArrayList<>(); -+ Collection allKeys = FileBasedIndex.getInstance() -+ .getAllKeys(PluginIndex.KEY, project); -+ -+ for (String targetClassName : allKeys) { -+ List> pluginsList = FileBasedIndex.getInstance() -+ .getValues(com.magento.idea.magento2plugin.stubs.indexes.PluginIndex.KEY, targetClassName, GlobalSearchScope.allScope(project)); -+ if (pluginsList.isEmpty()) { -+ continue; -+ } -+ for (Set plugins : pluginsList) { -+ for (String plugin : plugins) { -+ if (!plugin.equals(currentClassName)) { -+ continue; -+ } -+ targetClassNames.add(targetClassName); -+ } -+ } -+ } -+ -+ return targetClassNames; -+ } -+} -diff --git a/src/com/magento/idea/magento2plugin/util/magento/plugin/IsPluginAllowedForMethod.java b/src/com/magento/idea/magento2plugin/util/magento/plugin/IsPluginAllowedForMethod.java -new file mode 100644 -index 0000000..9a99840 ---- /dev/null -+++ b/src/com/magento/idea/magento2plugin/util/magento/plugin/IsPluginAllowedForMethod.java -@@ -0,0 +1,37 @@ -+/* -+ * Copyright © Magento, Inc. All rights reserved. -+ * See COPYING.txt for license details. -+ */ -+package com.magento.idea.magento2plugin.util.magento.plugin; -+ -+import com.jetbrains.php.lang.psi.elements.Method; -+import com.magento.idea.magento2plugin.magento.files.Plugin; -+ -+public class IsPluginAllowedForMethod { -+ private static IsPluginAllowedForMethod INSTANCE = null; -+ -+ public static IsPluginAllowedForMethod getInstance() { -+ if (null == INSTANCE) { -+ INSTANCE = new IsPluginAllowedForMethod(); -+ } -+ return INSTANCE; -+ } -+ -+ public boolean check(Method targetMethod) { -+ String targetMethodName = targetMethod.getName(); -+ if (targetMethodName.equals(Plugin.constructMethodName)) { -+ return false; -+ } -+ if (targetMethod.isFinal()) { -+ return false; -+ } -+ if (targetMethod.isStatic()) { -+ return false; -+ } -+ if (!targetMethod.getAccess().toString().equals(Plugin.publicAccess)) { -+ return false; -+ } -+ -+ return true; -+ } -+}