From 88a7b8faf64e94b127cdd725009b8a12a3e71bc5 Mon Sep 17 00:00:00 2001 From: Volodymyr Klymenko Date: Tue, 31 Mar 2020 22:22:29 +0300 Subject: [PATCH] Applied patch to sign-off CLA --- .gitignore | 3 +- CODE_OF_CONDUCT.md | 46 +++ CONTRIBUTING.md | 12 +- COPYING.txt | 9 + LICENSE.md | 68 ++-- META-INF/plugin.xml | 6 + README.md | 30 ++ magento2plugin.iml | 8 +- .../idea/magento2plugin/MagentoIcons.java | 16 + .../magento/idea/magento2plugin/Settings.java | 14 +- .../idea/magento2plugin/SettingsForm.form | 8 +- .../idea/magento2plugin/SettingsForm.java | 22 +- .../provider/CompositeCompletionProvider.java | 30 ++ .../EventNameCompletionContributor.java | 34 ++ .../provider/FilePathCompletionProvider.java | 123 ++++++++ .../LayoutBlockCompletionContributor.java | 38 +++ .../LayoutContainerCompletionContributor.java | 38 +++ .../LayoutUpdateCompletionContributor.java | 42 +++ .../ModuleNameCompletionProvider.java | 45 +++ .../provider/PhpClassCompletionProvider.java | 110 +++++++ .../PhpClassMemberCompletionProvider.java | 65 ++++ ...ConstructorArgumentCompletionProvider.java | 47 +++ ...PhpServiceMethodCompletionContributor.java | 41 +++ .../VirtualTypeCompletionProvider.java | 44 +++ .../xml/XmlCompletionContributor.java | 109 +++++++ .../idea/magento2plugin/indexes/DiIndex.java | 4 + .../magento2plugin/indexes/EventIndex.java | 53 ++++ .../magento2plugin/indexes/IndexManager.java | 40 +++ .../magento2plugin/indexes/LayoutIndex.java | 124 ++++++++ .../idea/magento2plugin/indexes/XmlIndex.java | 92 ++++++ .../index/ModulePackageFileBasedIndex.java | 96 ------ .../php/inspections/MagentoApiInspection.java | 108 ------- .../inspections/ObjectManagerInspection.java | 97 ------ .../ClassConfigurationLineMarkerProvider.java | 72 ++--- .../php/linemarker/Collector.java | 13 - .../linemarker/PluginLineMarkerProvider.java | 178 +++++++++++ .../linemarker/WebApiLineMarkerProvider.java | 161 +++++----- .../php/module/ComposerPackageModel.java | 4 + .../php/module/ComposerPackageModelImpl.java | 4 + .../php/module/MagentoComponent.java | 5 +- .../php/module/MagentoComponentImp.java | 4 + .../php/module/MagentoComponentManager.java | 15 +- .../php/module/MagentoModule.java | 6 +- .../magento2plugin/php/module/ModuleUtil.java | 8 - .../magento2plugin/php/tool/ModuleTool.form | 26 -- .../php/tool/ModuleToolWindowFactory.java | 66 ---- .../php/util/ImplementationMatcher.java | 33 -- .../magento2plugin/php/util/MagentoTypes.java | 11 - .../magento2plugin/php/util/PhpRegex.java | 21 ++ .../project/ProjectDetector.java | 54 ++++ .../reference/js/JsReferenceContributor.java | 30 ++ .../php/PhpReferenceContributor.java | 22 ++ .../provider/CompositeReferenceProvider.java | 35 +++ .../EventDispatchReferenceProvider.java | 40 +++ .../provider/EventNameReferenceProvider.java | 67 ++++ .../provider/FilePathReferenceProvider.java | 239 ++++++++++++++ .../LayoutBlockReferenceProvider.java | 31 ++ .../LayoutContainerReferenceProvider.java | 34 ++ .../LayoutUpdateReferenceProvider.java | 31 ++ .../provider/ModuleNameReferenceProvider.java | 78 +++++ .../PhpClassMemberReferenceProvider.java | 62 ++++ .../provider/PhpClassReferenceProvider.java | 74 +++++ ...pConstructorArgumentReferenceProvider.java | 51 +++ .../PhpServiceMethodReferenceProvider.java | 45 +++ .../VirtualTypeReferenceProvider.java | 37 +++ .../xml/PolyVariantReferenceBase.java | 50 +++ .../xml/XmlReferenceContributor.java | 160 ++++++++++ .../stubs/indexes/BlockNameIndex.java | 29 ++ .../stubs/indexes/ContainerNameIndex.java | 35 +++ .../stubs/indexes/EventNameIndex.java | 137 +++++++++ .../stubs/indexes/EventObserverIndex.java | 124 ++++++++ .../stubs/indexes/ModuleNameIndex.java | 116 +++++++ .../stubs/indexes/ModulePackageIndex.java | 93 ++++++ .../stubs/indexes/NamedComponentIndex.java | 41 +++ .../stubs/indexes/PluginIndex.java | 127 ++++++++ .../stubs/indexes/VirtualTypeIndex.java | 91 ++++++ .../stubs/indexes/xml/PhpClassNameIndex.java | 109 +++++++ .../idea/magento2plugin/util/IndexUtil.java | 46 --- .../util/PsiContextMatcherI.java | 8 - .../idea/magento2plugin/util/RegExUtil.java | 15 + .../idea/magento2plugin/util/VfsUtil.java | 47 +++ .../util/magento/FileBasedIndexUtil.java | 73 +++++ .../magento2plugin/xml/XmlHelperUtility.java | 106 ------- .../magento2plugin/xml/XmlPsiTreeUtil.java | 55 ++++ .../completion/ClassCompletionProvider.java | 56 ---- .../xml/completion/CompletionProviderI.java | 17 - .../InterfaceCompletionProvider.java | 59 ---- .../VirtualTypeCompletionProvider.java | 45 --- .../idea/magento2plugin/xml/di/XmlHelper.java | 116 ------- .../completion/DiCompletionContributor.java | 192 ------------ .../TypeConfigurationFileBasedIndex.java | 291 ------------------ .../VirtualTypesNamesFileBasedIndex.java | 148 --------- .../di/reference/ArgumentNameReference.java | 112 ------- .../xml/di/reference/ConstantReference.java | 65 ---- .../di/reference/DiReferenceContributor.java | 117 ------- .../ArgumentNameReferenceProvider.java | 48 --- .../provider/XmlReferenceProvider.java | 27 -- .../provider/resolver/ClassNameResolver.java | 29 -- .../provider/resolver/TypeTagResolver.java | 25 -- .../resolver/VirtualTypeTagResolver.java | 36 --- .../xml/index/LineMarkerXmlTagDecorator.java | 10 +- .../xml/layout/LayoutUtility.java | 54 ---- .../LayoutCompletionContributor.java | 99 ------ .../ReferenceComponentCompletionProvider.java | 45 --- .../AbstractComponentNameFileBasedIndex.java | 52 ---- .../index/BlockClassFileBasedIndex.java | 25 -- .../xml/layout/index/BlockFileBasedIndex.java | 23 -- .../layout/index/ContainerFileBasedIndex.java | 28 -- .../xml/layout/index/LayoutDataIndexer.java | 40 ++- .../layout/index/util/LayoutIndexUtility.java | 129 -------- .../reference/LayoutReferenceContributor.java | 105 ------- .../reference/fill/BlockResultsFiller.java | 28 -- .../fill/ContainerResultsFiller.java | 28 -- .../xml/observer/PhpPatternsHelper.java | 6 +- .../xml/observer/XmlHelper.java | 24 -- .../EventCompletionContributor.java | 59 ---- .../index/EventObserverFileBasedIndex.java | 146 --------- .../EventsDeclarationsFileBasedIndex.java | 126 -------- .../reference/EventReferenceContributor.java | 27 -- .../reference/EventReferenceProvider.java | 59 ---- .../ObserverReferenceContributor.java | 39 --- .../util/ClassResultsFillerWrapper.java | 36 --- ...EventsConfigurationFilesResultsFiller.java | 41 --- .../EventsDeclarationsFilesResultsFiller.java | 56 ---- .../xml/reference/TypeReference.java | 54 ---- .../reference/util/ClassesResultsFiller.java | 32 -- .../util/ImplementationContextDecorator.java | 35 --- .../util/InterfacesResultsFiller.java | 28 -- .../util/ReferenceResultsFiller.java | 13 - .../util/VirtualTypesResultsFiller.java | 31 -- .../xml/util/ParentTypeMatcher.java | 42 --- .../xml/util/VirtualTypeParentMatcher.java | 31 -- .../magento2plugin/xml/webapi/XmlHelper.java | 55 ---- .../WebApiCompletionContributor.java | 91 ------ .../index/WebApiTypesFileBasedIndex.java | 134 ++++---- .../ServiceReferenceContributor.java | 39 --- .../fill/ServiceMethodResultsFiller.java | 67 ---- .../MagentoApiInspection.html | 5 - .../ObjectManagerInspection.html | 5 - 139 files changed, 3952 insertions(+), 4019 deletions(-) create mode 100644 CODE_OF_CONDUCT.md create mode 100644 COPYING.txt create mode 100644 README.md create mode 100644 src/com/magento/idea/magento2plugin/MagentoIcons.java create mode 100644 src/com/magento/idea/magento2plugin/completion/provider/CompositeCompletionProvider.java create mode 100644 src/com/magento/idea/magento2plugin/completion/provider/EventNameCompletionContributor.java create mode 100644 src/com/magento/idea/magento2plugin/completion/provider/FilePathCompletionProvider.java create mode 100644 src/com/magento/idea/magento2plugin/completion/provider/LayoutBlockCompletionContributor.java create mode 100644 src/com/magento/idea/magento2plugin/completion/provider/LayoutContainerCompletionContributor.java create mode 100644 src/com/magento/idea/magento2plugin/completion/provider/LayoutUpdateCompletionContributor.java create mode 100644 src/com/magento/idea/magento2plugin/completion/provider/ModuleNameCompletionProvider.java create mode 100644 src/com/magento/idea/magento2plugin/completion/provider/PhpClassCompletionProvider.java create mode 100644 src/com/magento/idea/magento2plugin/completion/provider/PhpClassMemberCompletionProvider.java create mode 100644 src/com/magento/idea/magento2plugin/completion/provider/PhpConstructorArgumentCompletionProvider.java create mode 100644 src/com/magento/idea/magento2plugin/completion/provider/PhpServiceMethodCompletionContributor.java create mode 100644 src/com/magento/idea/magento2plugin/completion/provider/VirtualTypeCompletionProvider.java create mode 100644 src/com/magento/idea/magento2plugin/completion/xml/XmlCompletionContributor.java create mode 100644 src/com/magento/idea/magento2plugin/indexes/EventIndex.java create mode 100644 src/com/magento/idea/magento2plugin/indexes/IndexManager.java create mode 100644 src/com/magento/idea/magento2plugin/indexes/LayoutIndex.java create mode 100644 src/com/magento/idea/magento2plugin/indexes/XmlIndex.java delete mode 100644 src/com/magento/idea/magento2plugin/php/index/ModulePackageFileBasedIndex.java delete mode 100644 src/com/magento/idea/magento2plugin/php/inspections/MagentoApiInspection.java delete mode 100644 src/com/magento/idea/magento2plugin/php/inspections/ObjectManagerInspection.java delete mode 100644 src/com/magento/idea/magento2plugin/php/linemarker/Collector.java create mode 100644 src/com/magento/idea/magento2plugin/php/linemarker/PluginLineMarkerProvider.java delete mode 100644 src/com/magento/idea/magento2plugin/php/module/ModuleUtil.java delete mode 100644 src/com/magento/idea/magento2plugin/php/tool/ModuleTool.form delete mode 100644 src/com/magento/idea/magento2plugin/php/tool/ModuleToolWindowFactory.java delete mode 100644 src/com/magento/idea/magento2plugin/php/util/ImplementationMatcher.java delete mode 100644 src/com/magento/idea/magento2plugin/php/util/MagentoTypes.java create mode 100644 src/com/magento/idea/magento2plugin/php/util/PhpRegex.java create mode 100644 src/com/magento/idea/magento2plugin/project/ProjectDetector.java create mode 100644 src/com/magento/idea/magento2plugin/reference/js/JsReferenceContributor.java create mode 100644 src/com/magento/idea/magento2plugin/reference/php/PhpReferenceContributor.java create mode 100644 src/com/magento/idea/magento2plugin/reference/provider/CompositeReferenceProvider.java create mode 100644 src/com/magento/idea/magento2plugin/reference/provider/EventDispatchReferenceProvider.java create mode 100644 src/com/magento/idea/magento2plugin/reference/provider/EventNameReferenceProvider.java create mode 100644 src/com/magento/idea/magento2plugin/reference/provider/FilePathReferenceProvider.java create mode 100644 src/com/magento/idea/magento2plugin/reference/provider/LayoutBlockReferenceProvider.java create mode 100644 src/com/magento/idea/magento2plugin/reference/provider/LayoutContainerReferenceProvider.java create mode 100644 src/com/magento/idea/magento2plugin/reference/provider/LayoutUpdateReferenceProvider.java create mode 100644 src/com/magento/idea/magento2plugin/reference/provider/ModuleNameReferenceProvider.java create mode 100644 src/com/magento/idea/magento2plugin/reference/provider/PhpClassMemberReferenceProvider.java create mode 100644 src/com/magento/idea/magento2plugin/reference/provider/PhpClassReferenceProvider.java create mode 100644 src/com/magento/idea/magento2plugin/reference/provider/PhpConstructorArgumentReferenceProvider.java create mode 100644 src/com/magento/idea/magento2plugin/reference/provider/PhpServiceMethodReferenceProvider.java create mode 100644 src/com/magento/idea/magento2plugin/reference/provider/VirtualTypeReferenceProvider.java create mode 100644 src/com/magento/idea/magento2plugin/reference/xml/PolyVariantReferenceBase.java create mode 100644 src/com/magento/idea/magento2plugin/reference/xml/XmlReferenceContributor.java create mode 100644 src/com/magento/idea/magento2plugin/stubs/indexes/BlockNameIndex.java create mode 100644 src/com/magento/idea/magento2plugin/stubs/indexes/ContainerNameIndex.java create mode 100644 src/com/magento/idea/magento2plugin/stubs/indexes/EventNameIndex.java create mode 100644 src/com/magento/idea/magento2plugin/stubs/indexes/EventObserverIndex.java create mode 100644 src/com/magento/idea/magento2plugin/stubs/indexes/ModuleNameIndex.java create mode 100644 src/com/magento/idea/magento2plugin/stubs/indexes/ModulePackageIndex.java create mode 100644 src/com/magento/idea/magento2plugin/stubs/indexes/NamedComponentIndex.java create mode 100644 src/com/magento/idea/magento2plugin/stubs/indexes/PluginIndex.java create mode 100644 src/com/magento/idea/magento2plugin/stubs/indexes/VirtualTypeIndex.java create mode 100644 src/com/magento/idea/magento2plugin/stubs/indexes/xml/PhpClassNameIndex.java delete mode 100644 src/com/magento/idea/magento2plugin/util/IndexUtil.java delete mode 100644 src/com/magento/idea/magento2plugin/util/PsiContextMatcherI.java create mode 100644 src/com/magento/idea/magento2plugin/util/RegExUtil.java create mode 100644 src/com/magento/idea/magento2plugin/util/VfsUtil.java create mode 100644 src/com/magento/idea/magento2plugin/util/magento/FileBasedIndexUtil.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/XmlHelperUtility.java create mode 100644 src/com/magento/idea/magento2plugin/xml/XmlPsiTreeUtil.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/completion/ClassCompletionProvider.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/completion/CompletionProviderI.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/completion/InterfaceCompletionProvider.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/completion/VirtualTypeCompletionProvider.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/di/XmlHelper.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/di/completion/DiCompletionContributor.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/di/index/TypeConfigurationFileBasedIndex.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/di/index/VirtualTypesNamesFileBasedIndex.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/di/reference/ArgumentNameReference.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/di/reference/ConstantReference.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/di/reference/DiReferenceContributor.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/di/reference/provider/ArgumentNameReferenceProvider.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/di/reference/provider/XmlReferenceProvider.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/di/reference/provider/resolver/ClassNameResolver.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/di/reference/provider/resolver/TypeTagResolver.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/di/reference/provider/resolver/VirtualTypeTagResolver.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/layout/LayoutUtility.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/layout/completion/LayoutCompletionContributor.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/layout/completion/ReferenceComponentCompletionProvider.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/layout/index/AbstractComponentNameFileBasedIndex.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/layout/index/BlockClassFileBasedIndex.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/layout/index/BlockFileBasedIndex.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/layout/index/ContainerFileBasedIndex.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/layout/index/util/LayoutIndexUtility.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/layout/reference/LayoutReferenceContributor.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/layout/reference/fill/BlockResultsFiller.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/layout/reference/fill/ContainerResultsFiller.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/observer/XmlHelper.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/observer/completion/EventCompletionContributor.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/observer/index/EventObserverFileBasedIndex.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/observer/index/EventsDeclarationsFileBasedIndex.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/observer/reference/EventReferenceContributor.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/observer/reference/EventReferenceProvider.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/observer/reference/ObserverReferenceContributor.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/observer/reference/util/ClassResultsFillerWrapper.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/observer/reference/util/EventsConfigurationFilesResultsFiller.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/observer/reference/util/EventsDeclarationsFilesResultsFiller.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/reference/TypeReference.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/reference/util/ClassesResultsFiller.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/reference/util/ImplementationContextDecorator.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/reference/util/InterfacesResultsFiller.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/reference/util/ReferenceResultsFiller.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/reference/util/VirtualTypesResultsFiller.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/util/ParentTypeMatcher.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/util/VirtualTypeParentMatcher.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/webapi/XmlHelper.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/webapi/completion/WebApiCompletionContributor.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/webapi/reference/ServiceReferenceContributor.java delete mode 100644 src/com/magento/idea/magento2plugin/xml/webapi/reference/fill/ServiceMethodResultsFiller.java delete mode 100644 src/inspectionDescriptions/MagentoApiInspection.html delete mode 100644 src/inspectionDescriptions/ObjectManagerInspection.html diff --git a/.gitignore b/.gitignore index 031b47bc7..70ca3b3a5 100644 --- a/.gitignore +++ b/.gitignore @@ -44,4 +44,5 @@ Temporary Items .idea .git -out \ No newline at end of file +out +build diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..8d5fa291b --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,46 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +* Using welcoming and inclusive language. +* Being respectful of differing viewpoints and experiences. +* Gracefully accepting constructive criticism. +* Focusing on what is best for the community. +* Showing empathy towards other community members. + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or advances. +* Trolling, insulting/derogatory comments, and personal or political attacks. +* Public or private harassment. +* Publishing others' private information, such as a physical or electronic address, without explicit permission. +* Other conduct which could reasonably be considered inappropriate in a professional setting. + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at engcom@magento.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]. + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 980eeb648..7f4808780 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -13,4 +13,14 @@ 1. [Build a new version of the plugin](https://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/deploying_plugin.html) 1. [Install the newly created archive/jar file from disk](https://www.jetbrains.com/help/idea/managing-plugins.html#installing-plugins-from-disk) for testing -1. [Publish](https://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/publishing_plugin.html) \ No newline at end of file +1. [Publish](https://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/publishing_plugin.html) + +# Contribution process + +If you are a new GitHub user, we recommend that you create your own [free github account](https://github.com/signup/free). This will allow you to collaborate with the Magento 2 development team, fork this project and send pull requests. + +1. Search current [listed issues](https://github.com/magento/magento2-phpstorm-plugin/issues) (open or closed) for similar proposals of intended contribution before starting work on a new contribution. +2. Review and sign the [Contributor License Agreement (CLA)](https://opensource.adobe.com/cla.html) if this is your first time contributing. You only need to sign the CLA once. +3. Create and test your work. +4. Fork this repository and create a pull request. +5. Once your contribution is received the Magento 2 development team will review the contribution and collaborate with you as needed. diff --git a/COPYING.txt b/COPYING.txt new file mode 100644 index 000000000..5bd6a165b --- /dev/null +++ b/COPYING.txt @@ -0,0 +1,9 @@ +Copyright © 2015-present Dmytro Kvashnin. + +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. diff --git a/LICENSE.md b/LICENSE.md index 38d56cc47..49dc8ec82 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,20 +1,48 @@ -Copyright (c) 2015 Dmytro Kvashnin - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Open Software License ("OSL") v. 3.0 + +This Open Software License (the "License") applies to any original work of authorship (the "Original Work") whose owner (the "Licensor") has placed the following licensing notice adjacent to the copyright notice for the Original Work: + +Licensed under the Open Software License version 3.0 + + 1. Grant of Copyright License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, for the duration of the copyright, to do the following: + + 1. to reproduce the Original Work in copies, either alone or as part of a collective work; + + 2. to translate, adapt, alter, transform, modify, or arrange the Original Work, thereby creating derivative works ("Derivative Works") based upon the Original Work; + + 3. to distribute or communicate copies of the Original Work and Derivative Works to the public, with the proviso that copies of Original Work or Derivative Works that You distribute or communicate shall be licensed under this Open Software License; + + 4. to perform the Original Work publicly; and + + 5. to display the Original Work publicly. + + 2. Grant of Patent License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, under patent claims owned or controlled by the Licensor that are embodied in the Original Work as furnished by the Licensor, for the duration of the patents, to make, use, sell, offer for sale, have made, and import the Original Work and Derivative Works. + + 3. Grant of Source Code License. The term "Source Code" means the preferred form of the Original Work for making modifications to it and all available documentation describing how to modify the Original Work. Licensor agrees to provide a machine-readable copy of the Source Code of the Original Work along with each copy of the Original Work that Licensor distributes. Licensor reserves the right to satisfy this obligation by placing a machine-readable copy of the Source Code in an information repository reasonably calculated to permit inexpensive and convenient access by You for as long as Licensor continues to distribute the Original Work. + + 4. Exclusions From License Grant. Neither the names of Licensor, nor the names of any contributors to the Original Work, nor any of their trademarks or service marks, may be used to endorse or promote products derived from this Original Work without express prior permission of the Licensor. Except as expressly stated herein, nothing in this License grants any license to Licensor's trademarks, copyrights, patents, trade secrets or any other intellectual property. No patent license is granted to make, use, sell, offer for sale, have made, or import embodiments of any patent claims other than the licensed claims defined in Section 2. No license is granted to the trademarks of Licensor even if such marks are included in the Original Work. Nothing in this License shall be interpreted to prohibit Licensor from licensing under terms different from this License any Original Work that Licensor otherwise would have a right to license. + + 5. External Deployment. The term "External Deployment" means the use, distribution, or communication of the Original Work or Derivative Works in any way such that the Original Work or Derivative Works may be used by anyone other than You, whether those works are distributed or communicated to those persons or made available as an application intended for use over a network. As an express condition for the grants of license hereunder, You must treat any External Deployment by You of the Original Work or a Derivative Work as a distribution under section 1(c). + + 6. Attribution Rights. You must retain, in the Source Code of any Derivative Works that You create, all copyright, patent, or trademark notices from the Source Code of the Original Work, as well as any notices of licensing and any descriptive text identified therein as an "Attribution Notice." You must cause the Source Code for any Derivative Works that You create to carry a prominent Attribution Notice reasonably calculated to inform recipients that You have modified the Original Work. + + 7. Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that the copyright in and to the Original Work and the patent rights granted herein by Licensor are owned by the Licensor or are sublicensed to You under the terms of this License with the permission of the contributor(s) of those copyrights and patent rights. Except as expressly stated in the immediately preceding sentence, the Original Work is provided under this License on an "AS IS" BASIS and WITHOUT WARRANTY, either express or implied, including, without limitation, the warranties of non-infringement, merchantability or fitness for a particular purpose. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No license to the Original Work is granted by this License except under this disclaimer. + + 8. Limitation of Liability. Under no circumstances and under no legal theory, whether in tort (including negligence), contract, or otherwise, shall the Licensor be liable to anyone for any indirect, special, incidental, or consequential damages of any character arising as a result of this License or the use of the Original Work including, without limitation, damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses. This limitation of liability shall not apply to the extent applicable law prohibits such limitation. + + 9. Acceptance and Termination. If, at any time, You expressly assented to this License, that assent indicates your clear and irrevocable acceptance of this License and all of its terms and conditions. If You distribute or communicate copies of the Original Work or a Derivative Work, You must make a reasonable effort under the circumstances to obtain the express assent of recipients to the terms of this License. This License conditions your rights to undertake the activities listed in Section 1, including your right to create Derivative Works based upon the Original Work, and doing so without honoring these terms and conditions is prohibited by copyright law and international treaty. Nothing in this License is intended to affect copyright exceptions and limitations (including 'fair use' or 'fair dealing'). This License shall terminate immediately and You may no longer exercise any of the rights granted to You by this License upon your failure to honor the conditions in Section 1(c). + + 10. Termination for Patent Action. This License shall terminate automatically and You may no longer exercise any of the rights granted to You by this License as of the date You commence an action, including a cross-claim or counterclaim, against Licensor or any licensee alleging that the Original Work infringes a patent. This termination provision shall not apply for an action alleging patent infringement by combinations of the Original Work with other software or hardware. + + 11. Jurisdiction, Venue and Governing Law. Any action or suit relating to this License may be brought only in the courts of a jurisdiction wherein the Licensor resides or in which Licensor conducts its primary business, and under the laws of that jurisdiction excluding its conflict-of-law provisions. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any use of the Original Work outside the scope of this License or after its termination shall be subject to the requirements and penalties of copyright or patent law in the appropriate jurisdiction. This section shall survive the termination of this License. + + 12. Attorneys' Fees. In any action to enforce the terms of this License or seeking damages relating thereto, the prevailing party shall be entitled to recover its costs and expenses, including, without limitation, reasonable attorneys' fees and costs incurred in connection with such action, including any appeal of such action. This section shall survive the termination of this License. + + 13. Miscellaneous. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. + + 14. Definition of "You" in This License. "You" throughout this License, whether in upper or lower case, means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License. For legal entities, "You" includes any entity that controls, is controlled by, or is under common control with you. For purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + 15. Right to Use. You may use the Original Work in all ways not otherwise restricted or conditioned by this License or by law, and Licensor promises not to interfere with or be responsible for such uses by You. + + 16. Modification of This License. This License is Copyright (C) 2005 Lawrence Rosen. Permission is granted to copy, distribute, or communicate this License without modification. Nothing in this License permits You to modify this License as applied to the Original Work or to Derivative Works. However, You may modify the text of this License and copy, distribute or communicate your modified version (the "Modified License") and apply it to other original works of authorship subject to the following conditions: (i) You may not indicate in any way that your Modified License is the "Open Software License" or "OSL" and you may not use those names in the name of your Modified License; (ii) You must replace the notice specified in the first paragraph above with the notice "Licensed under " or with a notice of your own that is not confusingly similar to the notice in this License; and (iii) You may not claim that your original works are open source software unless your Modified License has been approved by Open Source Initiative (OSI) and You comply with its license review and certification process. diff --git a/META-INF/plugin.xml b/META-INF/plugin.xml index 8c70dea6f..795eb465c 100644 --- a/META-INF/plugin.xml +++ b/META-INF/plugin.xml @@ -1,3 +1,9 @@ + com.magento.idea.magento2plugin Magento PhpStorm diff --git a/README.md b/README.md new file mode 100644 index 000000000..93c3a7b0d --- /dev/null +++ b/README.md @@ -0,0 +1,30 @@ +# PhpStorm Magento 2 Plugin + +[![Version](http://phpstorm.espend.de/badge/8024/version)](https://plugins.jetbrains.com/plugin/8024) +[![Downloads](http://phpstorm.espend.de/badge/8024/downloads)](https://plugins.jetbrains.com/plugin/8024) +[![Downloads last month](http://phpstorm.espend.de/badge/8024/last-month)](https://plugins.jetbrains.com/plugin/8024) + +This is a plugin for Magento 2 development in the PhpStorm IDE. It is available via the [JetBrains Plugin Repository](https://plugins.jetbrains.com/plugin/8024) +## Installation + +1. Go to Settings / Preferences in the PhpStorm IDE +2. Navigate to "Plugins" +3. Click the "Browse repositories..." button and search for "Magento PhpStorm" +4. Install the plugin and restart PhpStorm +5. Go to Settings / Preferences / Languages & Frameworks / PHP / Magento in the PhpStorm IDE +6. Check "Enable" and "OK" button. + +## Works with +* PhpStorm >= 2017.2 +* JRE >= 1.8 + +## Features + +* Configuration smart completion and references for XML/JavaScript files +* "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 + +## License + +Copyright (c) 2015 Dmytro Kvashnin. See LICENSE.md for details. diff --git a/magento2plugin.iml b/magento2plugin.iml index 0f0805366..e05bb8cc6 100644 --- a/magento2plugin.iml +++ b/magento2plugin.iml @@ -1,4 +1,10 @@ + @@ -9,7 +15,7 @@ - + \ No newline at end of file diff --git a/src/com/magento/idea/magento2plugin/MagentoIcons.java b/src/com/magento/idea/magento2plugin/MagentoIcons.java new file mode 100644 index 000000000..ae139608a --- /dev/null +++ b/src/com/magento/idea/magento2plugin/MagentoIcons.java @@ -0,0 +1,16 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin; + +import com.intellij.openapi.util.IconLoader; + +import javax.swing.*; + +/** + * Created by dkvashnin on 11/14/15. + */ +public class MagentoIcons { + public static final Icon WEB_API = IconLoader.getIcon("icons/webapi.png"); +} diff --git a/src/com/magento/idea/magento2plugin/Settings.java b/src/com/magento/idea/magento2plugin/Settings.java index 8c6f73cb8..47b8a3262 100644 --- a/src/com/magento/idea/magento2plugin/Settings.java +++ b/src/com/magento/idea/magento2plugin/Settings.java @@ -1,4 +1,8 @@ -package com.magento.idea.magento2plugin; +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.project; import com.intellij.openapi.components.*; import com.intellij.openapi.project.Project; @@ -26,14 +30,8 @@ public void loadState(Settings settings) { XmlSerializerUtil.copyBean(settings, this); } - protected Project project; - public static Settings getInstance(Project project) { - Settings settings = ServiceManager.getService(project, Settings.class); - - settings.project = project; - - return settings; + return ServiceManager.getService(project, Settings.class); } public static boolean isEnabled(@NotNull Project project) { diff --git a/src/com/magento/idea/magento2plugin/SettingsForm.form b/src/com/magento/idea/magento2plugin/SettingsForm.form index 3317a0f20..6a596098b 100644 --- a/src/com/magento/idea/magento2plugin/SettingsForm.form +++ b/src/com/magento/idea/magento2plugin/SettingsForm.form @@ -1,5 +1,11 @@ -
+ + diff --git a/src/com/magento/idea/magento2plugin/SettingsForm.java b/src/com/magento/idea/magento2plugin/SettingsForm.java index d55631887..4eb818305 100644 --- a/src/com/magento/idea/magento2plugin/SettingsForm.java +++ b/src/com/magento/idea/magento2plugin/SettingsForm.java @@ -1,4 +1,8 @@ -package com.magento.idea.magento2plugin; +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.project; import com.intellij.javaee.ExternalResourceManager; import com.intellij.javaee.ExternalResourceManagerEx; @@ -11,27 +15,29 @@ import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; import com.intellij.psi.search.FilenameIndex; +import com.magento.idea.magento2plugin.indexes.IndexManager; import com.magento.idea.magento2plugin.php.module.ComposerPackageModel; import com.magento.idea.magento2plugin.php.module.MagentoComponent; import com.magento.idea.magento2plugin.php.module.MagentoComponentManager; import com.magento.idea.magento2plugin.php.module.MagentoModule; -import com.magento.idea.magento2plugin.util.IndexUtil; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; -import java.util.*; +import java.util.Collection; +import java.util.Stack; /** * Created by dkvashnin on 1/9/16. */ public class SettingsForm implements Configurable { - private Project project; + + private final static String DISPLAY_NAME = "Magento"; + + private final Project project; private JCheckBox pluginEnabled; private JButton buttonReindex; private JPanel panel1; @@ -44,7 +50,7 @@ public SettingsForm(@NotNull final Project project) { @Nls @Override public String getDisplayName() { - return "Magento2 plugin"; + return SettingsForm.DISPLAY_NAME; } @Nullable @@ -76,7 +82,7 @@ public void mouseClicked(MouseEvent e) { } private void reindex() { - IndexUtil.manualReindex(); + IndexManager.manualReindex(); MagentoComponentManager.getInstance(project).flushModules(); } diff --git a/src/com/magento/idea/magento2plugin/completion/provider/CompositeCompletionProvider.java b/src/com/magento/idea/magento2plugin/completion/provider/CompositeCompletionProvider.java new file mode 100644 index 000000000..f4dc6f1f8 --- /dev/null +++ b/src/com/magento/idea/magento2plugin/completion/provider/CompositeCompletionProvider.java @@ -0,0 +1,30 @@ +/** + * Copyright © Dmytro Kvashnin. 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.util.ProcessingContext; +import org.jetbrains.annotations.NotNull; + +public class CompositeCompletionProvider extends CompletionProvider { + + private CompletionProvider[] providers = null; + + @SafeVarargs + public CompositeCompletionProvider(CompletionProvider ...providers) { + this.providers = providers; + } + + @Override + protected void addCompletions(@NotNull CompletionParameters parameters, + ProcessingContext context, + @NotNull CompletionResultSet result) { + for (CompletionProvider provider : providers) { + provider.addCompletionVariants(parameters, context, result); + } + } +} diff --git a/src/com/magento/idea/magento2plugin/completion/provider/EventNameCompletionContributor.java b/src/com/magento/idea/magento2plugin/completion/provider/EventNameCompletionContributor.java new file mode 100644 index 000000000..ca6f2a032 --- /dev/null +++ b/src/com/magento/idea/magento2plugin/completion/provider/EventNameCompletionContributor.java @@ -0,0 +1,34 @@ +/** + * Copyright © Dmytro Kvashnin. 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.psi.PsiElement; +import com.intellij.util.ProcessingContext; +import com.intellij.util.indexing.FileBasedIndex; +import com.magento.idea.magento2plugin.stubs.indexes.EventNameIndex; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; + +public class EventNameCompletionContributor extends CompletionProvider { + + @Override + protected void addCompletions(@NotNull CompletionParameters parameters, + ProcessingContext context, + @NotNull CompletionResultSet result) { + PsiElement position = parameters.getPosition().getOriginalElement(); + + Collection eventNames = FileBasedIndex.getInstance() + .getAllKeys(EventNameIndex.KEY, position.getProject()); + + for (String eventName: eventNames) { + result.addElement(LookupElementBuilder.create(eventName)); + } + } +} diff --git a/src/com/magento/idea/magento2plugin/completion/provider/FilePathCompletionProvider.java b/src/com/magento/idea/magento2plugin/completion/provider/FilePathCompletionProvider.java new file mode 100644 index 000000000..ff52f0586 --- /dev/null +++ b/src/com/magento/idea/magento2plugin/completion/provider/FilePathCompletionProvider.java @@ -0,0 +1,123 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.completion.provider; + +import com.intellij.codeInsight.completion.CompletionParameters; +import com.intellij.codeInsight.completion.CompletionProvider; +import com.intellij.codeInsight.completion.CompletionResultSet; +import com.intellij.codeInsight.lookup.LookupElementBuilder; +import com.intellij.icons.AllIcons; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiElement; +import com.intellij.util.ProcessingContext; +import com.magento.idea.magento2plugin.util.RegExUtil; +import com.magento.idea.magento2plugin.util.VfsUtil; +import com.magento.idea.magento2plugin.util.magento.FileBasedIndexUtil; +import org.jetbrains.annotations.NotNull; + +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class FilePathCompletionProvider 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(); + + String filePath; + String filePathPrefix; + boolean removeFileExtension = false; + + Pattern pattern = Pattern.compile( + "(" + RegExUtil.Magento.MODULE_NAME + "(\\W+))(" + RegExUtil.FILE_PATH + ")?" + ); + Matcher matcher = pattern.matcher(prefix); + if (matcher.find()) { + filePathPrefix = matcher.group(1); + removeFileExtension = matcher.group(2).equals("/"); + filePath = matcher.group(3) != null ? matcher.group(3) : ""; + } else { + pattern = Pattern.compile("(" + RegExUtil.FILE_PATH + ")+"); + matcher = pattern.matcher(prefix); + if (!matcher.find()) { + return; + } + filePathPrefix = ""; + filePath = matcher.group(1); + } + + // find all view virtual files + Collection viewVfs = findViewVfs(parameters, result); + + for (VirtualFile vf:viewVfs) { + for (VirtualFile file : VfsUtil.getAllSubFiles(vf)) { + String label = file.getPath().replace(vf.getPath(), ""); + + pattern = label.matches("(/[\\w-]+){2}/template/.*") + //e.g. (adminhtml|frontend|base|*)/(web|layout|*)/template/{whatever client typed} + ? Pattern.compile("^((/[\\w-]+){3}/)" + filePath) + //e.g. (adminhtml|frontend|base|*)/(web|layout|*)/{whatever client typed} + : Pattern.compile("^((/[\\w-]+){2}/)" + filePath); + + matcher = pattern.matcher(label); + if (!matcher.find()) { + continue; + } + + //remove prefix + label = label.replace(matcher.group(0), ""); + boolean lastPathSegment = !(label.indexOf("/", 1) > 0); + label = lastPathSegment ? label : label.substring(0, label.indexOf("/", 1)); + label = filePathPrefix + filePath + label; + label = !removeFileExtension ? label : (label.lastIndexOf(".") > 0 + ? label.substring(0, label.lastIndexOf(".")) + : label + ); + + result.addElement( + LookupElementBuilder + .create(label) + .withIcon(lastPathSegment ? file.getFileType().getIcon() : AllIcons.Nodes.Folder) + ); + } + } + } + + private Collection findViewVfs(CompletionParameters parameters, CompletionResultSet result) + { + Collection viewVfs = new ArrayList<>(); + + Pattern pattern = Pattern.compile(RegExUtil.Magento.MODULE_NAME); + Matcher matcher = pattern.matcher(result.getPrefixMatcher().getPrefix()); + + if (matcher.find()) { + viewVfs.addAll( + FileBasedIndexUtil.findViewVfsByModuleName(matcher.group(0), parameters.getPosition().getProject()) + ); + } else { + VirtualFile tf = parameters.getOriginalFile().getVirtualFile(); + if (tf != null) { + VirtualFile moduleVf = + VfsUtil.findVfUp(tf, "registration.php"); + + if (moduleVf != null) { + viewVfs.addAll( + FileBasedIndexUtil.findViewVfsByModuleVf(moduleVf, parameters.getPosition().getProject()) + ); + } + } + } + + return viewVfs; + } +} diff --git a/src/com/magento/idea/magento2plugin/completion/provider/LayoutBlockCompletionContributor.java b/src/com/magento/idea/magento2plugin/completion/provider/LayoutBlockCompletionContributor.java new file mode 100644 index 000000000..9885fd22e --- /dev/null +++ b/src/com/magento/idea/magento2plugin/completion/provider/LayoutBlockCompletionContributor.java @@ -0,0 +1,38 @@ +/** + * Copyright © Dmytro Kvashnin. 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.psi.PsiElement; +import com.intellij.util.ProcessingContext; +import com.jetbrains.php.PhpIcons; +import com.magento.idea.magento2plugin.indexes.LayoutIndex; +import com.magento.idea.magento2plugin.stubs.indexes.BlockNameIndex; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; + +public class LayoutBlockCompletionContributor extends CompletionProvider { + + @Override + protected void addCompletions(@NotNull CompletionParameters parameters, + ProcessingContext context, + @NotNull CompletionResultSet result) { + PsiElement position = parameters.getPosition().getOriginalElement(); + if (position == null) { + return; + } + + Collection keys = LayoutIndex.getAllKeys(BlockNameIndex.KEY, position.getProject()); + for (String key: keys) { + result.addElement( + LookupElementBuilder.create(key).withIcon(PhpIcons.XML_TAG_ICON) + ); + } + } +} diff --git a/src/com/magento/idea/magento2plugin/completion/provider/LayoutContainerCompletionContributor.java b/src/com/magento/idea/magento2plugin/completion/provider/LayoutContainerCompletionContributor.java new file mode 100644 index 000000000..6093efc6b --- /dev/null +++ b/src/com/magento/idea/magento2plugin/completion/provider/LayoutContainerCompletionContributor.java @@ -0,0 +1,38 @@ +/** + * Copyright © Dmytro Kvashnin. 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.psi.PsiElement; +import com.intellij.util.ProcessingContext; +import com.jetbrains.php.PhpIcons; +import com.magento.idea.magento2plugin.indexes.LayoutIndex; +import com.magento.idea.magento2plugin.stubs.indexes.ContainerNameIndex; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; + +public class LayoutContainerCompletionContributor extends CompletionProvider { + + @Override + protected void addCompletions(@NotNull CompletionParameters parameters, + ProcessingContext context, + @NotNull CompletionResultSet result) { + PsiElement position = parameters.getPosition().getOriginalElement(); + if (position == null) { + return; + } + + Collection keys = LayoutIndex.getAllKeys(ContainerNameIndex.KEY, position.getProject()); + for (String key: keys) { + result.addElement( + LookupElementBuilder.create(key).withIcon(PhpIcons.XML_TAG_ICON) + ); + } + } +} diff --git a/src/com/magento/idea/magento2plugin/completion/provider/LayoutUpdateCompletionContributor.java b/src/com/magento/idea/magento2plugin/completion/provider/LayoutUpdateCompletionContributor.java new file mode 100644 index 000000000..3fe032cd2 --- /dev/null +++ b/src/com/magento/idea/magento2plugin/completion/provider/LayoutUpdateCompletionContributor.java @@ -0,0 +1,42 @@ +/** + * Copyright © Dmytro Kvashnin. 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.psi.PsiElement; +import com.intellij.psi.xml.XmlFile; +import com.intellij.util.ProcessingContext; +import com.jetbrains.php.PhpIcons; +import com.magento.idea.magento2plugin.indexes.LayoutIndex; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public class LayoutUpdateCompletionContributor extends CompletionProvider { + + @Override + protected void addCompletions(@NotNull CompletionParameters parameters, + ProcessingContext context, + @NotNull CompletionResultSet result) { + PsiElement position = parameters.getPosition().getOriginalElement(); + if (position == null) { + return; + } + + List targets = LayoutIndex.getLayoutFiles(position.getProject()); + if (targets.size() > 0) { + for (XmlFile file : targets) { + result.addElement( + LookupElementBuilder + .create(file.getVirtualFile().getNameWithoutExtension()) + .withIcon(PhpIcons.XML_TAG_ICON) + ); + } + } + } +} diff --git a/src/com/magento/idea/magento2plugin/completion/provider/ModuleNameCompletionProvider.java b/src/com/magento/idea/magento2plugin/completion/provider/ModuleNameCompletionProvider.java new file mode 100644 index 000000000..fd336ca49 --- /dev/null +++ b/src/com/magento/idea/magento2plugin/completion/provider/ModuleNameCompletionProvider.java @@ -0,0 +1,45 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.completion.provider; + +import com.intellij.codeInsight.completion.CompletionParameters; +import com.intellij.codeInsight.completion.CompletionProvider; +import com.intellij.codeInsight.completion.CompletionResultSet; +import com.intellij.codeInsight.lookup.LookupElementBuilder; +import com.intellij.icons.AllIcons; +import com.intellij.psi.PsiElement; +import com.intellij.util.ProcessingContext; +import com.intellij.util.indexing.FileBasedIndex; +import com.magento.idea.magento2plugin.stubs.indexes.ModuleNameIndex; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; + +public class ModuleNameCompletionProvider 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 moduleNames + = FileBasedIndex.getInstance().getAllKeys(ModuleNameIndex.KEY, position.getProject()); + + + moduleNames.removeIf(m -> !m.startsWith(prefix)); + for (String moduleName : moduleNames) { + result.addElement( + LookupElementBuilder + .create(moduleName) + .withIcon(AllIcons.Modules.ModulesNode) + ); + } + } +} diff --git a/src/com/magento/idea/magento2plugin/completion/provider/PhpClassCompletionProvider.java b/src/com/magento/idea/magento2plugin/completion/provider/PhpClassCompletionProvider.java new file mode 100644 index 000000000..568d44b9a --- /dev/null +++ b/src/com/magento/idea/magento2plugin/completion/provider/PhpClassCompletionProvider.java @@ -0,0 +1,110 @@ +/** + * Copyright © Dmytro Kvashnin. 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.completion.impl.CamelHumpMatcher; +import com.intellij.codeInsight.lookup.LookupElementBuilder; +import com.intellij.psi.PsiElement; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.ProcessingContext; +import com.jetbrains.php.PhpIcons; +import com.jetbrains.php.PhpIndex; +import com.jetbrains.php.lang.psi.elements.PhpClass; +import com.jetbrains.php.lang.psi.elements.PhpNamespace; +import com.magento.idea.magento2plugin.php.util.PhpRegex; +import gnu.trove.THashSet; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +public class PhpClassCompletionProvider extends CompletionProvider { + + final private static String PHP_CLASS_COMPLETION_REGEX + = "\\\\?" + PhpRegex.FQN + "\\\\?"; + + @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(); + Matcher matcher = Pattern.compile(PHP_CLASS_COMPLETION_REGEX).matcher(prefix); + if (!matcher.matches()) { + return; + } + + String className = prefix.lastIndexOf(92) < 0 ? prefix : prefix.substring(prefix.lastIndexOf(92) + 1); + String namespace = prefix.lastIndexOf(92) < 0 ? "" : prefix.substring(0, prefix.lastIndexOf(92)); + + PhpIndex phpIndex = PhpIndex.getInstance(parameters.getPosition().getProject()); + + final Collection phpClasses = new THashSet<>(); + Collection namespaceNames = new ArrayList<>(); + + if (!className.isEmpty()) { + // case for input: "SomeClassOrNamespace" + + // add classes + Collection classNames = phpIndex.getAllClassNames(new CamelHumpMatcher(className)); + for (String cName: classNames) { + phpClasses.addAll(phpIndex.getClassesByName(cName)); + } + // add interfaces + Collection interfaceNames = phpIndex.getAllInterfaceNames(); + interfaceNames.removeIf(i -> !i.contains(className)); + for (String iName: interfaceNames) { + phpClasses.addAll(phpIndex.getInterfacesByName(iName)); + } + if (!namespace.isEmpty()) { + phpClasses.removeIf(c -> !c.getPresentableFQN().startsWith(namespace)); + } else { + namespaceNames = phpIndex.getChildNamespacesByParentName("\\"); + namespaceNames.removeIf(n -> !n.contains(prefix)); + } + } else { + // case for input: "Some\Namespace\ + ^+" + + // add namespaces + Collection namespaces = phpIndex.getNamespacesByName(("\\" + namespace).toLowerCase()); + for (PhpNamespace nsp: namespaces) { + phpClasses.addAll(PsiTreeUtil.getChildrenOfTypeAsList(nsp.getStatements(), PhpClass.class)); + } + + // add namespaces and classes (string representation) + namespaceNames + = phpIndex.getChildNamespacesByParentName("\\".concat(namespace).concat("\\").toLowerCase()); + namespaceNames + = namespaceNames.stream().map(n -> namespace.concat("\\").concat(n)).collect(Collectors.toList()); + } + + // add all above founded items to lookup builder + // order is important (items with the same name override each other), add classes first + for (PhpClass phpClass : phpClasses) { + result.addElement( + LookupElementBuilder + .create(phpClass.getPresentableFQN()) + .withIcon(phpClass.getIcon()) + ); + } + + for (String nsName : namespaceNames) { + result.addElement( + LookupElementBuilder + .create(nsName) + .withIcon(PhpIcons.NAMESPACE) + ); + } + } +} diff --git a/src/com/magento/idea/magento2plugin/completion/provider/PhpClassMemberCompletionProvider.java b/src/com/magento/idea/magento2plugin/completion/provider/PhpClassMemberCompletionProvider.java new file mode 100644 index 000000000..46ccfa205 --- /dev/null +++ b/src/com/magento/idea/magento2plugin/completion/provider/PhpClassMemberCompletionProvider.java @@ -0,0 +1,65 @@ +/** + * Copyright © Dmytro Kvashnin. 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.psi.PsiElement; +import com.intellij.util.ProcessingContext; +import com.jetbrains.php.PhpIndex; +import com.jetbrains.php.lang.psi.elements.Field; +import com.jetbrains.php.lang.psi.elements.PhpClass; +import com.jetbrains.php.lang.psi.elements.PhpClassMember; +import gnu.trove.THashSet; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; + +public class PhpClassMemberCompletionProvider extends CompletionProvider { + + @Override + protected void addCompletions(@NotNull CompletionParameters parameters, + ProcessingContext context, + @NotNull CompletionResultSet result) { + PsiElement position = parameters.getPosition().getOriginalElement(); + if (position == null) { + return; + } + + final Collection members = new THashSet<>(); + String prefix = result.getPrefixMatcher().getPrefix(); + + if (!(prefix.lastIndexOf("::") > 0 && prefix.lastIndexOf("\\") > 0 + && prefix.lastIndexOf("::") > prefix.lastIndexOf("\\"))) { + return; + } + + String className = prefix.substring(0, prefix.lastIndexOf("::")); + + PhpIndex phpIndex = PhpIndex.getInstance(parameters.getPosition().getProject()); + for (PhpClass phpClass : phpIndex.getAnyByFQN(className)) { + members.addAll(phpClass.getFields()); + members.addAll(phpClass.getMethods()); + } + + for (PhpClassMember member : members) { + if (Field.class.isInstance(member)) { + result.addElement( + LookupElementBuilder + .create(className + (((Field) member).isConstant() ? "::" : "::$") + member.getName()) + .withIcon(member.getIcon()) + ); + } else { + result.addElement( + LookupElementBuilder + .create(className + "::" + member.getName() + "()") + .withIcon(member.getIcon()) + ); + } + } + } +} diff --git a/src/com/magento/idea/magento2plugin/completion/provider/PhpConstructorArgumentCompletionProvider.java b/src/com/magento/idea/magento2plugin/completion/provider/PhpConstructorArgumentCompletionProvider.java new file mode 100644 index 000000000..a86c9f0f0 --- /dev/null +++ b/src/com/magento/idea/magento2plugin/completion/provider/PhpConstructorArgumentCompletionProvider.java @@ -0,0 +1,47 @@ +/** + * Copyright © Dmytro Kvashnin. 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.psi.PsiElement; +import com.intellij.psi.xml.XmlElement; +import com.intellij.util.ProcessingContext; +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.magento.idea.magento2plugin.indexes.DiIndex; +import org.jetbrains.annotations.NotNull; + +public class PhpConstructorArgumentCompletionProvider extends CompletionProvider { + + @Override + protected void addCompletions(@NotNull CompletionParameters parameters, + ProcessingContext context, + @NotNull CompletionResultSet result) { + PsiElement position = parameters.getPosition().getOriginalElement(); + if (position == null || !(position instanceof XmlElement)) { + return; + } + + + DiIndex diIndex = DiIndex.getInstance(position.getProject()); + PhpClass phpClass = diIndex.getPhpClassOfArgument((XmlElement) position); + if (phpClass != null) { + Method constructor = phpClass.getConstructor(); + if (constructor != null) { + for (Parameter parameter : constructor.getParameters()) { + result.addElement( + LookupElementBuilder + .create(parameter.getName()) + .withIcon(parameter.getIcon()) + ); + } + } + } + } +} diff --git a/src/com/magento/idea/magento2plugin/completion/provider/PhpServiceMethodCompletionContributor.java b/src/com/magento/idea/magento2plugin/completion/provider/PhpServiceMethodCompletionContributor.java new file mode 100644 index 000000000..f9b67b9d1 --- /dev/null +++ b/src/com/magento/idea/magento2plugin/completion/provider/PhpServiceMethodCompletionContributor.java @@ -0,0 +1,41 @@ +/** + * Copyright © Dmytro Kvashnin. 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.psi.PsiElement; +import com.intellij.psi.xml.XmlElement; +import com.intellij.util.ProcessingContext; +import com.jetbrains.php.lang.psi.elements.Method; +import com.jetbrains.php.lang.psi.elements.PhpClass; +import com.magento.idea.magento2plugin.indexes.DiIndex; +import org.jetbrains.annotations.NotNull; + +public class PhpServiceMethodCompletionContributor extends CompletionProvider { + + @Override + protected void addCompletions(@NotNull CompletionParameters parameters, + ProcessingContext context, + @NotNull CompletionResultSet result) { + PsiElement position = parameters.getPosition().getOriginalElement(); + if (position == null) { + return; + } + + PhpClass phpClass = DiIndex.getPhpClassOfServiceMethod((XmlElement) position); + if (phpClass != null) { + for (Method method : phpClass.getMethods()) { + result.addElement( + LookupElementBuilder + .create(method.getName()) + .withIcon(method.getIcon()) + ); + } + } + } +} diff --git a/src/com/magento/idea/magento2plugin/completion/provider/VirtualTypeCompletionProvider.java b/src/com/magento/idea/magento2plugin/completion/provider/VirtualTypeCompletionProvider.java new file mode 100644 index 000000000..ee547d60e --- /dev/null +++ b/src/com/magento/idea/magento2plugin/completion/provider/VirtualTypeCompletionProvider.java @@ -0,0 +1,44 @@ +/** + * Copyright © Dmytro Kvashnin. 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.completion.PlainPrefixMatcher; +import com.intellij.codeInsight.lookup.LookupElementBuilder; +import com.intellij.psi.PsiElement; +import com.intellij.util.ProcessingContext; +import com.jetbrains.php.PhpIcons; +import com.magento.idea.magento2plugin.indexes.DiIndex; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; + +public class VirtualTypeCompletionProvider extends CompletionProvider { + + @Override + protected void addCompletions(@NotNull CompletionParameters parameters, + ProcessingContext context, + @NotNull CompletionResultSet result) { + PsiElement position = parameters.getPosition().getOriginalElement(); + if (position == null) { + return; + } + + String prefix = result.getPrefixMatcher().getPrefix(); + + DiIndex index = DiIndex.getInstance(position.getProject()); + Collection elements = index.getAllVirtualTypeElementNames(new PlainPrefixMatcher(prefix), position.getResolveScope()); + + for (String elementName:elements) { + result.addElement( + LookupElementBuilder + .create(elementName) + .withIcon(PhpIcons.CLASS_ICON) + ); + } + } +} diff --git a/src/com/magento/idea/magento2plugin/completion/xml/XmlCompletionContributor.java b/src/com/magento/idea/magento2plugin/completion/xml/XmlCompletionContributor.java new file mode 100644 index 000000000..c1a5ff150 --- /dev/null +++ b/src/com/magento/idea/magento2plugin/completion/xml/XmlCompletionContributor.java @@ -0,0 +1,109 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.completion.xml; + +import com.intellij.codeInsight.completion.CompletionContributor; +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 static com.intellij.patterns.PlatformPatterns.psiElement; +import static com.intellij.patterns.StandardPatterns.string; +import static com.intellij.patterns.XmlPatterns.xmlFile; + +public class XmlCompletionContributor extends CompletionContributor { + + public XmlCompletionContributor() { + extend(CompletionType.BASIC, psiElement(XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN), + new CompositeCompletionProvider( + new PhpClassCompletionProvider(), + new PhpClassMemberCompletionProvider(), + new ModuleNameCompletionProvider(), + new FilePathCompletionProvider() + ) + ); + + extend(CompletionType.BASIC, psiElement(XmlTokenType.XML_DATA_CHARACTERS), + new CompositeCompletionProvider( + new PhpClassCompletionProvider(), + new PhpClassMemberCompletionProvider(), + new ModuleNameCompletionProvider(), + new FilePathCompletionProvider() + ) + ); + + extend(CompletionType.BASIC, psiElement(XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN) + .inside(XmlPatterns.xmlAttribute().withName("type")), + new VirtualTypeCompletionProvider() + ); + extend(CompletionType.BASIC, psiElement(XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN) + .inside(XmlPatterns.xmlAttribute().withName("name") + .withParent(XmlPatterns.xmlTag().withName("virtualType"))), + new VirtualTypeCompletionProvider() + ); + extend(CompletionType.BASIC, psiElement(XmlTokenType.XML_DATA_CHARACTERS) + .withParent(XmlPatterns.xmlText().withParent(XmlPatterns.xmlTag().withChild( + XmlPatterns.xmlAttribute().withName("xsi:type").withValue(string().oneOf("object")))) + ), + new VirtualTypeCompletionProvider() + ); + + // + extend(CompletionType.BASIC, psiElement(XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN) + .inside(XmlPatterns.xmlAttribute().withName("name") + .withParent(XmlPatterns.xmlTag().withName("argument") + .withParent(XmlPatterns.xmlTag().withName("arguments")) + ) + ).inFile(xmlFile().withName(string().endsWith("di.xml"))), + new PhpConstructorArgumentCompletionProvider() + ); + + // + extend(CompletionType.BASIC, psiElement(XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN) + .inside(XmlPatterns.xmlAttribute().withName("method") + .withParent(XmlPatterns.xmlTag().withName("service")) + ).inFile(xmlFile().withName(string().endsWith("webapi.xml"))), + new PhpServiceMethodCompletionContributor() + ); + + extend(CompletionType.BASIC, psiElement(XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN) + .inside(XmlPatterns.xmlAttribute().withName("name") + .withParent(XmlPatterns.xmlTag().withName("referenceContainer")) + ), + new LayoutContainerCompletionContributor() + ); + + extend(CompletionType.BASIC, XmlPatterns.or( + psiElement(XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN).inside(XmlPatterns.xmlAttribute().withName("name") + .withParent(XmlPatterns.xmlTag().withName("referenceBlock"))), + psiElement(XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN).inside(XmlPatterns.xmlAttribute() + .withName(string().oneOf("before", "after")) + .withParent(XmlPatterns.xmlTag().withName("block"))), + psiElement(XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN).inside(XmlPatterns.xmlAttribute() + .withName(string().oneOf("before", "after", "destination", "element")) + .withParent(XmlPatterns.xmlTag().withName("move"))), + psiElement(XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN).inside(XmlPatterns.xmlAttribute().withName("name") + .withParent(XmlPatterns.xmlTag().withName("remove"))) + ), + new LayoutBlockCompletionContributor() + ); + + extend(CompletionType.BASIC, psiElement(XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN) + .inside(XmlPatterns.xmlAttribute().withName("handle") + .withParent(XmlPatterns.xmlTag().withName("update")) + ), + new LayoutUpdateCompletionContributor() + ); + + // event name completion contributor + extend(CompletionType.BASIC, psiElement(XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN) + .inside(XmlPatterns.xmlAttribute().withName("name") + .withParent(XmlPatterns.xmlTag().withName("event")) + ).inFile(xmlFile().withName(string().endsWith("events.xml"))), + new EventNameCompletionContributor() + ); + } +} diff --git a/src/com/magento/idea/magento2plugin/indexes/DiIndex.java b/src/com/magento/idea/magento2plugin/indexes/DiIndex.java index 97b438e30..94cd57aad 100644 --- a/src/com/magento/idea/magento2plugin/indexes/DiIndex.java +++ b/src/com/magento/idea/magento2plugin/indexes/DiIndex.java @@ -1,3 +1,7 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ package com.magento.idea.magento2plugin.indexes; import com.intellij.codeInsight.completion.PrefixMatcher; diff --git a/src/com/magento/idea/magento2plugin/indexes/EventIndex.java b/src/com/magento/idea/magento2plugin/indexes/EventIndex.java new file mode 100644 index 000000000..2e7bc0743 --- /dev/null +++ b/src/com/magento/idea/magento2plugin/indexes/EventIndex.java @@ -0,0 +1,53 @@ +/** + * Copyright © Dmytro Kvashnin. 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.search.GlobalSearchScope; +import com.intellij.psi.xml.XmlAttributeValue; +import com.intellij.psi.xml.XmlFile; +import com.intellij.util.indexing.FileBasedIndex; +import com.magento.idea.magento2plugin.stubs.indexes.EventNameIndex; +import com.magento.idea.magento2plugin.xml.XmlPsiTreeUtil; + +import java.util.ArrayList; +import java.util.Collection; + +public class EventIndex { + + private static EventIndex INSTANCE; + + private Project project; + + private EventIndex() { + } + + public static EventIndex getInstance(final Project project) { + if (null == INSTANCE) { + INSTANCE = new EventIndex(); + } + INSTANCE.project = project; + + return INSTANCE; + } + + public Collection getEventElements(final String name, final GlobalSearchScope scope) { + Collection result = new ArrayList<>(); + + Collection virtualFiles = + FileBasedIndex.getInstance().getContainingFiles(EventNameIndex.KEY, name, scope); + + for (VirtualFile virtualFile : virtualFiles) { + XmlFile xmlFile = (XmlFile) PsiManager.getInstance(project).findFile(virtualFile); + Collection valueElements = XmlPsiTreeUtil + .findAttributeValueElements(xmlFile, "event", "name", name); + result.addAll(valueElements); + } + return result; + } +} diff --git a/src/com/magento/idea/magento2plugin/indexes/IndexManager.java b/src/com/magento/idea/magento2plugin/indexes/IndexManager.java new file mode 100644 index 000000000..e20c4a682 --- /dev/null +++ b/src/com/magento/idea/magento2plugin/indexes/IndexManager.java @@ -0,0 +1,40 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +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.xml.PhpClassNameIndex; + +/** + * Created by dkvashnin on 1/9/16. + */ +public class IndexManager { + public static void manualReindex() { + ID[] indexIds = new ID[] { + // php + ModulePackageIndex.KEY, + // xml|di configuration + PluginIndex.KEY, + VirtualTypeIndex.KEY, + // layouts + BlockNameIndex.KEY, + ContainerNameIndex.KEY, + // events + EventNameIndex.KEY, + EventObserverIndex.KEY, + // webapi + WebApiTypeIndex.KEY, + ModuleNameIndex.KEY, + PhpClassNameIndex.KEY + }; + + for (ID id: indexIds) { + FileBasedIndexImpl.getInstance().requestRebuild(id); + FileBasedIndexImpl.getInstance().scheduleRebuild(id, new Throwable()); + } + } +} diff --git a/src/com/magento/idea/magento2plugin/indexes/LayoutIndex.java b/src/com/magento/idea/magento2plugin/indexes/LayoutIndex.java new file mode 100644 index 000000000..2d987aee7 --- /dev/null +++ b/src/com/magento/idea/magento2plugin/indexes/LayoutIndex.java @@ -0,0 +1,124 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.indexes; + +import com.intellij.ide.highlighter.XmlFileType; +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.FilenameIndex; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.xml.XmlFile; +import com.intellij.psi.xml.XmlTag; +import com.intellij.util.indexing.FileBasedIndex; +import com.intellij.util.indexing.ID; +import com.magento.idea.magento2plugin.stubs.indexes.BlockNameIndex; +import com.magento.idea.magento2plugin.stubs.indexes.ContainerNameIndex; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * Created by dkvashnin on 11/20/15. + */ +public class LayoutIndex { + private static List getComponentDeclarations(String componentValue, String componentType, ID id, Project project, ComponentMatcher componentMatcher) { + List results = new ArrayList(); + Collection containingFiles = FileBasedIndex.getInstance() + .getContainingFiles( + id, + componentValue, + GlobalSearchScope.allScope(project) + ); + PsiManager psiManager = PsiManager.getInstance(project); + + for (VirtualFile virtualFile: containingFiles) { + XmlFile xmlFile = (XmlFile)psiManager.findFile(virtualFile); + if (xmlFile == null) { + continue; + } + + XmlTag rootTag = xmlFile.getRootTag(); + if (rootTag == null) { + continue; + } + collectComponentDeclarations(rootTag, results, componentValue, componentType, componentMatcher); + } + + return results; + } + + public static boolean isLayoutFile(VirtualFile virtualFile) { + VirtualFile parent = virtualFile.getParent(); + return virtualFile.getFileType() == XmlFileType.INSTANCE && parent.isDirectory() + && parent.getName().endsWith("layout"); + } + + public static boolean isLayoutFile(PsiFile psiFile) { + VirtualFile virtualFile = psiFile.getOriginalFile().getVirtualFile(); + return isLayoutFile(virtualFile); + } + + public static List getLayoutFiles(Project project, @Nullable String fileName) { + List results = new ArrayList(); + Collection xmlFiles = FilenameIndex.getAllFilesByExt(project, "xml"); + + PsiManager psiManager = PsiManager.getInstance(project); + for (VirtualFile xmlFile: xmlFiles) { + if (isLayoutFile(xmlFile)) { + if (fileName != null && !xmlFile.getNameWithoutExtension().equals(fileName)) { + continue; + } + + PsiFile file = psiManager.findFile(xmlFile); + if (file != null) { + results.add((XmlFile)file); + } + } + } + + return results; + } + + public static List getLayoutFiles(Project project) { + return getLayoutFiles(project, null); + } + + public static Collection getAllKeys(ID id, Project project) { + return FileBasedIndex.getInstance().getAllKeys(id, project); + } + + private static void collectComponentDeclarations(XmlTag parentTag, List results, String componentName, String componentType, ComponentMatcher componentMatcher) { + for (XmlTag childTag: parentTag.getSubTags()) { + if (componentType.equals(childTag.getName()) && componentMatcher.matches(componentName, childTag)) { + results.add(childTag); + } else if(childTag.getSubTags().length > 0 ) { + collectComponentDeclarations(childTag, results, componentName, componentType, componentMatcher); + } + } + } + + public static List getBlockDeclarations(String componentName, Project project) { + return getComponentDeclarations(componentName, "block", BlockNameIndex.KEY, project, new NameComponentMatcher()); + } + + public static List getContainerDeclarations(String componentName, Project project) { + return getComponentDeclarations(componentName, "container", ContainerNameIndex.KEY, project, new NameComponentMatcher()); + } + + private interface ComponentMatcher { + boolean matches(String value, XmlTag tag); + } + + private static class NameComponentMatcher implements ComponentMatcher { + @Override + public boolean matches(String value, XmlTag tag) { + return value.equals(tag.getAttributeValue("name")); + } + } +} diff --git a/src/com/magento/idea/magento2plugin/indexes/XmlIndex.java b/src/com/magento/idea/magento2plugin/indexes/XmlIndex.java new file mode 100644 index 000000000..22a0e37c7 --- /dev/null +++ b/src/com/magento/idea/magento2plugin/indexes/XmlIndex.java @@ -0,0 +1,92 @@ +/** + * Copyright © Dmytro Kvashnin. 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.PsiManager; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.xml.*; +import com.intellij.util.indexing.FileBasedIndex; +import com.jetbrains.php.lang.psi.elements.PhpClass; +import com.magento.idea.magento2plugin.stubs.indexes.xml.PhpClassNameIndex; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class XmlIndex { + + private static XmlIndex INSTANCE; + + private Project project; + + private XmlIndex() { + } + + public static XmlIndex getInstance(final Project project) { + if (null == INSTANCE) { + INSTANCE = new XmlIndex(); + } + INSTANCE.project = project; + return INSTANCE; + } + + public static List getPhpClassDeclarations(PhpClass phpClass) { + + List result = new ArrayList<>(); + + String fqn = phpClass.getPresentableFQN(); + + PsiManager psiManager = PsiManager.getInstance(phpClass.getProject()); + + Collection vfs = FileBasedIndex.getInstance() + .getContainingFiles(PhpClassNameIndex.KEY, fqn, GlobalSearchScope.allScope(phpClass.getProject())); + + for (VirtualFile vf : vfs) { + XmlFile xmlFile = (XmlFile)psiManager.findFile(vf); + if (xmlFile == null) { + continue; + } + + XmlTag xmlTags[] = PsiTreeUtil.getChildrenOfType(xmlFile.getFirstChild(), XmlTag.class); + if (xmlTags == null) { + continue; + } + + for (XmlTag xmlTag: xmlTags) { + fillList(xmlTag, fqn, result); + } + } + + return result; + + } + + private static void fillList(XmlTag parentTag, String fqn, List list) { + for (XmlTag childTag: parentTag.getSubTags()) { + for (XmlAttribute xmlAttribute: childTag.getAttributes()) { + String xmlAttributeValue = xmlAttribute.getValue(); + if (xmlAttributeValue != null) { + xmlAttributeValue = xmlAttributeValue.startsWith("\\") + ? xmlAttributeValue.substring(1) : xmlAttributeValue; + if (xmlAttributeValue.startsWith(fqn)) { + list.add(childTag); + } + } + } + XmlTagValue childTagValue = childTag.getValue(); + String tagValue = childTagValue.getTrimmedText(); + tagValue = tagValue.startsWith("\\") ? tagValue.substring(1) : tagValue; + if (!tagValue.isEmpty() && tagValue.startsWith(fqn)) { + list.add(childTag); + } + + + fillList(childTag, fqn, list); + } + } +} diff --git a/src/com/magento/idea/magento2plugin/php/index/ModulePackageFileBasedIndex.java b/src/com/magento/idea/magento2plugin/php/index/ModulePackageFileBasedIndex.java deleted file mode 100644 index b06e7b972..000000000 --- a/src/com/magento/idea/magento2plugin/php/index/ModulePackageFileBasedIndex.java +++ /dev/null @@ -1,96 +0,0 @@ -package com.magento.idea.magento2plugin.php.index; - -import com.intellij.json.JsonFileType; -import com.intellij.json.psi.*; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.util.indexing.*; -import com.intellij.util.io.EnumeratorStringDescriptor; -import com.intellij.util.io.KeyDescriptor; -import com.magento.idea.magento2plugin.Settings; -import com.magento.idea.magento2plugin.php.module.ComposerPackageModel; -import com.magento.idea.magento2plugin.php.module.ComposerPackageModelImpl; -import org.jetbrains.annotations.NotNull; - -import java.util.HashMap; -import java.util.Map; - -/** - * Created by dkvashnin on 12/3/15. - */ -public class ModulePackageFileBasedIndex extends ScalarIndexExtension { - public static final ID NAME = ID.create("com.magento.idea.magento2plugin.php.index.module"); - - @NotNull - @Override - public ID getName() { - return NAME; - } - - @NotNull - @Override - public DataIndexer getIndexer() { - return new DataIndexer() { - @NotNull - @Override - public Map map(@NotNull FileContent fileContent) { - Map map = new HashMap<>(); - JsonFile jsonFile = (JsonFile)fileContent.getPsiFile(); - if (!Settings.isEnabled(jsonFile.getProject())) { - return map; - } - - JsonObject jsonObject = PsiTreeUtil.getChildOfType(jsonFile, JsonObject.class); - if (jsonObject == null) { - return map; - } - ComposerPackageModel composerObject = new ComposerPackageModelImpl(jsonObject); - - String type = composerObject.getType(); - if (type == null) { - return map; - } - - if (!type.startsWith("magento2-")) { - return map; - } - - String name = composerObject.getName(); - - if (name != null) { - map.put(name, null); - } - - - return map; - } - }; - } - - @NotNull - @Override - public KeyDescriptor getKeyDescriptor() { - return new EnumeratorStringDescriptor(); - } - - @NotNull - @Override - public FileBasedIndex.InputFilter getInputFilter() { - return new FileBasedIndex.InputFilter() { - @Override - public boolean acceptInput(@NotNull VirtualFile virtualFile) { - return virtualFile.getFileType().equals(JsonFileType.INSTANCE) && virtualFile.getName().equals("composer.json"); - } - }; - } - - @Override - public boolean dependsOnFileContent() { - return true; - } - - @Override - public int getVersion() { - return 1; - } -} diff --git a/src/com/magento/idea/magento2plugin/php/inspections/MagentoApiInspection.java b/src/com/magento/idea/magento2plugin/php/inspections/MagentoApiInspection.java deleted file mode 100644 index 216f09672..000000000 --- a/src/com/magento/idea/magento2plugin/php/inspections/MagentoApiInspection.java +++ /dev/null @@ -1,108 +0,0 @@ -package com.magento.idea.magento2plugin.php.inspections; - -import com.intellij.codeInspection.ProblemHighlightType; -import com.intellij.codeInspection.ProblemsHolder; -import com.intellij.openapi.project.DumbService; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiElementVisitor; -import com.jetbrains.php.lang.documentation.phpdoc.psi.PhpDocComment; -import com.jetbrains.php.lang.documentation.phpdoc.psi.tags.PhpDocTag; -import com.jetbrains.php.lang.inspections.PhpInspection; -import com.jetbrains.php.lang.psi.elements.*; -import com.jetbrains.php.lang.psi.visitors.PhpElementVisitor; -import com.magento.idea.magento2plugin.Settings; -import com.magento.idea.magento2plugin.php.module.MagentoModule; -import com.magento.idea.magento2plugin.php.module.MagentoComponentManager; -import org.jetbrains.annotations.NotNull; - -/** - * Created by dkvashnin on 12/4/15. - */ -public class MagentoApiInspection extends PhpInspection { - public static final String API_TAG = "@api"; - - @NotNull - @Override - public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder problemsHolder, boolean isOnTheFly) { - - return new ApiInspectionVisitor(problemsHolder); - } - - private class ApiInspectionVisitor extends PhpElementVisitor { - - private ProblemsHolder problemsHolder; - - public ApiInspectionVisitor(@NotNull ProblemsHolder problemsHolder) { - super(); - - this.problemsHolder = problemsHolder; - } - - @Override - public void visitPhpMethodReference(MethodReference reference) { - if (!Settings.isEnabled(reference.getProject())) { - return; - } - - PsiElement referencedElement = reference.resolve(); - - if(referencedElement instanceof Method) { - PhpClass phpClass = ((Method) referencedElement).getContainingClass(); - - if (phpClass == null) { - return; - } - - if (!MagentoApiInspection.isValidReference(phpClass, reference.getElement()) - && !MagentoApiInspection.isValidReference((Method) referencedElement, reference.getElement())) { - problemsHolder.registerProblem(reference, "Method #ref is not in module API", ProblemHighlightType.GENERIC_ERROR_OR_WARNING); - } - } - } - - @Override - public void visitPhpClassReference(ClassReference reference) { - if (!Settings.isEnabled(reference.getProject())) { - return; - } - PsiElement referencedElement = reference.resolve(); - - if(referencedElement instanceof PhpClass) { - if (!MagentoApiInspection.isValidReference((PhpClass) referencedElement, reference.getElement())) { - problemsHolder.registerProblem(reference, "Class #ref is not in module API", ProblemHighlightType.GENERIC_ERROR_OR_WARNING); - } - } - } - } - - private static boolean isValidReference(PhpNamedElement referencedElement, PsiElement contextElement) { - MagentoModule referenceSourceModule = getMagentoModule(referencedElement); - MagentoModule currentModule = getMagentoModule(contextElement); - - - if (!areDifferentModules(referenceSourceModule, currentModule)) { - return true; - } - - PhpDocComment docComment = referencedElement.getDocComment(); - if(docComment == null) { - return false; - } - - PhpDocTag[] elements = docComment.getTagElementsByName(API_TAG); - return elements.length > 0; - } - - private static MagentoModule getMagentoModule(PsiElement element) { - MagentoComponentManager magentoComponentManager = MagentoComponentManager.getInstance(element.getProject()); - return magentoComponentManager.getComponentOfTypeForFile(element.getContainingFile(), MagentoModule.class); - } - - private static boolean areDifferentModules(MagentoModule magentoModule, MagentoModule currentPackage) { - if (magentoModule == null) { - return false; - } - - return magentoModule != currentPackage; - } -} diff --git a/src/com/magento/idea/magento2plugin/php/inspections/ObjectManagerInspection.java b/src/com/magento/idea/magento2plugin/php/inspections/ObjectManagerInspection.java deleted file mode 100644 index d7b3fa84b..000000000 --- a/src/com/magento/idea/magento2plugin/php/inspections/ObjectManagerInspection.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.magento.idea.magento2plugin.php.inspections; - -import com.intellij.codeInspection.ProblemHighlightType; -import com.intellij.codeInspection.ProblemsHolder; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiElementVisitor; -import com.intellij.psi.PsiReference; -import com.jetbrains.php.lang.inspections.PhpInspection; -import com.jetbrains.php.lang.psi.elements.ClassReference; -import com.jetbrains.php.lang.psi.elements.Method; -import com.jetbrains.php.lang.psi.elements.MethodReference; -import com.jetbrains.php.lang.psi.elements.PhpClass; -import com.jetbrains.php.lang.psi.visitors.PhpElementVisitor; -import com.magento.idea.magento2plugin.Settings; -import com.magento.idea.magento2plugin.php.module.MagentoComponentManager; -import com.magento.idea.magento2plugin.php.module.MagentoModule; -import com.magento.idea.magento2plugin.php.util.MagentoTypes; -import org.jetbrains.annotations.NotNull; - -/** - * Created by dkvashnin on 12/18/15. - */ -public class ObjectManagerInspection extends PhpInspection { - @NotNull - @Override - public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder problemsHolder, boolean b) { - return new OMInspectionVisitor(problemsHolder); - } - - private class OMInspectionVisitor extends PhpElementVisitor { - - private ProblemsHolder problemsHolder; - - public OMInspectionVisitor(@NotNull ProblemsHolder problemsHolder) { - super(); - this.problemsHolder = problemsHolder; - } - - @Override - public void visitPhpMethodReference(MethodReference reference) { - if (!Settings.isEnabled(reference.getProject())) { - return; - } - PsiElement referencedElement = reference.resolve(); - - if(referencedElement instanceof Method) { - MagentoComponentManager magentoComponentManager = MagentoComponentManager.getInstance(referencedElement.getProject()); - if (magentoComponentManager.getComponentOfTypeForFile(reference.getContainingFile(), MagentoModule.class) == null) { - return; - } - - PhpClass phpClass = ((Method) referencedElement).getContainingClass(); - - verifyPhpClass(phpClass, reference); - } - } - - @Override - public void visitPhpClassReference(ClassReference reference) { - if (!Settings.isEnabled(reference.getProject())) { - return; - } - PsiElement referencedElement = reference.resolve(); - - if(referencedElement instanceof PhpClass) { - MagentoComponentManager magentoComponentManager = MagentoComponentManager.getInstance(referencedElement.getProject()); - if (magentoComponentManager.getComponentOfTypeForFile(reference.getContainingFile(), MagentoModule.class) == null) { - return; - } - - verifyPhpClass((PhpClass)referencedElement, reference); - } - } - - private void verifyPhpClass(PhpClass phpClass, PsiReference reference) { - if (phpClass == null) { - return; - } - - if (phpClass.getPresentableFQN().equals(MagentoTypes.OBJECT_MANAGER_TYPE)) { - registerProblem(reference); - return; - } - - for (PhpClass implementedInterface : phpClass.getImplementedInterfaces()) { - if (implementedInterface.getPresentableFQN().equals(MagentoTypes.OBJECT_MANAGER_TYPE)) { - registerProblem(reference); - return; - } - } - } - - private void registerProblem(PsiReference reference) { - problemsHolder.registerProblem(reference, "ObjectManager is not recommended to use in module", ProblemHighlightType.GENERIC_ERROR_OR_WARNING); - } - } -} diff --git a/src/com/magento/idea/magento2plugin/php/linemarker/ClassConfigurationLineMarkerProvider.java b/src/com/magento/idea/magento2plugin/php/linemarker/ClassConfigurationLineMarkerProvider.java index 968b5d590..9ba39d2ff 100644 --- a/src/com/magento/idea/magento2plugin/php/linemarker/ClassConfigurationLineMarkerProvider.java +++ b/src/com/magento/idea/magento2plugin/php/linemarker/ClassConfigurationLineMarkerProvider.java @@ -1,29 +1,30 @@ +/** + * Copyright © Dmytro Kvashnin. 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.icons.AllIcons; import com.intellij.psi.PsiElement; import com.intellij.psi.xml.XmlTag; import com.jetbrains.php.lang.psi.elements.PhpClass; -import com.magento.idea.magento2plugin.Magento2Icons; -import com.magento.idea.magento2plugin.Settings; -import com.magento.idea.magento2plugin.xml.di.index.TypeConfigurationFileBasedIndex; -import com.magento.idea.magento2plugin.xml.layout.index.util.LayoutIndexUtility; +import com.magento.idea.magento2plugin.indexes.XmlIndex; +import com.magento.idea.magento2plugin.project.Settings; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.List; /** * Created by dkvashnin on 11/15/15. */ public class ClassConfigurationLineMarkerProvider implements LineMarkerProvider { - public static List> COLLECTORS = new ArrayList>() {{ - add(new DiConfigurationCollector()); - add(new LayoutConfigurationCollector()); - }}; - @Nullable @Override public LineMarkerInfo getLineMarkerInfo(@NotNull PsiElement psiElement) { @@ -40,48 +41,25 @@ public void collectSlowLineMarkers(@NotNull List list, @NotNull Coll for (PsiElement psiElement: list) { if (psiElement instanceof PhpClass) { List results = new ArrayList(); - for (Collector collector: COLLECTORS) { - results.addAll(collector.collect((PhpClass) psiElement)); - } - if (results.size() == 0) { + results.addAll(XmlIndex.getPhpClassDeclarations((PhpClass) psiElement)); + + if (!(results.size() > 0)) { continue; } - Collections.sort( - results, - new Comparator() { - @Override - public int compare(XmlTag firstTag, XmlTag secondTag) { - return firstTag.getName().compareTo(secondTag.getName()); - } - } - ); - String tooltipText = "Navigate to configuration:"; - for (XmlTag resultItem: results) { - tooltipText += "\n " + resultItem.getName(); - } - NavigationGutterIconBuilder builder = NavigationGutterIconBuilder. - create(Magento2Icons.CONFIGURATION). - setTargets(results). - setTooltipText(tooltipText); + results.sort(Comparator.comparing(XmlTag::getName)); - collection.add(builder.createLineMarkerInfo(psiElement)); + String tooltipText = "Navigate to configuration"; + NavigationGutterIconBuilder builder = NavigationGutterIconBuilder + .create(AllIcons.FileTypes.Xml) + .setTargets(results) + .setTooltipText(tooltipText); + + PsiElement className = ((PhpClass) psiElement).getNameIdentifier(); + if (className != null) { + collection.add(builder.createLineMarkerInfo(className)); + } } } } } - -class DiConfigurationCollector implements Collector { - @Override - public List collect(@NotNull PhpClass psiElement) { - return TypeConfigurationFileBasedIndex - .getClassConfigurations(psiElement); - } -} - -class LayoutConfigurationCollector implements Collector { - @Override - public List collect(@NotNull PhpClass psiElement) { - return LayoutIndexUtility.getBlockClassDeclarations(psiElement, psiElement.getProject()); - } -} \ No newline at end of file diff --git a/src/com/magento/idea/magento2plugin/php/linemarker/Collector.java b/src/com/magento/idea/magento2plugin/php/linemarker/Collector.java deleted file mode 100644 index e78d400cb..000000000 --- a/src/com/magento/idea/magento2plugin/php/linemarker/Collector.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.magento.idea.magento2plugin.php.linemarker; - -import com.intellij.psi.PsiElement; -import org.jetbrains.annotations.NotNull; - -import java.util.List; - -/** - * Created by dkvashnin on 11/20/15. - */ -interface Collector { - List collect(@NotNull T psiElement); -} diff --git a/src/com/magento/idea/magento2plugin/php/linemarker/PluginLineMarkerProvider.java b/src/com/magento/idea/magento2plugin/php/linemarker/PluginLineMarkerProvider.java new file mode 100644 index 000000000..637879bfe --- /dev/null +++ b/src/com/magento/idea/magento2plugin/php/linemarker/PluginLineMarkerProvider.java @@ -0,0 +1,178 @@ +/** + * Copyright © Dmytro Kvashnin. 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.icons.AllIcons; +import com.intellij.psi.PsiElement; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.util.indexing.FileBasedIndex; +import com.jetbrains.php.PhpIndex; +import com.jetbrains.php.lang.psi.elements.Method; +import com.jetbrains.php.lang.psi.elements.PhpClass; +import com.magento.idea.magento2plugin.project.Settings; +import com.magento.idea.magento2plugin.stubs.indexes.PluginIndex; +import org.apache.commons.lang.WordUtils; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.*; + +/** + * Created by dkvashnin on 11/12/15. + */ +public class PluginLineMarkerProvider 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; + } + } + PluginClassCache pluginClassCache = new PluginClassCache(); + ClassPluginCollector classPluginCollector = new ClassPluginCollector(pluginClassCache); + MethodPluginCollector methodPluginCollector = new MethodPluginCollector(pluginClassCache); + + for (PsiElement psiElement : psiElements) { + if (psiElement instanceof PhpClass || psiElement instanceof Method) { + List results; + + if (psiElement instanceof PhpClass) { + results = classPluginCollector.collect((PhpClass) psiElement); + } else { + results = methodPluginCollector.collect((Method) psiElement); + } + + if (results.size() > 0 ) { + collection.add(NavigationGutterIconBuilder + .create(AllIcons.Nodes.Plugin) + .setTargets(results) + .setTooltipText("Navigate to plugins") + .createLineMarkerInfo(psiElement) + ); + } + } + } + } + + private static class PluginClassCache { + private HashMap> classPluginsMap = new HashMap>(); + + List getPluginsForClass(@NotNull PhpClass phpClass, @NotNull String classFQN) { + List results = new ArrayList<>(); + + if (classPluginsMap.containsKey(classFQN)) { + return classPluginsMap.get(classFQN); + } + + List> plugins = FileBasedIndex.getInstance() + .getValues(PluginIndex.KEY, classFQN, GlobalSearchScope.allScope(phpClass.getProject())); + + if (plugins.size() == 0) { + classPluginsMap.put(classFQN, results); + return results; + } + + PhpIndex phpIndex = PhpIndex.getInstance(phpClass.getProject()); + + for (Set pluginClassNames: plugins) { + for (String pluginClassName: pluginClassNames) { + results.addAll(phpIndex.getClassesByFQN(pluginClassName)); + } + } + classPluginsMap.put(classFQN, results); + return results; + } + + List getPluginsForClass(@NotNull PhpClass phpClass) + { + List pluginsForClass = getPluginsForClass(phpClass, phpClass.getPresentableFQN()); + for (PhpClass parent: phpClass.getSupers()) { + pluginsForClass.addAll(getPluginsForClass(parent)); + } + + return pluginsForClass; + } + + List getPluginMethods(@NotNull PhpClass plugin) { + List methodList = new ArrayList(); + for (Method method : plugin.getMethods()) { + if (method.getAccess().isPublic()) { + String pluginMethodName = method.getName(); + if (pluginMethodName.length() > 6) { + methodList.add(method); + } + } + } + return methodList; + } + + List getPluginMethods(List plugins) { + List methodList = new ArrayList(); + for (PhpClass plugin: plugins) { + methodList.addAll(getPluginMethods(plugin)); + } + return methodList; + } + } + + private static class ClassPluginCollector implements Collector { + private PluginLineMarkerProvider.PluginClassCache pluginClassCache; + + ClassPluginCollector(PluginLineMarkerProvider.PluginClassCache pluginClassCache) { + this.pluginClassCache = pluginClassCache; + } + + @Override + public List collect(@NotNull PhpClass psiElement) { + return pluginClassCache.getPluginsForClass(psiElement); + } + } + + private static class MethodPluginCollector implements Collector { + private PluginLineMarkerProvider.PluginClassCache pluginClassCache; + + MethodPluginCollector(PluginLineMarkerProvider.PluginClassCache pluginClassCache) { + this.pluginClassCache = pluginClassCache; + } + + @Override + public List collect(@NotNull Method psiElement) { + List results = new ArrayList<>(); + + PhpClass methodClass = psiElement.getContainingClass(); + if (methodClass == null) { + return results; + } + + List pluginsList = pluginClassCache.getPluginsForClass(methodClass); + List pluginMethods = pluginClassCache.getPluginMethods(pluginsList); + + String classMethodName = WordUtils.capitalize(psiElement.getName()); + for (Method pluginMethod: pluginMethods) { + if (isPluginMethodName(pluginMethod.getName(), classMethodName)) { + results.add(pluginMethod); + } + } + return results; + } + + private boolean isPluginMethodName(String pluginMethodName, String classMethodName) { + return pluginMethodName.substring(5).equals(classMethodName) || pluginMethodName.substring(6).equals(classMethodName); + } + } + + private interface Collector { + List collect(@NotNull T psiElement); + } +} diff --git a/src/com/magento/idea/magento2plugin/php/linemarker/WebApiLineMarkerProvider.java b/src/com/magento/idea/magento2plugin/php/linemarker/WebApiLineMarkerProvider.java index ce367d0be..bacbeb384 100644 --- a/src/com/magento/idea/magento2plugin/php/linemarker/WebApiLineMarkerProvider.java +++ b/src/com/magento/idea/magento2plugin/php/linemarker/WebApiLineMarkerProvider.java @@ -1,3 +1,7 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ package com.magento.idea.magento2plugin.php.linemarker; import com.intellij.codeInsight.daemon.LineMarkerInfo; @@ -7,9 +11,9 @@ import com.intellij.psi.xml.XmlTag; import com.jetbrains.php.lang.psi.elements.Method; import com.jetbrains.php.lang.psi.elements.PhpClass; -import com.magento.idea.magento2plugin.Magento2Icons; -import com.magento.idea.magento2plugin.Settings; -import com.magento.idea.magento2plugin.xml.webapi.index.WebApiTypesFileBasedIndex; +import com.magento.idea.magento2plugin.MagentoIcons; +import com.magento.idea.magento2plugin.project.Settings; +import com.magento.idea.magento2plugin.stubs.indexes.WebApiTypeIndex; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -30,13 +34,13 @@ public LineMarkerInfo getLineMarkerInfo(@NotNull PsiElement psiElement) { } @Override - public void collectSlowLineMarkers(@NotNull List list, @NotNull Collection collection) { - if (list.size() > 0) { - if (!Settings.isEnabled(list.get(0).getProject())) { + public void collectSlowLineMarkers(@NotNull List psiElements, @NotNull Collection collection) { + if (psiElements.size() > 0) { + if (!Settings.isEnabled(psiElements.get(0).getProject())) { return; } } - for (PsiElement psiElement : list) { + for (PsiElement psiElement: psiElements) { WebApiRoutesCollector collector = new WebApiRoutesCollector(); List results = new ArrayList<>(); if (psiElement instanceof Method) { @@ -45,105 +49,102 @@ public void collectSlowLineMarkers(@NotNull List list, @NotNull Coll results = collector.getRoutes((PhpClass) psiElement); } - if (results.size() == 0) { + if (!(results.size() > 0)) { continue; } - String tooltipText = "Navigate to Web API configuration:
";
+
+            StringBuilder tooltipText = new StringBuilder("Navigate to Web API configuration:
");
             for (XmlTag routeTag : results) {
-                tooltipText += routeTag.getName() + "\n";
+                tooltipText.append(routeTag.getName()).append("\n");
             }
-            tooltipText += "
"; - NavigationGutterIconBuilder builder = NavigationGutterIconBuilder. - create(Magento2Icons.WEB_API). - setTargets(results). - setTooltipText(tooltipText); + tooltipText.append("
"); + NavigationGutterIconBuilder builder = NavigationGutterIconBuilder + .create(MagentoIcons.WEB_API) + .setTargets(results) + .setTooltipText(tooltipText.toString()); collection.add(builder.createLineMarkerInfo(psiElement)); } } -} -/** - * Web API config nodes collector for service methods and classes. Has built in caching. - */ -class WebApiRoutesCollector { + /** + * Web API config nodes collector for service methods and classes. Has built in caching. + */ + private static class WebApiRoutesCollector { - private HashMap> routesCache = new HashMap<>(); + private HashMap> routesCache = new HashMap<>(); - private static final Map HTTP_METHODS_SORT_ORDER = new HashMap() {{ - put("GET", 1); - put("PUT", 2); - put("POS", 3); - put("DEL", 4); - }}; + private static final Map HTTP_METHODS_SORT_ORDER = new HashMap() {{ + put("GET", 1); + put("PUT", 2); + put("POS", 3); + put("DEL", 4); + }}; - /** - * Get sorted list of Web API routes related to the specified class. - */ - public List getRoutes(@NotNull PhpClass phpClass) { - List routesForClass = new ArrayList<>(); - for (Method method : phpClass.getMethods()) { - routesForClass.addAll(getRoutes(method)); + /** + * Get sorted list of Web API routes related to the specified class. + */ + List getRoutes(@NotNull PhpClass phpClass) { + List routesForClass = new ArrayList<>(); + for (Method method : phpClass.getMethods()) { + routesForClass.addAll(getRoutes(method)); + } + sortRoutes(routesForClass); + return routesForClass; } - sortRoutes(routesForClass); - return routesForClass; - } - /** - * Get list of Web API routes related to the specified method. - *

- * Results are cached. - */ - public List getRoutes(@NotNull Method method) { - String methodFqn = method.getFQN(); - if (!routesCache.containsKey(methodFqn)) { - List routesForMethod = extractRoutesForMethod(method); - sortRoutes(routesForMethod); - routesCache.put(methodFqn, routesForMethod); + /** + * Get list of Web API routes related to the specified method. + *

+ * Results are cached. + */ + List getRoutes(@NotNull Method method) { + String methodFqn = method.getFQN(); + if (!routesCache.containsKey(methodFqn)) { + List routesForMethod = extractRoutesForMethod(method); + sortRoutes(routesForMethod); + routesCache.put(methodFqn, routesForMethod); + } + return routesCache.get(methodFqn); } - return routesCache.get(methodFqn); - } - /** - * Get list of Web API routes related to the specified method. - *

- * Web API declarations for parent classes are taken into account. - * Results are not cached. - */ - public List extractRoutesForMethod(@NotNull Method method) { - List routesForMethod = WebApiTypesFileBasedIndex.getWebApiRoutes(method); - PhpClass phpClass = method.getContainingClass(); - if (phpClass == null) { - return routesForMethod; - } - for (PhpClass parent : method.getContainingClass().getSupers()) { - for (Method parentMethod : parent.getMethods()) { - if (parentMethod.getName().equals(method.getName())) { - routesForMethod.addAll(extractRoutesForMethod(parentMethod)); + /** + * Get list of Web API routes related to the specified method. + *

+ * Web API declarations for parent classes are taken into account. + * Results are not cached. + */ + List extractRoutesForMethod(@NotNull Method method) { + List routesForMethod = WebApiTypeIndex.getWebApiRoutes(method); + PhpClass phpClass = method.getContainingClass(); + if (phpClass == null) { + return routesForMethod; + } + for (PhpClass parent : method.getContainingClass().getSupers()) { + for (Method parentMethod : parent.getMethods()) { + if (parentMethod.getName().equals(method.getName())) { + routesForMethod.addAll(extractRoutesForMethod(parentMethod)); + } } } + return routesForMethod; } - return routesForMethod; - } - /** - * Make sure that routes are sorted as follows: GET, PUT, POST, DELETE. Then by path. - */ - private void sortRoutes(List routes) { - Collections.sort( - routes, - new Comparator() { - @Override - public int compare(XmlTag firstTag, XmlTag secondTag) { + /** + * Make sure that routes are sorted as follows: GET, PUT, POST, DELETE. Then by path. + */ + private void sortRoutes(List routes) { + routes.sort( + (firstTag, secondTag) -> { String substring = firstTag.getName().substring(2, 5); Integer firstSortOrder = HTTP_METHODS_SORT_ORDER.get(substring); Integer secondSortOrder = HTTP_METHODS_SORT_ORDER.get(secondTag.getName().substring(2, 5)); if (firstSortOrder.compareTo(secondSortOrder) == 0) { - /** Sort by route if HTTP methods are equal */ + // Sort by route if HTTP methods are equal return firstTag.getName().compareTo(secondTag.getName()); } return firstSortOrder.compareTo(secondSortOrder); } - } - ); + ); + } } } diff --git a/src/com/magento/idea/magento2plugin/php/module/ComposerPackageModel.java b/src/com/magento/idea/magento2plugin/php/module/ComposerPackageModel.java index 187d8bc94..768066aa8 100644 --- a/src/com/magento/idea/magento2plugin/php/module/ComposerPackageModel.java +++ b/src/com/magento/idea/magento2plugin/php/module/ComposerPackageModel.java @@ -1,3 +1,7 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ package com.magento.idea.magento2plugin.php.module; import org.jetbrains.annotations.Nullable; diff --git a/src/com/magento/idea/magento2plugin/php/module/ComposerPackageModelImpl.java b/src/com/magento/idea/magento2plugin/php/module/ComposerPackageModelImpl.java index ec10d8eb4..e2cf2a453 100644 --- a/src/com/magento/idea/magento2plugin/php/module/ComposerPackageModelImpl.java +++ b/src/com/magento/idea/magento2plugin/php/module/ComposerPackageModelImpl.java @@ -1,3 +1,7 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ package com.magento.idea.magento2plugin.php.module; import com.intellij.json.psi.*; diff --git a/src/com/magento/idea/magento2plugin/php/module/MagentoComponent.java b/src/com/magento/idea/magento2plugin/php/module/MagentoComponent.java index ea597b20f..ba6d9895f 100644 --- a/src/com/magento/idea/magento2plugin/php/module/MagentoComponent.java +++ b/src/com/magento/idea/magento2plugin/php/module/MagentoComponent.java @@ -1,9 +1,12 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ package com.magento.idea.magento2plugin.php.module; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; /** * Created by dkvashnin on 1/9/16. diff --git a/src/com/magento/idea/magento2plugin/php/module/MagentoComponentImp.java b/src/com/magento/idea/magento2plugin/php/module/MagentoComponentImp.java index 524bfa8ae..503b7cace 100644 --- a/src/com/magento/idea/magento2plugin/php/module/MagentoComponentImp.java +++ b/src/com/magento/idea/magento2plugin/php/module/MagentoComponentImp.java @@ -1,3 +1,7 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ package com.magento.idea.magento2plugin.php.module; import com.intellij.psi.PsiDirectory; diff --git a/src/com/magento/idea/magento2plugin/php/module/MagentoComponentManager.java b/src/com/magento/idea/magento2plugin/php/module/MagentoComponentManager.java index b8e0f0bb3..3007238cc 100644 --- a/src/com/magento/idea/magento2plugin/php/module/MagentoComponentManager.java +++ b/src/com/magento/idea/magento2plugin/php/module/MagentoComponentManager.java @@ -1,3 +1,7 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ package com.magento.idea.magento2plugin.php.module; import com.intellij.json.psi.JsonFile; @@ -13,11 +17,14 @@ import com.intellij.psi.xml.XmlFile; import com.intellij.psi.xml.XmlTag; import com.intellij.util.indexing.FileBasedIndex; -import com.magento.idea.magento2plugin.php.index.ModulePackageFileBasedIndex; +import com.magento.idea.magento2plugin.stubs.indexes.ModulePackageIndex; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; /** * Created by dkvashnin on 12/5/15. @@ -99,7 +106,7 @@ synchronized public void flushModules() { } private void loadModules() { - Collection packages = FileBasedIndex.getInstance().getAllKeys(ModulePackageFileBasedIndex.NAME, this.project); + Collection packages = FileBasedIndex.getInstance().getAllKeys(ModulePackageIndex.KEY, this.project); PsiManager psiManager = PsiManager.getInstance(this.project); for (String packageName: packages) { if (components.containsKey(packageName)) { @@ -107,7 +114,7 @@ private void loadModules() { } Collection containingFiles = FileBasedIndex.getInstance() - .getContainingFiles(ModulePackageFileBasedIndex.NAME, packageName, GlobalSearchScope.allScope(this.project)); + .getContainingFiles(ModulePackageIndex.KEY, packageName, GlobalSearchScope.allScope(this.project)); if (containingFiles.size() > 0) { VirtualFile configurationFile = containingFiles.iterator().next(); diff --git a/src/com/magento/idea/magento2plugin/php/module/MagentoModule.java b/src/com/magento/idea/magento2plugin/php/module/MagentoModule.java index 9dbb79885..110dce6d3 100644 --- a/src/com/magento/idea/magento2plugin/php/module/MagentoModule.java +++ b/src/com/magento/idea/magento2plugin/php/module/MagentoModule.java @@ -1,7 +1,9 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ package com.magento.idea.magento2plugin.php.module; -import org.jetbrains.annotations.Nullable; - /** * Created by dkvashnin on 12/5/15. */ diff --git a/src/com/magento/idea/magento2plugin/php/module/ModuleUtil.java b/src/com/magento/idea/magento2plugin/php/module/ModuleUtil.java deleted file mode 100644 index b1dddc9fa..000000000 --- a/src/com/magento/idea/magento2plugin/php/module/ModuleUtil.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.magento.idea.magento2plugin.php.module; - -/** - * Created by dkvashnin on 12/5/15. - */ -public class ModuleUtil { - -} diff --git a/src/com/magento/idea/magento2plugin/php/tool/ModuleTool.form b/src/com/magento/idea/magento2plugin/php/tool/ModuleTool.form deleted file mode 100644 index 4b6cc17a1..000000000 --- a/src/com/magento/idea/magento2plugin/php/tool/ModuleTool.form +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/com/magento/idea/magento2plugin/php/tool/ModuleToolWindowFactory.java b/src/com/magento/idea/magento2plugin/php/tool/ModuleToolWindowFactory.java deleted file mode 100644 index d5e5d2041..000000000 --- a/src/com/magento/idea/magento2plugin/php/tool/ModuleToolWindowFactory.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.magento.idea.magento2plugin.php.tool; - -import com.intellij.openapi.project.Project; -import com.intellij.openapi.wm.ToolWindow; -import com.intellij.openapi.wm.ToolWindowFactory; -import com.intellij.ui.content.Content; -import com.intellij.ui.content.ContentFactory; -import com.magento.idea.magento2plugin.php.module.ComposerPackageModel; -import com.magento.idea.magento2plugin.php.module.MagentoModule; -import com.magento.idea.magento2plugin.php.module.MagentoComponentManager; -import org.jetbrains.annotations.NotNull; - -import javax.swing.*; -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.DefaultTreeModel; -import java.util.HashMap; -import java.util.Map; - -/** - * Created by dkvashnin on 12/7/15. - */ -public class ModuleToolWindowFactory implements ToolWindowFactory { - private JPanel windowContent; - private JTree modulesTree; - private ToolWindow myToolWindow; - - private static final String UNDEFINED_VENDOR = "Undefined"; - - @Override - public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) { - myToolWindow = toolWindow; - initializeModulesTree(project); - ContentFactory contentFactory = ContentFactory.SERVICE.getInstance(); - Content content = contentFactory.createContent(windowContent, "", false); - toolWindow.getContentManager().addContent(content); - } - - private void initializeModulesTree(Project project) { - MagentoComponentManager magentoComponentManager = MagentoComponentManager.getInstance(project); - - Map vendorNodes = new HashMap<>(); - - DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("Project modules"); - - modulesTree.setModel(new DefaultTreeModel(rootNode)); - - for (MagentoModule magentoModule: magentoComponentManager.getAllComponentsOfType(MagentoModule.class)) { - ComposerPackageModel packageModel = magentoModule.getComposerModel(); - if (packageModel == null) { - continue; - } - - String vendorName = packageModel.getVendor(); - if (vendorName == null) { - vendorName = UNDEFINED_VENDOR; - } - - if (!vendorNodes.containsKey(vendorName)) { - vendorNodes.put(vendorName, new DefaultMutableTreeNode(vendorName)); - rootNode.add(vendorNodes.get(vendorName)); - } - - vendorNodes.get(vendorName).add(new DefaultMutableTreeNode(magentoModule.getMagentoName())); - } - } -} \ No newline at end of file diff --git a/src/com/magento/idea/magento2plugin/php/util/ImplementationMatcher.java b/src/com/magento/idea/magento2plugin/php/util/ImplementationMatcher.java deleted file mode 100644 index 41fd5c3fd..000000000 --- a/src/com/magento/idea/magento2plugin/php/util/ImplementationMatcher.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.magento.idea.magento2plugin.php.util; - -import com.intellij.psi.PsiElement; -import com.jetbrains.php.lang.psi.elements.PhpClass; -import com.magento.idea.magento2plugin.util.PsiContextMatcherI; - -/** -* Created by dkvashnin on 12/18/15. -*/ -public class ImplementationMatcher implements PsiContextMatcherI { - private String type; - - public ImplementationMatcher(String type) { - this.type = type; - } - - @Override - public boolean match(PsiElement psiElement) { - if (psiElement instanceof PhpClass) { - for (PhpClass parent : ((PhpClass)psiElement).getImplementedInterfaces()) { - if (parent.getPresentableFQN().equals(type)) { - return true; - } - } - - PhpClass parent = ((PhpClass) psiElement).getSuperClass(); - if (parent != null) { - return match(parent); - } - } - return false; - } -} diff --git a/src/com/magento/idea/magento2plugin/php/util/MagentoTypes.java b/src/com/magento/idea/magento2plugin/php/util/MagentoTypes.java deleted file mode 100644 index 2221bda0a..000000000 --- a/src/com/magento/idea/magento2plugin/php/util/MagentoTypes.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.magento.idea.magento2plugin.php.util; - -/** - * Created by dkvashnin on 12/18/15. - */ -public class MagentoTypes { - public static final String BLOCK_TYPE = "Magento\\Framework\\View\\Element\\BlockInterface"; - public static final String OBSERVER_TYPE = "Magento\\Framework\\Event\\ObserverInterface"; - public static final String OBJECT_MANAGER_TYPE = "Magento\\Framework\\ObjectManagerInterface"; - public static final String EVENT_MANAGER_TYPE = "Magento\\Framework\\Event\\ManagerInterface"; -} diff --git a/src/com/magento/idea/magento2plugin/php/util/PhpRegex.java b/src/com/magento/idea/magento2plugin/php/util/PhpRegex.java new file mode 100644 index 000000000..632c924a4 --- /dev/null +++ b/src/com/magento/idea/magento2plugin/php/util/PhpRegex.java @@ -0,0 +1,21 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.php.util; + +public class PhpRegex { + + public static final String CLASS_NAME + = "[A-Z][a-zA-Z0-9_\\x7f-\\xff]*"; + + public static final String FQN + = CLASS_NAME + "(\\\\" + CLASS_NAME + ")*"; + + public static class Xml { + + public static final String CLASS_MEMBER_NAME = "::\\$?([a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*)(\\(\\))?"; + + public static final String CLASS_ELEMENT = "\\\\?" + PhpRegex.FQN + "(" + CLASS_MEMBER_NAME + ")?.*"; + } +} diff --git a/src/com/magento/idea/magento2plugin/project/ProjectDetector.java b/src/com/magento/idea/magento2plugin/project/ProjectDetector.java new file mode 100644 index 000000000..182632c14 --- /dev/null +++ b/src/com/magento/idea/magento2plugin/project/ProjectDetector.java @@ -0,0 +1,54 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.project; + +import com.intellij.notification.Notification; +import com.intellij.notification.NotificationListener; +import com.intellij.notification.NotificationType; +import com.intellij.notification.Notifications; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.DumbService; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.startup.StartupManager; +import com.intellij.openapi.util.Ref; +import com.intellij.openapi.vfs.*; +import com.intellij.platform.DirectoryProjectConfigurator; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiFileSystemItem; +import com.intellij.psi.search.FilenameIndex; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.util.indexing.FileBasedIndex; +import com.magento.idea.magento2plugin.indexes.IndexManager; +import com.magento.idea.magento2plugin.php.module.MagentoComponentManager; +import org.jetbrains.annotations.NotNull; + +import javax.swing.event.HyperlinkEvent; + + +public class ProjectDetector implements DirectoryProjectConfigurator { + @Override + public void configureProject(Project project, @NotNull VirtualFile virtualFile, Ref ref) { + 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(); + } + } + ); + 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 new file mode 100644 index 000000000..138b699a1 --- /dev/null +++ b/src/com/magento/idea/magento2plugin/reference/js/JsReferenceContributor.java @@ -0,0 +1,30 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.reference.js; + +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.util.RegExUtil; +import org.jetbrains.annotations.NotNull; + +import static com.intellij.patterns.StandardPatterns.string; + +public class JsReferenceContributor extends PsiReferenceContributor { + @Override + public void registerReferenceProviders(@NotNull PsiReferenceRegistrar registrar) { + registrar.registerReferenceProvider( + JSPatterns.jsLiteralExpression() + .withText(string().matches(".*" + RegExUtil.Magento.MODULE_NAME + ".*")), + new ModuleNameReferenceProvider() + ); + + registrar.registerReferenceProvider( + JSPatterns.jsLiteralExpression().withText(string().matches(".*\\W" + RegExUtil.FILE_PATH + ".*")), + new FilePathReferenceProvider() + ); + } +} diff --git a/src/com/magento/idea/magento2plugin/reference/php/PhpReferenceContributor.java b/src/com/magento/idea/magento2plugin/reference/php/PhpReferenceContributor.java new file mode 100644 index 000000000..4099f34f3 --- /dev/null +++ b/src/com/magento/idea/magento2plugin/reference/php/PhpReferenceContributor.java @@ -0,0 +1,22 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.reference.php; + +import com.intellij.psi.PsiReferenceContributor; +import com.intellij.psi.PsiReferenceRegistrar; +import com.magento.idea.magento2plugin.php.util.PhpPatternsHelper; +import com.magento.idea.magento2plugin.reference.provider.EventDispatchReferenceProvider; +import org.jetbrains.annotations.NotNull; + +public class PhpReferenceContributor extends PsiReferenceContributor { + @Override + public void registerReferenceProviders(@NotNull PsiReferenceRegistrar registrar) { + // ->dispatch("event_name") + registrar.registerReferenceProvider( + PhpPatternsHelper.STRING_METHOD_ARGUMENT, + new EventDispatchReferenceProvider() + ); + } +} diff --git a/src/com/magento/idea/magento2plugin/reference/provider/CompositeReferenceProvider.java b/src/com/magento/idea/magento2plugin/reference/provider/CompositeReferenceProvider.java new file mode 100644 index 000000000..c2e5dd8ca --- /dev/null +++ b/src/com/magento/idea/magento2plugin/reference/provider/CompositeReferenceProvider.java @@ -0,0 +1,35 @@ +/** + * Copyright © Dmytro Kvashnin. 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 org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class CompositeReferenceProvider extends PsiReferenceProvider { + + private PsiReferenceProvider[] providers = null; + + public CompositeReferenceProvider(PsiReferenceProvider ...providers) { + this.providers = providers; + } + + @NotNull + @Override + public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) { + List result = new ArrayList<>(); + for (PsiReferenceProvider provider : providers) { + result.addAll(Arrays.asList(provider.getReferencesByElement(element, context))); + } + + return result.toArray(new PsiReference[result.size()]); + } +} diff --git a/src/com/magento/idea/magento2plugin/reference/provider/EventDispatchReferenceProvider.java b/src/com/magento/idea/magento2plugin/reference/provider/EventDispatchReferenceProvider.java new file mode 100644 index 000000000..86bc9a2d3 --- /dev/null +++ b/src/com/magento/idea/magento2plugin/reference/provider/EventDispatchReferenceProvider.java @@ -0,0 +1,40 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.reference.provider; + +import com.intellij.ide.highlighter.XmlFileType; +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.search.GlobalSearchScope; +import com.intellij.util.ProcessingContext; +import com.magento.idea.magento2plugin.indexes.EventIndex; +import com.magento.idea.magento2plugin.reference.xml.PolyVariantReferenceBase; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; + +public class EventDispatchReferenceProvider extends PsiReferenceProvider { + + @NotNull + @Override + public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) { + String value = StringUtil.unquoteString(element.getText()); + Collection targets = EventIndex.getInstance(element.getProject()) + .getEventElements( + value, + GlobalSearchScope.getScopeRestrictedByFileTypes( + GlobalSearchScope.allScope(element.getProject()), + XmlFileType.INSTANCE + ) + ); + + if (targets.size() > 0) { + return new PsiReference[] {new PolyVariantReferenceBase(element, targets)}; + } + return PsiReference.EMPTY_ARRAY; + } +} diff --git a/src/com/magento/idea/magento2plugin/reference/provider/EventNameReferenceProvider.java b/src/com/magento/idea/magento2plugin/reference/provider/EventNameReferenceProvider.java new file mode 100644 index 000000000..bfed6cdf6 --- /dev/null +++ b/src/com/magento/idea/magento2plugin/reference/provider/EventNameReferenceProvider.java @@ -0,0 +1,67 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.reference.provider; + +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.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.php.util.PhpPatternsHelper; +import com.magento.idea.magento2plugin.reference.xml.PolyVariantReferenceBase; +import com.magento.idea.magento2plugin.stubs.indexes.EventNameIndex; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class EventNameReferenceProvider extends PsiReferenceProvider { + + @NotNull + @Override + public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) { + String value = StringUtil.unquoteString(element.getText()); + Collection containingFiles = FileBasedIndex.getInstance() + .getContainingFiles(EventNameIndex.KEY, value, + GlobalSearchScope.getScopeRestrictedByFileTypes( + GlobalSearchScope.allScope(element.getProject()), + PhpFileType.INSTANCE + ) + ); + + PsiManager psiManager = PsiManager.getInstance(element.getProject()); + for (VirtualFile virtualFile: containingFiles) { + PhpFile phpFile = (PhpFile) psiManager.findFile(virtualFile); + if (phpFile != null) { + List psiElements = new ArrayList<>(); + recursiveFill(psiElements, phpFile, value); + if (psiElements.size() > 0) { + return new PsiReference[] {new PolyVariantReferenceBase(element, psiElements)}; + } + } + } + return PsiReference.EMPTY_ARRAY; + } + + private void recursiveFill(List psiElements, PsiElement psiElement, String typeName) { + if (PhpPatternsHelper.STRING_METHOD_ARGUMENT.accepts(psiElement)) { + if (StringUtil.unquoteString(psiElement.getText()).equals(typeName)) { + psiElements.add(psiElement); + } + return; + } + + for (PsiElement child: psiElement.getChildren()) { + recursiveFill(psiElements, child, typeName); + } + } +} diff --git a/src/com/magento/idea/magento2plugin/reference/provider/FilePathReferenceProvider.java b/src/com/magento/idea/magento2plugin/reference/provider/FilePathReferenceProvider.java new file mode 100644 index 000000000..c2a01a199 --- /dev/null +++ b/src/com/magento/idea/magento2plugin/reference/provider/FilePathReferenceProvider.java @@ -0,0 +1,239 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.reference.provider; + +import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.vfs.*; +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.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 { + + @NotNull + @Override + public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) { + + List psiReferences = new ArrayList<>(); + + String origValue = element.getText(); + + String filePath = getFilePath(element); + if (null == filePath) { + return PsiReference.EMPTY_ARRAY; + } + + // Find all files based on provided path + Collection files = getFiles(element); + if (!(files.size() > 0)) { + return PsiReference.EMPTY_ARRAY; + } + + PsiManager psiManager = PsiManager.getInstance(element.getProject()); + + String currentPath = ""; + String[] pathParts = filePath.split("/"); + for (int i = 0; i < pathParts.length; i++) { + String pathPart = pathParts[i]; + Boolean currentPathIsBuilt = false; + + Map> psiPathElements = new THashMap<>(); + + for (VirtualFile file : files) { + String fileUrl = file.getUrl(); + if (!fileUrl.contains(filePath)) { + continue; + } + String rootPathUrl = fileUrl.substring(0, fileUrl.indexOf(filePath)); + String[] relativePathParts = fileUrl.substring(fileUrl.indexOf(filePath)).split("/"); + + if (!currentPathIsBuilt) { + currentPath = currentPath.isEmpty() + ? currentPath.concat(relativePathParts[i]) + : currentPath.concat("/").concat(relativePathParts[i]); + currentPathIsBuilt = true; + } + + VirtualFile currentVf = VirtualFileManager.getInstance() + .findFileByUrl(rootPathUrl.concat(currentPath)); + + if (null != currentVf) { + PsiElement psiElement = currentVf.isDirectory() + ? psiManager.findDirectory(currentVf) + : psiManager.findFile(currentVf); + if (null != psiElement) { + + TextRange pathRange = new TextRange( + origValue.indexOf(filePath) + + (currentPath.lastIndexOf("/") == -1 ? 0 : currentPath.lastIndexOf("/") + 1), + origValue.indexOf(filePath) + + (currentPath.lastIndexOf("/") == -1 ? 0 : currentPath.lastIndexOf("/") + 1) + + pathPart.length() + ); + + if (!psiPathElements.containsKey(pathRange)) { + List list = new ArrayList<>(); + list.add(psiElement); + psiPathElements.put(pathRange, list); + } else { + psiPathElements.get(pathRange).add(psiElement); + } + } + } + } + + if (psiPathElements.size() > 0) { + psiPathElements.forEach(((textRange, psiElements) -> + psiReferences.add(new PolyVariantReferenceBase(element, textRange, psiElements)) + )); + } + } + + return psiReferences.toArray(new PsiReference[psiReferences.size()]); + } + + private Collection getFiles(@NotNull PsiElement element) + { + Collection files = new ArrayList<>(); + + String filePath = getFilePath(element); + if (null == filePath) { + return files; + } + + String fileName = filePath.substring(filePath.lastIndexOf("/") + 1); + + if (fileName.matches(".*\\.\\w+$")) { + // extension presents + files = FilenameIndex.getVirtualFilesByName( + element.getProject(), + fileName, + GlobalSearchScope.allScope(element.getProject()) + ); + files.removeIf(f -> !f.getPath().endsWith(filePath)); + + // filter by module + Collection vfs = getModuleSourceFiles(element); + if (null != vfs) { + files.removeIf(f -> { + for (VirtualFile vf : vfs) { + if (f.getPath().startsWith(vf.getPath().concat("/"))) { + return false; + } + } + return true; + }); + } + } else if (isModuleNamePresent(element)) { + // extension absent + Collection vfs = getModuleSourceFiles(element); + if (null != vfs) { + for (VirtualFile vf : vfs) { + Collection vfChildren = getAllSubFiles(vf); + if (null != vfChildren) { + vfChildren.removeIf(f -> { + if (!f.isDirectory()) { + String ext = f.getExtension(); + if (null != ext) { + return !f.getPath().endsWith(filePath.concat(".").concat(ext)); + } + } + return true; + }); + files.addAll(vfChildren); + } + } + } + } + + 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; + } +} diff --git a/src/com/magento/idea/magento2plugin/reference/provider/LayoutBlockReferenceProvider.java b/src/com/magento/idea/magento2plugin/reference/provider/LayoutBlockReferenceProvider.java new file mode 100644 index 000000000..3c7d73abd --- /dev/null +++ b/src/com/magento/idea/magento2plugin/reference/provider/LayoutBlockReferenceProvider.java @@ -0,0 +1,31 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.reference.provider; + +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.XmlTag; +import com.intellij.util.ProcessingContext; +import com.magento.idea.magento2plugin.indexes.LayoutIndex; +import com.magento.idea.magento2plugin.reference.xml.PolyVariantReferenceBase; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public class LayoutBlockReferenceProvider extends PsiReferenceProvider { + + @NotNull + @Override + public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) { + String value = StringUtil.unquoteString(element.getText()); + List targets = LayoutIndex.getBlockDeclarations(value, element.getProject()); + if (targets.size() > 0) { + return new PsiReference[] {new PolyVariantReferenceBase(element, targets)}; + } + return PsiReference.EMPTY_ARRAY; + } +} diff --git a/src/com/magento/idea/magento2plugin/reference/provider/LayoutContainerReferenceProvider.java b/src/com/magento/idea/magento2plugin/reference/provider/LayoutContainerReferenceProvider.java new file mode 100644 index 000000000..ebb19ae46 --- /dev/null +++ b/src/com/magento/idea/magento2plugin/reference/provider/LayoutContainerReferenceProvider.java @@ -0,0 +1,34 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.reference.provider; + +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.XmlTag; +import com.intellij.util.ProcessingContext; +import com.magento.idea.magento2plugin.indexes.LayoutIndex; +import com.magento.idea.magento2plugin.reference.xml.PolyVariantReferenceBase; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +/** + * Created by dkvashnin on 11/18/15. + */ +public class LayoutContainerReferenceProvider extends PsiReferenceProvider { + + @NotNull + @Override + public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) { + String value = StringUtil.unquoteString(element.getText()); + List targets = LayoutIndex.getContainerDeclarations(value, element.getProject()); + if (targets.size() > 0) { + return new PsiReference[] {new PolyVariantReferenceBase(element, targets)}; + } + return PsiReference.EMPTY_ARRAY; + } +} diff --git a/src/com/magento/idea/magento2plugin/reference/provider/LayoutUpdateReferenceProvider.java b/src/com/magento/idea/magento2plugin/reference/provider/LayoutUpdateReferenceProvider.java new file mode 100644 index 000000000..df1ea53d4 --- /dev/null +++ b/src/com/magento/idea/magento2plugin/reference/provider/LayoutUpdateReferenceProvider.java @@ -0,0 +1,31 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.reference.provider; + +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.XmlFile; +import com.intellij.util.ProcessingContext; +import com.magento.idea.magento2plugin.indexes.LayoutIndex; +import com.magento.idea.magento2plugin.reference.xml.PolyVariantReferenceBase; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public class LayoutUpdateReferenceProvider extends PsiReferenceProvider { + + @NotNull + @Override + public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) { + String value = StringUtil.unquoteString(element.getText()); + List targets = LayoutIndex.getLayoutFiles(element.getProject(), value); + if (targets.size() > 0) { + return new PsiReference[] {new PolyVariantReferenceBase(element, targets)}; + } + return PsiReference.EMPTY_ARRAY; + } +} diff --git a/src/com/magento/idea/magento2plugin/reference/provider/ModuleNameReferenceProvider.java b/src/com/magento/idea/magento2plugin/reference/provider/ModuleNameReferenceProvider.java new file mode 100644 index 000000000..7fcaa832b --- /dev/null +++ b/src/com/magento/idea/magento2plugin/reference/provider/ModuleNameReferenceProvider.java @@ -0,0 +1,78 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.reference.provider; + +import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.*; +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.xml.PolyVariantReferenceBase; +import com.magento.idea.magento2plugin.stubs.indexes.ModuleNameIndex; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class ModuleNameReferenceProvider extends PsiReferenceProvider { + + @NotNull + @Override + public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) { + + List psiReferences = new ArrayList<>(); + String origValue = element.getText(); + + Pattern pattern = Pattern.compile("(([A-Z][a-zA-Z0-9]+)_([A-Z][a-zA-Z0-9]+))"); + Matcher matcher = pattern.matcher(element.getText()); + if (!matcher.find()) { + return PsiReference.EMPTY_ARRAY; + } + + String moduleName = matcher.group(1); + + Collection moduleFiles = FileBasedIndex.getInstance() + .getContainingFiles(ModuleNameIndex.KEY, moduleName, + GlobalSearchScope.getScopeRestrictedByFileTypes( + GlobalSearchScope.allScope(element.getProject()), + PhpFileType.INSTANCE + ) + ); + + PsiManager psiManager = PsiManager.getInstance(element.getProject()); + List psiElements = new ArrayList<>(); + + for (VirtualFile moduleVf : moduleFiles) { + if (moduleVf.getParent() == null) { + continue; + } + VirtualFile moduleSourceVf = moduleVf.getParent(); + if (!moduleSourceVf.isDirectory()) { + continue; + } + + PsiDirectory moduleSourceDirectory = psiManager.findDirectory(moduleSourceVf); + if (null == moduleSourceDirectory) { + continue; + } + + psiElements.add(moduleSourceDirectory); + } + + if (psiElements.size() > 0) { + TextRange range = new TextRange( + origValue.indexOf(moduleName), origValue.indexOf(moduleName) + moduleName.length() + ); + psiReferences.add(new PolyVariantReferenceBase(element, range, psiElements)); + } + + return psiReferences.toArray(new PsiReference[psiReferences.size()]); + } +} diff --git a/src/com/magento/idea/magento2plugin/reference/provider/PhpClassMemberReferenceProvider.java b/src/com/magento/idea/magento2plugin/reference/provider/PhpClassMemberReferenceProvider.java new file mode 100644 index 000000000..7323f0c0a --- /dev/null +++ b/src/com/magento/idea/magento2plugin/reference/provider/PhpClassMemberReferenceProvider.java @@ -0,0 +1,62 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.reference.provider; + +import com.intellij.openapi.util.TextRange; +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.util.ProcessingContext; +import com.jetbrains.php.PhpIndex; +import com.jetbrains.php.lang.psi.elements.PhpClass; +import com.jetbrains.php.lang.psi.elements.PhpClassMember; +import com.magento.idea.magento2plugin.php.util.PhpRegex; +import com.magento.idea.magento2plugin.reference.xml.PolyVariantReferenceBase; +import gnu.trove.THashSet; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class PhpClassMemberReferenceProvider extends PsiReferenceProvider { + + @NotNull + @Override + public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) { + List psiReferences = new ArrayList<>(); + final Collection members = new THashSet<>(); + + String origValue = element.getText(); + String value = StringUtil.unquoteString(element.getText()); + + Matcher matcher = Pattern.compile(PhpRegex.Xml.CLASS_MEMBER_NAME).matcher(value); + if (!matcher.find()) { + return PsiReference.EMPTY_ARRAY; + } + + String elementName = matcher.group(1); + String classFQN = value.substring(0, value.lastIndexOf("::")); + + PhpIndex phpIndex = PhpIndex.getInstance(element.getProject()); + for (final PhpClass phpClass : phpIndex.getAnyByFQN(classFQN)) { + members.addAll(phpClass.getFields()); + members.addAll(phpClass.getMethods()); + members.removeIf(c -> !c.getName().equals(elementName)); + } + + if (members.size() > 0) { + TextRange range = new TextRange( + origValue.indexOf(elementName), + origValue.indexOf(elementName) + elementName.length() + ); + psiReferences.add(new PolyVariantReferenceBase(element, range, members)); + } + return psiReferences.toArray(new PsiReference[psiReferences.size()]); + } +} diff --git a/src/com/magento/idea/magento2plugin/reference/provider/PhpClassReferenceProvider.java b/src/com/magento/idea/magento2plugin/reference/provider/PhpClassReferenceProvider.java new file mode 100644 index 000000000..0b4c2d08b --- /dev/null +++ b/src/com/magento/idea/magento2plugin/reference/provider/PhpClassReferenceProvider.java @@ -0,0 +1,74 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.reference.provider; + +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiReference; +import com.intellij.psi.PsiReferenceProvider; +import com.intellij.util.ProcessingContext; +import com.jetbrains.php.PhpIndex; +import com.jetbrains.php.lang.psi.elements.PhpClass; +import com.jetbrains.php.lang.psi.elements.PhpNamespace; +import com.magento.idea.magento2plugin.php.util.PhpRegex; +import com.magento.idea.magento2plugin.reference.xml.PolyVariantReferenceBase; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class PhpClassReferenceProvider extends PsiReferenceProvider { + + @NotNull + @Override + public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) { + List psiReferences = new ArrayList<>(); + + String origValue = element.getText(); + + Pattern pattern = Pattern.compile(PhpRegex.FQN); + Matcher matcher = pattern.matcher(origValue); + if (!matcher.find()) { + return PsiReference.EMPTY_ARRAY; + } + + String classFQN = matcher.group(); + String[] fqnParts = classFQN.split("\\\\"); + + PhpIndex phpIndex = PhpIndex.getInstance(element.getProject()); + + StringBuilder namespace = new StringBuilder(); + String namespacePart; + for (int i = 0; i < fqnParts.length - 1; i++) { + namespacePart = fqnParts[i]; + + namespace.append("\\"); + namespace.append(namespacePart); + Collection references = phpIndex.getNamespacesByName(namespace.toString().toLowerCase()); + if (references.size() > 0) { + TextRange range = new TextRange( + origValue.indexOf(classFQN) + namespace.toString().lastIndexOf(92), + origValue.indexOf(classFQN) + namespace.toString().lastIndexOf(92) + namespacePart.length() + ); + psiReferences.add(new PolyVariantReferenceBase(element, range, references)); + } + } + + String className = classFQN.substring(classFQN.lastIndexOf(92) + 1); + Collection classes = phpIndex.getAnyByFQN(classFQN); + if (classes.size() > 0) { + TextRange range = new TextRange( + origValue.lastIndexOf(92) + 1, + origValue.lastIndexOf(92) + 1 + className.length() + ); + psiReferences.add(new PolyVariantReferenceBase(element, range, classes)); + } + + return psiReferences.toArray(new PsiReference[psiReferences.size()]); + } +} diff --git a/src/com/magento/idea/magento2plugin/reference/provider/PhpConstructorArgumentReferenceProvider.java b/src/com/magento/idea/magento2plugin/reference/provider/PhpConstructorArgumentReferenceProvider.java new file mode 100644 index 000000000..15d389c1a --- /dev/null +++ b/src/com/magento/idea/magento2plugin/reference/provider/PhpConstructorArgumentReferenceProvider.java @@ -0,0 +1,51 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.reference.provider; + +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.XmlElement; +import com.intellij.util.ProcessingContext; +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.magento.idea.magento2plugin.indexes.DiIndex; +import com.magento.idea.magento2plugin.reference.xml.PolyVariantReferenceBase; +import gnu.trove.THashSet; +import org.jetbrains.annotations.NotNull; + +import java.util.Arrays; +import java.util.Collection; + +public class PhpConstructorArgumentReferenceProvider extends PsiReferenceProvider { + + @NotNull + @Override + public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) { + + String parameterName = StringUtil.unquoteString(element.getText()); + if (parameterName.isEmpty() || !(element instanceof XmlElement)) { + return PsiReference.EMPTY_ARRAY; + } + + + DiIndex diIndex = DiIndex.getInstance(element.getProject()); + PhpClass phpClass = diIndex.getPhpClassOfArgument((XmlElement) element); + if (phpClass != null) { + Method constructor = phpClass.getConstructor(); + if (constructor != null) { + Collection parameterList = new THashSet<>(Arrays.asList(constructor.getParameters())); + parameterList.removeIf(p -> !p.getName().contains(parameterName)); + if (parameterList.size() > 0) { + return new PsiReference[] {new PolyVariantReferenceBase(element, parameterList)}; + } + } + } + + return PsiReference.EMPTY_ARRAY; + } +} diff --git a/src/com/magento/idea/magento2plugin/reference/provider/PhpServiceMethodReferenceProvider.java b/src/com/magento/idea/magento2plugin/reference/provider/PhpServiceMethodReferenceProvider.java new file mode 100644 index 000000000..b025ab426 --- /dev/null +++ b/src/com/magento/idea/magento2plugin/reference/provider/PhpServiceMethodReferenceProvider.java @@ -0,0 +1,45 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.reference.provider; + +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.XmlElement; +import com.intellij.util.ProcessingContext; +import com.jetbrains.php.lang.psi.elements.Method; +import com.jetbrains.php.lang.psi.elements.PhpClass; +import com.magento.idea.magento2plugin.indexes.DiIndex; +import com.magento.idea.magento2plugin.reference.xml.PolyVariantReferenceBase; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class PhpServiceMethodReferenceProvider extends PsiReferenceProvider { + + @NotNull + @Override + public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) { + if (!(element instanceof XmlElement)) { + return PsiReference.EMPTY_ARRAY; + } + + List psiReferences = new ArrayList<>(); + + String methodName = StringUtil.unquoteString(element.getText()); + + PhpClass phpClass = DiIndex.getPhpClassOfServiceMethod((XmlElement) element); + if (phpClass != null) { + Collection methods = phpClass.getMethods(); + methods.removeIf(m -> !m.getName().equalsIgnoreCase(methodName)); + psiReferences.add(new PolyVariantReferenceBase(element, methods)); + } + + return psiReferences.toArray(new PsiReference[psiReferences.size()]); + } +} diff --git a/src/com/magento/idea/magento2plugin/reference/provider/VirtualTypeReferenceProvider.java b/src/com/magento/idea/magento2plugin/reference/provider/VirtualTypeReferenceProvider.java new file mode 100644 index 000000000..78ff758c9 --- /dev/null +++ b/src/com/magento/idea/magento2plugin/reference/provider/VirtualTypeReferenceProvider.java @@ -0,0 +1,37 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.reference.provider; + +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.util.ProcessingContext; +import com.magento.idea.magento2plugin.indexes.DiIndex; +import com.magento.idea.magento2plugin.reference.xml.PolyVariantReferenceBase; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; + +public class VirtualTypeReferenceProvider extends PsiReferenceProvider { + + @NotNull + @Override + public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) { + + String value = StringUtil.unquoteString(element.getText()); + + DiIndex index = DiIndex.getInstance(element.getProject()); + Collection targets = index.getVirtualTypeElements(value, element.getResolveScope()); + + if (!(targets.size() > 0)) { + return PsiReference.EMPTY_ARRAY; + } + + return new PsiReference[] { + new PolyVariantReferenceBase(element, targets) + }; + } +} diff --git a/src/com/magento/idea/magento2plugin/reference/xml/PolyVariantReferenceBase.java b/src/com/magento/idea/magento2plugin/reference/xml/PolyVariantReferenceBase.java new file mode 100644 index 000000000..3ec5d1e95 --- /dev/null +++ b/src/com/magento/idea/magento2plugin/reference/xml/PolyVariantReferenceBase.java @@ -0,0 +1,50 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.reference.xml; + +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiElementResolveResult; +import com.intellij.psi.PsiPolyVariantReferenceBase; +import com.intellij.psi.ResolveResult; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; + +public class PolyVariantReferenceBase extends PsiPolyVariantReferenceBase { + + /** + * Target elements + */ + private Collection targets; + + public PolyVariantReferenceBase(PsiElement element, Collection targets) { + super(element); + this.targets = targets; + } + + public PolyVariantReferenceBase(PsiElement element, TextRange range, Collection targets) { + super(element, range); + this.targets = targets; + } + + @NotNull + @Override + public ResolveResult[] multiResolve(boolean incompleteCode) { + ResolveResult[] resolveResults = new ResolveResult[targets.size()]; + + int i = 0; + for (PsiElement target : targets) { + resolveResults[i++] = new PsiElementResolveResult(target); + } + return resolveResults; + } + + @NotNull + @Override + public Object[] getVariants() { + return new Object[0]; + } +} diff --git a/src/com/magento/idea/magento2plugin/reference/xml/XmlReferenceContributor.java b/src/com/magento/idea/magento2plugin/reference/xml/XmlReferenceContributor.java new file mode 100644 index 000000000..650712e5d --- /dev/null +++ b/src/com/magento/idea/magento2plugin/reference/xml/XmlReferenceContributor.java @@ -0,0 +1,160 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.reference.xml; + +import com.intellij.patterns.XmlPatterns; +import com.intellij.psi.PsiReferenceContributor; +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 org.jetbrains.annotations.NotNull; + +import static com.intellij.patterns.XmlPatterns.string; +import static com.intellij.patterns.XmlPatterns.xmlFile; + +public class XmlReferenceContributor extends PsiReferenceContributor { + + @Override + public void registerReferenceProviders(@NotNull PsiReferenceRegistrar registrar) { + + // + registrar.registerReferenceProvider( + XmlPatterns.xmlAttributeValue().withValue(string().matches(PhpRegex.Xml.CLASS_ELEMENT)), + new CompositeReferenceProvider( + new PhpClassReferenceProvider(), + new PhpClassMemberReferenceProvider() + ) + ); + + // Some\Php\ClassName[::CONST|$property|method()] + registrar.registerReferenceProvider( + XmlPatterns.psiElement(XmlTokenType.XML_DATA_CHARACTERS) + .withText(string().matches(PhpRegex.Xml.CLASS_ELEMENT)), + new CompositeReferenceProvider( + new PhpClassReferenceProvider(), + new PhpClassMemberReferenceProvider() + ) + ); + + // virtual type references + registrar.registerReferenceProvider( + XmlPatterns.xmlAttributeValue().withParent( + XmlPatterns.xmlAttribute().withName("type")).inFile(xmlFile().withName(string().endsWith("di.xml")) + ), + new VirtualTypeReferenceProvider() + ); + registrar.registerReferenceProvider( + XmlPatterns.psiElement(XmlTokenType.XML_DATA_CHARACTERS).withParent( + XmlPatterns.xmlText().withParent( + XmlPatterns.xmlTag().withChild( + XmlPatterns.xmlAttribute().withName("xsi:type") + ) + ) + ).inFile(xmlFile().withName(string().endsWith("di.xml"))), + new VirtualTypeReferenceProvider() + ); + + // arguments + registrar.registerReferenceProvider( + XmlPatterns.xmlAttributeValue().withParent( + XmlPatterns.xmlAttribute().withName("name").withParent( + XmlPatterns.xmlTag().withName("argument").withParent( + XmlPatterns.xmlTag().withName("arguments") + ) + ) + ).inFile(xmlFile().withName(string().endsWith("di.xml"))), + new PhpConstructorArgumentReferenceProvider() + ); + + // + registrar.registerReferenceProvider( + XmlPatterns.xmlAttributeValue().withParent( + XmlPatterns.xmlAttribute().withName("method").withParent( + XmlPatterns.xmlTag().withName("service") + ) + ).inFile(xmlFile().withName(string().endsWith("webapi.xml"))), + new PhpServiceMethodReferenceProvider() + ); + + registrar.registerReferenceProvider( + XmlPatterns.xmlAttributeValue().withParent( + XmlPatterns.xmlAttribute().withName("name").withParent( + XmlPatterns.xmlTag().withName("referenceContainer") + ) + ), + new LayoutContainerReferenceProvider() + ); + + registrar.registerReferenceProvider( + XmlPatterns.or( + XmlPatterns.xmlAttributeValue().withParent(XmlPatterns.xmlAttribute().withName("name") + .withParent(XmlPatterns.xmlTag().withName("referenceBlock"))), + XmlPatterns.xmlAttributeValue().withParent(XmlPatterns.xmlAttribute() + .withName(string().oneOf("before", "after")) + .withParent(XmlPatterns.xmlTag().withName("block"))), + XmlPatterns.xmlAttributeValue().withParent(XmlPatterns.xmlAttribute() + .withName(string().oneOf("before", "after", "destination", "element")) + .withParent(XmlPatterns.xmlTag().withName("move"))), + XmlPatterns.xmlAttributeValue().withParent(XmlPatterns.xmlAttribute().withName("name") + .withParent(XmlPatterns.xmlTag().withName("remove"))) + ), + new LayoutBlockReferenceProvider() + ); + + registrar.registerReferenceProvider( + XmlPatterns.xmlAttributeValue().withParent( + XmlPatterns.xmlAttribute().withName("handle").withParent( + XmlPatterns.xmlTag().withName("update") + ) + ), + new LayoutUpdateReferenceProvider() + ); + + // + registrar.registerReferenceProvider( + XmlPatterns.xmlAttributeValue().withParent( + XmlPatterns.xmlAttribute().withName("name").withParent( + XmlPatterns.xmlTag().withName("event") + ) + ), + new EventNameReferenceProvider() + ); + + // + registrar.registerReferenceProvider( + XmlPatterns.xmlAttributeValue().withValue(string().matches(".*[A-Z][a-zA-Z0-9]+_[A-Z][a-zA-Z0-9]+.*")), + new CompositeReferenceProvider( + new ModuleNameReferenceProvider() + ) + ); + + // Module_Name[.*] + registrar.registerReferenceProvider( + XmlPatterns.psiElement(XmlTokenType.XML_DATA_CHARACTERS) + .withText(string().matches(".*[A-Z][a-zA-Z0-9]+_[A-Z][a-zA-Z0-9]+.*")), + new CompositeReferenceProvider( + new ModuleNameReferenceProvider() + ) + ); + + // + registrar.registerReferenceProvider( + XmlPatterns.xmlAttributeValue().withValue(string().matches(".*\\W([\\w-]+/)*[\\w\\.-]+.*")), + new CompositeReferenceProvider( + new FilePathReferenceProvider() + ) + ); + + // path/to/some-of-file.some-ext + registrar.registerReferenceProvider( + XmlPatterns.psiElement(XmlTokenType.XML_DATA_CHARACTERS) + .withText(string().matches(".*\\W([\\w-]+/)*[\\w\\.-]+.*")), + new CompositeReferenceProvider( + new FilePathReferenceProvider() + ) + ); + } +} diff --git a/src/com/magento/idea/magento2plugin/stubs/indexes/BlockNameIndex.java b/src/com/magento/idea/magento2plugin/stubs/indexes/BlockNameIndex.java new file mode 100644 index 000000000..133dc59ed --- /dev/null +++ b/src/com/magento/idea/magento2plugin/stubs/indexes/BlockNameIndex.java @@ -0,0 +1,29 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.stubs.indexes; + +import com.intellij.util.indexing.DataIndexer; +import com.intellij.util.indexing.FileContent; +import com.intellij.util.indexing.ID; +import org.jetbrains.annotations.NotNull; + +/** + * Created by dkvashnin on 11/18/15. + */ +public class BlockNameIndex extends NamedComponentIndex { + public static final ID KEY = ID.create("com.magento.idea.magento2plugin.stubs.indexes.block_name"); + + @NotNull + @Override + public ID getName() { + return KEY; + } + + @NotNull + @Override + public DataIndexer getIndexer() { + return new LayoutDataIndexer("block", "name"); + } +} diff --git a/src/com/magento/idea/magento2plugin/stubs/indexes/ContainerNameIndex.java b/src/com/magento/idea/magento2plugin/stubs/indexes/ContainerNameIndex.java new file mode 100644 index 000000000..b4d41daa5 --- /dev/null +++ b/src/com/magento/idea/magento2plugin/stubs/indexes/ContainerNameIndex.java @@ -0,0 +1,35 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.stubs.indexes; + +import com.intellij.util.indexing.DataIndexer; +import com.intellij.util.indexing.FileContent; +import com.intellij.util.indexing.ID; +import org.jetbrains.annotations.NotNull; + +/** + * Created by dkvashnin on 11/18/15. + */ +public class ContainerNameIndex extends NamedComponentIndex { + public static final ID KEY = + ID.create("com.magento.idea.magento2plugin.stubs.indexes.container_name"); + + @NotNull + @Override + public ID getName() { + return KEY; + } + + @NotNull + @Override + public DataIndexer getIndexer() { + return new LayoutDataIndexer("container", "name"); + } + + @Override + public int getVersion() { + return 1; + } +} \ No newline at end of file diff --git a/src/com/magento/idea/magento2plugin/stubs/indexes/EventNameIndex.java b/src/com/magento/idea/magento2plugin/stubs/indexes/EventNameIndex.java new file mode 100644 index 000000000..033a0aa78 --- /dev/null +++ b/src/com/magento/idea/magento2plugin/stubs/indexes/EventNameIndex.java @@ -0,0 +1,137 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.stubs.indexes; + +import com.intellij.ide.highlighter.XmlFileType; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.PsiElement; +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.EnumeratorStringDescriptor; +import com.intellij.util.io.KeyDescriptor; +import com.jetbrains.php.lang.PhpFileType; +import com.jetbrains.php.lang.psi.PhpFile; +import com.jetbrains.php.lang.psi.elements.MethodReference; +import com.jetbrains.php.lang.psi.elements.ParameterList; +import com.magento.idea.magento2plugin.project.Settings; +import com.magento.idea.magento2plugin.php.util.PhpPatternsHelper; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Created by dkvashnin on 11/5/15. + */ +public class EventNameIndex extends ScalarIndexExtension { + public static final ID KEY = ID.create("com.magento.idea.magento2plugin.stubs.indexes.event_name"); + private final KeyDescriptor myKeyDescriptor = new EnumeratorStringDescriptor(); + + @NotNull + @Override + public ID getName() { + return KEY; + } + + @NotNull + @Override + public DataIndexer getIndexer() { + return inputData -> { + Map map = new HashMap<>(); + PsiFile psiFile = inputData.getPsiFile(); + + if (!Settings.isEnabled(psiFile.getProject())) { + return map; + } + + if (psiFile instanceof PhpFile) { + grabEventNamesFromPhpFile((PhpFile) psiFile, map); + } else if (psiFile instanceof XmlFile) { + grabEventNamesFromXmlFile((XmlFile) psiFile, map); + } + + return map; + }; + } + + private void grabEventNamesFromPhpFile(PhpFile file, Map map) { + List results = new ArrayList<>(); + recursiveFill(results, file); + for (String result: results) { + map.put(result, null); + } + } + + private void recursiveFill(List results, PsiElement psiElement) { + if (PhpPatternsHelper.STRING_METHOD_ARGUMENT.accepts(psiElement) && isInContextOfDispatchMethod(psiElement)) { + String eventName= StringUtil.unquoteString(psiElement.getText()); + if (eventName.length() > 0) { + results.add(eventName); + } + return; + } + for(PsiElement child: psiElement.getChildren()) { + recursiveFill(results, child); + } + } + + private boolean isInContextOfDispatchMethod(PsiElement psiElement) { + ParameterList parameterList = PsiTreeUtil.getParentOfType(psiElement, ParameterList.class); + if (parameterList == null) { + return false; + } + if (!(parameterList.getContext() instanceof MethodReference)) { + return false; + } + MethodReference methodReference = (MethodReference)parameterList.getContext(); + return methodReference.getName() != null && methodReference.getName().equals("dispatch"); + } + + private void grabEventNamesFromXmlFile(XmlFile file, Map map) { + XmlDocument xmlDocument = file.getDocument(); + if (xmlDocument != null) { + XmlTag xmlRootTag = xmlDocument.getRootTag(); + if (xmlRootTag != null) { + for (XmlTag eventTag : xmlRootTag.findSubTags("event")) { + String name = eventTag.getAttributeValue("name"); + if (name != null && !name.isEmpty()) { + map.put(name, null); + } + } + } + } + } + + @NotNull + @Override + public KeyDescriptor getKeyDescriptor() { + return myKeyDescriptor; + } + + @NotNull + @Override + public FileBasedIndex.InputFilter getInputFilter() { + return file -> ( + file.getFileType() == PhpFileType.INSTANCE + || (file.getFileType() == XmlFileType.INSTANCE && file.getName().equals("events.xml")) + ); + } + + @Override + public boolean dependsOnFileContent() { + return true; + } + + @Override + public int getVersion() { + return 1; + } +} diff --git a/src/com/magento/idea/magento2plugin/stubs/indexes/EventObserverIndex.java b/src/com/magento/idea/magento2plugin/stubs/indexes/EventObserverIndex.java new file mode 100644 index 000000000..c91f9528f --- /dev/null +++ b/src/com/magento/idea/magento2plugin/stubs/indexes/EventObserverIndex.java @@ -0,0 +1,124 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.stubs.indexes; + +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.jetbrains.php.lang.PhpLangUtil; +import com.jetbrains.php.lang.psi.stubs.indexes.StringSetDataExternalizer; +import com.magento.idea.magento2plugin.project.Settings; +import org.jetbrains.annotations.NotNull; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * Created by dkvashnin on 11/2/15. + */ +public class EventObserverIndex extends FileBasedIndexExtension> { + public static final ID> KEY = + ID.create("com.magento.idea.magento2plugin.stubs.indexes.event_observer"); + private final KeyDescriptor myKeyDescriptor = new EnumeratorStringDescriptor(); + + @NotNull + @Override + public ID> getName() { + return KEY; + } + + @NotNull + @Override + public DataIndexer, FileContent> getIndexer() { + return new DataIndexer, FileContent>() { + @NotNull + @Override + public Map> map(@NotNull FileContent fileContent) { + Map> map = new HashMap<>(); + + PsiFile psiFile = fileContent.getPsiFile(); + if (!Settings.isEnabled(psiFile.getProject())) { + return map; + } + + if (!(psiFile instanceof XmlFile)) { + return map; + } + + XmlDocument document = ((XmlFile) psiFile).getDocument(); + if (document == null) { + return map; + } + + XmlTag xmlTags[] = PsiTreeUtil.getChildrenOfType(psiFile.getFirstChild(), XmlTag.class); + if (xmlTags == null) { + return map; + } + + for (XmlTag xmlTag: xmlTags) { + if (xmlTag.getName().equals("config")) { + for (XmlTag eventNode: xmlTag.findSubTags("event")) { + if (eventNode.getAttributeValue("name") != null) { + map.put(eventNode.getAttributeValue("name"), getObserversForEvent(eventNode)); + } + } + } + } + + return map; + } + + private Set getObserversForEvent(XmlTag eventNode) { + Set observerNames = new HashSet(); + + for (XmlTag observerTag: eventNode.findSubTags("observer")) { + String name = observerTag.getAttributeValue("instance"); + if (name != null) { + observerNames.add(PhpLangUtil.toPresentableFQN(name)); + } + } + + return observerNames; + } + }; + } + + @NotNull + @Override + public KeyDescriptor getKeyDescriptor() { + return myKeyDescriptor; + } + + @NotNull + @Override + public DataExternalizer> getValueExternalizer() { + return new StringSetDataExternalizer(); + } + + @NotNull + @Override + public FileBasedIndex.InputFilter getInputFilter() { + return file -> (file.getFileType() == XmlFileType.INSTANCE && file.getName().equals("events.xml")); + } + + @Override + public boolean dependsOnFileContent() { + return true; + } + + @Override + public int getVersion() { + return 2; + } +} diff --git a/src/com/magento/idea/magento2plugin/stubs/indexes/ModuleNameIndex.java b/src/com/magento/idea/magento2plugin/stubs/indexes/ModuleNameIndex.java new file mode 100644 index 000000000..a69c4dfcb --- /dev/null +++ b/src/com/magento/idea/magento2plugin/stubs/indexes/ModuleNameIndex.java @@ -0,0 +1,116 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.stubs.indexes; + +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +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 com.jetbrains.php.lang.PhpFileType; +import com.jetbrains.php.lang.psi.PhpFile; +import com.jetbrains.php.lang.psi.elements.*; +import com.magento.idea.magento2plugin.project.Settings; +import org.jetbrains.annotations.NotNull; + + +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class ModuleNameIndex extends FileBasedIndexExtension { + public static final ID KEY = + ID.create("com.magento.idea.magento2plugin.stubs.indexes.module_name"); + + @NotNull + @Override + public ID getName() { + return KEY; + } + + @NotNull + @Override + public DataIndexer getIndexer() { + return inputData -> { + Map map = new HashMap<>(); + PsiFile psiFile = inputData.getPsiFile(); + + if (!Settings.isEnabled(psiFile.getProject())) { + return map; + } + + if (psiFile instanceof PhpFile) { + MethodReference method = PsiTreeUtil.findChildOfAnyType(psiFile, MethodReference.class); + if (method != null) { + ParameterList parameterList = method.getParameterList(); + if (parameterList != null) { + PsiElement firstParameter = parameterList.getFirstPsiChild(); + if (firstParameter != null && firstParameter instanceof ClassConstantReference) { + String constantName = ((ClassConstantReference) firstParameter).getName(); + if (constantName != null) { + PsiElement moduleNameEl = ((ClassConstantReference) firstParameter).getNextPsiSibling(); + if (moduleNameEl != null && moduleNameEl instanceof StringLiteralExpression) { + String moduleName = StringUtil.unquoteString(moduleNameEl.getText()); + + PsiElement modulePathEl = + ((StringLiteralExpression) moduleNameEl).getNextPsiSibling(); + if (modulePathEl != null) { + Pattern pattern = Pattern.compile( + "__DIR__(\\s*[.,]\\s*[\\'\\\"]((/[\\w-]+)+)/?[\\'\\\"])?" + ); + Matcher matcher = pattern.matcher(modulePathEl.getText()); + if (matcher.find()) { + String modulePath = matcher.group(2); + map.put( + moduleName, + modulePath == null ? "" : modulePath + ); + } + } + } + } + } + } + } + } + + return map; + }; + } + + @NotNull + @Override + public KeyDescriptor getKeyDescriptor() { + return new EnumeratorStringDescriptor(); + } + + @NotNull + public DataExternalizer getValueExternalizer() { + return EnumeratorStringDescriptor.INSTANCE; + } + + @NotNull + @Override + public FileBasedIndex.InputFilter getInputFilter() { + return virtualFile -> ( + virtualFile.getFileType().equals(PhpFileType.INSTANCE) + && virtualFile.getName().equals("registration.php") + ); + } + + @Override + public boolean dependsOnFileContent() { + return true; + } + + @Override + public int getVersion() { + return 1; + } +} diff --git a/src/com/magento/idea/magento2plugin/stubs/indexes/ModulePackageIndex.java b/src/com/magento/idea/magento2plugin/stubs/indexes/ModulePackageIndex.java new file mode 100644 index 000000000..94e8c0a1b --- /dev/null +++ b/src/com/magento/idea/magento2plugin/stubs/indexes/ModulePackageIndex.java @@ -0,0 +1,93 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.stubs.indexes; + +import com.intellij.json.JsonFileType; +import com.intellij.json.psi.JsonFile; +import com.intellij.json.psi.JsonObject; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.indexing.*; +import com.intellij.util.io.EnumeratorStringDescriptor; +import com.intellij.util.io.KeyDescriptor; +import com.magento.idea.magento2plugin.project.Settings; +import com.magento.idea.magento2plugin.php.module.ComposerPackageModel; +import com.magento.idea.magento2plugin.php.module.ComposerPackageModelImpl; +import org.jetbrains.annotations.NotNull; + +import java.util.HashMap; +import java.util.Map; + +/** + * Created by dkvashnin on 12/3/15. + */ +public class ModulePackageIndex extends ScalarIndexExtension { + public static final ID KEY = + ID.create("com.magento.idea.magento2plugin.stubs.indexes.module_package"); + + @NotNull + @Override + public ID getName() { + return KEY; + } + + @NotNull + @Override + public DataIndexer getIndexer() { + return inputData -> { + Map map = new HashMap<>(); + JsonFile jsonFile = (JsonFile)inputData.getPsiFile(); + if (!Settings.isEnabled(jsonFile.getProject())) { + return map; + } + + JsonObject jsonObject = PsiTreeUtil.getChildOfType(jsonFile, JsonObject.class); + if (jsonObject == null) { + return map; + } + ComposerPackageModel composerObject = new ComposerPackageModelImpl(jsonObject); + + String type = composerObject.getType(); + if (type == null) { + return map; + } + + if (!type.startsWith("magento2-")) { + return map; + } + + String name = composerObject.getName(); + + if (name != null) { + map.put(name, null); + } + + return map; + }; + } + + @NotNull + @Override + public KeyDescriptor getKeyDescriptor() { + return new EnumeratorStringDescriptor(); + } + + @NotNull + @Override + public FileBasedIndex.InputFilter getInputFilter() { + return virtualFile -> ( + virtualFile.getFileType().equals(JsonFileType.INSTANCE) && virtualFile.getName().equals("composer.json") + ); + } + + @Override + public boolean dependsOnFileContent() { + return true; + } + + @Override + public int getVersion() { + return 1; + } +} diff --git a/src/com/magento/idea/magento2plugin/stubs/indexes/NamedComponentIndex.java b/src/com/magento/idea/magento2plugin/stubs/indexes/NamedComponentIndex.java new file mode 100644 index 000000000..fa0eb4a1c --- /dev/null +++ b/src/com/magento/idea/magento2plugin/stubs/indexes/NamedComponentIndex.java @@ -0,0 +1,41 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.stubs.indexes; + +import com.intellij.util.indexing.FileBasedIndex; +import com.intellij.util.indexing.ScalarIndexExtension; +import com.intellij.util.io.EnumeratorStringDescriptor; +import com.intellij.util.io.KeyDescriptor; +import com.magento.idea.magento2plugin.indexes.LayoutIndex; +import org.jetbrains.annotations.NotNull; + +/** + * Created by dkvashnin on 11/18/15. + */ +public abstract class NamedComponentIndex extends ScalarIndexExtension { + private EnumeratorStringDescriptor myKeyDescriptor = new EnumeratorStringDescriptor(); + + @NotNull + @Override + public KeyDescriptor getKeyDescriptor() { + return myKeyDescriptor; + } + + @NotNull + @Override + public FileBasedIndex.InputFilter getInputFilter() { + return LayoutIndex::isLayoutFile; + } + + @Override + public boolean dependsOnFileContent() { + return true; + } + + @Override + public int getVersion() { + return 0; + } +} diff --git a/src/com/magento/idea/magento2plugin/stubs/indexes/PluginIndex.java b/src/com/magento/idea/magento2plugin/stubs/indexes/PluginIndex.java new file mode 100644 index 000000000..e3c13fb07 --- /dev/null +++ b/src/com/magento/idea/magento2plugin/stubs/indexes/PluginIndex.java @@ -0,0 +1,127 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.stubs.indexes; + +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.jetbrains.php.lang.PhpLangUtil; +import com.jetbrains.php.lang.psi.stubs.indexes.StringSetDataExternalizer; +import com.magento.idea.magento2plugin.project.Settings; +import org.jetbrains.annotations.NotNull; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * Created by dkvashnin on 11/10/15. + */ +public class PluginIndex extends FileBasedIndexExtension> { + public static final ID> KEY + = ID.create("com.magento.idea.magento2plugin.stubs.indexes.plugin_to_type"); + private final KeyDescriptor myKeyDescriptor = new EnumeratorStringDescriptor(); + + @NotNull + @Override + public ID> getName() { + return KEY; + } + + @NotNull + @Override + public DataIndexer, FileContent> getIndexer() { + return new DataIndexer, FileContent>() { + @NotNull + @Override + public Map> map(@NotNull FileContent fileContent) { + Map> map = new HashMap<>(); + + PsiFile psiFile = fileContent.getPsiFile(); + if (!Settings.isEnabled(psiFile.getProject())) { + return map; + } + + if (!(psiFile instanceof XmlFile)) { + return map; + } + XmlDocument document = ((XmlFile) psiFile).getDocument(); + if(document == null) { + return map; + } + + XmlTag xmlTags[] = PsiTreeUtil.getChildrenOfType(psiFile.getFirstChild(), XmlTag.class); + if (xmlTags == null) { + return map; + } + + for (XmlTag xmlTag: xmlTags) { + if (xmlTag.getName().equals("config")) { + for (XmlTag typeNode: xmlTag.findSubTags("type")) { + String typeName = typeNode.getAttributeValue("name"); + if (typeName != null) { + Set plugins = getPluginsForType(typeNode); + if (plugins.size() > 0) { + map.put(PhpLangUtil.toPresentableFQN(typeName), plugins); + } + } + } + } + } + + return map; + } + + private Set getPluginsForType(XmlTag typeNode) { + Set results = new HashSet(); + + for (XmlTag pluginTag: typeNode.findSubTags("plugin")) { + String pluginType = pluginTag.getAttributeValue("type"); + if (pluginType != null) { + results.add(PhpLangUtil.toPresentableFQN(pluginType)); + } + } + return results; + } + }; + } + + @NotNull + @Override + public KeyDescriptor getKeyDescriptor() { + return myKeyDescriptor; + } + + @NotNull + @Override + public DataExternalizer> getValueExternalizer() { + return new StringSetDataExternalizer(); + } + + @NotNull + @Override + public FileBasedIndex.InputFilter getInputFilter() { + return virtualFile -> (virtualFile.getFileType() == XmlFileType.INSTANCE + && virtualFile.getNameWithoutExtension().equals("di")); + } + + @Override + public boolean dependsOnFileContent() { + return true; + } + + @Override + public int getVersion() { + return 1; + } +} diff --git a/src/com/magento/idea/magento2plugin/stubs/indexes/VirtualTypeIndex.java b/src/com/magento/idea/magento2plugin/stubs/indexes/VirtualTypeIndex.java new file mode 100644 index 000000000..815cc2334 --- /dev/null +++ b/src/com/magento/idea/magento2plugin/stubs/indexes/VirtualTypeIndex.java @@ -0,0 +1,91 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.stubs.indexes; + +import com.intellij.ide.highlighter.XmlFileType; +import com.intellij.psi.PsiFile; +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.intellij.util.xml.impl.DomApplicationComponent; +import com.magento.idea.magento2plugin.project.Settings; +import gnu.trove.THashMap; +import org.jetbrains.annotations.NotNull; + +import java.util.Map; + +public class VirtualTypeIndex extends FileBasedIndexExtension { + public static final ID KEY = ID.create( + "com.magento.idea.magento2plugin.stubs.indexes.virtual_type"); + 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) { + XmlDocument xmlDocument = ((XmlFile) psiFile).getDocument(); + if (xmlDocument != null) { + XmlTag xmlRootTag = xmlDocument.getRootTag(); + if (xmlRootTag != null) { + for (XmlTag virtualTypeTag : xmlRootTag.findSubTags("virtualType")) { + String name = virtualTypeTag.getAttributeValue("name"); + String type = virtualTypeTag.getAttributeValue("type"); + + if (name != null && type != null && !name.isEmpty() && !type.isEmpty()) { + map.put(name, type); + } + } + } + } + } + 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.getName().equalsIgnoreCase("di.xml"); + } + + @Override + public boolean dependsOnFileContent() { + return true; + } + + @Override + public int getVersion() { + return DomApplicationComponent.getInstance().getCumulativeVersion(false); + } +} diff --git a/src/com/magento/idea/magento2plugin/stubs/indexes/xml/PhpClassNameIndex.java b/src/com/magento/idea/magento2plugin/stubs/indexes/xml/PhpClassNameIndex.java new file mode 100644 index 000000000..04ef622ea --- /dev/null +++ b/src/com/magento/idea/magento2plugin/stubs/indexes/xml/PhpClassNameIndex.java @@ -0,0 +1,109 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.stubs.indexes.xml; + +import com.intellij.ide.highlighter.XmlFileType; +import com.intellij.psi.PsiFile; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.xml.XmlAttribute; +import com.intellij.psi.xml.XmlFile; +import com.intellij.psi.xml.XmlTag; +import com.intellij.psi.xml.XmlTagValue; +import com.intellij.util.indexing.*; +import com.intellij.util.io.EnumeratorStringDescriptor; +import com.intellij.util.io.KeyDescriptor; +import com.intellij.util.xml.impl.DomApplicationComponent; +import com.jetbrains.php.lang.PhpLangUtil; +import com.magento.idea.magento2plugin.php.util.PhpRegex; +import com.magento.idea.magento2plugin.project.Settings; +import gnu.trove.THashMap; +import org.jetbrains.annotations.NotNull; + +import java.util.Map; + +public class PhpClassNameIndex extends ScalarIndexExtension { + private static final String CLASS_NAME_PATTERN = + "\\\\?" + PhpRegex.CLASS_NAME + "(\\\\" + PhpRegex.CLASS_NAME + ")+"; + + public static final ID KEY = ID.create( + "com.magento.idea.magento2plugin.stubs.indexes.xml.php_class_name"); + + @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; + } + + XmlTag xmlTags[] = PsiTreeUtil.getChildrenOfType(psiFile.getFirstChild(), XmlTag.class); + if (xmlTags == null) { + return map; + } + + for (XmlTag xmlTag: xmlTags) { + fillMap(xmlTag, map); + } + + return map; + }; + } + + private void fillMap(XmlTag parentTag, Map resultMap) { + for (XmlTag childTag: parentTag.getSubTags()) { + for (XmlAttribute xmlAttribute: childTag.getAttributes()) { + String xmlAttributeValue = xmlAttribute.getValue(); + if (xmlAttributeValue != null + && !xmlAttributeValue.isEmpty() + && xmlAttributeValue.matches(CLASS_NAME_PATTERN) + ) { + resultMap.put(PhpLangUtil.toPresentableFQN(xmlAttributeValue), null); + } + } + XmlTagValue childTagValue = childTag.getValue(); + String tagValue = childTagValue.getTrimmedText(); + if (!tagValue.isEmpty() && tagValue.matches(CLASS_NAME_PATTERN)) { + resultMap.put(PhpLangUtil.toPresentableFQN(tagValue), null); + } + + fillMap(childTag, resultMap); + } + } + + @NotNull + @Override + public ID getName() { + return KEY; + } + + @NotNull + @Override + public KeyDescriptor getKeyDescriptor() { + return new EnumeratorStringDescriptor(); + } + + @NotNull + @Override + public FileBasedIndex.InputFilter getInputFilter() { + return file -> + file.getFileType() == XmlFileType.INSTANCE; + } + + @Override + public boolean dependsOnFileContent() { + return true; + } + + @Override + public int getVersion() { + return 1; + } +} diff --git a/src/com/magento/idea/magento2plugin/util/IndexUtil.java b/src/com/magento/idea/magento2plugin/util/IndexUtil.java deleted file mode 100644 index 1de05d6d2..000000000 --- a/src/com/magento/idea/magento2plugin/util/IndexUtil.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.magento.idea.magento2plugin.util; - -import com.intellij.util.indexing.FileBasedIndexImpl; -import com.intellij.util.indexing.ID; -import com.magento.idea.magento2plugin.php.index.ModulePackageFileBasedIndex; -import com.magento.idea.magento2plugin.xml.di.index.PluginToTypeFileBasedIndex; -import com.magento.idea.magento2plugin.xml.di.index.TypeConfigurationFileBasedIndex; -import com.magento.idea.magento2plugin.xml.di.index.VirtualTypesNamesFileBasedIndex; -import com.magento.idea.magento2plugin.xml.layout.index.BlockClassFileBasedIndex; -import com.magento.idea.magento2plugin.xml.layout.index.BlockFileBasedIndex; -import com.magento.idea.magento2plugin.xml.layout.index.ContainerFileBasedIndex; -import com.magento.idea.magento2plugin.xml.observer.index.EventObserverFileBasedIndex; -import com.magento.idea.magento2plugin.xml.observer.index.EventsDeclarationsFileBasedIndex; -import com.magento.idea.magento2plugin.xml.webapi.index.WebApiTypesFileBasedIndex; - -/** - * Created by dkvashnin on 1/9/16. - */ -public class IndexUtil { - public static void manualReindex() { - ID[] indexIds = new ID[] { - // php - ModulePackageFileBasedIndex.NAME, - EventsDeclarationsFileBasedIndex.NAME, - - // xml configuration - // di - PluginToTypeFileBasedIndex.NAME, - TypeConfigurationFileBasedIndex.NAME, - VirtualTypesNamesFileBasedIndex.NAME, - // layouts - BlockClassFileBasedIndex.NAME, - BlockFileBasedIndex.NAME, - ContainerFileBasedIndex.NAME, - // events - EventObserverFileBasedIndex.NAME, - // webapi - WebApiTypesFileBasedIndex.NAME - }; - - for(ID id: indexIds) { - FileBasedIndexImpl.getInstance().requestRebuild(id); - FileBasedIndexImpl.getInstance().scheduleRebuild(id, new Throwable()); - } - } -} diff --git a/src/com/magento/idea/magento2plugin/util/PsiContextMatcherI.java b/src/com/magento/idea/magento2plugin/util/PsiContextMatcherI.java deleted file mode 100644 index 7ab6d1ff4..000000000 --- a/src/com/magento/idea/magento2plugin/util/PsiContextMatcherI.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.magento.idea.magento2plugin.util; - -/** - * Created by dkvashnin on 12/18/15. - */ -public interface PsiContextMatcherI { - boolean match(T psiElement); -} diff --git a/src/com/magento/idea/magento2plugin/util/RegExUtil.java b/src/com/magento/idea/magento2plugin/util/RegExUtil.java new file mode 100644 index 000000000..9728ed44e --- /dev/null +++ b/src/com/magento/idea/magento2plugin/util/RegExUtil.java @@ -0,0 +1,15 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.util; + +public class RegExUtil { + + public static final String FILE_PATH = "[\\w-]+(/[\\w-]*)*"; + + public static class Magento { + public static final String MODULE_NAME + = "[A-Z][a-zA-Z0-9]+_[A-Z][a-zA-Z0-9]+"; + } +} diff --git a/src/com/magento/idea/magento2plugin/util/VfsUtil.java b/src/com/magento/idea/magento2plugin/util/VfsUtil.java new file mode 100644 index 000000000..f4e75ed68 --- /dev/null +++ b/src/com/magento/idea/magento2plugin/util/VfsUtil.java @@ -0,0 +1,47 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.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 org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Collection; + +public class VfsUtil { + + @Nullable + public static VirtualFile findVfUp(VirtualFile item, String searchItemName) + { + if (item.getParent() != null) { + VirtualFile vf = VfsUtilCore.findRelativeFile(searchItemName, item.getParent()); + if (vf != null && !vf.isDirectory()) { + return vf; + } + return findVfUp(item.getParent(), searchItemName); + } + return null; + } + + public static 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; + } +} diff --git a/src/com/magento/idea/magento2plugin/util/magento/FileBasedIndexUtil.java b/src/com/magento/idea/magento2plugin/util/magento/FileBasedIndexUtil.java new file mode 100644 index 000000000..cb12b3741 --- /dev/null +++ b/src/com/magento/idea/magento2plugin/util/magento/FileBasedIndexUtil.java @@ -0,0 +1,73 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.util.magento; + +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 com.magento.idea.magento2plugin.util.RegExUtil; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class FileBasedIndexUtil { + + public static Collection findViewVfsByModuleName(String moduleName, Project project) + { + Collection viewVfs = new ArrayList<>(); + + Pattern pattern = Pattern.compile(RegExUtil.Magento.MODULE_NAME); + Matcher matcher = pattern.matcher(moduleName); + if (!matcher.find()) { + return viewVfs; + } + + Collection moduleVfs = + FileBasedIndex.getInstance().getContainingFiles(ModuleNameIndex.KEY, moduleName, + GlobalSearchScope.getScopeRestrictedByFileTypes( + GlobalSearchScope.allScope(project), + PhpFileType.INSTANCE + ) + ); + + for (VirtualFile moduleVf : moduleVfs) { + viewVfs.addAll(getValues(moduleName, moduleVf, project)); + } + return viewVfs; + } + + public static Collection findViewVfsByModuleVf(VirtualFile moduleVf, Project project) + { + Collection viewVfs = new ArrayList<>(); + + for (String moduleName : FileBasedIndex.getInstance().getAllKeys(ModuleNameIndex.KEY, project)) { + viewVfs.addAll(getValues(moduleName, moduleVf, project)); + } + return viewVfs; + } + + private static Collection getValues(String moduleName, VirtualFile moduleVf, Project project) + { + Collection viewVfs = new ArrayList<>(); + FileBasedIndex.getInstance() + .processValues( + ModuleNameIndex.KEY, moduleName, moduleVf, + (file, value) -> { + VirtualFile viewVf = file.getParent().findFileByRelativePath(value.concat("/view")); + if (viewVf != null) { + viewVfs.add(viewVf); + } + return false; + }, + GlobalSearchScope.fileScope(project, moduleVf) + ); + return viewVfs; + } +} diff --git a/src/com/magento/idea/magento2plugin/xml/XmlHelperUtility.java b/src/com/magento/idea/magento2plugin/xml/XmlHelperUtility.java deleted file mode 100644 index ecb5e635f..000000000 --- a/src/com/magento/idea/magento2plugin/xml/XmlHelperUtility.java +++ /dev/null @@ -1,106 +0,0 @@ -package com.magento.idea.magento2plugin.xml; - -import com.intellij.patterns.*; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; -import com.intellij.psi.xml.XmlTag; -import org.jetbrains.annotations.Nullable; - -/** - * Created by dkvashnin on 11/2/15. - */ -public class XmlHelperUtility { - public static PsiFilePattern.Capture getXmlFilePattern(@Nullable String fileName) { - if (fileName == null) { - return getXmlFilePattern(); - } - - return XmlPatterns.psiFile() - .withName(XmlPatterns.string().equalTo(fileName + ".xml")); - } - - public static PsiFilePattern.Capture getXmlFilePattern() { - return XmlPatterns.psiFile() - .withName(XmlPatterns.string().endsWith(".xml")); - } - - public static PsiElementPattern.Capture getInsideTagPattern(String insideTagName) { - return XmlPatterns.psiElement(XmlTag.class).withName(insideTagName); - } - - /** - * - */ - public static XmlAttributeValuePattern getTagAttributeValuePattern(String tagName, String attributeName, String fileType) { - return XmlPatterns - .xmlAttributeValue() - .withParent( - XmlPatterns - .xmlAttribute(attributeName) - .withParent( - XmlPatterns - .xmlTag() - .withName(tagName) - ) - ).inside( - getInsideTagPattern(tagName) - ).inFile(getXmlFilePattern(fileType)); - } - - /** - * - */ - public static XmlAttributeValuePattern getTagAttributeValuePattern(String tagName, String attributeName) { - return XmlPatterns - .xmlAttributeValue() - .withParent( - XmlPatterns - .xmlAttribute(attributeName) - .withParent( - XmlPatterns - .xmlTag() - .withName(tagName) - ) - ).inside( - getInsideTagPattern(tagName) - ).inFile(getXmlFilePattern()); - } - - /** - * - */ - public static PsiElementPattern.Capture getTagAttributePattern(String tag, String attributeName, String fileName) { - return XmlPatterns - .psiElement() - .inside(XmlPatterns - .xmlAttributeValue() - .inside(XmlPatterns - .xmlAttribute() - .withName(attributeName) - .withParent(XmlPatterns - .xmlTag() - .withName(tag) - ) - ) - ).inFile(getXmlFilePattern(fileName)); - } - - /** - * - */ - public static PsiElementPattern.Capture getTagAttributePattern(String tag, String attributeName) { - return XmlPatterns - .psiElement() - .inside(XmlPatterns - .xmlAttributeValue() - .inside(XmlPatterns - .xmlAttribute() - .withName(attributeName) - .withParent(XmlPatterns - .xmlTag() - .withName(tag) - ) - ) - ).inFile(getXmlFilePattern()); - } -} diff --git a/src/com/magento/idea/magento2plugin/xml/XmlPsiTreeUtil.java b/src/com/magento/idea/magento2plugin/xml/XmlPsiTreeUtil.java new file mode 100644 index 000000000..7f5779ab4 --- /dev/null +++ b/src/com/magento/idea/magento2plugin/xml/XmlPsiTreeUtil.java @@ -0,0 +1,55 @@ +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.xml; + +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.xml.*; +import gnu.trove.THashSet; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; + +public class XmlPsiTreeUtil { + + @Nullable + public static XmlTag getTypeTagOfArgument(XmlElement psiArgumentValueElement) { + + XmlTag argumentTag = PsiTreeUtil.getParentOfType(psiArgumentValueElement, XmlTag.class); + XmlTag argumentsTag = PsiTreeUtil.getParentOfType(argumentTag, XmlTag.class); + return PsiTreeUtil.getParentOfType(argumentsTag, XmlTag.class); + } + + public static Collection findAttributeValueElements(XmlFile xmlFile, + String tagName, + String attributeName) { + Collection psiElements = new THashSet<>(); + + + XmlTag rootTag = xmlFile.getRootTag(); + if (rootTag == null) { + return psiElements; + } + + for (XmlTag tag: rootTag.findSubTags(tagName)) { + if (tag != null) { + XmlAttribute attribute = tag.getAttribute(attributeName); + if (attribute != null && attribute.getValueElement() != null) { + psiElements.add(attribute.getValueElement()); + } + } + }; + + return psiElements; + } + + public static Collection findAttributeValueElements(XmlFile xmlFile, + String tagName, + String attributeName, + String value) { + Collection psiElements = findAttributeValueElements(xmlFile, tagName, attributeName); + psiElements.removeIf(e -> e.getValue() == null || !e.getValue().equals(value)); + return psiElements; + } +} diff --git a/src/com/magento/idea/magento2plugin/xml/completion/ClassCompletionProvider.java b/src/com/magento/idea/magento2plugin/xml/completion/ClassCompletionProvider.java deleted file mode 100644 index 327a4ee31..000000000 --- a/src/com/magento/idea/magento2plugin/xml/completion/ClassCompletionProvider.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.magento.idea.magento2plugin.xml.completion; - -import com.intellij.codeInsight.completion.impl.CamelHumpMatcher; -import com.intellij.codeInsight.lookup.LookupElement; -import com.intellij.codeInsight.lookup.LookupElementBuilder; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.psi.PsiElement; -import com.jetbrains.php.PhpIcons; -import com.jetbrains.php.PhpIndex; -import com.jetbrains.php.lang.psi.elements.PhpClass; -import com.magento.idea.magento2plugin.util.PsiContextMatcherI; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -/** - * Created by dkvashnin on 11/17/15. - */ -public class ClassCompletionProvider implements CompletionProviderI { - public final static ClassCompletionProvider INSTANCE = new ClassCompletionProvider(); - - @Override - public List collectCompletionResult(PsiElement psiElement, @Nullable PsiContextMatcherI context) { - List result = new ArrayList<>(); - PhpIndex phpIndex = PhpIndex.getInstance(psiElement.getProject()); - String prefix = StringUtil.unquoteString(psiElement.getText()); - - Collection classNames = phpIndex.getAllClassNames(new CamelHumpMatcher(prefix)); - - for (String className: classNames) { - Collection classesByName = phpIndex.getClassesByName(className); - for (PhpClass phpClass: classesByName) { - if (context != null && !context.match(phpClass)) { - continue; - } - - String classFqn = phpClass.getPresentableFQN(); - - result.add( - LookupElementBuilder - .create(classFqn) - .withIcon(PhpIcons.CLASS_ICON) - ); - } - } - - return result; - } - - @Override - public List collectCompletionResult(PsiElement psiElement) { - return collectCompletionResult(psiElement, null); - } -} diff --git a/src/com/magento/idea/magento2plugin/xml/completion/CompletionProviderI.java b/src/com/magento/idea/magento2plugin/xml/completion/CompletionProviderI.java deleted file mode 100644 index 09348290d..000000000 --- a/src/com/magento/idea/magento2plugin/xml/completion/CompletionProviderI.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.magento.idea.magento2plugin.xml.completion; - -import com.intellij.codeInsight.lookup.LookupElement; -import com.intellij.psi.PsiElement; -import com.magento.idea.magento2plugin.util.PsiContextMatcherI; -import org.jetbrains.annotations.Nullable; - -import java.util.List; - -/** - * Created by dkvashnin on 11/17/15. - */ -public interface CompletionProviderI { - public List collectCompletionResult(PsiElement psiElement, @Nullable PsiContextMatcherI context); - - public List collectCompletionResult(PsiElement psiElement); -} diff --git a/src/com/magento/idea/magento2plugin/xml/completion/InterfaceCompletionProvider.java b/src/com/magento/idea/magento2plugin/xml/completion/InterfaceCompletionProvider.java deleted file mode 100644 index 63dfe4f2d..000000000 --- a/src/com/magento/idea/magento2plugin/xml/completion/InterfaceCompletionProvider.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.magento.idea.magento2plugin.xml.completion; - -import com.intellij.codeInsight.lookup.LookupElement; -import com.intellij.codeInsight.lookup.LookupElementBuilder; -import com.intellij.psi.PsiElement; -import com.jetbrains.php.PhpIcons; -import com.jetbrains.php.PhpIndex; -import com.jetbrains.php.lang.psi.elements.PhpClass; -import com.magento.idea.magento2plugin.util.PsiContextMatcherI; -import org.apache.commons.lang.StringUtils; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -/** - * Created by mslabko on 18.12.2015. - */ -public class InterfaceCompletionProvider implements CompletionProviderI { - public final static InterfaceCompletionProvider INSTANCE = new InterfaceCompletionProvider(); - - @Override - public List collectCompletionResult(PsiElement psiElement, @Nullable PsiContextMatcherI context) { - List result = new ArrayList<>(); - PhpIndex phpIndex = PhpIndex.getInstance(psiElement.getProject()); - String input = StringUtils.strip(psiElement.getText(), "\""); - - Collection interfaceNames = phpIndex.getAllInterfaceNames(); - - for (String interfaceName: interfaceNames) { - if (!interfaceName.toLowerCase().contains(input.toLowerCase())) { - continue; - } - - Collection classesByName = phpIndex.getInterfacesByName(interfaceName); - for (PhpClass phpClass: classesByName) { - if (context != null && !context.match(phpClass)) { - continue; - } - - String classFqn = phpClass.getPresentableFQN(); - - result.add( - LookupElementBuilder - .create(classFqn) - .withIcon(PhpIcons.INTERFACE_ICON) - ); - } - } - - return result; - } - - @Override - public List collectCompletionResult(PsiElement psiElement) { - return collectCompletionResult(psiElement, null); - } -} diff --git a/src/com/magento/idea/magento2plugin/xml/completion/VirtualTypeCompletionProvider.java b/src/com/magento/idea/magento2plugin/xml/completion/VirtualTypeCompletionProvider.java deleted file mode 100644 index 82d51b4b0..000000000 --- a/src/com/magento/idea/magento2plugin/xml/completion/VirtualTypeCompletionProvider.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.magento.idea.magento2plugin.xml.completion; - -import com.intellij.codeInsight.lookup.LookupElement; -import com.intellij.codeInsight.lookup.LookupElementBuilder; -import com.intellij.psi.PsiElement; -import com.magento.idea.magento2plugin.util.PsiContextMatcherI; -import com.magento.idea.magento2plugin.xml.di.index.VirtualTypesNamesFileBasedIndex; -import org.apache.commons.lang.StringUtils; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by dkvashnin on 11/17/15. - */ -public class VirtualTypeCompletionProvider implements CompletionProviderI { - public final static VirtualTypeCompletionProvider INSTANCE = new VirtualTypeCompletionProvider(); - - @Override - public List collectCompletionResult(PsiElement psiElement, @Nullable PsiContextMatcherI context) { - List result = new ArrayList<>(); - String input = StringUtils.strip(psiElement.getText(), "\""); - String[] allVirtualTypesNames = VirtualTypesNamesFileBasedIndex.getAllVirtualTypesNames( - psiElement.getProject() - ); - - for (String name: allVirtualTypesNames) { - if (name.toLowerCase().contains(input.toLowerCase())) { - if (context != null && !context.match(name)) { - continue; - } - - result.add(LookupElementBuilder.create(name)); - } - } - - return result; - } - - @Override - public List collectCompletionResult(PsiElement psiElement) { - return collectCompletionResult(psiElement, null); - } -} diff --git a/src/com/magento/idea/magento2plugin/xml/di/XmlHelper.java b/src/com/magento/idea/magento2plugin/xml/di/XmlHelper.java deleted file mode 100644 index 8149c0c29..000000000 --- a/src/com/magento/idea/magento2plugin/xml/di/XmlHelper.java +++ /dev/null @@ -1,116 +0,0 @@ -package com.magento.idea.magento2plugin.xml.di; - -import com.intellij.patterns.*; -import com.intellij.psi.PsiElement; -import com.intellij.psi.xml.XmlTokenType; -import com.magento.idea.magento2plugin.xml.XmlHelperUtility; - -/** - * Created by Warider on 17.08.2015. - */ -public class XmlHelper extends XmlHelperUtility { - public static final String FILE_TYPE = "di"; - - public static final String TYPE_TAG = "type"; - public static final String PLUGIN_TAG = "plugin"; - public static final String VIRTUAL_TYPE_TAG = "virtualType"; - public static final String PREFERENCE_TAG = "preference"; - public static final String ARGUMENT_TAG = "argument"; - public static final String ARGUMENTS_TAG = "arguments"; - - public static final String NAME_ATTRIBUTE = "name"; - public static final String TYPE_ATTRIBUTE = "type"; - public static final String FOR_ATTRIBUTE = "for"; - - public static final String OBJECT_TYPE = "object"; - public static final String STRING_TYPE = "string"; - public static final String CONST_TYPE = "const"; - public static final String INIT_TYPE = "init_parameter"; - - - /** - * - */ - public static XmlAttributeValuePattern getDiTypePattern() { - return getTagAttributeValuePattern(TYPE_TAG, NAME_ATTRIBUTE, FILE_TYPE); - } - - /** - * - */ - public static XmlAttributeValuePattern getPluginTypePattern() { - return getTagAttributeValuePattern(PLUGIN_TAG, TYPE_ATTRIBUTE, FILE_TYPE); - } - - /** - * - */ - public static XmlAttributeValuePattern getDiPreferenceTypePattern() { - return getTagAttributeValuePattern(PREFERENCE_TAG, TYPE_ATTRIBUTE, FILE_TYPE); - } - - /** - * - */ - public static XmlAttributeValuePattern getDiPreferenceForPattern() { - return getTagAttributeValuePattern(PREFERENCE_TAG, FOR_ATTRIBUTE, FILE_TYPE); - } - - /** - * - */ - public static XmlAttributeValuePattern getDiVirtualTypePattern() { - return getTagAttributeValuePattern(VIRTUAL_TYPE_TAG, TYPE_ATTRIBUTE, FILE_TYPE); - } - - - /** - * - */ - public static XmlAttributeValuePattern getArgumentNamePattern() { - return getTagAttributeValuePattern(ARGUMENT_TAG, NAME_ATTRIBUTE, FILE_TYPE); - } - - /** - * \Namespace\Class - * @param typeName Type name - */ - public static PsiElementPattern.Capture getArgumentValuePatternForType(String typeName) { - return XmlPatterns - .psiElement(XmlTokenType.XML_DATA_CHARACTERS) - .withParent( - XmlPatterns - .xmlText() - .withParent(XmlPatterns - .xmlTag() - .withName("argument") - .withAttributeValue("xsi:type", typeName) - ) - ).inFile(XmlHelper.getXmlFilePattern(FILE_TYPE)); - } - - /** - * \Namespace\Class - * @param typeName Type name - */ - public static PsiElementPattern.Capture getItemValuePatternForType(String typeName) { - return XmlPatterns - .psiElement(XmlTokenType.XML_DATA_CHARACTERS) - .withParent( - XmlPatterns - .xmlText() - .withParent(XmlPatterns - .xmlTag() - .withName("item") - .withAttributeValue("xsi:type", typeName) - ) - ).inFile(XmlHelper.getXmlFilePattern(FILE_TYPE)); - } - - /** - * - */ - public static PsiElementPattern.Capture getTagAttributePattern(String tag, String attributeName) { - return getTagAttributePattern(tag, attributeName, FILE_TYPE); - } -} diff --git a/src/com/magento/idea/magento2plugin/xml/di/completion/DiCompletionContributor.java b/src/com/magento/idea/magento2plugin/xml/di/completion/DiCompletionContributor.java deleted file mode 100644 index 0d8357437..000000000 --- a/src/com/magento/idea/magento2plugin/xml/di/completion/DiCompletionContributor.java +++ /dev/null @@ -1,192 +0,0 @@ -package com.magento.idea.magento2plugin.xml.di.completion; - -import com.intellij.codeInsight.completion.*; -import com.intellij.patterns.XmlPatterns; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiReference; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.psi.xml.XmlAttribute; -import com.intellij.psi.xml.XmlAttributeValue; -import com.intellij.psi.xml.XmlTag; -import com.intellij.util.ProcessingContext; -import com.jetbrains.php.PhpIndex; -import com.jetbrains.php.lang.psi.elements.Parameter; -import com.jetbrains.php.lang.psi.elements.PhpClass; -import com.magento.idea.magento2plugin.xml.completion.ClassCompletionProvider; -import com.magento.idea.magento2plugin.xml.completion.CompletionProviderI; -import com.magento.idea.magento2plugin.xml.completion.InterfaceCompletionProvider; -import com.magento.idea.magento2plugin.xml.completion.VirtualTypeCompletionProvider; -import com.magento.idea.magento2plugin.xml.di.XmlHelper; -import com.magento.idea.magento2plugin.xml.util.ParentTypeMatcher; -import com.magento.idea.magento2plugin.xml.util.VirtualTypeParentMatcher; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; - -/** - * Created by dkvashnin on 10/15/15. - */ -public class DiCompletionContributor extends CompletionContributor { - private CompletionProviderI[] completionProviders = new CompletionProviderI[] { - ClassCompletionProvider.INSTANCE, - VirtualTypeCompletionProvider.INSTANCE - }; - - public DiCompletionContributor() { - extend(CompletionType.BASIC, - XmlPatterns.or( - XmlHelper.getItemValuePatternForType(XmlHelper.OBJECT_TYPE), - XmlHelper.getItemValuePatternForType(XmlHelper.STRING_TYPE), - XmlHelper.getTagAttributePattern(XmlHelper.TYPE_TAG, XmlHelper.NAME_ATTRIBUTE), - XmlHelper.getTagAttributePattern(XmlHelper.VIRTUAL_TYPE_TAG, XmlHelper.TYPE_ATTRIBUTE), - XmlHelper.getTagAttributePattern(XmlHelper.PLUGIN_TAG, XmlHelper.TYPE_ATTRIBUTE) - ), - new CompletionProvider() { - public void addCompletions(@NotNull CompletionParameters parameters, - ProcessingContext context, - @NotNull CompletionResultSet resultSet) { - PsiElement psiElement = parameters.getOriginalPosition(); - for (CompletionProviderI completionProvider: completionProviders) { - resultSet.addAllElements(completionProvider.collectCompletionResult(psiElement)); - } - } - } - ); - - extend( - CompletionType.BASIC, - XmlHelper.getTagAttributePattern(XmlHelper.PREFERENCE_TAG, XmlHelper.FOR_ATTRIBUTE), - new CompletionProvider() { - public void addCompletions(@NotNull CompletionParameters parameters, - ProcessingContext context, - @NotNull CompletionResultSet resultSet) { - PsiElement psiElement = parameters.getOriginalPosition(); - resultSet.addAllElements(InterfaceCompletionProvider.INSTANCE - .collectCompletionResult(psiElement) - ); - } - } - ); - - extend(CompletionType.BASIC, - XmlHelper.getTagAttributePattern(XmlHelper.PREFERENCE_TAG, XmlHelper.TYPE_ATTRIBUTE), - new CompletionProvider() { - public void addCompletions(@NotNull CompletionParameters parameters, - ProcessingContext context, - @NotNull CompletionResultSet resultSet) { - PsiElement psiElement = parameters.getOriginalPosition(); - PhpClass preferenceClass = getPreferenceClass(psiElement); - - if (preferenceClass == null) { - return; - } - - ParentTypeMatcher parentTypeMatcher = new ParentTypeMatcher(preferenceClass); - resultSet.addAllElements(ClassCompletionProvider.INSTANCE - .collectCompletionResult(psiElement, parentTypeMatcher) - ); - - resultSet.addAllElements(VirtualTypeCompletionProvider.INSTANCE - .collectCompletionResult( - psiElement, - new VirtualTypeParentMatcher(parentTypeMatcher, psiElement.getProject()) - ) - ); - } - } - ); - - extend(CompletionType.BASIC, - XmlHelper.getArgumentValuePatternForType(XmlHelper.OBJECT_TYPE), - new CompletionProvider() { - public void addCompletions(@NotNull CompletionParameters parameters, - ProcessingContext context, - @NotNull CompletionResultSet resultSet) { - PsiElement psiElement = parameters.getOriginalPosition(); - - PhpClass argumentClass = getArgumentClass(psiElement); - - if (argumentClass == null) { - return; - } - - ParentTypeMatcher parentTypeMatcher = new ParentTypeMatcher(argumentClass); - - resultSet.addAllElements(ClassCompletionProvider.INSTANCE - .collectCompletionResult(psiElement, parentTypeMatcher) - ); - - resultSet.addAllElements(VirtualTypeCompletionProvider.INSTANCE - .collectCompletionResult( - psiElement, - new VirtualTypeParentMatcher(parentTypeMatcher, psiElement.getProject()) - ) - ); - } - } - ); - } - - @Nullable - private PhpClass getPreferenceClass(PsiElement psiElement) { - XmlAttribute parentAttribute = PsiTreeUtil.getParentOfType(psiElement, XmlAttribute.class); - if (parentAttribute == null) { - return null; - } - - XmlTag xmlTag = parentAttribute.getParent(); - XmlAttribute preferenceAttr = xmlTag.getAttribute(XmlHelper.FOR_ATTRIBUTE); - if (preferenceAttr == null) { - return null; - } - - XmlAttributeValue valueElement = preferenceAttr.getValueElement(); - PsiReference reference = valueElement.getReference(); - if (reference == null) { - return null; - } - - PsiElement element = reference.resolve(); - if (element instanceof PhpClass) { - return (PhpClass) element; - } - - return null; - } - - @Nullable - private PhpClass getArgumentClass(PsiElement psiElement) { - XmlTag xmlTag = PsiTreeUtil.getParentOfType(psiElement, XmlTag.class); - if (xmlTag == null) { - return null; - } - - XmlAttribute preferenceAttr = xmlTag.getAttribute(XmlHelper.NAME_ATTRIBUTE); - if (preferenceAttr == null) { - return null; - } - - XmlAttributeValue valueElement = preferenceAttr.getValueElement(); - PsiReference reference = valueElement.getReference(); - if (reference == null) { - return null; - } - - PsiElement element = reference.resolve(); - if (element instanceof Parameter) { - String stringResolved = ((Parameter) element).getDeclaredType().toStringResolved(); - PhpIndex phpIndex = PhpIndex.getInstance(psiElement.getProject()); - - ArrayList result = new ArrayList<>(); - result.addAll(phpIndex.getClassesByFQN(stringResolved)); - result.addAll(phpIndex.getInterfacesByFQN(stringResolved)); - - if (result.size() > 0) { - return result.get(0); - } - } - - return null; - } -} diff --git a/src/com/magento/idea/magento2plugin/xml/di/index/TypeConfigurationFileBasedIndex.java b/src/com/magento/idea/magento2plugin/xml/di/index/TypeConfigurationFileBasedIndex.java deleted file mode 100644 index b4c72bc42..000000000 --- a/src/com/magento/idea/magento2plugin/xml/di/index/TypeConfigurationFileBasedIndex.java +++ /dev/null @@ -1,291 +0,0 @@ -package com.magento.idea.magento2plugin.xml.di.index; - -import com.intellij.ide.highlighter.XmlFileType; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiManager; -import com.intellij.psi.impl.source.xml.XmlDocumentImpl; -import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.psi.util.PsiTreeUtil; -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.jetbrains.php.lang.PhpLangUtil; -import com.jetbrains.php.lang.psi.elements.PhpClass; -import com.magento.idea.magento2plugin.Settings; -import com.magento.idea.magento2plugin.xml.di.XmlHelper; -import com.magento.idea.magento2plugin.xml.index.LineMarkerXmlTagDecorator; -import com.magento.idea.magento2plugin.xml.index.StringSetDataExternalizer; -import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.*; - -/** - * Created by dkvashnin on 11/15/15. - */ -public class TypeConfigurationFileBasedIndex extends ScalarIndexExtension { - public static final ID NAME = ID.create("com.magento.idea.magento2plugin.xml.di.index.type_configuration"); - private final EnumeratorStringDescriptor myKeyDescriptor = new EnumeratorStringDescriptor(); - - public static final Map TAG_ATTRIBUTE_RELATION = new HashMap() {{ - put(XmlHelper.TYPE_TAG, XmlHelper.NAME_ATTRIBUTE); - put(XmlHelper.PREFERENCE_TAG, XmlHelper.FOR_ATTRIBUTE); - put(XmlHelper.PLUGIN_TAG, XmlHelper.TYPE_ATTRIBUTE); - put(XmlHelper.VIRTUAL_TYPE_TAG, XmlHelper.TYPE_ATTRIBUTE); - }}; - - @Nullable - public static List getClassConfigurations(PhpClass phpClass) { - String classFqn = phpClass.getPresentableFQN(); - - Collection containingFiles = FileBasedIndex - .getInstance() - .getContainingFiles( - NAME, - classFqn, - GlobalSearchScope.allScope(phpClass.getProject()) - ); - - PsiManager psiManager = PsiManager.getInstance(phpClass.getProject()); - - List tags = new ArrayList(); - - for (VirtualFile virtualFile: containingFiles) { - XmlFile file = (XmlFile)psiManager.findFile(virtualFile); - - if (file == null) { - continue; - } - - XmlTag rootTag = file.getRootTag(); - fillRelatedTags(classFqn, rootTag, tags); - } - - return tags; - } - - private static void fillRelatedTags(String classFqn, XmlTag parentTag, List tagsReferences) { - for (XmlTag childTag: parentTag.getSubTags()) { - String tagName = childTag.getName(); - String attribute = TAG_ATTRIBUTE_RELATION.get(tagName); - if (attribute == null) { - continue; - } - - String className = childTag.getAttributeValue(attribute); - if (className != null && PhpLangUtil.toPresentableFQN(className).equals(classFqn)) { - tagsReferences.add(getLineMarkerDecorator(childTag)); - } - - // type tag has plugin tags - if (tagName.equals(XmlHelper.TYPE_TAG)) { - fillRelatedTags(classFqn, childTag, tagsReferences); - } - } - } - - /** - * Decorate tag with appropriate line marker decorator. - */ - @NotNull - private static XmlTag getLineMarkerDecorator(XmlTag tag) { - switch (tag.getName()) { - case XmlHelper.PREFERENCE_TAG: - return new DiPreferenceLineMarkerXmlTagDecorator(tag); - case XmlHelper.TYPE_TAG: - return new DiTypeLineMarkerXmlTagDecorator(tag); - case XmlHelper.PLUGIN_TAG: - return new DiPluginLineMarkerXmlTagDecorator(tag); - case XmlHelper.VIRTUAL_TYPE_TAG: - return new DiVirtualTypeLineMarkerXmlTagDecorator(tag); - default: - return tag; - } - } - - @NotNull - @Override - public ID getName() { - return NAME; - } - - @NotNull - @Override - public DataIndexer getIndexer() { - return new DataIndexer() { - @NotNull - @Override - public Map map(@NotNull FileContent fileContent) { - Map map = new HashMap<>(); - - PsiFile psiFile = fileContent.getPsiFile(); - if (!Settings.isEnabled(psiFile.getProject())) { - return map; - } - - XmlDocumentImpl document = PsiTreeUtil.getChildOfType(psiFile, XmlDocumentImpl.class); - if(document == null) { - return map; - } - - XmlTag xmlTags[] = PsiTreeUtil.getChildrenOfType(psiFile.getFirstChild(), XmlTag.class); - if(xmlTags == null) { - return map; - } - - for(XmlTag xmlTag: xmlTags) { - if(xmlTag.getName().equals("config")) { - processConfigurationTags(xmlTag, map); - } - } - - return map; - } - - private void processConfigurationTags(XmlTag parentTag, Map results) { - for (XmlTag childTag: parentTag.getSubTags()) { - String tagName = childTag.getName(); - - String attribute = TAG_ATTRIBUTE_RELATION.get(tagName); - if (attribute == null) { - continue; - } - - String className = childTag.getAttributeValue(attribute); - if (className != null) { - results.put(PhpLangUtil.toPresentableFQN(className), null); - } - - // type tag has plugin tags - if (tagName.equals(XmlHelper.TYPE_TAG)) { - processConfigurationTags(childTag, results); - } - } - } - }; - } - - @NotNull - @Override - public KeyDescriptor getKeyDescriptor() { - return myKeyDescriptor; - } - - @NotNull - @Override - public FileBasedIndex.InputFilter getInputFilter() { - return new FileBasedIndex.InputFilter() { - @Override - public boolean acceptInput(@NotNull VirtualFile file) { - return file.getFileType() == XmlFileType.INSTANCE && file.getNameWithoutExtension().equals("di"); - } - }; - } - - @Override - public boolean dependsOnFileContent() { - return true; - } - - @Override - public int getVersion() { - return 0; - } -} - -/** - * Decorator for XmlTag, which improves readability of "preference" node in configuration line marker. - */ -class DiPreferenceLineMarkerXmlTagDecorator extends LineMarkerXmlTagDecorator { - - public DiPreferenceLineMarkerXmlTagDecorator(XmlTag xmlTag) { - super(xmlTag); - } - - @NotNull - @Override - public String getDescription() { - String preference = xmlTag.getAttributeValue(XmlHelper.TYPE_ATTRIBUTE); - if (preference != null) { - return String.format("preference %s", preference); - } - return xmlTag.getName(); - } - - @Override - @NotNull - @NonNls - public String getName() { - String preference = xmlTag.getAttributeValue(XmlHelper.TYPE_ATTRIBUTE); - if (preference != null) { - return String.format("[%s] preference %s", getAreaName(), preference); - } - return xmlTag.getName(); - } -} - -/** - * Decorator for XmlTag, which improves readability of "type" node in configuration line marker. - */ -class DiTypeLineMarkerXmlTagDecorator extends LineMarkerXmlTagDecorator { - - public DiTypeLineMarkerXmlTagDecorator(XmlTag xmlTag) { - super(xmlTag); - } - - @NotNull - @Override - public String getDescription() { - return "type declaration"; - } -} - -/** - * Decorator for XmlTag, which improves readability of "plugin" node in configuration line marker. - */ -class DiPluginLineMarkerXmlTagDecorator extends LineMarkerXmlTagDecorator { - - public DiPluginLineMarkerXmlTagDecorator(XmlTag xmlTag) { - super(xmlTag); - } - - @NotNull - @Override - public String getDescription() { - XmlTag typeTag = xmlTag.getParentTag(); - if (typeTag == null) { - return xmlTag.getName(); - } - String type = typeTag.getAttributeValue(XmlHelper.NAME_ATTRIBUTE); - if (type == null) { - return xmlTag.getName(); - } - - return String.format("plugin for %s", type); - } -} - -/** - * Decorator for XmlTag, which improves readability of "virtualType" node in configuration line marker. - */ -class DiVirtualTypeLineMarkerXmlTagDecorator extends LineMarkerXmlTagDecorator { - - public DiVirtualTypeLineMarkerXmlTagDecorator(XmlTag xmlTag) { - super(xmlTag); - } - - @NotNull - @Override - public String getDescription() { - String type = xmlTag.getAttributeValue(XmlHelper.NAME_ATTRIBUTE); - if (type != null) { - return String.format("virtual type %s", type); - } - return xmlTag.getName(); - } -} diff --git a/src/com/magento/idea/magento2plugin/xml/di/index/VirtualTypesNamesFileBasedIndex.java b/src/com/magento/idea/magento2plugin/xml/di/index/VirtualTypesNamesFileBasedIndex.java deleted file mode 100644 index 447690ef3..000000000 --- a/src/com/magento/idea/magento2plugin/xml/di/index/VirtualTypesNamesFileBasedIndex.java +++ /dev/null @@ -1,148 +0,0 @@ -package com.magento.idea.magento2plugin.xml.di.index; - -import com.intellij.ide.highlighter.XmlFileType; -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.impl.source.xml.XmlDocumentImpl; -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.XmlFile; -import com.intellij.psi.xml.XmlTag; -import com.intellij.util.ArrayUtil; -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.*; - -/** - * Created by dkvashnin on 10/13/15. - */ -public class VirtualTypesNamesFileBasedIndex extends FileBasedIndexExtension { - public static final ID NAME = ID.create("com.magento.idea.magento2plugin.xml.di.index.virtual_types_names"); - private final EnumeratorStringDescriptor myKeyDescriptor = new EnumeratorStringDescriptor(); - private final MyDataIndexer myDataIndexer = new MyDataIndexer(); - - public static String[] getAllVirtualTypesNames(final Project project) { - final Collection allKeys = FileBasedIndex.getInstance().getAllKeys(NAME, project); - return ArrayUtil.toStringArray(allKeys); - } - - public static XmlAttributeValue[] getVirtualTypesByName(final Project project, final String name, final GlobalSearchScope scope) { - List xmlAttributeList = new ArrayList(); - - Collection virtualFileCollection = FileBasedIndex.getInstance().getContainingFiles(NAME, name, scope); - - for (VirtualFile virtualFile: virtualFileCollection) { - PsiManager psiManager = PsiManager.getInstance(project); - XmlFile xmlFile = (XmlFile)psiManager.findFile(virtualFile); - if (xmlFile == null) { - continue; - } - - XmlTag rootTag = xmlFile.getRootTag(); - if (rootTag == null) { - continue; - } - - for (XmlTag typeTag: rootTag.getSubTags()) { - if (typeTag.getName().equals("virtualType")) { - XmlAttribute nameAttribute = typeTag.getAttribute("name"); - if (nameAttribute != null) { - if (nameAttribute.getValue() != null && nameAttribute.getValue().equals(name)) - - xmlAttributeList.add(nameAttribute.getValueElement()); - } - } - } - } - - return xmlAttributeList.toArray(new XmlAttributeValue[xmlAttributeList.size()]); - } - - @NotNull - @Override - public ID getName() { - return NAME; - } - - @NotNull - @Override - public DataIndexer getIndexer() { - return myDataIndexer; - } - - @NotNull - @Override - public KeyDescriptor getKeyDescriptor() { - return myKeyDescriptor; - } - - @NotNull - @Override - public DataExternalizer getValueExternalizer() { - return EnumeratorStringDescriptor.INSTANCE; - } - - @NotNull - @Override - public FileBasedIndex.InputFilter getInputFilter() { - return new FileBasedIndex.InputFilter() { - @Override - public boolean acceptInput(@NotNull VirtualFile file) { - return file.getFileType() == XmlFileType.INSTANCE && file.getNameWithoutExtension().equals("di"); - } - }; - } - - @Override - public boolean dependsOnFileContent() { - return true; - } - - @Override - public int getVersion() { - return 1; - } - - private class MyDataIndexer implements DataIndexer { - - @NotNull - @Override - public Map map(@NotNull FileContent fileContent) { - Map map = new HashMap<>(); - - PsiFile psiFile = fileContent.getPsiFile(); - XmlDocumentImpl document = PsiTreeUtil.getChildOfType(psiFile, XmlDocumentImpl.class); - if(document == null) { - return map; - } - - XmlTag xmlTags[] = PsiTreeUtil.getChildrenOfType(psiFile.getFirstChild(), XmlTag.class); - if(xmlTags == null) { - return map; - } - - for(XmlTag xmlTag: xmlTags) { - if(xmlTag.getName().equals("config")) { - for(XmlTag typeNode: xmlTag.findSubTags("virtualType")) { - if (typeNode.getAttributeValue("name") != null && typeNode.getAttributeValue("type") != null) { - map.put( - typeNode.getAttributeValue("name"), - typeNode.getAttributeValue("type") - ); - } - } - } - } - - return map; - } - } -} diff --git a/src/com/magento/idea/magento2plugin/xml/di/reference/ArgumentNameReference.java b/src/com/magento/idea/magento2plugin/xml/di/reference/ArgumentNameReference.java deleted file mode 100644 index ab8bb4715..000000000 --- a/src/com/magento/idea/magento2plugin/xml/di/reference/ArgumentNameReference.java +++ /dev/null @@ -1,112 +0,0 @@ -package com.magento.idea.magento2plugin.xml.di.reference; - -import com.intellij.codeInsight.lookup.LookupElement; -import com.intellij.codeInsight.lookup.LookupElementBuilder; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiElementResolveResult; -import com.intellij.psi.PsiPolyVariantReferenceBase; -import com.intellij.psi.ResolveResult; -import com.intellij.psi.xml.XmlTag; -import com.jetbrains.php.PhpIcons; -import com.jetbrains.php.PhpIndex; -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.magento.idea.magento2plugin.xml.di.XmlHelper; -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -/** - * Created by dkvashnin on 10/18/15. - */ -public class ArgumentNameReference extends PsiPolyVariantReferenceBase { - private XmlTag typeTag; - private String typeName; - - public ArgumentNameReference(@NotNull PsiElement psiElement, @NotNull XmlTag typeTag, @NotNull String typeName) { - super(psiElement); - - this.typeTag = typeTag; - this.typeName = typeName; - } - - @NotNull - @Override - public ResolveResult[] multiResolve(boolean b) { - List list = new ArrayList(); - - String argumentName = StringUtil.unquoteString(getElement().getText()); - for (Parameter parameter: getParameters()) { - if (argumentName.equals(parameter.getName())) { - list.add(new PsiElementResolveResult(parameter)); - } - } - - return list.toArray(new ResolveResult[list.size()]); - } - - @NotNull - @Override - public Object[] getVariants() { - List variants = new ArrayList(); - List definedArguments = getAlreadyConfiguredArguments(); - - for (Parameter parameter: getParameters()) { - String argumentName = parameter.getName(); - if (definedArguments.contains(argumentName)) { - continue; - } - - variants.add( - LookupElementBuilder - .create(argumentName) - .withIcon(PhpIcons.PARAMETER) - .withTypeText(parameter.getDeclaredType().toStringResolved()) - ); - } - - return variants.toArray(); - } - - private List getParameters() { - List parameterList = new ArrayList(); - - PhpIndex phpIndex = PhpIndex.getInstance(getElement().getProject()); - Collection classesByFQN = phpIndex.getClassesByFQN(typeName); - - for (PhpClass phpClass: classesByFQN) { - Method constructor = phpClass.getConstructor(); - if (constructor == null) { - continue; - } - - Parameter[] parameters = constructor.getParameters(); - Collections.addAll(parameterList, parameters); - } - - return parameterList; - } - - private List getAlreadyConfiguredArguments() - { - List result = new ArrayList<>(); - - XmlTag argumentsTag = typeTag.findFirstSubTag(XmlHelper.ARGUMENTS_TAG); - if (argumentsTag == null) { - return result; - } - - for (XmlTag argumentTag: argumentsTag.findSubTags(XmlHelper.ARGUMENT_TAG)) { - result.add( - argumentTag.getAttributeValue(XmlHelper.NAME_ATTRIBUTE) - ); - } - - return result; - } -} diff --git a/src/com/magento/idea/magento2plugin/xml/di/reference/ConstantReference.java b/src/com/magento/idea/magento2plugin/xml/di/reference/ConstantReference.java deleted file mode 100644 index f34cf7714..000000000 --- a/src/com/magento/idea/magento2plugin/xml/di/reference/ConstantReference.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.magento.idea.magento2plugin.xml.di.reference; - -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiElementResolveResult; -import com.intellij.psi.PsiPolyVariantReferenceBase; -import com.intellij.psi.ResolveResult; -import com.jetbrains.php.PhpIndex; -import com.jetbrains.php.lang.PhpLangUtil; -import com.jetbrains.php.lang.psi.elements.Field; -import com.jetbrains.php.lang.psi.elements.PhpClass; -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -/** - * Created by dkvashnin on 10/22/15. - */ -public class ConstantReference extends PsiPolyVariantReferenceBase { - public ConstantReference(PsiElement psiElement) { - super(psiElement); - } - - @NotNull - @Override - public ResolveResult[] multiResolve(boolean b) { - PhpIndex phpIndex = PhpIndex.getInstance(getElement().getProject()); - List parts = StringUtil.split( - PhpLangUtil.toFQN( - StringUtil.unquoteString(getElement().getText()) - ), - "::" - ); - - if (parts.size() != 2) { - return new ResolveResult[0]; - } - - String className = parts.get(0); - String constantName = parts.get(1); - - List fields = new ArrayList(); - Collection classesAndInterfaces = new ArrayList<>(); - classesAndInterfaces.addAll(phpIndex.getClassesByFQN(className)); - classesAndInterfaces.addAll(phpIndex.getInterfacesByFQN(className)); - - for (PhpClass phpClass: classesAndInterfaces) { - for(Field field: phpClass.getFields()) { - if (field.isConstant() && field.getName().equals(constantName)) { - fields.add(new PsiElementResolveResult(field)); - } - } - } - - return fields.toArray(new ResolveResult[fields.size()]); - } - - @NotNull - @Override - public Object[] getVariants() { - return new Object[0]; - } -} diff --git a/src/com/magento/idea/magento2plugin/xml/di/reference/DiReferenceContributor.java b/src/com/magento/idea/magento2plugin/xml/di/reference/DiReferenceContributor.java deleted file mode 100644 index 65986886d..000000000 --- a/src/com/magento/idea/magento2plugin/xml/di/reference/DiReferenceContributor.java +++ /dev/null @@ -1,117 +0,0 @@ -package com.magento.idea.magento2plugin.xml.di.reference; - -import com.intellij.patterns.XmlPatterns; -import com.intellij.psi.*; -import com.intellij.util.ProcessingContext; -import com.magento.idea.magento2plugin.xml.di.XmlHelper; -import com.magento.idea.magento2plugin.xml.di.reference.provider.ArgumentNameReferenceProvider; -import com.magento.idea.magento2plugin.xml.di.reference.provider.DiInstanceReferenceProvider; -import com.magento.idea.magento2plugin.xml.reference.TypeReference; -import com.magento.idea.magento2plugin.xml.reference.util.ClassesResultsFiller; -import com.magento.idea.magento2plugin.xml.reference.util.InterfacesResultsFiller; -import com.magento.idea.magento2plugin.xml.reference.util.ResolveResultsFiller; -import com.magento.idea.magento2plugin.xml.reference.util.VirtualTypesResultsFiller; -import org.jetbrains.annotations.NotNull; - -/** - * Created by Warider on 17.08.2015. - */ -public class DiReferenceContributor extends PsiReferenceContributor { - private static final String OBJECT_TYPE_NAME = "object"; - private static final String CONST_TYPE_NAME = "const"; - private static final String INIT_TYPE_NAME = "init_parameter"; - - @Override - public void registerReferenceProviders(@NotNull PsiReferenceRegistrar psiReferenceRegistrar) { - // - psiReferenceRegistrar.registerReferenceProvider( - XmlHelper.getDiPreferenceForPattern(), - new DiInstanceReferenceProvider( - new ResolveResultsFiller[]{ - ClassesResultsFiller.INSTANCE, - InterfacesResultsFiller.INSTANCE - } - ) - ); - - // - psiReferenceRegistrar.registerReferenceProvider( - XmlHelper.getDiPreferenceTypePattern(), - new DiInstanceReferenceProvider( - new ResolveResultsFiller[]{ - ClassesResultsFiller.INSTANCE, - VirtualTypesResultsFiller.INSTANCE - } - ) - ); - - // - psiReferenceRegistrar.registerReferenceProvider( - XmlHelper.getDiTypePattern(), - new DiInstanceReferenceProvider( - new ResolveResultsFiller[]{ - ClassesResultsFiller.INSTANCE - } - ) - ); - - // - psiReferenceRegistrar.registerReferenceProvider( - XmlHelper.getDiVirtualTypePattern(), - new DiInstanceReferenceProvider( - new ResolveResultsFiller[]{ - ClassesResultsFiller.INSTANCE, - VirtualTypesResultsFiller.INSTANCE - } - ) - ); - - // SomeClassOrVirtualType - psiReferenceRegistrar.registerReferenceProvider( - XmlPatterns.or( - XmlHelper.getArgumentValuePatternForType(OBJECT_TYPE_NAME), - XmlHelper.getItemValuePatternForType(OBJECT_TYPE_NAME) - ), - new DiInstanceReferenceProvider( - new ResolveResultsFiller[]{ - ClassesResultsFiller.INSTANCE, - VirtualTypesResultsFiller.INSTANCE - } - ) - ); - - // - psiReferenceRegistrar.registerReferenceProvider( - XmlHelper.getArgumentNamePattern(), - new ArgumentNameReferenceProvider() - ); - - // SomeClass::SOME_CONSTANT - psiReferenceRegistrar.registerReferenceProvider( - XmlPatterns.or( - XmlHelper.getArgumentValuePatternForType(CONST_TYPE_NAME), - XmlHelper.getArgumentValuePatternForType(INIT_TYPE_NAME), - XmlHelper.getItemValuePatternForType(CONST_TYPE_NAME), - XmlHelper.getItemValuePatternForType(INIT_TYPE_NAME) - ), - new PsiReferenceProvider() { - @NotNull - @Override - public PsiReference[] getReferencesByElement(@NotNull PsiElement psiElement, @NotNull ProcessingContext processingContext) { - return new PsiReference[] {new ConstantReference(psiElement)}; - } - } - ); - - // - psiReferenceRegistrar.registerReferenceProvider( - XmlHelper.getPluginTypePattern(), - new DiInstanceReferenceProvider( - new ResolveResultsFiller[]{ - ClassesResultsFiller.INSTANCE, - VirtualTypesResultsFiller.INSTANCE - } - ) - ); - } -} diff --git a/src/com/magento/idea/magento2plugin/xml/di/reference/provider/ArgumentNameReferenceProvider.java b/src/com/magento/idea/magento2plugin/xml/di/reference/provider/ArgumentNameReferenceProvider.java deleted file mode 100644 index 8c6b52884..000000000 --- a/src/com/magento/idea/magento2plugin/xml/di/reference/provider/ArgumentNameReferenceProvider.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.magento.idea.magento2plugin.xml.di.reference.provider; - -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiReference; -import com.intellij.psi.PsiReferenceProvider; -import com.intellij.psi.xml.XmlAttributeValue; -import com.intellij.psi.xml.XmlTag; -import com.intellij.util.ProcessingContext; -import com.magento.idea.magento2plugin.xml.di.reference.ArgumentNameReference; -import com.magento.idea.magento2plugin.xml.di.reference.provider.resolver.ClassNameResolver; -import com.magento.idea.magento2plugin.xml.di.reference.provider.resolver.TypeTagResolver; -import com.magento.idea.magento2plugin.xml.di.reference.provider.resolver.VirtualTypeTagResolver; -import org.jetbrains.annotations.NotNull; - -/** - * Created by dkvashnin on 10/19/15. - */ -public class ArgumentNameReferenceProvider extends PsiReferenceProvider { - private static ClassNameResolver[] classNameResolvers = new ClassNameResolver[] { - TypeTagResolver.INSTANCE, - VirtualTypeTagResolver.INSTANCE - }; - - @NotNull - @Override - public PsiReference[] getReferencesByElement(@NotNull PsiElement psiElement, @NotNull ProcessingContext processingContext) { - if (!(psiElement instanceof XmlAttributeValue)) { - return new PsiReference[0]; - } - - for (ClassNameResolver classNameResolver: classNameResolvers) { - XmlTag typeTag = classNameResolver.findTypeTag(psiElement); - - if (typeTag == null) { - continue; - } - - String typeName = classNameResolver.resolveTypeName(typeTag); - if (typeName == null) { - continue; - } - - return new PsiReference[]{new ArgumentNameReference(psiElement, typeTag, typeName)}; - } - - return new PsiReference[0]; - } -} diff --git a/src/com/magento/idea/magento2plugin/xml/di/reference/provider/XmlReferenceProvider.java b/src/com/magento/idea/magento2plugin/xml/di/reference/provider/XmlReferenceProvider.java deleted file mode 100644 index 132dfab7b..000000000 --- a/src/com/magento/idea/magento2plugin/xml/di/reference/provider/XmlReferenceProvider.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.magento.idea.magento2plugin.xml.di.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.xml.reference.TypeReference; -import com.magento.idea.magento2plugin.xml.reference.util.ReferenceResultsFiller; -import org.jetbrains.annotations.NotNull; - -/** - * Created by Warider on 17.08.2015. - */ -public class XmlReferenceProvider extends PsiReferenceProvider { - private final ReferenceResultsFiller[] resultsFillers; - - public XmlReferenceProvider(ReferenceResultsFiller[] resultsFillers) { - super(); - this.resultsFillers = resultsFillers; - } - - @NotNull - @Override - public PsiReference[] getReferencesByElement(@NotNull PsiElement psiElement, @NotNull ProcessingContext processingContext) { - return new PsiReference[]{new TypeReference(psiElement, resultsFillers)}; - } -} diff --git a/src/com/magento/idea/magento2plugin/xml/di/reference/provider/resolver/ClassNameResolver.java b/src/com/magento/idea/magento2plugin/xml/di/reference/provider/resolver/ClassNameResolver.java deleted file mode 100644 index 4dca347dc..000000000 --- a/src/com/magento/idea/magento2plugin/xml/di/reference/provider/resolver/ClassNameResolver.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.magento.idea.magento2plugin.xml.di.reference.provider.resolver; - -import com.intellij.psi.PsiElement; -import com.intellij.psi.xml.XmlElement; -import com.intellij.psi.xml.XmlTag; -import org.jetbrains.annotations.Nullable; - -/** - * Created by dkvashnin on 10/19/15. - */ -public abstract class ClassNameResolver { - - public XmlTag findTypeTag(PsiElement psiElement) { - if (psiElement instanceof XmlTag && ((XmlTag) psiElement).getName().equals(getTagName())) { - return (XmlTag) psiElement; - } - - if (psiElement.getParent() == null || !(psiElement.getParent() instanceof XmlElement)) { - return null; - } - - return findTypeTag(psiElement.getParent()); - } - - @Nullable - abstract public String resolveTypeName(XmlTag xmlTag); - - abstract protected String getTagName(); -} diff --git a/src/com/magento/idea/magento2plugin/xml/di/reference/provider/resolver/TypeTagResolver.java b/src/com/magento/idea/magento2plugin/xml/di/reference/provider/resolver/TypeTagResolver.java deleted file mode 100644 index 4528cf864..000000000 --- a/src/com/magento/idea/magento2plugin/xml/di/reference/provider/resolver/TypeTagResolver.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.magento.idea.magento2plugin.xml.di.reference.provider.resolver; - -import com.intellij.psi.xml.XmlTag; -import com.magento.idea.magento2plugin.xml.di.XmlHelper; -import org.jetbrains.annotations.Nullable; - -/** - * Created by dkvashnin on 10/19/15. - */ -public class TypeTagResolver extends ClassNameResolver { - public static final TypeTagResolver INSTANCE = new TypeTagResolver(); - - private TypeTagResolver() {} - - @Nullable - @Override - public String resolveTypeName(XmlTag xmlTag) { - return xmlTag.getAttributeValue(XmlHelper.NAME_ATTRIBUTE); - } - - @Override - protected String getTagName() { - return XmlHelper.TYPE_TAG; - } -} diff --git a/src/com/magento/idea/magento2plugin/xml/di/reference/provider/resolver/VirtualTypeTagResolver.java b/src/com/magento/idea/magento2plugin/xml/di/reference/provider/resolver/VirtualTypeTagResolver.java deleted file mode 100644 index 1268d6bdc..000000000 --- a/src/com/magento/idea/magento2plugin/xml/di/reference/provider/resolver/VirtualTypeTagResolver.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.magento.idea.magento2plugin.xml.di.reference.provider.resolver; - -import com.intellij.psi.xml.XmlTag; -import com.intellij.util.indexing.FileBasedIndex; -import com.magento.idea.magento2plugin.xml.di.XmlHelper; -import com.magento.idea.magento2plugin.xml.di.index.VirtualTypesNamesFileBasedIndex; -import org.jetbrains.annotations.Nullable; - -/** - * Created by dkvashnin on 10/20/15. - */ -public class VirtualTypeTagResolver extends ClassNameResolver { - public static final VirtualTypeTagResolver INSTANCE = new VirtualTypeTagResolver(); - - private VirtualTypeTagResolver() {} - - @Nullable - @Override - public String resolveTypeName(XmlTag xmlTag) { - String parentTypeName = xmlTag.getAttributeValue(XmlHelper.TYPE_ATTRIBUTE); - - if (parentTypeName == null) { - return null; - } - - String superParentName = VirtualTypesNamesFileBasedIndex.getSuperParentTypeName(xmlTag.getProject(), parentTypeName); - - return superParentName == null ? parentTypeName : superParentName; - - } - - @Override - protected String getTagName() { - return XmlHelper.VIRTUAL_TYPE_TAG; - } -} diff --git a/src/com/magento/idea/magento2plugin/xml/index/LineMarkerXmlTagDecorator.java b/src/com/magento/idea/magento2plugin/xml/index/LineMarkerXmlTagDecorator.java index 7d6778f07..1def7014a 100644 --- a/src/com/magento/idea/magento2plugin/xml/index/LineMarkerXmlTagDecorator.java +++ b/src/com/magento/idea/magento2plugin/xml/index/LineMarkerXmlTagDecorator.java @@ -1,8 +1,11 @@ -package com.magento.idea.magento2plugin.xml.index; +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.xml; import com.intellij.lang.ASTNode; import com.intellij.lang.Language; -import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.TextRange; @@ -20,7 +23,6 @@ import com.intellij.util.IncorrectOperationException; import com.intellij.xml.XmlElementDescriptor; import com.intellij.xml.XmlNSDescriptor; -import com.magento.idea.magento2plugin.php.module.MagentoComponent; import com.magento.idea.magento2plugin.php.module.MagentoComponentManager; import com.magento.idea.magento2plugin.php.module.MagentoModule; import org.jetbrains.annotations.Contract; @@ -61,7 +63,7 @@ protected String getAreaName() { } @NotNull - protected String getComponentName() { + private String getComponentName() { MagentoComponentManager moduleManager = MagentoComponentManager.getInstance(project); MagentoModule module = moduleManager.getComponentOfTypeForFile(xmlTag.getContainingFile(), MagentoModule.class); diff --git a/src/com/magento/idea/magento2plugin/xml/layout/LayoutUtility.java b/src/com/magento/idea/magento2plugin/xml/layout/LayoutUtility.java deleted file mode 100644 index 0c2867b7d..000000000 --- a/src/com/magento/idea/magento2plugin/xml/layout/LayoutUtility.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.magento.idea.magento2plugin.xml.layout; - -import com.intellij.ide.highlighter.XmlFileType; -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.FilenameIndex; -import com.intellij.psi.xml.XmlFile; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -/** - * Created by dkvashnin on 11/22/15. - */ -public class LayoutUtility { - public static boolean isLayoutFile(VirtualFile virtualFile) { - VirtualFile parent = virtualFile.getParent(); - return virtualFile.getFileType() == XmlFileType.INSTANCE && parent.isDirectory() && parent.getName().endsWith("layout"); - } - - public static boolean isLayoutFile(PsiFile psiFile) { - VirtualFile virtualFile = psiFile.getOriginalFile().getVirtualFile(); - return isLayoutFile(virtualFile); - } - - public static List getLayoutFiles(Project project, @Nullable String fileName) { - List results = new ArrayList(); - Collection xmlFiles = FilenameIndex.getAllFilesByExt(project, "xml"); - - PsiManager psiManager = PsiManager.getInstance(project); - for (VirtualFile xmlFile: xmlFiles) { - if (LayoutUtility.isLayoutFile(xmlFile)) { - if (fileName != null && !xmlFile.getNameWithoutExtension().equals(fileName)) { - continue; - } - - PsiFile file = psiManager.findFile(xmlFile); - if (file != null) { - results.add((XmlFile)file); - } - } - } - - return results; - } - - public static List getLayoutFiles(Project project) { - return getLayoutFiles(project, null); - } -} diff --git a/src/com/magento/idea/magento2plugin/xml/layout/completion/LayoutCompletionContributor.java b/src/com/magento/idea/magento2plugin/xml/layout/completion/LayoutCompletionContributor.java deleted file mode 100644 index 4272d091f..000000000 --- a/src/com/magento/idea/magento2plugin/xml/layout/completion/LayoutCompletionContributor.java +++ /dev/null @@ -1,99 +0,0 @@ -package com.magento.idea.magento2plugin.xml.layout.completion; - -import com.intellij.codeInsight.completion.*; -import com.intellij.codeInsight.lookup.LookupElementBuilder; -import com.intellij.openapi.project.Project; -import com.intellij.patterns.XmlPatterns; -import com.intellij.psi.PsiElement; -import com.intellij.psi.xml.XmlFile; -import com.intellij.util.ProcessingContext; -import com.magento.idea.magento2plugin.php.util.ImplementationMatcher; -import com.magento.idea.magento2plugin.php.util.MagentoTypes; -import com.magento.idea.magento2plugin.xml.XmlHelperUtility; -import com.magento.idea.magento2plugin.xml.completion.ClassCompletionProvider; -import com.magento.idea.magento2plugin.xml.completion.VirtualTypeCompletionProvider; -import com.magento.idea.magento2plugin.xml.layout.LayoutUtility; -import com.magento.idea.magento2plugin.xml.layout.index.BlockFileBasedIndex; -import com.magento.idea.magento2plugin.xml.layout.index.ContainerFileBasedIndex; -import org.jetbrains.annotations.NotNull; - -/** - * Created by dkvashnin on 11/18/15. - */ -public class LayoutCompletionContributor extends CompletionContributor { - private ReferenceComponentCompletionProvider containerCompletionProvider = new ReferenceComponentCompletionProvider(ContainerFileBasedIndex.NAME); - private ReferenceComponentCompletionProvider blockCompletionProvider = new ReferenceComponentCompletionProvider(BlockFileBasedIndex.NAME); - - - public LayoutCompletionContributor() { - extend( - CompletionType.BASIC, - XmlHelperUtility.getTagAttributePattern("block", "class"), - new CompletionProvider() { - @Override - protected void addCompletions(@NotNull CompletionParameters completionParameters, ProcessingContext processingContext, @NotNull CompletionResultSet completionResultSet) { - PsiElement psiElement = completionParameters.getOriginalPosition(); - ImplementationMatcher completionContext = new ImplementationMatcher(MagentoTypes.BLOCK_TYPE); - completionResultSet.addAllElements( - ClassCompletionProvider.INSTANCE.collectCompletionResult(psiElement, completionContext) - ); - - completionResultSet.addAllElements( - VirtualTypeCompletionProvider.INSTANCE.collectCompletionResult(psiElement) - ); - } - } - ); - - extend( - CompletionType.BASIC, - XmlHelperUtility.getTagAttributePattern("referenceContainer", "name"), - new CompletionProvider() { - @Override - protected void addCompletions(@NotNull CompletionParameters completionParameters, ProcessingContext processingContext, @NotNull CompletionResultSet completionResultSet) { - PsiElement psiElement = completionParameters.getOriginalPosition(); - completionResultSet.addAllElements(containerCompletionProvider.collectCompletionResult(psiElement)); - } - } - ); - - extend( - CompletionType.BASIC, - XmlPatterns.or( - XmlHelperUtility.getTagAttributePattern("referenceBlock", "name"), - XmlHelperUtility.getTagAttributePattern("block", "before"), - XmlHelperUtility.getTagAttributePattern("block", "after"), - XmlHelperUtility.getTagAttributePattern("remove", "name"), - XmlHelperUtility.getTagAttributePattern("move", "element"), - XmlHelperUtility.getTagAttributePattern("move", "destination"), - XmlHelperUtility.getTagAttributePattern("move", "before"), - XmlHelperUtility.getTagAttributePattern("move", "after") - ), - new CompletionProvider() { - @Override - protected void addCompletions(@NotNull CompletionParameters completionParameters, ProcessingContext processingContext, @NotNull CompletionResultSet completionResultSet) { - PsiElement psiElement = completionParameters.getOriginalPosition(); - completionResultSet.addAllElements(blockCompletionProvider.collectCompletionResult(psiElement)); - } - } - ); - - extend( - CompletionType.BASIC, - XmlHelperUtility.getTagAttributePattern("update", "handle"), - new CompletionProvider() { - @Override - protected void addCompletions(@NotNull CompletionParameters completionParameters, ProcessingContext processingContext, @NotNull CompletionResultSet completionResultSet) { - PsiElement psiElement = completionParameters.getOriginalPosition(); - Project project = psiElement.getProject(); - for (XmlFile xmlFile: LayoutUtility.getLayoutFiles(project)) { - completionResultSet.addElement( - LookupElementBuilder.create(xmlFile.getVirtualFile().getNameWithoutExtension()) - ); - } - } - } - ); - } - -} diff --git a/src/com/magento/idea/magento2plugin/xml/layout/completion/ReferenceComponentCompletionProvider.java b/src/com/magento/idea/magento2plugin/xml/layout/completion/ReferenceComponentCompletionProvider.java deleted file mode 100644 index ca6daaf67..000000000 --- a/src/com/magento/idea/magento2plugin/xml/layout/completion/ReferenceComponentCompletionProvider.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.magento.idea.magento2plugin.xml.layout.completion; - -import com.intellij.codeInsight.lookup.LookupElement; -import com.intellij.codeInsight.lookup.LookupElementBuilder; -import com.intellij.psi.PsiElement; -import com.intellij.util.indexing.ID; -import com.jetbrains.php.PhpIcons; -import com.magento.idea.magento2plugin.util.PsiContextMatcherI; -import com.magento.idea.magento2plugin.xml.completion.CompletionProviderI; -import com.magento.idea.magento2plugin.xml.layout.index.util.LayoutIndexUtility; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -/** - * Created by dkvashnin on 11/18/15. - */ -public class ReferenceComponentCompletionProvider implements CompletionProviderI { - private ID indexId; - - public ReferenceComponentCompletionProvider(ID indexId) { - this.indexId = indexId; - } - - @Override - public List collectCompletionResult(PsiElement psiElement, @Nullable PsiContextMatcherI context) { - Collection keys = LayoutIndexUtility.getAllKeys(indexId, psiElement.getProject()); - - List results = new ArrayList<>(); - for (String key: keys) { - results.add( - LookupElementBuilder.create(key).withIcon(PhpIcons.XML_TAG_ICON) - ); - } - - return results; - } - - @Override - public List collectCompletionResult(PsiElement psiElement) { - return collectCompletionResult(psiElement, null); - } -} diff --git a/src/com/magento/idea/magento2plugin/xml/layout/index/AbstractComponentNameFileBasedIndex.java b/src/com/magento/idea/magento2plugin/xml/layout/index/AbstractComponentNameFileBasedIndex.java deleted file mode 100644 index 6cb598d14..000000000 --- a/src/com/magento/idea/magento2plugin/xml/layout/index/AbstractComponentNameFileBasedIndex.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.magento.idea.magento2plugin.xml.layout.index; - -import com.intellij.ide.highlighter.XmlFileType; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.PsiManager; -import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.psi.xml.XmlFile; -import com.intellij.psi.xml.XmlTag; -import com.intellij.util.indexing.*; -import com.intellij.util.io.EnumeratorStringDescriptor; -import com.intellij.util.io.KeyDescriptor; -import com.magento.idea.magento2plugin.xml.layout.LayoutUtility; -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -/** - * Created by dkvashnin on 11/18/15. - */ -public abstract class AbstractComponentNameFileBasedIndex extends ScalarIndexExtension { - private EnumeratorStringDescriptor myKeyDescriptor = new EnumeratorStringDescriptor(); - - @NotNull - @Override - public KeyDescriptor getKeyDescriptor() { - return myKeyDescriptor; - } - - @NotNull - @Override - public FileBasedIndex.InputFilter getInputFilter() { - return new FileBasedIndex.InputFilter() { - @Override - public boolean acceptInput(@NotNull VirtualFile virtualFile) { - return LayoutUtility.isLayoutFile(virtualFile); - } - }; - } - - @Override - public boolean dependsOnFileContent() { - return true; - } - - @Override - public int getVersion() { - return 0; - } -} diff --git a/src/com/magento/idea/magento2plugin/xml/layout/index/BlockClassFileBasedIndex.java b/src/com/magento/idea/magento2plugin/xml/layout/index/BlockClassFileBasedIndex.java deleted file mode 100644 index cfc9766f2..000000000 --- a/src/com/magento/idea/magento2plugin/xml/layout/index/BlockClassFileBasedIndex.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.magento.idea.magento2plugin.xml.layout.index; - -import com.intellij.util.indexing.DataIndexer; -import com.intellij.util.indexing.FileContent; -import com.intellij.util.indexing.ID; -import org.jetbrains.annotations.NotNull; - -/** - * Created by dkvashnin on 11/20/15. - */ -public class BlockClassFileBasedIndex extends AbstractComponentNameFileBasedIndex { - public static final ID NAME = ID.create("com.magento.idea.magento2plugin.xml.layout.index.block_class"); - - @NotNull - @Override - public ID getName() { - return NAME; - } - - @NotNull - @Override - public DataIndexer getIndexer() { - return new LayoutDataIndexer("block", "class"); - } -} diff --git a/src/com/magento/idea/magento2plugin/xml/layout/index/BlockFileBasedIndex.java b/src/com/magento/idea/magento2plugin/xml/layout/index/BlockFileBasedIndex.java deleted file mode 100644 index 7c2063309..000000000 --- a/src/com/magento/idea/magento2plugin/xml/layout/index/BlockFileBasedIndex.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.magento.idea.magento2plugin.xml.layout.index; - -import com.intellij.util.indexing.*; -import org.jetbrains.annotations.NotNull; - -/** - * Created by dkvashnin on 11/18/15. - */ -public class BlockFileBasedIndex extends AbstractComponentNameFileBasedIndex { - public static final ID NAME = ID.create("com.magento.idea.magento2plugin.xml.layout.index.block_name"); - - @NotNull - @Override - public ID getName() { - return NAME; - } - - @NotNull - @Override - public DataIndexer getIndexer() { - return new LayoutDataIndexer("block", "name"); - } -} diff --git a/src/com/magento/idea/magento2plugin/xml/layout/index/ContainerFileBasedIndex.java b/src/com/magento/idea/magento2plugin/xml/layout/index/ContainerFileBasedIndex.java deleted file mode 100644 index f6d4935a0..000000000 --- a/src/com/magento/idea/magento2plugin/xml/layout/index/ContainerFileBasedIndex.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.magento.idea.magento2plugin.xml.layout.index; - -import com.intellij.util.indexing.*; -import org.jetbrains.annotations.NotNull; - -/** - * Created by dkvashnin on 11/18/15. - */ -public class ContainerFileBasedIndex extends AbstractComponentNameFileBasedIndex { - public static final ID NAME = ID.create("com.magento.idea.magento2plugin.xml.layout.index.container_name"); - - @NotNull - @Override - public ID getName() { - return NAME; - } - - @NotNull - @Override - public DataIndexer getIndexer() { - return new LayoutDataIndexer("container", "name"); - } - - @Override - public int getVersion() { - return 1; - } -} \ No newline at end of file diff --git a/src/com/magento/idea/magento2plugin/xml/layout/index/LayoutDataIndexer.java b/src/com/magento/idea/magento2plugin/xml/layout/index/LayoutDataIndexer.java index c7869fc7d..852d98a89 100644 --- a/src/com/magento/idea/magento2plugin/xml/layout/index/LayoutDataIndexer.java +++ b/src/com/magento/idea/magento2plugin/xml/layout/index/LayoutDataIndexer.java @@ -1,30 +1,43 @@ -package com.magento.idea.magento2plugin.xml.layout.index; +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.stubs.indexes; import com.intellij.psi.PsiFile; -import com.intellij.psi.impl.source.xml.XmlDocumentImpl; 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.DataIndexer; import com.intellij.util.indexing.FileContent; -import com.jetbrains.php.lang.PhpLangUtil; -import com.magento.idea.magento2plugin.Settings; +import com.magento.idea.magento2plugin.project.Settings; import org.jetbrains.annotations.NotNull; import java.util.HashMap; import java.util.Map; +import java.util.function.Function; /** * Created by dkvashnin on 11/18/15. */ public class LayoutDataIndexer implements DataIndexer { private String indexTag; + private String indexAttribute; - public LayoutDataIndexer(String indexTag, String indexAttribute) { + private Function valueProcessor; + + LayoutDataIndexer(String indexTag, String indexAttribute) { this.indexTag = indexTag; this.indexAttribute = indexAttribute; } + LayoutDataIndexer(String indexTag, String indexAttribute, Function valueProcessor) { + this(indexTag, indexAttribute); + this.valueProcessor = valueProcessor; + } + @NotNull @Override public Map map(@NotNull FileContent fileContent) { @@ -35,13 +48,17 @@ public Map map(@NotNull FileContent fileContent) { return map; } - XmlDocumentImpl document = PsiTreeUtil.getChildOfType(psiFile, XmlDocumentImpl.class); - if(document == null) { + if (!(psiFile instanceof XmlFile)) { + return map; + } + + XmlDocument document = ((XmlFile) psiFile).getDocument(); + if (document == null) { return map; } XmlTag xmlTags[] = PsiTreeUtil.getChildrenOfType(psiFile.getFirstChild(), XmlTag.class); - if(xmlTags == null) { + if (xmlTags == null) { return map; } @@ -54,10 +71,11 @@ public Map map(@NotNull FileContent fileContent) { private void fillResultMap(XmlTag parentTag, Map resultMap) { for (XmlTag childTag: parentTag.getSubTags()) { - if (indexTag.equals(childTag.getName())) { - String attributeValue = childTag.getAttributeValue(this.indexAttribute); + if (childTag.getName().equals(indexTag)) { + String attributeValue = childTag.getAttributeValue(indexAttribute); if (attributeValue != null) { - resultMap.put(PhpLangUtil.toPresentableFQN(attributeValue), null); + attributeValue = valueProcessor != null ? valueProcessor.apply(attributeValue) : attributeValue; + resultMap.put(attributeValue, null); } } fillResultMap(childTag, resultMap); diff --git a/src/com/magento/idea/magento2plugin/xml/layout/index/util/LayoutIndexUtility.java b/src/com/magento/idea/magento2plugin/xml/layout/index/util/LayoutIndexUtility.java deleted file mode 100644 index a8f9798bb..000000000 --- a/src/com/magento/idea/magento2plugin/xml/layout/index/util/LayoutIndexUtility.java +++ /dev/null @@ -1,129 +0,0 @@ -package com.magento.idea.magento2plugin.xml.layout.index.util; - -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.PsiManager; -import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.psi.xml.XmlFile; -import com.intellij.psi.xml.XmlTag; -import com.intellij.util.indexing.FileBasedIndex; -import com.intellij.util.indexing.ID; -import com.jetbrains.php.lang.psi.elements.PhpClass; -import com.magento.idea.magento2plugin.xml.index.LineMarkerXmlTagDecorator; -import com.magento.idea.magento2plugin.xml.layout.index.BlockClassFileBasedIndex; -import com.magento.idea.magento2plugin.xml.layout.index.BlockFileBasedIndex; -import com.magento.idea.magento2plugin.xml.layout.index.ContainerFileBasedIndex; -import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -/** - * Created by dkvashnin on 11/20/15. - */ -public class LayoutIndexUtility { - public static List getComponentDeclarations(String componentValue, String componentType, ID id, Project project, ComponentMatcher componentMatcher) { - List results = new ArrayList(); - Collection containingFiles = FileBasedIndex.getInstance() - .getContainingFiles( - id, - componentValue, - GlobalSearchScope.allScope(project) - ); - PsiManager psiManager = PsiManager.getInstance(project); - - for (VirtualFile virtualFile: containingFiles) { - XmlFile xmlFile = (XmlFile)psiManager.findFile(virtualFile); - if (xmlFile == null) { - continue; - } - - XmlTag rootTag = xmlFile.getRootTag(); - if (rootTag == null) { - continue; - } - collectComponentDeclarations(rootTag, results, componentValue, componentType, componentMatcher); - } - - return results; - } - - public static Collection getAllKeys(ID id, Project project) { - return FileBasedIndex.getInstance().getAllKeys(id, project); - } - - public static void collectComponentDeclarations(XmlTag parentTag, List results, String componentName, String componentType, ComponentMatcher componentMatcher) { - for (XmlTag childTag: parentTag.getSubTags()) { - if (componentType.equals(childTag.getName()) && componentMatcher.matches(componentName, childTag)) { - results.add(childTag); - } else if(childTag.getSubTags().length > 0 ) { - collectComponentDeclarations(childTag, results, componentName, componentType, componentMatcher); - } - } - } - - public static List getBlockDeclarations(String componentName, Project project) { - return getComponentDeclarations(componentName, "block", BlockFileBasedIndex.NAME, project, new NameComponentMatcher()); - } - - public static List getContainerDeclarations(String componentName, Project project) { - return getComponentDeclarations(componentName, "container", ContainerFileBasedIndex.NAME, project, new NameComponentMatcher()); - } - - public static List getBlockClassDeclarations(PhpClass phpClass, Project project) { - String className = phpClass.getPresentableFQN(); - - List blockTags = getComponentDeclarations(className, "block", BlockClassFileBasedIndex.NAME, project, new ClassComponentMatcher()); - List decoratedBlockTags = new ArrayList<>(); - for (XmlTag blockTag: blockTags) { - decoratedBlockTags.add(new LayoutBlockLineMarkerXmlTagDecorator(blockTag)); - } - return decoratedBlockTags; - } -} - -interface ComponentMatcher { - boolean matches(String value, XmlTag tag); -} - -class NameComponentMatcher implements ComponentMatcher { - @Override - public boolean matches(String value, XmlTag tag) { - return value.equals(tag.getAttributeValue("name")); - } -} - -class ClassComponentMatcher implements ComponentMatcher { - @Override - public boolean matches(String value, XmlTag tag) { - return value.equals(tag.getAttributeValue("class")); - } -} - -/** - * Decorator for XmlTag, which improves readability of "block" node in configuration line marker. - */ -class LayoutBlockLineMarkerXmlTagDecorator extends LineMarkerXmlTagDecorator { - - public LayoutBlockLineMarkerXmlTagDecorator(XmlTag xmlTag) { - super(xmlTag); - } - - @NotNull - @Override - protected String getAreaName() { - return xmlTag.getContainingFile().getVirtualFile().getParent().getParent().getName(); - } - - @NotNull - @Override - public String getDescription() { - String name = xmlTag.getAttributeValue("name"); - if (name != null) { - return String.format("block %s", name); - } - return xmlTag.getName(); - } -} \ No newline at end of file diff --git a/src/com/magento/idea/magento2plugin/xml/layout/reference/LayoutReferenceContributor.java b/src/com/magento/idea/magento2plugin/xml/layout/reference/LayoutReferenceContributor.java deleted file mode 100644 index ccd1f1743..000000000 --- a/src/com/magento/idea/magento2plugin/xml/layout/reference/LayoutReferenceContributor.java +++ /dev/null @@ -1,105 +0,0 @@ -package com.magento.idea.magento2plugin.xml.layout.reference; - -import com.intellij.patterns.XmlPatterns; -import com.intellij.psi.*; -import com.intellij.util.ProcessingContext; -import com.magento.idea.magento2plugin.xml.XmlHelperUtility; -import com.magento.idea.magento2plugin.xml.di.reference.provider.XmlReferenceProvider; -import com.magento.idea.magento2plugin.xml.layout.LayoutUtility; -import com.magento.idea.magento2plugin.xml.layout.reference.fill.BlockResultsFiller; -import com.magento.idea.magento2plugin.xml.layout.reference.fill.ContainerResultsFiller; -import com.magento.idea.magento2plugin.xml.reference.TypeReference; -import com.magento.idea.magento2plugin.xml.reference.util.ClassesResultsFiller; -import com.magento.idea.magento2plugin.xml.reference.util.ReferenceResultsFiller; -import com.magento.idea.magento2plugin.xml.reference.util.VirtualTypesResultsFiller; -import org.jetbrains.annotations.NotNull; - -import java.util.Arrays; -import java.util.List; - -/** - * Created by dkvashnin on 11/18/15. - */ -public class LayoutReferenceContributor extends PsiReferenceContributor { - @Override - public void registerReferenceProviders(@NotNull PsiReferenceRegistrar psiReferenceRegistrar) { - // - psiReferenceRegistrar.registerReferenceProvider( - XmlHelperUtility.getTagAttributeValuePattern("block", "class"), - new LayoutReferenceProvider( - new ReferenceResultsFiller[]{ - ClassesResultsFiller.INSTANCE, - VirtualTypesResultsFiller.INSTANCE - } - ) - ); - - psiReferenceRegistrar.registerReferenceProvider( - XmlPatterns.or( - XmlHelperUtility.getTagAttributeValuePattern("referenceBlock", "name"), - XmlHelperUtility.getTagAttributeValuePattern("block", "before"), - XmlHelperUtility.getTagAttributeValuePattern("block", "after"), - XmlHelperUtility.getTagAttributeValuePattern("remove", "name"), - XmlHelperUtility.getTagAttributeValuePattern("move", "element"), - XmlHelperUtility.getTagAttributeValuePattern("move", "destination"), - XmlHelperUtility.getTagAttributeValuePattern("move", "before"), - XmlHelperUtility.getTagAttributeValuePattern("move", "after") - ), - new LayoutReferenceProvider( - new ReferenceResultsFiller[]{ - new BlockResultsFiller() - } - ) - ); - - psiReferenceRegistrar.registerReferenceProvider( - XmlHelperUtility.getTagAttributeValuePattern("referenceContainer", "name"), - new LayoutReferenceProvider( - new ReferenceResultsFiller[]{ - new ContainerResultsFiller() - } - ) - ); - - psiReferenceRegistrar.registerReferenceProvider( - XmlHelperUtility.getTagAttributeValuePattern("update", "handle"), - new LayoutReferenceProvider( - new ReferenceResultsFiller[]{ - new ReferenceResultsFiller() { - @Override - public void fillResolveResults(PsiElement psiElement, List results, String typeName) { - results.addAll( - Arrays.asList( - PsiElementResolveResult.createResults( - LayoutUtility.getLayoutFiles(psiElement.getProject(), typeName) - ) - ) - ); - } - } - } - ) - ); - } - - private class LayoutReferenceProvider extends PsiReferenceProvider { - private final ReferenceResultsFiller[] resultsFillers; - - public LayoutReferenceProvider(ReferenceResultsFiller[] resultsFillers) { - super(); - this.resultsFillers = resultsFillers; - } - - @NotNull - @Override - public PsiReference[] getReferencesByElement(@NotNull PsiElement psiElement, @NotNull ProcessingContext processingContext) { - PsiFile containingFile = psiElement.getContainingFile(); - if (!LayoutUtility.isLayoutFile(containingFile)) { - return new PsiReference[0]; - } - - return new PsiReference[]{new TypeReference(psiElement, resultsFillers)}; - } - } - -} diff --git a/src/com/magento/idea/magento2plugin/xml/layout/reference/fill/BlockResultsFiller.java b/src/com/magento/idea/magento2plugin/xml/layout/reference/fill/BlockResultsFiller.java deleted file mode 100644 index 1071ef103..000000000 --- a/src/com/magento/idea/magento2plugin/xml/layout/reference/fill/BlockResultsFiller.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.magento.idea.magento2plugin.xml.layout.reference.fill; - -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiElementResolveResult; -import com.intellij.psi.ResolveResult; -import com.intellij.psi.xml.XmlTag; -import com.magento.idea.magento2plugin.xml.layout.index.util.LayoutIndexUtility; -import com.magento.idea.magento2plugin.xml.reference.util.ReferenceResultsFiller; - -import java.util.Arrays; -import java.util.List; - -/** - * Created by dkvashnin on 11/20/15. - */ -public class BlockResultsFiller implements ReferenceResultsFiller { - @Override - public void fillResolveResults(PsiElement psiElement, List results, String typeName) { - List componentDeclarations = LayoutIndexUtility - .getBlockDeclarations( - typeName, - psiElement.getProject() - ); - - ResolveResult[] resolveResults = PsiElementResolveResult.createResults(componentDeclarations); - results.addAll(Arrays.asList(resolveResults)); - } -} \ No newline at end of file diff --git a/src/com/magento/idea/magento2plugin/xml/layout/reference/fill/ContainerResultsFiller.java b/src/com/magento/idea/magento2plugin/xml/layout/reference/fill/ContainerResultsFiller.java deleted file mode 100644 index 3cf4d1324..000000000 --- a/src/com/magento/idea/magento2plugin/xml/layout/reference/fill/ContainerResultsFiller.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.magento.idea.magento2plugin.xml.layout.reference.fill; - -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiElementResolveResult; -import com.intellij.psi.ResolveResult; -import com.intellij.psi.xml.XmlTag; -import com.magento.idea.magento2plugin.xml.layout.index.util.LayoutIndexUtility; -import com.magento.idea.magento2plugin.xml.reference.util.ReferenceResultsFiller; - -import java.util.Arrays; -import java.util.List; - -/** - * Created by dkvashnin on 11/18/15. - */ -public class ContainerResultsFiller implements ReferenceResultsFiller { - @Override - public void fillResolveResults(PsiElement psiElement, List results, String typeName) { - List componentDeclarations = LayoutIndexUtility - .getContainerDeclarations( - typeName, - psiElement.getProject() - ); - - ResolveResult[] resolveResults = PsiElementResolveResult.createResults(componentDeclarations); - results.addAll(Arrays.asList(resolveResults)); - } -} diff --git a/src/com/magento/idea/magento2plugin/xml/observer/PhpPatternsHelper.java b/src/com/magento/idea/magento2plugin/xml/observer/PhpPatternsHelper.java index 25a4df7af..f2627f5d0 100644 --- a/src/com/magento/idea/magento2plugin/xml/observer/PhpPatternsHelper.java +++ b/src/com/magento/idea/magento2plugin/xml/observer/PhpPatternsHelper.java @@ -1,4 +1,8 @@ -package com.magento.idea.magento2plugin.xml.observer; +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.php.util; import com.intellij.patterns.ElementPattern; import com.intellij.patterns.PlatformPatterns; diff --git a/src/com/magento/idea/magento2plugin/xml/observer/XmlHelper.java b/src/com/magento/idea/magento2plugin/xml/observer/XmlHelper.java deleted file mode 100644 index 1a60455e6..000000000 --- a/src/com/magento/idea/magento2plugin/xml/observer/XmlHelper.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.magento.idea.magento2plugin.xml.observer; - -import com.intellij.patterns.XmlAttributeValuePattern; -import com.magento.idea.magento2plugin.xml.XmlHelperUtility; - -/** - * Created by dkvashnin on 11/17/15. - */ -public class XmlHelper extends XmlHelperUtility { - public static final String FILE_TYPE = "events"; - - public static final String OBSERVER_TAG = "observer"; - public static final String EVENT_TAG = "event"; - - public static final String NAME_ATTRIBUTE = "name"; - public static final String INSTANCE_ATTRIBUTE = "instance"; - - /** - * - */ - public static XmlAttributeValuePattern getTagAttributeValuePattern(String tagName, String attributeName) { - return getTagAttributeValuePattern(tagName, attributeName, FILE_TYPE); - } -} diff --git a/src/com/magento/idea/magento2plugin/xml/observer/completion/EventCompletionContributor.java b/src/com/magento/idea/magento2plugin/xml/observer/completion/EventCompletionContributor.java deleted file mode 100644 index b0cd063d3..000000000 --- a/src/com/magento/idea/magento2plugin/xml/observer/completion/EventCompletionContributor.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.magento.idea.magento2plugin.xml.observer.completion; - -import com.intellij.codeInsight.completion.*; -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.php.util.MagentoTypes; -import com.magento.idea.magento2plugin.xml.XmlHelperUtility; -import com.magento.idea.magento2plugin.xml.completion.ClassCompletionProvider; -import com.magento.idea.magento2plugin.xml.completion.VirtualTypeCompletionProvider; -import com.magento.idea.magento2plugin.php.util.ImplementationMatcher; -import com.magento.idea.magento2plugin.xml.observer.XmlHelper; -import com.magento.idea.magento2plugin.xml.observer.index.EventsDeclarationsFileBasedIndex; -import org.jetbrains.annotations.NotNull; - -import java.util.Collection; - -/** - * Created by dkvashnin on 11/17/15. - */ -public class EventCompletionContributor extends CompletionContributor { - public EventCompletionContributor() { - extend( - CompletionType.BASIC, - XmlHelperUtility.getTagAttributePattern(XmlHelper.OBSERVER_TAG, XmlHelper.INSTANCE_ATTRIBUTE, XmlHelper.FILE_TYPE), - new CompletionProvider() { - @Override - protected void addCompletions(@NotNull CompletionParameters completionParameters, ProcessingContext processingContext, @NotNull CompletionResultSet completionResultSet) { - ImplementationMatcher completionContext = new ImplementationMatcher(MagentoTypes.OBSERVER_TYPE); - PsiElement psiElement = completionParameters.getOriginalPosition(); - - completionResultSet.addAllElements( - ClassCompletionProvider.INSTANCE.collectCompletionResult(psiElement, completionContext) - ); - completionResultSet.addAllElements(VirtualTypeCompletionProvider.INSTANCE.collectCompletionResult(psiElement)); - } - } - ); - - extend( - CompletionType.BASIC, - XmlHelperUtility.getTagAttributePattern(XmlHelper.EVENT_TAG, XmlHelper.NAME_ATTRIBUTE, XmlHelper.FILE_TYPE), - new CompletionProvider() { - @Override - protected void addCompletions(@NotNull CompletionParameters completionParameters, ProcessingContext processingContext, @NotNull CompletionResultSet completionResultSet) { - PsiElement psiElement = completionParameters.getOriginalPosition(); - Collection eventNames = FileBasedIndex.getInstance().getAllKeys(EventsDeclarationsFileBasedIndex.NAME, psiElement.getProject()); - - for (String eventName: eventNames) { - completionResultSet.addElement(LookupElementBuilder.create(eventName)); - } - } - } - ); - } - -} - diff --git a/src/com/magento/idea/magento2plugin/xml/observer/index/EventObserverFileBasedIndex.java b/src/com/magento/idea/magento2plugin/xml/observer/index/EventObserverFileBasedIndex.java deleted file mode 100644 index eeb4fd308..000000000 --- a/src/com/magento/idea/magento2plugin/xml/observer/index/EventObserverFileBasedIndex.java +++ /dev/null @@ -1,146 +0,0 @@ -package com.magento.idea.magento2plugin.xml.observer.index; - -import com.intellij.ide.highlighter.XmlFileType; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.PsiFile; -import com.intellij.psi.impl.source.xml.XmlDocumentImpl; -import com.intellij.psi.util.PsiTreeUtil; -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 org.jetbrains.annotations.NotNull; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Created by dkvashnin on 11/2/15. - */ -public class EventObserverFileBasedIndex extends FileBasedIndexExtension { - public static final ID NAME = ID.create("com.magento.idea.magento2plugin.xml.observer.index.event_observer"); - private final KeyDescriptor myKeyDescriptor = new EnumeratorStringDescriptor(); - - @NotNull - @Override - public ID getName() { - return NAME; - } - - @NotNull - @Override - public DataIndexer getIndexer() { - return new DataIndexer() { - @NotNull - @Override - public Map map(@NotNull FileContent fileContent) { - Map map = new HashMap<>(); - - PsiFile psiFile = fileContent.getPsiFile(); - XmlDocumentImpl document = PsiTreeUtil.getChildOfType(psiFile, XmlDocumentImpl.class); - if(document == null) { - return map; - } - - XmlTag xmlTags[] = PsiTreeUtil.getChildrenOfType(psiFile.getFirstChild(), XmlTag.class); - if(xmlTags == null) { - return map; - } - - for(XmlTag xmlTag: xmlTags) { - if(xmlTag.getName().equals("config")) { - for(XmlTag eventNode: xmlTag.findSubTags("event")) { - if (eventNode.getAttributeValue("name") != null) { - map.put( - eventNode.getAttributeValue("name"), - getObserversForEvent(eventNode) - ); - } - } - } - } - - return map; - } - - private String[] getObserversForEvent(XmlTag eventNode) { - List observerNames = new ArrayList(); - - for (XmlTag observerTag: eventNode.findSubTags("observer")) { - String name = observerTag.getAttributeValue("instance"); - if (name != null) { - observerNames.add(name); - } - } - - return observerNames.toArray(new String[observerNames.size()]); - } - }; - } - - @NotNull - @Override - public KeyDescriptor getKeyDescriptor() { - return myKeyDescriptor; - } - - @NotNull - @Override - public DataExternalizer getValueExternalizer() { - return new MySetDataExternalizer(); - } - - @NotNull - @Override - public FileBasedIndex.InputFilter getInputFilter() { - return new FileBasedIndex.InputFilter() { - @Override - public boolean acceptInput(@NotNull VirtualFile file) { - return file.getFileType() == XmlFileType.INSTANCE && file.getNameWithoutExtension().equals("events"); - } - }; - } - - @Override - public boolean dependsOnFileContent() { - return true; - } - - @Override - public int getVersion() { - return 1; - } - - public static class MySetDataExternalizer implements DataExternalizer { - - private final EnumeratorStringDescriptor myStringEnumerator = new EnumeratorStringDescriptor(); - - public synchronized void save(@NotNull DataOutput out, String[] values) throws IOException { - - out.writeInt(values.length); - for(String value: values) { - this.myStringEnumerator.save(out, value != null ? value : ""); - } - - } - - public synchronized String[] read(@NotNull DataInput in) throws IOException { - List list = new ArrayList(); - int r = in.readInt(); - - while (r > 0) { - list.add(this.myStringEnumerator.read(in)); - r--; - } - - return list.toArray(new String[list.size()]); - } - - } -} diff --git a/src/com/magento/idea/magento2plugin/xml/observer/index/EventsDeclarationsFileBasedIndex.java b/src/com/magento/idea/magento2plugin/xml/observer/index/EventsDeclarationsFileBasedIndex.java deleted file mode 100644 index 76a81002f..000000000 --- a/src/com/magento/idea/magento2plugin/xml/observer/index/EventsDeclarationsFileBasedIndex.java +++ /dev/null @@ -1,126 +0,0 @@ -package com.magento.idea.magento2plugin.xml.observer.index; - -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.VirtualFile; - -import com.intellij.patterns.ElementPattern; -import com.intellij.patterns.PlatformPatterns; -import com.intellij.psi.PsiElement; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.util.indexing.*; -import com.intellij.util.io.EnumeratorStringDescriptor; -import com.intellij.util.io.KeyDescriptor; -import com.jetbrains.php.lang.PhpFileType; -import com.jetbrains.php.lang.PhpLanguage; -import com.jetbrains.php.lang.patterns.PhpPatterns; -import com.jetbrains.php.lang.psi.PhpFile; -import com.jetbrains.php.lang.psi.elements.MethodReference; -import com.jetbrains.php.lang.psi.elements.ParameterList; -import com.magento.idea.magento2plugin.Settings; -import com.magento.idea.magento2plugin.xml.observer.PhpPatternsHelper; -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Created by dkvashnin on 11/5/15. - */ -public class EventsDeclarationsFileBasedIndex extends ScalarIndexExtension { - public static final ID NAME = ID.create("com.magento.idea.magento2plugin.xml.observer.index.events"); - private final KeyDescriptor myKeyDescriptor = new EnumeratorStringDescriptor(); - - @NotNull - @Override - public ID getName() { - return NAME; - } - - @NotNull - @Override - public DataIndexer getIndexer() { - return new DataIndexer() { - @NotNull - @Override - public Map map(@NotNull FileContent fileContent) { - Map map = new HashMap<>(); - PhpFile phpFile = (PhpFile)fileContent.getPsiFile(); - - if (!Settings.isEnabled(phpFile.getProject())) { - return map; - } - - List results = new ArrayList(); - recursiveFill(results, phpFile); - for (String result: results) { - map.put(result, null); - } - - return map; - } - - private void recursiveFill(List results, PsiElement psiElement) { - if (PhpPatternsHelper.STRING_METHOD_ARGUMENT.accepts(psiElement) && isInContextOfDispatchMethod(psiElement)) { - String eventName= StringUtil.unquoteString(psiElement.getText()); - if (eventName.length() > 0) { - results.add(eventName); - } - - return; - } - - for(PsiElement child: psiElement.getChildren()) { - recursiveFill(results, child); - } - } - - private boolean isInContextOfDispatchMethod(PsiElement psiElement) { - ParameterList parameterList = PsiTreeUtil.getParentOfType(psiElement, ParameterList.class); - - if (parameterList == null) { - return false; - } - - if(!(parameterList.getContext() instanceof MethodReference)) { - return false; - } - - MethodReference methodReference = (MethodReference)parameterList.getContext(); - if (!methodReference.getName().equals("dispatch")) { - return false; - } - - return true; - } - }; - } - - @NotNull - @Override - public KeyDescriptor getKeyDescriptor() { - return myKeyDescriptor; - } - - @NotNull - @Override - public FileBasedIndex.InputFilter getInputFilter() { - return new FileBasedIndex.InputFilter() { - @Override - public boolean acceptInput(@NotNull VirtualFile file) { - return file.getFileType() == PhpFileType.INSTANCE; - } - }; - } - - @Override - public boolean dependsOnFileContent() { - return true; - } - - @Override - public int getVersion() { - return 1; - } -} diff --git a/src/com/magento/idea/magento2plugin/xml/observer/reference/EventReferenceContributor.java b/src/com/magento/idea/magento2plugin/xml/observer/reference/EventReferenceContributor.java deleted file mode 100644 index ab84e86b7..000000000 --- a/src/com/magento/idea/magento2plugin/xml/observer/reference/EventReferenceContributor.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.magento.idea.magento2plugin.xml.observer.reference; - -import com.intellij.psi.*; -import com.magento.idea.magento2plugin.xml.observer.PhpPatternsHelper; -import com.magento.idea.magento2plugin.xml.observer.reference.util.ClassResultsFillerWrapper; -import com.magento.idea.magento2plugin.xml.observer.reference.util.EventsConfigurationFilesResultsFiller; -import com.magento.idea.magento2plugin.xml.reference.util.ReferenceResultsFiller; -import org.jetbrains.annotations.NotNull; - -/** - * Created by dkvashnin on 11/2/15. - */ -public class EventReferenceContributor extends PsiReferenceContributor { - @Override - public void registerReferenceProviders(@NotNull PsiReferenceRegistrar psiReferenceRegistrar) { - psiReferenceRegistrar.registerReferenceProvider( - PhpPatternsHelper.STRING_METHOD_ARGUMENT, - new EventReferenceProvider( - new ReferenceResultsFiller[] { - EventsConfigurationFilesResultsFiller.INSTANCE, - ClassResultsFillerWrapper.INSTANCE - } - ) - ); - } - -} \ No newline at end of file diff --git a/src/com/magento/idea/magento2plugin/xml/observer/reference/EventReferenceProvider.java b/src/com/magento/idea/magento2plugin/xml/observer/reference/EventReferenceProvider.java deleted file mode 100644 index e1be2efdc..000000000 --- a/src/com/magento/idea/magento2plugin/xml/observer/reference/EventReferenceProvider.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.magento.idea.magento2plugin.xml.observer.reference; - -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiReference; -import com.intellij.psi.PsiReferenceProvider; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.util.ProcessingContext; -import com.jetbrains.php.lang.psi.elements.Method; -import com.jetbrains.php.lang.psi.elements.MethodReference; -import com.jetbrains.php.lang.psi.elements.ParameterList; -import com.jetbrains.php.lang.psi.elements.PhpClass; -import com.magento.idea.magento2plugin.php.util.MagentoTypes; -import com.magento.idea.magento2plugin.xml.observer.PhpPatternsHelper; -import com.magento.idea.magento2plugin.xml.reference.TypeReference; -import com.magento.idea.magento2plugin.xml.reference.util.ReferenceResultsFiller; -import org.jetbrains.annotations.NotNull; - -/** -* Created by dkvashnin on 11/3/15. -*/ -class EventReferenceProvider extends PsiReferenceProvider { - private final ReferenceResultsFiller[] resultsFillers; - private static final String DISPATCH_METHOD = "dispatch"; - - public EventReferenceProvider(ReferenceResultsFiller[] resultsFillers) { - this.resultsFillers = resultsFillers; - } - - @NotNull - @Override - public PsiReference[] getReferencesByElement(@NotNull PsiElement psiElement, @NotNull ProcessingContext processingContext) { - ParameterList parameterList = PsiTreeUtil.getParentOfType(psiElement, ParameterList.class); - - if (parameterList == null) { - return new PsiReference[0]; - } - - if(!(parameterList.getContext() instanceof MethodReference)) { - return new PsiReference[0]; - } - - MethodReference methodReference = (MethodReference)parameterList.getContext(); - if (!DISPATCH_METHOD.equals(methodReference.getName())) { - return new PsiReference[0]; - } - - PsiElement resolvedElement = methodReference.resolve(); - if (resolvedElement != null && resolvedElement instanceof Method) { - PhpClass containingClass = ((Method) resolvedElement).getContainingClass(); - - if (containingClass != null && MagentoTypes.EVENT_MANAGER_TYPE.equals(containingClass.getPresentableFQN())) { - return new PsiReference[]{new TypeReference(psiElement, this.resultsFillers, true)}; - } - } - - - return new PsiReference[0]; - } -} diff --git a/src/com/magento/idea/magento2plugin/xml/observer/reference/ObserverReferenceContributor.java b/src/com/magento/idea/magento2plugin/xml/observer/reference/ObserverReferenceContributor.java deleted file mode 100644 index c90e2d50c..000000000 --- a/src/com/magento/idea/magento2plugin/xml/observer/reference/ObserverReferenceContributor.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.magento.idea.magento2plugin.xml.observer.reference; - -import com.intellij.psi.*; -import com.magento.idea.magento2plugin.xml.di.reference.provider.XmlReferenceProvider; -import com.magento.idea.magento2plugin.xml.observer.XmlHelper; -import com.magento.idea.magento2plugin.xml.observer.reference.util.EventsDeclarationsFilesResultsFiller; -import com.magento.idea.magento2plugin.xml.reference.util.ClassesResultsFiller; -import com.magento.idea.magento2plugin.xml.reference.util.ReferenceResultsFiller; -import com.magento.idea.magento2plugin.xml.reference.util.VirtualTypesResultsFiller; -import org.jetbrains.annotations.NotNull; - - -/** - * Created by dkvashnin on 11/2/15. - */ -public class ObserverReferenceContributor extends PsiReferenceContributor { - @Override - public void registerReferenceProviders(@NotNull PsiReferenceRegistrar psiReferenceRegistrar) { - // - psiReferenceRegistrar.registerReferenceProvider( - XmlHelper.getTagAttributeValuePattern(XmlHelper.OBSERVER_TAG, XmlHelper.INSTANCE_ATTRIBUTE), - new XmlReferenceProvider( - new ReferenceResultsFiller[]{ - ClassesResultsFiller.INSTANCE, - VirtualTypesResultsFiller.INSTANCE - } - ) - ); - - psiReferenceRegistrar.registerReferenceProvider( - XmlHelper.getTagAttributeValuePattern(XmlHelper.EVENT_TAG, XmlHelper.NAME_ATTRIBUTE), - new XmlReferenceProvider( - new ReferenceResultsFiller[]{ - EventsDeclarationsFilesResultsFiller.INSTANCE - } - ) - ); - } -} diff --git a/src/com/magento/idea/magento2plugin/xml/observer/reference/util/ClassResultsFillerWrapper.java b/src/com/magento/idea/magento2plugin/xml/observer/reference/util/ClassResultsFillerWrapper.java deleted file mode 100644 index df1ab025b..000000000 --- a/src/com/magento/idea/magento2plugin/xml/observer/reference/util/ClassResultsFillerWrapper.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.magento.idea.magento2plugin.xml.observer.reference.util; - -import com.intellij.psi.PsiElement; -import com.intellij.psi.ResolveResult; -import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.util.indexing.FileBasedIndex; -import com.magento.idea.magento2plugin.xml.observer.index.EventObserverFileBasedIndex; -import com.magento.idea.magento2plugin.xml.reference.util.ClassesResultsFiller; -import com.magento.idea.magento2plugin.xml.reference.util.ReferenceResultsFiller; -import com.magento.idea.magento2plugin.xml.reference.util.VirtualTypesResultsFiller; - -import java.util.List; -import java.util.Set; - -/** - * Created by dkvashnin on 11/3/15. - */ -public class ClassResultsFillerWrapper implements ReferenceResultsFiller { - public static final ReferenceResultsFiller INSTANCE = new ClassResultsFillerWrapper(); - - @Override - public void fillResolveResults(PsiElement psiElement, List results, String typeName) { - List> observersTypesList = FileBasedIndex.getInstance().getValues( - EventObserverFileBasedIndex.NAME, - typeName, - GlobalSearchScope.allScope(psiElement.getProject()) - ); - - for (Set observerTypes: observersTypesList) { - for (String type: observerTypes) { - ClassesResultsFiller.INSTANCE.fillResolveResults(psiElement, results, type); - VirtualTypesResultsFiller.INSTANCE.fillResolveResults(psiElement, results, type); - } - } - } -} diff --git a/src/com/magento/idea/magento2plugin/xml/observer/reference/util/EventsConfigurationFilesResultsFiller.java b/src/com/magento/idea/magento2plugin/xml/observer/reference/util/EventsConfigurationFilesResultsFiller.java deleted file mode 100644 index 04aeae84d..000000000 --- a/src/com/magento/idea/magento2plugin/xml/observer/reference/util/EventsConfigurationFilesResultsFiller.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.magento.idea.magento2plugin.xml.observer.reference.util; - -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiManager; -import com.intellij.psi.ResolveResult; -import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.psi.xml.XmlFile; -import com.intellij.util.indexing.FileBasedIndex; -import com.jetbrains.php.lang.psi.resolve.PhpResolveResult; -import com.magento.idea.magento2plugin.xml.observer.index.EventObserverFileBasedIndex; -import com.magento.idea.magento2plugin.xml.reference.util.ReferenceResultsFiller; - -import java.util.Collection; -import java.util.List; - -/** - * Created by dkvashnin on 11/3/15. - */ -public class EventsConfigurationFilesResultsFiller implements ReferenceResultsFiller { - public static final ReferenceResultsFiller INSTANCE = new EventsConfigurationFilesResultsFiller(); - - @Override - public void fillResolveResults(PsiElement psiElement, List results, String typeName) { - Collection containingFiles = FileBasedIndex - .getInstance() - .getContainingFiles( - EventObserverFileBasedIndex.NAME, - typeName, - GlobalSearchScope.allScope(psiElement.getProject()) - ); - - PsiManager psiManager = PsiManager.getInstance(psiElement.getProject()); - for (VirtualFile virtualFile: containingFiles) { - XmlFile xmlFile = (XmlFile)psiManager.findFile(virtualFile); - if (xmlFile != null) { - results.add(new PhpResolveResult(xmlFile)); - } - } - } -} diff --git a/src/com/magento/idea/magento2plugin/xml/observer/reference/util/EventsDeclarationsFilesResultsFiller.java b/src/com/magento/idea/magento2plugin/xml/observer/reference/util/EventsDeclarationsFilesResultsFiller.java deleted file mode 100644 index bf707e386..000000000 --- a/src/com/magento/idea/magento2plugin/xml/observer/reference/util/EventsDeclarationsFilesResultsFiller.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.magento.idea.magento2plugin.xml.observer.reference.util; - -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.ResolveResult; -import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.util.indexing.FileBasedIndex; -import com.jetbrains.php.lang.psi.PhpFile; -import com.jetbrains.php.lang.psi.resolve.PhpResolveResult; -import com.magento.idea.magento2plugin.xml.observer.PhpPatternsHelper; -import com.magento.idea.magento2plugin.xml.observer.index.EventsDeclarationsFileBasedIndex; -import com.magento.idea.magento2plugin.xml.reference.util.ReferenceResultsFiller; - -import java.util.Collection; -import java.util.List; - -/** - * Created by dkvashnin on 11/5/15. - */ -public class EventsDeclarationsFilesResultsFiller implements ReferenceResultsFiller { - public static final ReferenceResultsFiller INSTANCE = new EventsDeclarationsFilesResultsFiller(); - - @Override - public void fillResolveResults(PsiElement psiElement, List results, String typeName) { - Collection containingFiles = FileBasedIndex - .getInstance() - .getContainingFiles( - EventsDeclarationsFileBasedIndex.NAME, - typeName, - GlobalSearchScope.allScope(psiElement.getProject()) - ); - - PsiManager psiManager = PsiManager.getInstance(psiElement.getProject()); - for (VirtualFile virtualFile: containingFiles) { - PhpFile phpFile = (PhpFile)psiManager.findFile(virtualFile); - if (phpFile != null) { - recursiveFill(results, phpFile, typeName); - } - } - } - - private void recursiveFill(List results, PsiElement psiElement, String typeName) { - if (PhpPatternsHelper.STRING_METHOD_ARGUMENT.accepts(psiElement)) { - if (StringUtil.unquoteString(psiElement.getText()).equals(typeName)) { - results.add(new PhpResolveResult(psiElement)); - } - return; - } - - for(PsiElement child: psiElement.getChildren()) { - recursiveFill(results, child, typeName); - } - } -} \ No newline at end of file diff --git a/src/com/magento/idea/magento2plugin/xml/reference/TypeReference.java b/src/com/magento/idea/magento2plugin/xml/reference/TypeReference.java deleted file mode 100644 index 31dbf5563..000000000 --- a/src/com/magento/idea/magento2plugin/xml/reference/TypeReference.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.magento.idea.magento2plugin.xml.reference; - -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiPolyVariantReferenceBase; -import com.intellij.psi.ResolveResult; -import com.magento.idea.magento2plugin.xml.reference.util.ReferenceResultsFiller; -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Warider on 17.08.2015. - */ -public class TypeReference extends PsiPolyVariantReferenceBase { - private final boolean greedy; - - private ReferenceResultsFiller[] resultsFillers; - - public TypeReference(@NotNull PsiElement element, ReferenceResultsFiller[] resultsFillers) { - this(element, resultsFillers, false); - } - - public TypeReference(@NotNull PsiElement element, ReferenceResultsFiller[] resultsFillers, boolean greedy) { - super(element); - - this.resultsFillers = resultsFillers; - this.greedy = greedy; - } - - @NotNull - @Override - public ResolveResult[] multiResolve(boolean incompleteCode) { - List resolveResults = new ArrayList<>(); - String typeName = StringUtil.unquoteString(getElement().getText()); - - for (ReferenceResultsFiller referenceResultsFiller : resultsFillers) { - referenceResultsFiller.fillResolveResults(getElement(), resolveResults, typeName); - if (!greedy && resolveResults.size() > 0) { - break; - } - } - - return resolveResults.toArray(new ResolveResult[resolveResults.size()]); - } - - @NotNull - @Override - public Object[] getVariants() { - return new Object[0]; - } -} - diff --git a/src/com/magento/idea/magento2plugin/xml/reference/util/ClassesResultsFiller.java b/src/com/magento/idea/magento2plugin/xml/reference/util/ClassesResultsFiller.java deleted file mode 100644 index cce7c8310..000000000 --- a/src/com/magento/idea/magento2plugin/xml/reference/util/ClassesResultsFiller.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.magento.idea.magento2plugin.xml.reference.util; - -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiElementResolveResult; -import com.intellij.psi.ResolveResult; -import com.jetbrains.php.PhpIndex; -import com.jetbrains.php.lang.PhpLangUtil; -import com.jetbrains.php.lang.psi.elements.PhpClass; - -import java.util.List; - -/** - * Created by dkvashnin on 11/3/15. - */ -public class ClassesResultsFiller implements ReferenceResultsFiller { - public static final ReferenceResultsFiller INSTANCE = new ClassesResultsFiller(); - - private ClassesResultsFiller() {} - - @Override - public void fillResolveResults(PsiElement psiElement, List results, String typeName) { - PhpIndex phpIndex = PhpIndex.getInstance(psiElement.getProject()); - - for (PhpClass phpClass : phpIndex.getClassesByFQN(PhpLangUtil.toFQN(typeName))) { - addResult(results, phpClass); - } - } - - protected void addResult(List results, PhpClass phpClass) { - results.add(new PsiElementResolveResult(phpClass)); - } -} diff --git a/src/com/magento/idea/magento2plugin/xml/reference/util/ImplementationContextDecorator.java b/src/com/magento/idea/magento2plugin/xml/reference/util/ImplementationContextDecorator.java deleted file mode 100644 index 66fe5a4b8..000000000 --- a/src/com/magento/idea/magento2plugin/xml/reference/util/ImplementationContextDecorator.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.magento.idea.magento2plugin.xml.reference.util; - -import com.intellij.psi.PsiElement; -import com.intellij.psi.ResolveResult; -import com.jetbrains.php.lang.psi.elements.PhpClass; -import com.magento.idea.magento2plugin.php.util.ImplementationMatcher; - -import java.util.List; - -/** - * Created by dkvashnin on 12/18/15. - */ -public class ImplementationContextDecorator implements ReferenceResultsFiller { - private ReferenceResultsFiller subject; - private ImplementationMatcher implementationMatcher; - - public ImplementationContextDecorator(ReferenceResultsFiller subject, ImplementationMatcher implementationMatcher) { - this.subject = subject; - this.implementationMatcher = implementationMatcher; - } - - @Override - public void fillResolveResults(PsiElement psiElement, List results, String typeName) { - subject.fillResolveResults(psiElement, results, typeName); - - for (ResolveResult resolveResult : results) { - PsiElement element = resolveResult.getElement(); - - if (element instanceof PhpClass && !implementationMatcher.match(element)) { - results.remove(resolveResult); - } - } - - } -} diff --git a/src/com/magento/idea/magento2plugin/xml/reference/util/InterfacesResultsFiller.java b/src/com/magento/idea/magento2plugin/xml/reference/util/InterfacesResultsFiller.java deleted file mode 100644 index 4b53a716c..000000000 --- a/src/com/magento/idea/magento2plugin/xml/reference/util/InterfacesResultsFiller.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.magento.idea.magento2plugin.xml.reference.util; - -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiElementResolveResult; -import com.intellij.psi.ResolveResult; -import com.jetbrains.php.PhpIndex; -import com.jetbrains.php.lang.PhpLangUtil; -import com.jetbrains.php.lang.psi.elements.PhpClass; - -import java.util.List; - -/** - * Created by dkvashnin on 11/3/15. - */ -public class InterfacesResultsFiller implements ReferenceResultsFiller { - public static final ReferenceResultsFiller INSTANCE = new InterfacesResultsFiller(); - - private InterfacesResultsFiller() {} - - @Override - public void fillResolveResults(PsiElement psiElement, List results, String typeName) { - PhpIndex phpIndex = PhpIndex.getInstance(psiElement.getProject()); - - for (PhpClass phpClass : phpIndex.getInterfacesByFQN(PhpLangUtil.toFQN(typeName))) { - results.add(new PsiElementResolveResult(phpClass)); - } - } -} diff --git a/src/com/magento/idea/magento2plugin/xml/reference/util/ReferenceResultsFiller.java b/src/com/magento/idea/magento2plugin/xml/reference/util/ReferenceResultsFiller.java deleted file mode 100644 index 25bdbbf3c..000000000 --- a/src/com/magento/idea/magento2plugin/xml/reference/util/ReferenceResultsFiller.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.magento.idea.magento2plugin.xml.reference.util; - -import com.intellij.psi.PsiElement; -import com.intellij.psi.ResolveResult; - -import java.util.List; - -/** - * Created by dkvashnin on 11/3/15. - */ -public interface ReferenceResultsFiller { - public void fillResolveResults(PsiElement psiElement, List results, String typeName); -} diff --git a/src/com/magento/idea/magento2plugin/xml/reference/util/VirtualTypesResultsFiller.java b/src/com/magento/idea/magento2plugin/xml/reference/util/VirtualTypesResultsFiller.java deleted file mode 100644 index 77edfd3b5..000000000 --- a/src/com/magento/idea/magento2plugin/xml/reference/util/VirtualTypesResultsFiller.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.magento.idea.magento2plugin.xml.reference.util; - -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiElementResolveResult; -import com.intellij.psi.ResolveResult; -import com.intellij.psi.xml.XmlAttributeValue; -import com.magento.idea.magento2plugin.xml.di.index.VirtualTypesNamesFileBasedIndex; - -import java.util.List; - -/** - * Created by dkvashnin on 11/3/15. - */ -public class VirtualTypesResultsFiller implements ReferenceResultsFiller { - public static final ReferenceResultsFiller INSTANCE = new VirtualTypesResultsFiller(); - - private VirtualTypesResultsFiller() {} - - @Override - public void fillResolveResults(PsiElement psiElement, List results, String typeName) { - XmlAttributeValue[] virtualTypesByName = VirtualTypesNamesFileBasedIndex.getVirtualTypesByName( - psiElement.getProject(), - typeName, - psiElement.getResolveScope() - ); - - for (XmlAttributeValue virtualType: virtualTypesByName) { - results.add(new PsiElementResolveResult(virtualType)); - } - } -} diff --git a/src/com/magento/idea/magento2plugin/xml/util/ParentTypeMatcher.java b/src/com/magento/idea/magento2plugin/xml/util/ParentTypeMatcher.java deleted file mode 100644 index 69500cf85..000000000 --- a/src/com/magento/idea/magento2plugin/xml/util/ParentTypeMatcher.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.magento.idea.magento2plugin.xml.util; - -import com.intellij.psi.PsiElement; -import com.jetbrains.php.lang.psi.elements.PhpClass; -import com.magento.idea.magento2plugin.util.PsiContextMatcherI; -import org.jetbrains.annotations.Nullable; - -/** -* Created by dkvashnin on 12/25/15. -*/ -public class ParentTypeMatcher implements PsiContextMatcherI { - private PhpClass parentType; - - public ParentTypeMatcher(PhpClass parentType) { - this.parentType = parentType; - } - - @Override - public boolean match(PsiElement psiElement) { - if (!(psiElement instanceof PhpClass)) { - return false; - } - - return parentType.equals(psiElement) - || match(((PhpClass)psiElement).getImplementedInterfaces()) - || match(((PhpClass) psiElement).getSuperClass()); - } - - public boolean match(@Nullable PhpClass[] probableMistakes) { - if (probableMistakes == null) { - return false; - } - - boolean result = false; - - for (PhpClass probableMistake : probableMistakes) { - result = parentType.equals(probableMistake) || match(probableMistake.getImplementedInterfaces()); - } - - return result; - } -} diff --git a/src/com/magento/idea/magento2plugin/xml/util/VirtualTypeParentMatcher.java b/src/com/magento/idea/magento2plugin/xml/util/VirtualTypeParentMatcher.java deleted file mode 100644 index b83b95ee9..000000000 --- a/src/com/magento/idea/magento2plugin/xml/util/VirtualTypeParentMatcher.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.magento.idea.magento2plugin.xml.util; - -import com.intellij.openapi.project.Project; -import com.jetbrains.php.lang.psi.elements.PhpClass; -import com.magento.idea.magento2plugin.util.PsiContextMatcherI; -import com.magento.idea.magento2plugin.xml.di.completion.DiCompletionContributor; -import com.magento.idea.magento2plugin.xml.di.index.VirtualTypesNamesFileBasedIndex; - -import java.util.List; - -/** -* Created by dkvashnin on 12/25/15. -*/ -public class VirtualTypeParentMatcher implements PsiContextMatcherI { - private ParentTypeMatcher parentTypeMatcher; - private Project project; - - public VirtualTypeParentMatcher(ParentTypeMatcher parentTypeMatcher, Project project) { - this.parentTypeMatcher = parentTypeMatcher; - this.project = project; - } - - @Override - public boolean match(String virtualType) { - List superParentTypes = VirtualTypesNamesFileBasedIndex.getSuperParentTypes(project, virtualType); - - return parentTypeMatcher.match( - superParentTypes.toArray(new PhpClass[superParentTypes.size()]) - ); - } -} diff --git a/src/com/magento/idea/magento2plugin/xml/webapi/XmlHelper.java b/src/com/magento/idea/magento2plugin/xml/webapi/XmlHelper.java deleted file mode 100644 index cbd6e4b73..000000000 --- a/src/com/magento/idea/magento2plugin/xml/webapi/XmlHelper.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.magento.idea.magento2plugin.xml.webapi; - -import com.intellij.patterns.PsiElementPattern; -import com.intellij.patterns.XmlAttributeValuePattern; -import com.intellij.patterns.XmlPatterns; -import com.intellij.psi.PsiElement; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.psi.xml.XmlAttribute; -import com.intellij.psi.xml.XmlTag; -import com.intellij.psi.xml.XmlTokenType; -import com.magento.idea.magento2plugin.xml.XmlHelperUtility; -import org.jetbrains.annotations.Nullable; - -/** - * Created by isentiabov on 20.12.2015. - */ -public class XmlHelper extends XmlHelperUtility { - public static final String FILE_TYPE = "webapi"; - public static final String SERVICE_TAG = "service"; - public static final String METHOD_ATTRIBUTE = "method"; - public static final String CLASS_ATTRIBUTE = "class"; - - /** - * - */ - public static XmlAttributeValuePattern getMethodAttributePattern() { - return getTagAttributeValuePattern(SERVICE_TAG, METHOD_ATTRIBUTE, FILE_TYPE); - } - - /** - * - */ - public static PsiElementPattern.Capture getTagAttributePattern(String tag, String attributeName) { - return getTagAttributePattern(tag, attributeName, FILE_TYPE); - } - - @Nullable - public static XmlAttribute getInterfaceAttributeByMethod(PsiElement psiElement) - { - // get service xml tag `method` attribute - XmlAttribute methodAttribute = PsiTreeUtil.getParentOfType(psiElement, XmlAttribute.class); - if (methodAttribute == null) { - return null; - } - - // get service xml tag - XmlTag serviceTag = PsiTreeUtil.getParentOfType(methodAttribute, XmlTag.class); - if (serviceTag == null) { - return null; - } - - // get service xml tag `class` attribute - return serviceTag.getAttribute(CLASS_ATTRIBUTE); - } -} diff --git a/src/com/magento/idea/magento2plugin/xml/webapi/completion/WebApiCompletionContributor.java b/src/com/magento/idea/magento2plugin/xml/webapi/completion/WebApiCompletionContributor.java deleted file mode 100644 index 61ef95a50..000000000 --- a/src/com/magento/idea/magento2plugin/xml/webapi/completion/WebApiCompletionContributor.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.magento.idea.magento2plugin.xml.webapi.completion; - -import com.intellij.codeInsight.completion.*; -import com.intellij.codeInsight.lookup.LookupElementBuilder; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiReference; -import com.intellij.psi.xml.XmlAttribute; -import com.intellij.psi.xml.XmlAttributeValue; -import com.intellij.util.ProcessingContext; -import com.jetbrains.php.PhpIcons; -import com.jetbrains.php.lang.psi.elements.Method; -import com.jetbrains.php.lang.psi.elements.PhpClass; -import com.magento.idea.magento2plugin.xml.completion.InterfaceCompletionProvider; -import com.magento.idea.magento2plugin.xml.webapi.XmlHelper; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * Created by mslabko on 10/15/15. - */ -public class WebApiCompletionContributor extends CompletionContributor { - public WebApiCompletionContributor() { - // add services to list - extend( - CompletionType.BASIC, - XmlHelper.getTagAttributePattern(XmlHelper.SERVICE_TAG, XmlHelper.CLASS_ATTRIBUTE), - new CompletionProvider() { - public void addCompletions(@NotNull CompletionParameters parameters, - ProcessingContext context, - @NotNull CompletionResultSet resultSet) { - PsiElement psiElement = parameters.getOriginalPosition(); - - resultSet.addAllElements(InterfaceCompletionProvider.INSTANCE.collectCompletionResult(psiElement)); - } - } - ); - - // Add service methods to list - extend( - CompletionType.BASIC, - XmlHelper.getTagAttributePattern(XmlHelper.SERVICE_TAG, XmlHelper.METHOD_ATTRIBUTE), - new CompletionProvider() { - public void addCompletions(@NotNull CompletionParameters parameters, - ProcessingContext context, - @NotNull CompletionResultSet resultSet) { - - PsiElement psiElement = parameters.getOriginalPosition(); - - PhpClass serviceInterface = getServiceInterface(psiElement); - if (serviceInterface != null) { - for (Method serviceMethod : serviceInterface.getMethods()) { - - resultSet.addElement( - LookupElementBuilder - .create(serviceMethod.getName()) - .withIcon(PhpIcons.METHOD_ICON) - ); - } - } - } - } - ); - } - - @Nullable - private PhpClass getServiceInterface(PsiElement psiElement) { - XmlAttribute classAttribute = XmlHelper.getInterfaceAttributeByMethod(psiElement); - if (classAttribute == null) { - return null; - } - - XmlAttributeValue xmlAttributeValue = classAttribute.getValueElement(); - - if (xmlAttributeValue == null) { - return null; - } - - PsiReference reference = xmlAttributeValue.getReference(); - if (reference == null) { - return null; - } - - PsiElement element = reference.resolve(); - - if (element instanceof PhpClass) { - return (PhpClass) element; - } - - return null; - } -} diff --git a/src/com/magento/idea/magento2plugin/xml/webapi/index/WebApiTypesFileBasedIndex.java b/src/com/magento/idea/magento2plugin/xml/webapi/index/WebApiTypesFileBasedIndex.java index b4809ad30..4f598150f 100644 --- a/src/com/magento/idea/magento2plugin/xml/webapi/index/WebApiTypesFileBasedIndex.java +++ b/src/com/magento/idea/magento2plugin/xml/webapi/index/WebApiTypesFileBasedIndex.java @@ -1,12 +1,16 @@ -package com.magento.idea.magento2plugin.xml.webapi.index; +/** + * Copyright © Dmytro Kvashnin. All rights reserved. + * See COPYING.txt for license details. + */ +package com.magento.idea.magento2plugin.stubs.indexes; import com.intellij.ide.highlighter.XmlFileType; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; -import com.intellij.psi.impl.source.xml.XmlDocumentImpl; import com.intellij.psi.search.GlobalSearchScope; 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.*; @@ -15,8 +19,8 @@ import com.jetbrains.php.lang.PhpLangUtil; import com.jetbrains.php.lang.psi.elements.Method; import com.jetbrains.php.lang.psi.elements.PhpClass; -import com.magento.idea.magento2plugin.Settings; -import com.magento.idea.magento2plugin.xml.index.LineMarkerXmlTagDecorator; +import com.magento.idea.magento2plugin.project.Settings; +import com.magento.idea.magento2plugin.xml.LineMarkerXmlTagDecorator; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -25,57 +29,56 @@ /** * Indexer for classes/interfaces which have methods exposed via Web API. */ -public class WebApiTypesFileBasedIndex extends ScalarIndexExtension { +public class WebApiTypeIndex extends ScalarIndexExtension { - public static final ID NAME = ID.create("com.magento.idea.magento2plugin.xml.webapi.index.webapi_types"); + public static final ID KEY = ID.create("com.magento.idea.magento2plugin.stubs.indexes.webapi_type"); private final KeyDescriptor keyDescriptor = new EnumeratorStringDescriptor(); @NotNull @Override public ID getName() { - return NAME; + return KEY; } @NotNull @Override public DataIndexer getIndexer() { - return new DataIndexer() { + return inputData -> { + Map map = new HashMap<>(); - @NotNull - @Override - public Map map(@NotNull FileContent fileContent) { - Map map = new HashMap<>(); + PsiFile psiFile = inputData.getPsiFile(); + if (!Settings.isEnabled(psiFile.getProject())) { + return map; + } - PsiFile psiFile = fileContent.getPsiFile(); - if (!Settings.isEnabled(psiFile.getProject())) { - return map; - } + if (!(psiFile instanceof XmlFile)) { + return map; + } - XmlDocumentImpl document = PsiTreeUtil.getChildOfType(psiFile, XmlDocumentImpl.class); - if (document == null) { - return map; - } + XmlDocument document = ((XmlFile) psiFile).getDocument(); + if (document == null) { + return map; + } - XmlTag xmlTags[] = PsiTreeUtil.getChildrenOfType(psiFile.getFirstChild(), XmlTag.class); - if (xmlTags == null) { - return map; - } + XmlTag xmlTags[] = PsiTreeUtil.getChildrenOfType(psiFile.getFirstChild(), XmlTag.class); + if (xmlTags == null) { + return map; + } - for (XmlTag xmlTag : xmlTags) { - if (xmlTag.getName().equals("routes")) { - for (XmlTag routeNode : xmlTag.findSubTags("route")) { - for (XmlTag serviceNode : routeNode.findSubTags("service")) { - String typeName = serviceNode.getAttributeValue("class"); - if (typeName != null) { - map.put(PhpLangUtil.toPresentableFQN(typeName), null); - } + for (XmlTag xmlTag : xmlTags) { + if (xmlTag.getName().equals("routes")) { + for (XmlTag routeNode : xmlTag.findSubTags("route")) { + for (XmlTag serviceNode : routeNode.findSubTags("service")) { + String typeName = serviceNode.getAttributeValue("class"); + if (typeName != null) { + map.put(PhpLangUtil.toPresentableFQN(typeName), null); } } } } - return map; } + return map; }; } @@ -88,13 +91,10 @@ public KeyDescriptor getKeyDescriptor() { @NotNull @Override public FileBasedIndex.InputFilter getInputFilter() { - return new FileBasedIndex.InputFilter() { - @Override - public boolean acceptInput(@NotNull VirtualFile file) { - return file.getFileType() == XmlFileType.INSTANCE && file.getNameWithoutExtension().equals("webapi") - && !file.getPath().contains("testsuite") && !file.getPath().contains("_files"); - } - }; + return file -> ( + file.getFileType() == XmlFileType.INSTANCE && file.getNameWithoutExtension().equals("webapi") + && !file.getPath().contains("testsuite") && !file.getPath().contains("_files") + ); } @Override @@ -123,16 +123,8 @@ public static List getWebApiRoutes(Method method) { return tags; } String classFqn = phpClass.getPresentableFQN(); - if (classFqn == null) { - return tags; - } Collection containingFiles = FileBasedIndex - .getInstance() - .getContainingFiles( - NAME, - classFqn, - GlobalSearchScope.allScope(phpClass.getProject()) - ); + .getInstance().getContainingFiles(KEY, classFqn, GlobalSearchScope.allScope(phpClass.getProject())); PsiManager psiManager = PsiManager.getInstance(phpClass.getProject()); for (VirtualFile virtualFile : containingFiles) { @@ -162,32 +154,32 @@ private static void fillRelatedTags(String classFqn, String methodFqn, XmlTag pa } } } -} -/** - * Decorator for XmlTag, which allows to render REST routes in web API line marker. - */ -class WebApiLineMarkerXmlTagDecorator extends LineMarkerXmlTagDecorator { + /** + * Decorator for XmlTag, which allows to render REST routes in web API line marker. + */ + private static class WebApiLineMarkerXmlTagDecorator extends LineMarkerXmlTagDecorator { - public WebApiLineMarkerXmlTagDecorator(XmlTag xmlTag) { - super(xmlTag); - } + WebApiLineMarkerXmlTagDecorator(XmlTag xmlTag) { + super(xmlTag); + } - @NotNull - @Override - public String getDescription() { - return ""; - } + @NotNull + @Override + public String getDescription() { + return ""; + } - @Override - @NotNull - @NonNls - public String getName() { - String httpMethod = this.xmlTag.getAttributeValue("method"); - String route = this.xmlTag.getAttributeValue("url"); - if (httpMethod != null && route != null) { - return String.format(" %-7s %s", httpMethod, route); + @Override + @NotNull + @NonNls + public String getName() { + String httpMethod = this.xmlTag.getAttributeValue("method"); + String route = this.xmlTag.getAttributeValue("url"); + if (httpMethod != null && route != null) { + return String.format(" %-7s %s", httpMethod, route); + } + return xmlTag.getName(); } - return xmlTag.getName(); } } diff --git a/src/com/magento/idea/magento2plugin/xml/webapi/reference/ServiceReferenceContributor.java b/src/com/magento/idea/magento2plugin/xml/webapi/reference/ServiceReferenceContributor.java deleted file mode 100644 index 1ee70712d..000000000 --- a/src/com/magento/idea/magento2plugin/xml/webapi/reference/ServiceReferenceContributor.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.magento.idea.magento2plugin.xml.webapi.reference; - -import com.intellij.patterns.XmlAttributeValuePattern; -import com.intellij.psi.PsiReferenceContributor; -import com.intellij.psi.PsiReferenceRegistrar; -import com.magento.idea.magento2plugin.xml.di.reference.provider.XmlReferenceProvider; -import com.magento.idea.magento2plugin.xml.reference.util.InterfacesResultsFiller; -import com.magento.idea.magento2plugin.xml.reference.util.ReferenceResultsFiller; -import com.magento.idea.magento2plugin.xml.webapi.XmlHelper; -import com.magento.idea.magento2plugin.xml.webapi.reference.fill.ServiceMethodResultsFiller; -import org.jetbrains.annotations.NotNull; - -/** - * Created by isentiabov on 20.12.2015. - */ -public class ServiceReferenceContributor extends PsiReferenceContributor{ - @Override - public void registerReferenceProviders(@NotNull PsiReferenceRegistrar psiReferenceRegistrar) { - // - XmlAttributeValuePattern serviceTag = XmlHelper.getTagAttributeValuePattern( - XmlHelper.SERVICE_TAG, - XmlHelper.CLASS_ATTRIBUTE - ); - psiReferenceRegistrar.registerReferenceProvider( - serviceTag, - new XmlReferenceProvider(new ReferenceResultsFiller[]{ - InterfacesResultsFiller.INSTANCE - })); - - // - XmlAttributeValuePattern methodAttribute = XmlHelper.getMethodAttributePattern(); - psiReferenceRegistrar.registerReferenceProvider( - methodAttribute, - new XmlReferenceProvider(new ReferenceResultsFiller[]{ - new ServiceMethodResultsFiller() - }) - ); - } -} diff --git a/src/com/magento/idea/magento2plugin/xml/webapi/reference/fill/ServiceMethodResultsFiller.java b/src/com/magento/idea/magento2plugin/xml/webapi/reference/fill/ServiceMethodResultsFiller.java deleted file mode 100644 index 65d0d665c..000000000 --- a/src/com/magento/idea/magento2plugin/xml/webapi/reference/fill/ServiceMethodResultsFiller.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.magento.idea.magento2plugin.xml.webapi.reference.fill; - -import com.intellij.psi.PsiElement; -import com.intellij.psi.ResolveResult; -import com.intellij.psi.xml.XmlAttribute; -import com.intellij.psi.xml.XmlAttributeValue; -import com.jetbrains.php.PhpIndex; -import com.jetbrains.php.lang.psi.elements.Method; -import com.jetbrains.php.lang.psi.elements.PhpClass; -import com.jetbrains.php.lang.psi.resolve.PhpResolveResult; -import com.magento.idea.magento2plugin.xml.reference.util.ReferenceResultsFiller; -import com.magento.idea.magento2plugin.xml.webapi.XmlHelper; -import org.jetbrains.annotations.Nullable; - -import java.util.Iterator; -import java.util.List; - -/** - * Created by isentiabov on 20.12.2015. - */ -public class ServiceMethodResultsFiller implements ReferenceResultsFiller { - @Override - public void fillResolveResults(PsiElement psiElement, List results, String typeName) { - XmlAttribute classAttribute = XmlHelper.getInterfaceAttributeByMethod(psiElement); - if (classAttribute == null) { - return; - } - - PhpClass serviceInterface = getServiceInterface(classAttribute); - if (serviceInterface == null) { - return; - } - - fillResults(serviceInterface, results, typeName); - } - - - - @Nullable - protected PhpClass getServiceInterface(XmlAttribute xmlAttribute) { - XmlAttributeValue value = xmlAttribute.getValueElement(); - if (value == null) { - return null; - } - - PhpIndex phpIndex = PhpIndex.getInstance(xmlAttribute.getProject()); - - Iterator iterator = phpIndex.getInterfacesByFQN(value.getValue()).iterator(); - if (iterator.hasNext()) { - return iterator.next(); - } - - return null; - } - - protected void fillResults(PhpClass serviceInterface, List results, String typeName) { - for (Method method : serviceInterface.getMethods()) { - if (method.getName().equals(typeName)) { - results.add( - new PhpResolveResult(method) - ); - - break; - } - } - } -} diff --git a/src/inspectionDescriptions/MagentoApiInspection.html b/src/inspectionDescriptions/MagentoApiInspection.html deleted file mode 100644 index 02a3c1db6..000000000 --- a/src/inspectionDescriptions/MagentoApiInspection.html +++ /dev/null @@ -1,5 +0,0 @@ - - -Non Module public API usage. - - \ No newline at end of file diff --git a/src/inspectionDescriptions/ObjectManagerInspection.html b/src/inspectionDescriptions/ObjectManagerInspection.html deleted file mode 100644 index 5c82c6735..000000000 --- a/src/inspectionDescriptions/ObjectManagerInspection.html +++ /dev/null @@ -1,5 +0,0 @@ - - -ObjectManager usage in Module scope - - \ No newline at end of file