1515import com .intellij .psi .search .GlobalSearchScope ;
1616import com .intellij .psi .util .PsiTreeUtil ;
1717import com .intellij .util .indexing .FileBasedIndex ;
18- import com .jetbrains .php .PhpIndex ;
1918import com .jetbrains .php .lang .psi .elements .Method ;
2019import com .jetbrains .php .lang .psi .elements .PhpClass ;
2120import com .magento .idea .magento2plugin .linemarker .SearchGutterIconNavigationHandler ;
21+ import com .magento .idea .magento2plugin .linemarker .php .data .PluginMethodData ;
2222import com .magento .idea .magento2plugin .project .Settings ;
2323import com .magento .idea .magento2plugin .stubs .indexes .PluginIndex ;
24+ import com .magento .idea .magento2plugin .stubs .indexes .data .PluginData ;
2425import java .util .ArrayList ;
2526import java .util .Collection ;
2627import 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,58 +116,62 @@ 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+ List <PluginMethodData > result = new ArrayList <>();
152154
153- for (final PhpClass plugin : plugins ) {
154- methodList .addAll (getPluginMethods (plugin ));
155+ for (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 , 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 (new PluginMethodData (method , sortOrder , 0 ));
169175 }
170176 }
171177 }
@@ -186,41 +192,133 @@ public ClassPluginCollector(
186192
187193 @ Override
188194 public List <PhpClass > collect (final @ NotNull PhpClass psiElement ) {
189- return pluginClassCache .getPluginsForClass (psiElement );
195+ List <PluginData > pluginDataList = pluginClassCache .getPluginsForClass (psiElement );
196+ List <PhpClass > phpClassList = new ArrayList <>();
197+
198+ for (PluginData pluginData : pluginDataList ) {
199+ phpClassList .addAll (pluginData .getPhpClassCollection ());
200+ }
201+
202+ return phpClassList ;
190203 }
191204 }
192205
193206 private static class MethodPluginCollector implements Collector <Method , Method > {
194207
195208 private final PluginLineMarkerProvider .PluginClassCache pluginClassCache ;
209+ private final Map <String , Integer > pluginMethodsSortOrder ;
196210
197211 public MethodPluginCollector (
198212 final PluginLineMarkerProvider .PluginClassCache pluginClassCache
199213 ) {
200214 this .pluginClassCache = pluginClassCache ;
215+ pluginMethodsSortOrder = new HashMap <>();
216+ pluginMethodsSortOrder .put ("before" , 1 );
217+ pluginMethodsSortOrder .put ("around" , 2 );
218+ pluginMethodsSortOrder .put ("after" , 3 );
201219 }
202220
221+ @ SuppressWarnings ("checkstyle:LineLength" )
203222 @ Override
204223 public List <Method > collect (final @ NotNull Method psiElement ) {
205224 final List <Method > results = new ArrayList <>();
206-
207225 final PhpClass methodClass = psiElement .getContainingClass ();
208226
209227 if (methodClass == null ) {
210228 return results ;
211229 }
212- final List <PhpClass > pluginsList = pluginClassCache .getPluginsForClass (methodClass );
213- final List <Method > pluginMethods = pluginClassCache .getPluginMethods (pluginsList );
214230
231+ final List <PluginData > pluginDataList = pluginClassCache .getPluginsForClass (methodClass );
232+ final List <PluginMethodData > pluginMethods = pluginClassCache .getPluginMethods (pluginDataList );
215233 final String classMethodName = WordUtils .capitalize (psiElement .getName ());
216234
217- for (final Method pluginMethod : pluginMethods ) {
218- if (isPluginMethodName (pluginMethod .getName (), classMethodName )) {
219- results .add (pluginMethod );
235+ pluginMethods .removeIf (pluginMethod -> !isPluginMethodName (pluginMethod .getMethodName (), classMethodName ));
236+ sortMethods (pluginMethods , results );
237+
238+ return results ;
239+ }
240+
241+ @ SuppressWarnings ({"checkstyle:Indentation" , "checkstyle:OperatorWrap" , "checkstyle:LineLength" })
242+ private void sortMethods (final @ NotNull List <PluginMethodData > methodDataList , List <Method > results ) {
243+ List <Integer > bufferSortOrderList = new ArrayList <>();
244+ int biggestSortOrder = 0 ;
245+
246+ for (PluginMethodData pluginMethodData : methodDataList ) {
247+ String methodName = pluginMethodData .getMethodName ();
248+
249+ if (methodName .startsWith ("around" )) {
250+ bufferSortOrderList .add (pluginMethodData .getSortOrder ());
251+ }
252+
253+ if (pluginMethodData .getSortOrder () > biggestSortOrder ) {
254+ biggestSortOrder = pluginMethodData .getSortOrder ();
220255 }
221256 }
222257
223- return results ;
258+ final int biggestSortOrderValue = biggestSortOrder ;
259+
260+ methodDataList .sort (
261+ (PluginMethodData method1 , PluginMethodData method2 ) -> {
262+ final String firstMethodName = method1 .getMethodName ();
263+ final String secondMethodName = method2 .getMethodName ();
264+ final int firstIndexEnd = firstMethodName .startsWith ("after" ) ? 5 : 6 ;
265+ final int secondIndexEnd = secondMethodName .startsWith ("after" ) ? 5 : 6 ;
266+ String firstMethodPrefix = firstMethodName .substring (0 ,firstIndexEnd );
267+ String secondMethodPrefix = secondMethodName .substring (0 ,secondIndexEnd );
268+
269+ if (!pluginMethodsSortOrder .containsKey (firstMethodPrefix )
270+ || !pluginMethodsSortOrder .containsKey (secondMethodPrefix )) {
271+ return firstMethodName .compareTo (secondMethodName );
272+ }
273+
274+ final Integer firstNameSortOrder = pluginMethodsSortOrder .get (firstMethodPrefix );
275+ final Integer secondNameSortOrder = pluginMethodsSortOrder .get (secondMethodPrefix );
276+
277+ if (firstNameSortOrder .compareTo (secondNameSortOrder ) != 0 ) {
278+ return firstNameSortOrder .compareTo (secondNameSortOrder );
279+ }
280+
281+ Integer firstBuffer = 0 ;
282+ Integer secondBuffer = 0 ;
283+ Integer firstModuleSequence = (method1 .getModuleSequence () + biggestSortOrderValue ) * -1 ;
284+ Integer secondModuleSequence = (method2 .getModuleSequence () + biggestSortOrderValue ) * -1 ;
285+ Integer firstSortOrder = method1 .getSortOrder () != 0 ?
286+ method1 .getSortOrder () :
287+ firstModuleSequence ;
288+ Integer secondSortOrder = method2 .getSortOrder () != 0 ?
289+ method2 .getSortOrder () :
290+ secondModuleSequence ;
291+
292+ if (!bufferSortOrderList .isEmpty () && firstMethodPrefix .equals ("after" )) {
293+ for (Integer bufferSortOrder : bufferSortOrderList ) {
294+ if (bufferSortOrder < firstSortOrder && firstBuffer < bufferSortOrder + 1 ) {
295+ firstBuffer = bufferSortOrder + 1 ;
296+ }
297+
298+ if (bufferSortOrder < secondSortOrder && secondBuffer < bufferSortOrder + 1 ) {
299+ secondBuffer = bufferSortOrder + 1 ;
300+ }
301+ }
302+ }
303+
304+ firstBuffer = firstBuffer .equals (0 ) ? firstSortOrder : firstBuffer * -1 ;
305+ secondBuffer = secondBuffer .equals (0 ) ? secondSortOrder : secondBuffer * -1 ;
306+
307+ if (firstBuffer .compareTo (secondBuffer ) == 0 && firstSortOrder .compareTo (secondSortOrder ) != 0 ) {
308+ return firstSortOrder .compareTo (secondSortOrder );
309+ }
310+
311+ if (firstBuffer .compareTo (secondBuffer ) == 0 && firstSortOrder .compareTo (secondSortOrder ) == 0 ) {
312+ return firstModuleSequence .compareTo (secondModuleSequence );
313+ }
314+
315+ return firstBuffer .compareTo (secondBuffer );
316+ }
317+ );
318+
319+ for (PluginMethodData pluginMethodData : methodDataList ) {
320+ results .add (pluginMethodData .getMethod ());
321+ }
224322 }
225323
226324 private boolean isPluginMethodName (
0 commit comments