Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -2,50 +2,56 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

package com.magento.idea.magento2plugin.linemarker.php;

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.util.PsiTreeUtil;
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.magento.files.Plugin;
import com.magento.idea.magento2plugin.project.Settings;
import com.magento.idea.magento2plugin.util.magento.plugin.GetTargetClassNamesByPluginClassName;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import com.magento.idea.magento2plugin.util.magento.plugin.GetTargetClassNamesByPluginClassName;
import com.intellij.psi.util.PsiTreeUtil;

import java.util.*;

public class PluginTargetLineMarkerProvider implements LineMarkerProvider {
@Nullable
@Override
public LineMarkerInfo getLineMarkerInfo(@NotNull PsiElement psiElement) {
public LineMarkerInfo getLineMarkerInfo(@NotNull final PsiElement psiElement) {
return null;
}

@Override
public void collectSlowLineMarkers(@NotNull List<PsiElement> psiElements, @NotNull Collection<LineMarkerInfo> collection) {
if (psiElements.size() > 0) {
if (!Settings.isEnabled(psiElements.get(0).getProject())) {
return;
}
public void collectSlowLineMarkers(
@NotNull final List<PsiElement> psiElements,
@NotNull final Collection<LineMarkerInfo> collection
) {
if (!psiElements.isEmpty() && !Settings.isEnabled(psiElements.get(0).getProject())) {
return;
}
PluginClassCache pluginClassCache = new PluginClassCache();
TargetClassesCollector TargetClassesCollector = new TargetClassesCollector(pluginClassCache);
TargetMethodsCollector TargetMethodsCollector = new TargetMethodsCollector(pluginClassCache);
final PluginClassCache pluginClassCache = new PluginClassCache();
final TargetClassesCollector targetClassesCollector =
new TargetClassesCollector(pluginClassCache);
final TargetMethodsCollector targetMethodsCollector =
new TargetMethodsCollector(pluginClassCache);

for (PsiElement psiElement : psiElements) {
for (final PsiElement psiElement : psiElements) {
if (psiElement instanceof PhpClass || psiElement instanceof Method) {
List<? extends PsiElement> results;

if (psiElement instanceof PhpClass) {
results = TargetClassesCollector.collect((PhpClass) psiElement);
if (results.size() > 0 ) {
results = targetClassesCollector.collect((PhpClass) psiElement);
if (!results.isEmpty()) {
collection.add(NavigationGutterIconBuilder
.create(AllIcons.Nodes.Class)
.setTargets(results)
Expand All @@ -54,8 +60,8 @@ public void collectSlowLineMarkers(@NotNull List<PsiElement> psiElements, @NotNu
);
}
} else {
results = TargetMethodsCollector.collect((Method) psiElement);
if (results.size() > 0 ) {
results = targetMethodsCollector.collect((Method) psiElement);
if (!results.isEmpty()) {
collection.add(NavigationGutterIconBuilder
.create(AllIcons.Nodes.Method)
.setTargets(results)
Expand All @@ -70,37 +76,49 @@ public void collectSlowLineMarkers(@NotNull List<PsiElement> psiElements, @NotNu
}

private static class PluginClassCache {
private HashMap<String, List<PhpClass>> pluginClassesMap = new HashMap<String, List<PhpClass>>();
private final HashMap<String, List<PhpClass>> pluginClassesMap = // NOPMD
new HashMap<>();

List<PhpClass> getTargetClassesForPlugin(@NotNull PhpClass phpClass, @NotNull String classFQN) {
List<PhpClass> results = new ArrayList<>();
private List<PhpClass> getTargetClassesForPlugin(
@NotNull final PhpClass phpClass,
@NotNull final String classFQN
) {

if (pluginClassesMap.containsKey(classFQN)) {
return pluginClassesMap.get(classFQN);
}

GetTargetClassNamesByPluginClassName targetClassesService = GetTargetClassNamesByPluginClassName.getInstance(phpClass.getProject());
ArrayList<String> targetClassNames = targetClassesService.execute(classFQN);
final GetTargetClassNamesByPluginClassName targetClassesService =
GetTargetClassNamesByPluginClassName.getInstance(phpClass.getProject());
final ArrayList<String> targetClassNames = targetClassesService.execute(classFQN);

final List<PhpClass> results = new ArrayList<>();

if (targetClassNames.size() == 0) {
if (targetClassNames.isEmpty()) {
pluginClassesMap.put(classFQN, results);
return results;
}

PhpIndex phpIndex = PhpIndex.getInstance(phpClass.getProject());
final PhpIndex phpIndex = PhpIndex.getInstance(phpClass.getProject());

for (String targetClassName : targetClassNames) {
Collection<PhpClass> targets = phpIndex.getClassesByFQN(targetClassName);
for (final String targetClassName : targetClassNames) {
Collection<PhpClass> targets = phpIndex.getInterfacesByFQN(targetClassName);

if (targets.isEmpty()) {
targets = phpIndex.getClassesByFQN(targetClassName);
}

results.addAll(targets);
}

return results;
}

List<PhpClass> getTargetClassesForPlugin(@NotNull PhpClass phpClass) {
List<PhpClass> classesForPlugin = getTargetClassesForPlugin(phpClass, phpClass.getPresentableFQN());
for (PhpClass parent: phpClass.getSupers()) {
protected List<PhpClass> getTargetClassesForPlugin(@NotNull final PhpClass phpClass) {
final List<PhpClass> classesForPlugin = getTargetClassesForPlugin(
phpClass, phpClass.getPresentableFQN()
);
for (final PhpClass parent: phpClass.getSupers()) {
classesForPlugin.addAll(getTargetClassesForPlugin(parent));
}

Expand All @@ -109,52 +127,59 @@ List<PhpClass> getTargetClassesForPlugin(@NotNull PhpClass phpClass) {
}

private static class TargetClassesCollector implements Collector<PhpClass, PhpClass> {
private PluginTargetLineMarkerProvider.PluginClassCache pluginClassCache;
private final PluginTargetLineMarkerProvider.PluginClassCache pluginClassCache;

TargetClassesCollector(PluginTargetLineMarkerProvider.PluginClassCache pluginClassCache) {
TargetClassesCollector(// NOPMD
final PluginTargetLineMarkerProvider.PluginClassCache pluginClassCache
) {
this.pluginClassCache = pluginClassCache;
}

@Override
public List<PhpClass> collect(@NotNull PhpClass psiElement) {
public List<PhpClass> collect(@NotNull final PhpClass psiElement) {
return pluginClassCache.getTargetClassesForPlugin(psiElement);
}
}

private static class TargetMethodsCollector implements Collector<Method, Method> {
private PluginTargetLineMarkerProvider.PluginClassCache pluginClassCache;
private final PluginTargetLineMarkerProvider.PluginClassCache pluginClassCache;

TargetMethodsCollector(PluginTargetLineMarkerProvider.PluginClassCache pluginClassCache) {
TargetMethodsCollector(// NOPMD
final PluginTargetLineMarkerProvider.PluginClassCache pluginClassCache
) {
this.pluginClassCache = pluginClassCache;
}

@Override
public List<Method> collect(@NotNull Method pluginMethod) {
List<Method> results = new ArrayList<>();
public List<Method> collect(@NotNull final Method pluginMethod) {
final List<Method> results = new ArrayList<>();

/* Check if the method is a plugin */
if (null == getPluginPrefix(pluginMethod)) {
return results;
}

PhpClass pluginClass = pluginMethod.getContainingClass();
final PhpClass pluginClass = pluginMethod.getContainingClass();
if (pluginClass == null) {
return results;
}

List<PhpClass> targetClasses = pluginClassCache.getTargetClassesForPlugin(pluginClass);
if (targetClasses.size() == 0) {
final List<PhpClass> targetClasses
= pluginClassCache.getTargetClassesForPlugin(pluginClass);
if (targetClasses.isEmpty()) {
return results;
}

for (PhpClass targetClass: targetClasses) {
String pluginPrefix = getPluginPrefix(pluginMethod);
String targetClassMethodName = getTargetMethodName(pluginMethod, pluginPrefix);
for (final PhpClass targetClass: targetClasses) {
final String pluginPrefix = getPluginPrefix(pluginMethod);
final String targetClassMethodName = getTargetMethodName(
pluginMethod, pluginPrefix
);
if (targetClassMethodName == null) {
continue;
}

Method targetMethod = targetClass.findMethodByName(targetClassMethodName);
final Method targetMethod = targetClass.findMethodByName(targetClassMethodName);
if (targetMethod == null) {
continue;
}
Expand All @@ -165,23 +190,21 @@ public List<Method> collect(@NotNull Method pluginMethod) {
return results;
}

private String getTargetMethodName(Method pluginMethod, String pluginPrefix) {
String pluginMethodName = pluginMethod.getName();
String targetClassMethodName = pluginMethodName.
replace(pluginPrefix, "");
private String getTargetMethodName(final Method pluginMethod, final String pluginPrefix) {
final String targetClassMethodName = pluginMethod.getName().replace(pluginPrefix, "");
if (targetClassMethodName.isEmpty()) {
return null;
}
char firstCharOfTargetName = targetClassMethodName.charAt(0);
int charType = Character.getType(firstCharOfTargetName);
if (charType == Character.LOWERCASE_LETTER) {
final char firstCharOfTargetName = targetClassMethodName.charAt(0);
if (Character.getType(firstCharOfTargetName) == Character.LOWERCASE_LETTER) {
return null;
}
return Character.toLowerCase(firstCharOfTargetName) + targetClassMethodName.substring(1);
return Character.toLowerCase(firstCharOfTargetName)
+ targetClassMethodName.substring(1);
}

private String getPluginPrefix(Method pluginMethod) {
String pluginMethodName = pluginMethod.getName();
private String getPluginPrefix(final Method pluginMethod) {
final String pluginMethodName = pluginMethod.getName();
if (pluginMethodName.startsWith(Plugin.PluginType.around.toString())) {
return Plugin.PluginType.around.toString();
}
Expand Down