Skip to content

Commit 53f7725

Browse files
Merge pull request #1121 from korovitskyi/406-sorting-plugin-marker
406: added sorting plugin list marker
2 parents cc17d24 + 9e2cde5 commit 53f7725

File tree

10 files changed

+390
-91
lines changed

10 files changed

+390
-91
lines changed

src/com/magento/idea/magento2plugin/actions/generation/PluginGenerateMethodHandlerBase.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242
import com.magento.idea.magento2plugin.util.magento.plugin.GetTargetClassNamesByPluginClassName;
4343
import com.magento.idea.magento2plugin.util.magento.plugin.IsPluginAllowedForMethodUtil;
4444
import gnu.trove.THashSet;
45-
import java.util.ArrayList;
4645
import java.util.Collection;
4746
import java.util.Iterator;
4847
import java.util.List;
@@ -88,9 +87,9 @@ public boolean isValidFor(final Editor editor, final PsiFile file) {
8887
return false;
8988
}
9089
final GetTargetClassNamesByPluginClassName targetClassesService
91-
= GetTargetClassNamesByPluginClassName.getInstance(editor.getProject());
90+
= new GetTargetClassNamesByPluginClassName(editor.getProject());
9291
final String currentClass = phpClass.getFQN().substring(1);
93-
final ArrayList<String> targetClassNames = targetClassesService.execute(currentClass);
92+
final List<String> targetClassNames = targetClassesService.execute(currentClass);
9493
return !targetClassNames.isEmpty();
9594
}
9695

