Skip to content

Commit 5723407

Browse files
committed
Modules tool view
1 parent 65a733a commit 5723407

10 files changed

+186
-32
lines changed

META-INF/plugin.xml

+7
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,13 @@
5858
<depends>com.intellij.modules.platform</depends>
5959

6060
<extensions defaultExtensionNs="com.intellij">
61+
<toolWindow id="Magento2 Modules"
62+
icon="/resources/magento2-module.png"
63+
anchor="left"
64+
secondary="false"
65+
factoryClass="com.magento.idea.magento2plugin.php.tool.ModuleToolWindowFactory" />
66+
67+
6168
<psi.referenceContributor implementation="com.magento.idea.magento2plugin.xml.di.reference.DiReferenceContributor"/>
6269
<psi.referenceContributor implementation="com.magento.idea.magento2plugin.xml.observer.reference.ObserverReferenceContributor"/>
6370
<psi.referenceContributor implementation="com.magento.idea.magento2plugin.xml.observer.reference.EventReferenceContributor"/>

src/com/magento/idea/magento2plugin/Magento2Icons.java

+1
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@
1010
public class Magento2Icons {
1111
public static final Icon PLUGIN = IconLoader.getIcon("icons/interception_reference.png");
1212
public static final Icon CONFIGURATION = IconLoader.getIcon("icons/xml_reference.png");
13+
1314
}

src/com/magento/idea/magento2plugin/php/inspections/MagentoApiInspection.java