@@ -241,9 +240,9 @@ protected PhpNamedElementNode[] targetMethods(
241240
final TreeMap<String, PhpNamedElementNode> nodes = new TreeMap();
242241

243242
final GetTargetClassNamesByPluginClassName targetClassesService =
244-
GetTargetClassNamesByPluginClassName.getInstance(phpClass.getProject());
243+
new GetTargetClassNamesByPluginClassName(phpClass.getProject());
245244
final String currentClass = phpClass.getFQN().substring(1);
246-
final ArrayList<String> targetClassNames = targetClassesService.execute(currentClass);
245+
final List<String> targetClassNames = targetClassesService.execute(currentClass);
247246
for (final String targetClassName : targetClassNames) {
248247
final PhpClass targetClass = GetPhpClassByFQN.getInstance(
249248
phpClass.getProject()

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

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
import com.magento.idea.magento2plugin.magento.packages.Package;
2828
import com.magento.idea.magento2plugin.util.GetPhpClassByFQN;
2929
import com.magento.idea.magento2plugin.util.magento.plugin.GetTargetClassNamesByPluginClassName;
30-
import java.util.ArrayList;
30+
import java.util.List;
3131
import org.jetbrains.annotations.NotNull;
3232

3333
@SuppressWarnings({"PMD.ExcessiveMethodLength", "PMD.NPathComplexity", "PMD.CognitiveComplexity"})
@@ -75,10 +75,8 @@ public void visitPhpMethod(final Method pluginMethod) {
7575
((PhpClass) parentClass).getNameIdentifier();
7676
final String currentClass = ((PhpClass) parentClass).getFQN().substring(1);
7777
final GetTargetClassNamesByPluginClassName targetClassesService =
78-
GetTargetClassNamesByPluginClassName.getInstance(
79-
problemsHolder.getProject()
80-
);
81-
final ArrayList<String> targetClassNames =
78+
new GetTargetClassNamesByPluginClassName(problemsHolder.getProject());
79+
final List<String> targetClassNames =
8280
targetClassesService.execute(currentClass);
8381

8482
for (final String targetClassName : targetClassNames) {

src/com/magento/idea/magento2plugin/linemarker/php/PluginLineMarkerProvider.java

Lines changed: 131 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,13 @@
1515
import com.intellij.psi.search.GlobalSearchScope;
1616
import com.intellij.psi.util.PsiTreeUtil;
1717
import com.intellij.util.indexing.FileBasedIndex;
18-
import com.jetbrains.php.PhpIndex;
1918
import com.jetbrains.php.lang.psi.elements.Method;
2019
import com.jetbrains.php.lang.psi.elements.PhpClass;
2120
import com.magento.idea.magento2plugin.linemarker.SearchGutterIconNavigationHandler;
21+
import com.magento.idea.magento2plugin.linemarker.php.data.PluginMethodData;
2222
import com.magento.idea.magento2plugin.project.Settings;
2323
import com.magento.idea.magento2plugin.stubs.indexes.PluginIndex;
24+
import com.magento.idea.magento2plugin.stubs.indexes.data.PluginData;
2425
import java.util.ArrayList;
2526
import java.util.Collection;
2627
import java.util.HashMap;
@@ -94,12 +95,13 @@ public void collectSlowLineMarkers(
9495
}
9596
}
9697

98+
@SuppressWarnings("checkstyle:LineLength")
9799
private static class PluginClassCache {
98100

99-
private final Map<String, List<PhpClass>> classPluginsMap = new HashMap<>();
101+
private final Map<String, List<PluginData>> classPluginsMap = new HashMap<>();
100102

101-
public List<PhpClass> getPluginsForClass(final @NotNull PhpClass phpClass) {
102-
final List<PhpClass> pluginsForClass = getPluginsForClass(
103+
public List<PluginData> getPluginsForClass(final @NotNull PhpClass phpClass) {
104+
final List<PluginData> pluginsForClass = getPluginsForClass(
103105
phpClass,
104106
phpClass.getPresentableFQN()
105107
);
@@ -114,64 +116,73 @@ public List<PhpClass> getPluginsForClass(final @NotNull PhpClass phpClass) {
114116
return pluginsForClass;
115117
}
116118

117-
public List<PhpClass> getPluginsForClass(
119+
public List<PluginData> getPluginsForClass(
118120
final @NotNull PhpClass phpClass,
119121
final @NotNull String classFQN
120122
) {
121123
if (classPluginsMap.containsKey(classFQN)) {
122124
return classPluginsMap.get(classFQN);
123125
}
124126

125-
final List<Set<String>> plugins = FileBasedIndex.getInstance()
127+
final List<Set<PluginData>> plugins = FileBasedIndex.getInstance()
126128
.getValues(
127129
PluginIndex.KEY,
128130
classFQN,
129131
GlobalSearchScope.allScope(phpClass.getProject())
130132
);
131-
final List<PhpClass> results = new ArrayList<>();
133+
final List<PluginData> results = new ArrayList<>();
132134

133135
if (plugins.isEmpty()) {
134136
classPluginsMap.put(classFQN, results);
135137

136138
return results;
137139
}
138-
final PhpIndex phpIndex = PhpIndex.getInstance(phpClass.getProject());
139140

140-
for (final Set<String> pluginClassNames : plugins) {
141-
for (final String pluginClassName: pluginClassNames) {
142-
results.addAll(phpIndex.getClassesByFQN(pluginClassName));
141+
for (final Set<PluginData> pluginDataList : plugins) {
142+
for (final PluginData pluginData: pluginDataList) {
143+
pluginData.setPhpClass(phpClass);
144+
results.add(pluginData);
143145
}
144146
}
145147
classPluginsMap.put(classFQN, results);
146148

147149
return results;
148150
}
149151

150-
public List<Method> getPluginMethods(final List<PhpClass> plugins) {
151-
final List<Method> methodList = new ArrayList<>();
152+
public List<PluginMethodData> getPluginMethods(final List<PluginData> pluginDataList) {
153+
final List<PluginMethodData> result = new ArrayList<>();
152154

153-
for (final PhpClass plugin: plugins) {
154-
methodList.addAll(getPluginMethods(plugin));
155+
for (final PluginData pluginData: pluginDataList) {
156+
for (final PhpClass plugin: pluginData.getPhpClassCollection()) {
157+
//@todo add module sequence ID if sortOrder equal zero. It should be negative value.
158+
result.addAll(getPluginMethods(plugin, pluginData.getSortOrder()));
159+
}
155160
}
156161

157-
return methodList;
162+
return result;
158163
}
159164

160-
public List<Method> getPluginMethods(final @NotNull PhpClass pluginClass) {
161-
final List<Method> methodList = new ArrayList<>();
165+
public List<PluginMethodData> getPluginMethods(final @NotNull PhpClass pluginClass, final int sortOrder) {
166+
final List<PluginMethodData> methodList = new ArrayList<>();
162167

163168
for (final Method method : pluginClass.getMethods()) {
164169
if (method.getAccess().isPublic()) {
165170
final String pluginMethodName = method.getName();
166171

167172
if (pluginMethodName.length() > MIN_PLUGIN_METHOD_NAME_LENGTH) {
168-
methodList.add(method);
173+
//@todo module sequence value should be set here instead of zero.
174+
methodList.add(getPluginMethodDataObject(method, sortOrder, 0));
169175
}
170176
}
171177
}
172178

173179
return methodList;
174180
}
181+
182+
@NotNull
183+
private PluginMethodData getPluginMethodDataObject(final Method method, final int sortOrder, final int moduleSequence) {
184+
return new PluginMethodData(method, sortOrder, moduleSequence);
185+
}
175186
}
176187

177188
private static class ClassPluginCollector implements Collector<PhpClass, PhpClass> {
@@ -186,41 +197,134 @@ public ClassPluginCollector(
186197

187198
@Override
188199
public List<PhpClass> collect(final @NotNull PhpClass psiElement) {
189-
return pluginClassCache.getPluginsForClass(psiElement);
200+
final List<PluginData> pluginDataList = pluginClassCache.getPluginsForClass(psiElement);
201+
final List<PhpClass> phpClassList = new ArrayList<>();
202+
203+
for (final PluginData pluginData: pluginDataList) {
204+
phpClassList.addAll(pluginData.getPhpClassCollection());
205+
}
206+
207+
return phpClassList;
190208
}
191209
}
192210

193211
private static class MethodPluginCollector implements Collector<Method, Method> {
194212

195213
private final PluginLineMarkerProvider.PluginClassCache pluginClassCache;
214+
private final Map<String, Integer> pluginMethodsSortOrder;
215+
private static final String AFTER_PLUGIN_PREFIX = "after";
196216

197217
public MethodPluginCollector(
198218
final PluginLineMarkerProvider.PluginClassCache pluginClassCache
199219
) {
200220
this.pluginClassCache = pluginClassCache;
221+
pluginMethodsSortOrder = new HashMap<>();
222+
pluginMethodsSortOrder.put("before", 1);
223+
pluginMethodsSortOrder.put("around", 2);
224+
pluginMethodsSortOrder.put(AFTER_PLUGIN_PREFIX, 3);
201225
}
202226

227+
@SuppressWarnings("checkstyle:LineLength")
203228
@Override
204229
public List<Method> collect(final @NotNull Method psiElement) {
205230
final List<Method> results = new ArrayList<>();
206-
207231
final PhpClass methodClass = psiElement.getContainingClass();
208232

209233
if (methodClass == null) {
210234
return results;
211235
}
212-
final List<PhpClass> pluginsList = pluginClassCache.getPluginsForClass(methodClass);
213-
final List<Method> pluginMethods = pluginClassCache.getPluginMethods(pluginsList);
214236

237+
final List<PluginData> pluginDataList = pluginClassCache.getPluginsForClass(methodClass);
238+
final List<PluginMethodData> pluginMethods = pluginClassCache.getPluginMethods(pluginDataList);
215239
final String classMethodName = WordUtils.capitalize(psiElement.getName());
216240

217-
for (final Method pluginMethod: pluginMethods) {
218-
if (isPluginMethodName(pluginMethod.getName(), classMethodName)) {
219-
results.add(pluginMethod);
241+
pluginMethods.removeIf(pluginMethod -> !isPluginMethodName(pluginMethod.getMethodName(), classMethodName));
242+
sortMethods(pluginMethods, results);
243+
244+
return results;
245+
}
246+
247+
@SuppressWarnings({"checkstyle:Indentation", "checkstyle:OperatorWrap", "checkstyle:LineLength", "PMD.NPathComplexity"})
248+
private void sortMethods(final @NotNull List<PluginMethodData> methodDataList, final List<Method> results) {
249+
final List<Integer> bufferSortOrderList = new ArrayList<>();
250+
int biggestSortOrder = 0;
251+
252+
for (final PluginMethodData pluginMethodData: methodDataList) {
253+
final String methodName = pluginMethodData.getMethodName();
254+
255+
if (methodName.startsWith("around")) {
256+
bufferSortOrderList.add(pluginMethodData.getSortOrder());
257+
}
258+
259+
if (pluginMethodData.getSortOrder() > biggestSortOrder) {
260+
biggestSortOrder = pluginMethodData.getSortOrder();
220261
}
221262
}
222263

223-
return results;
264+
final int biggestSortOrderValue = biggestSortOrder;
265+
266+
methodDataList.sort(
267+
(PluginMethodData method1, PluginMethodData method2) -> {
268+
final String firstMethodName = method1.getMethodName();
269+
final String secondMethodName = method2.getMethodName();
270+
final int firstIndexEnd = firstMethodName.startsWith(AFTER_PLUGIN_PREFIX) ? 5 : 6;
271+
final int secondIndexEnd = secondMethodName.startsWith(AFTER_PLUGIN_PREFIX) ? 5 : 6;
272+
final String firstMethodPrefix = firstMethodName.substring(0,firstIndexEnd);
273+
final String secondMethodPrefix = secondMethodName.substring(0,secondIndexEnd);
274+
275+
if (!pluginMethodsSortOrder.containsKey(firstMethodPrefix)
276+
|| !pluginMethodsSortOrder.containsKey(secondMethodPrefix)) {
277+
return firstMethodName.compareTo(secondMethodName);
278+
}
279+
280+
final Integer firstNameSortOrder = pluginMethodsSortOrder.get(firstMethodPrefix);
281+
final Integer secondNameSortOrder = pluginMethodsSortOrder.get(secondMethodPrefix);
282+
283+
if (firstNameSortOrder.compareTo(secondNameSortOrder) != 0) {
284+
return firstNameSortOrder.compareTo(secondNameSortOrder);
285+
}
286+
287+
Integer firstBuffer = 0;
288+
Integer secondBuffer = 0;
289+
final Integer firstModuleSequence = (method1.getModuleSequence() + biggestSortOrderValue) * -1;
290+
final Integer secondModuleSequence = (method2.getModuleSequence() + biggestSortOrderValue) * -1;
291+
final Integer firstSortOrder = method1.getSortOrder() == 0 ?
292+
firstModuleSequence :
293+
method1.getSortOrder();
294+
final Integer secondSortOrder = method2.getSortOrder() == 0 ?
295+
secondModuleSequence :
296+
method2.getSortOrder();
297+
298+
if (!bufferSortOrderList.isEmpty() && firstMethodPrefix.equals(AFTER_PLUGIN_PREFIX)) {
299+
for (final Integer bufferSortOrder : bufferSortOrderList) {
300+
if (bufferSortOrder < firstSortOrder && firstBuffer < bufferSortOrder + 1) {
301+
firstBuffer = bufferSortOrder + 1;
302+
}
303+
304+
if (bufferSortOrder < secondSortOrder && secondBuffer < bufferSortOrder + 1) {
305+
secondBuffer = bufferSortOrder + 1;
306+
}
307+
}
308+
}
309+
310+
firstBuffer = firstBuffer.equals(0) ? firstSortOrder : firstBuffer * -1;
311+
secondBuffer = secondBuffer.equals(0) ? secondSortOrder : secondBuffer * -1;
312+
313+
if (firstBuffer.compareTo(secondBuffer) == 0 && firstSortOrder.compareTo(secondSortOrder) != 0) {
314+
return firstSortOrder.compareTo(secondSortOrder);
315+
}
316+
317+
if (firstBuffer.compareTo(secondBuffer) == 0 && firstSortOrder.compareTo(secondSortOrder) == 0) {
318+
return firstModuleSequence.compareTo(secondModuleSequence);
319+
}
320+
321+
return firstBuffer.compareTo(secondBuffer);
322+
}
323+
);
324+
325+
for (final PluginMethodData pluginMethodData: methodDataList) {
326+
results.add(pluginMethodData.getMethod());
327+
}
224328
}
225329

226330
private boolean isPluginMethodName(

src/com/magento/idea/magento2plugin/linemarker/php/PluginTargetLineMarkerProvider.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,8 @@ private List<PhpClass> getTargetClassesForPlugin(
9797
}
9898

9999
final GetTargetClassNamesByPluginClassName targetClassesService =
100-
GetTargetClassNamesByPluginClassName.getInstance(phpClass.getProject());
101-
final ArrayList<String> targetClassNames = targetClassesService.execute(classFQN);
100+
new GetTargetClassNamesByPluginClassName(phpClass.getProject());
101+
final List<String> targetClassNames = targetClassesService.execute(classFQN);
102102

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

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright © Magento, Inc. All rights reserved.
3+
* See COPYING.txt for license details.
4+
*/
5+
6+
package com.magento.idea.magento2plugin.linemarker.php.data;
7+
8+
import com.jetbrains.php.lang.psi.elements.Method;
9+
10+
public class PluginMethodData {
11+
12+
private final Method method;
13+
private final int sortOrder;
14+
private final int moduleSequence;
15+
16+
/**
17+
* Plugin method data class.
18+
*
19+
* @param method Plugin method
20+
* @param sortOrder Plugin SortOrder integer value
21+
* @param moduleSequence PHP class placed module sequence integer value
22+
*/
23+
public PluginMethodData(final Method method, final int sortOrder, final int moduleSequence) {
24+
this.method = method;
25+
this.sortOrder = sortOrder;
26+
this.moduleSequence = moduleSequence;
27+
}
28+
29+
public Method getMethod() {
30+
return method;
31+
}
32+
33+
public int getSortOrder() {
34+
return sortOrder;
35+
}
36+
37+
public int getModuleSequence() {
38+
return moduleSequence;
39+
}
40+
41+
public String getMethodName() {
42+
return method.getName();
43+
}
44+
}

src/com/magento/idea/magento2plugin/magento/files/ModuleDiXml.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ public class ModuleDiXml implements ModuleFileInterface {
4646

4747
// attributes
4848
public static String NAME_ATTR = "name";
49+
public static String SORT_ORDER_ATTR = "sortOrder";
4950
public static String TYPE_ATTR = "type";
5051
public static String PREFERENCE_ATTR_FOR = "for";
5152
public static String CLI_COMMAND_ATTR_COMMANDS = "commands";

0 commit comments

Comments
 (0)