+38-30
Original file line numberDiff line numberDiff line change
@@ -25,55 +25,63 @@ public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder problemsHolder, bo
2525
return new PhpElementVisitor() {
2626
@Override
2727
public void visitPhpMethodReference(MethodReference reference) {
28-
MagentoApiInspection.check(reference, "Method #ref is not in module API", problemsHolder);
28+
PsiElement referencedElement = reference.resolve();
29+
30+
if(referencedElement instanceof Method) {
31+
PhpClass phpClass = ((Method) referencedElement).getContainingClass();
32+
33+
if (phpClass == null) {
34+
return;
35+
}
36+
37+
if (!MagentoApiInspection.isValidReference(phpClass, reference.getElement())
38+
|| !MagentoApiInspection.isValidReference((Method) referencedElement, reference.getElement())) {
39+
problemsHolder.registerProblem(reference, "Method #ref is not in module API", ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
40+
}
41+
}
2942
}
3043

3144
@Override
32-
public void visitPhpClassReference(ClassReference classReference) {
33-
MagentoApiInspection.check(classReference, "Class #ref is not in module API", problemsHolder);
45+
public void visitPhpClassReference(ClassReference reference) {
46+
PsiElement referencedElement = reference.resolve();
47+
48+
if(referencedElement instanceof PhpClass) {
49+
if (!MagentoApiInspection.isValidReference((PhpClass) referencedElement, reference.getElement())) {
50+
problemsHolder.registerProblem(reference, "Class #ref is not in module API", ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
51+
}
52+
}
3453
}
3554
};
3655
}
3756

38-
private static void check(PhpReference reference, String desc, ProblemsHolder holder) {
39-
PsiElement element = reference.resolve();
57+
private static boolean isValidReference(PhpNamedElement referencedElement, PsiElement contextElement) {
58+
MagentoModule referenceSourceModule = getMagentoModule(referencedElement);
59+
MagentoModule currentModule = getMagentoModule(contextElement);
4060

41-
if(element instanceof PhpNamedElement) {
42-
MagentoModule referenceSourceModule = getMagentoModule((PhpPsiElement) element);
43-
MagentoModule currentModule = getMagentoModule((PhpPsiElement) (reference.getElement()));
4461

62+
if (!areDifferentModules(referenceSourceModule, currentModule)) {
63+
return true;
64+
}
4565

46-
if (!areDifferentModules(referenceSourceModule, currentModule)) {
47-
return;
48-
}
49-
50-
PhpDocComment docComment = ((PhpNamedElement)element).getDocComment();
51-
if(docComment == null) {
52-
holder.registerProblem(reference, desc, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
53-
return;
54-
}
55-
56-
PhpDocTag[] elements = docComment.getTagElementsByName(API_TAG);
57-
if(elements.length == 0) {
58-
holder.registerProblem(reference, desc, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
59-
}
66+
PhpDocComment docComment = referencedElement.getDocComment();
67+
if(docComment == null) {
68+
return false;
6069
}
70+
71+
PhpDocTag[] elements = docComment.getTagElementsByName(API_TAG);
72+
return elements.length > 0;
6173
}
6274

63-
private static MagentoModule getMagentoModule(PhpPsiElement element) {
75+
private static MagentoModule getMagentoModule(PsiElement element) {
6476
ModuleManager moduleManager = ModuleManager.getInstance(element.getProject());
6577
return moduleManager.getModuleForFile(element.getContainingFile());
6678
}
6779

68-
private static boolean areDifferentModules(MagentoModule magentoModule1, MagentoModule magentoModule2) {
69-
if (magentoModule1 == null) {
70-
return false;
71-
}
72-
73-
if (magentoModule2 == null) {
80+
private static boolean areDifferentModules(MagentoModule magentoModule, MagentoModule currentPackage) {
81+
if (magentoModule == null) {
7482
return false;
7583
}
7684

77-
return magentoModule1 != magentoModule2;
85+
return magentoModule != currentPackage;
7886
}
7987
}

src/com/magento/idea/magento2plugin/php/module/ComposerPackageModel.java

+3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ public interface ComposerPackageModel {
1414
@Nullable
1515
String getType();
1616

17+
@Nullable
18+
String getVendor();
19+
1720
@Nullable
1821
String getVersion();
1922

src/com/magento/idea/magento2plugin/php/module/ComposerPackageModelImpl.java

+14-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ public class ComposerPackageModelImpl implements ComposerPackageModel {
2222
public static final String PSR4 = "psr4";
2323
public static final String FILES = "file";
2424

25-
2625
public ComposerPackageModelImpl(JsonObject sourceComposerJson) {
2726
this.sourceComposerJson = sourceComposerJson;
2827
}
@@ -39,6 +38,20 @@ public String getType() {
3938
return getStringPropertyValue(TYPE);
4039
}
4140

41+
@Nullable
42+
@Override
43+
public String getVendor() {
44+
String nameProperty = getStringPropertyValue(NAME);
45+
if (nameProperty != null) {
46+
String[] vendorAndPackage = nameProperty.split("/");
47+
if (vendorAndPackage.length == 2) {
48+
return vendorAndPackage[0];
49+
}
50+
}
51+
52+
return null;
53+
}
54+
4255
@Nullable
4356
@Override
4457
public String getVersion() {

src/com/magento/idea/magento2plugin/php/module/MagentoModule.java

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.magento.idea.magento2plugin.php.module;
22

3+
import com.intellij.psi.PsiDirectory;
34
import com.intellij.psi.PsiFile;
45
import com.jetbrains.php.lang.psi.elements.PhpClass;
56
import org.jetbrains.annotations.Nullable;
@@ -22,4 +23,6 @@ public interface MagentoModule {
2223
boolean isFileInContext(PsiFile psiFile);
2324

2425
boolean isClassInContext(PhpClass phpClass);
26+
27+
PsiDirectory getSourceDirectory();
2528
}

src/com/magento/idea/magento2plugin/php/module/ModuleManager.java

+25-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
import com.intellij.psi.PsiManager;
1010
import com.intellij.psi.search.GlobalSearchScope;
1111
import com.intellij.psi.util.PsiTreeUtil;
12+
import com.intellij.psi.xml.XmlFile;
13+
import com.intellij.psi.xml.XmlTag;
1214
import com.intellij.util.indexing.FileBasedIndex;
1315
import com.jetbrains.php.lang.psi.elements.PhpClass;
1416
import com.magento.idea.magento2plugin.php.index.ModulePackageFileBasedIndex;
@@ -96,6 +98,8 @@ private void loadModules() {
9698
class MagentoModuleImpl implements MagentoModule {
9799
private ComposerPackageModel composerPackageModel;
98100
private PsiDirectory directory;
101+
private static final String DEFAULT_MODULE_NAME = "Undefined module";
102+
private static final String CONFIGURATION_PATH = "etc";
99103

100104
public MagentoModuleImpl(ComposerPackageModel composerPackageModel, PsiDirectory directory) {
101105

@@ -106,7 +110,22 @@ public MagentoModuleImpl(ComposerPackageModel composerPackageModel, PsiDirectory
106110
@Nullable
107111
@Override
108112
public String getMagentoName() {
109-
return null;
113+
PsiDirectory configurationDir = directory.findSubdirectory(CONFIGURATION_PATH);
114+
if (configurationDir != null) {
115+
PsiFile configurationFile = configurationDir.findFile("module.xml");
116+
117+
if (configurationFile != null && configurationFile instanceof XmlFile) {
118+
XmlTag rootTag = ((XmlFile) configurationFile).getRootTag();
119+
if (rootTag != null) {
120+
XmlTag module = rootTag.findFirstSubTag("module");
121+
if (module != null && module.getAttributeValue("name") != null) {
122+
return module.getAttributeValue("name");
123+
}
124+
}
125+
}
126+
}
127+
128+
return DEFAULT_MODULE_NAME;
110129
}
111130

112131
@Nullable
@@ -139,4 +158,9 @@ public boolean isFileInContext(PsiFile psiFile) {
139158
public boolean isClassInContext(PhpClass phpClass) {
140159
return false;
141160
}
161+
162+
@Override
163+
public PsiDirectory getSourceDirectory() {
164+
return directory;
165+
}
142166
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.magento.idea.magento2plugin.php.tool.ModuleToolWindowFactory">
3+
<grid id="27dc6" binding="windowContent" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
4+
<margin top="0" left="0" bottom="0" right="0"/>
5+
<constraints>
6+
<xy x="20" y="20" width="154" height="267"/>
7+
</constraints>
8+
<properties/>
9+
<border type="none"/>
10+
<children>
11+
<scrollpane id="212da">
12+
<constraints>
13+
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
14+
</constraints>
15+
<properties/>
16+
<border type="none"/>
17+
<children>
18+
<component id="73282" class="javax.swing.JTree" binding="modulesTree">
19+
<constraints/>
20+
<properties/>
21+
</component>
22+
</children>
23+
</scrollpane>
24+
</children>
25+
</grid>
26+
</form>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package com.magento.idea.magento2plugin.php.tool;
2+
3+
import com.intellij.openapi.project.Project;
4+
import com.intellij.openapi.wm.ToolWindow;
5+
import com.intellij.openapi.wm.ToolWindowFactory;
6+
import com.intellij.ui.content.Content;
7+
import com.intellij.ui.content.ContentFactory;
8+
import com.magento.idea.magento2plugin.php.module.ComposerPackageModel;
9+
import com.magento.idea.magento2plugin.php.module.MagentoModule;
10+
import com.magento.idea.magento2plugin.php.module.ModuleManager;
11+
import org.jetbrains.annotations.NotNull;
12+
13+
import javax.swing.*;
14+
import javax.swing.event.TreeModelListener;
15+
import javax.swing.tree.DefaultMutableTreeNode;
16+
import javax.swing.tree.DefaultTreeModel;
17+
import javax.swing.tree.TreeModel;
18+
import javax.swing.tree.TreePath;
19+
import java.util.HashMap;
20+
import java.util.Map;
21+
22+
/**
23+
* Created by dkvashnin on 12/7/15.
24+
*/
25+
public class ModuleToolWindowFactory implements ToolWindowFactory {
26+
private JPanel windowContent;
27+
private JTree modulesTree;
28+
private ToolWindow myToolWindow;
29+
30+
private static final String UNDEFINED_VENDOR = "Undefined";
31+
32+
@Override
33+
public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) {
34+
myToolWindow = toolWindow;
35+
initializeModulesTree(project);
36+
ContentFactory contentFactory = ContentFactory.SERVICE.getInstance();
37+
Content content = contentFactory.createContent(windowContent, "", false);
38+
toolWindow.getContentManager().addContent(content);
39+
}
40+
41+
private void initializeModulesTree(Project project) {
42+
ModuleManager moduleManager = ModuleManager.getInstance(project);
43+
44+
Map<String, DefaultMutableTreeNode> vendorNodes = new HashMap<>();
45+
46+
DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("Project modules");
47+
48+
modulesTree.setModel(new DefaultTreeModel(rootNode));
49+
50+
for (MagentoModule magentoModule: moduleManager.getModules()) {
51+
ComposerPackageModel packageModel = magentoModule.getComposerModel();
52+
if (packageModel == null) {
53+
continue;
54+
}
55+
56+
String vendorName = packageModel.getVendor();
57+
if (vendorName == null) {
58+
vendorName = UNDEFINED_VENDOR;
59+
}
60+
61+
if (!vendorNodes.containsKey(vendorName)) {
62+
vendorNodes.put(vendorName, new DefaultMutableTreeNode(vendorName));
63+
rootNode.add(vendorNodes.get(vendorName));
64+
}
65+
66+
vendorNodes.get(vendorName).add(new DefaultMutableTreeNode(magentoModule.getMagentoName()));
67+
}
68+
}
69+
}

src/resources/magento2-module.png

1.11 KB
Loading

0 commit comments

Comments
 (0)