|
12 | 12 | import com.laytonsmith.abstraction.bukkit.BukkitMCCommandSender; |
13 | 13 | import com.laytonsmith.abstraction.bukkit.entities.BukkitMCPlayer; |
14 | 14 | import com.laytonsmith.annotations.api; |
| 15 | +import com.laytonsmith.annotations.api.Platforms; |
15 | 16 | import com.laytonsmith.commandhelper.CommandHelperPlugin; |
16 | 17 | import com.laytonsmith.core.MethodScriptComplete; |
17 | 18 | import com.laytonsmith.core.ObjectGenerator; |
@@ -363,26 +364,37 @@ public void testVoidAndReturnedVoidAreSEqualsAndOthers() throws Exception { |
363 | 364 | public void testFunctionsAreOnlyDefinedOnce() throws Exception { |
364 | 365 | Set<String> uhohs = new HashSet<>(); |
365 | 366 | Set<Class<Function>> set = ClassDiscovery.getDefaultInstance().loadClassesThatExtend(Function.class); |
366 | | - for(Class<Function> cf1 : set) { |
367 | | - for(Class<Function> cf2 : set) { |
368 | | - if(cf1 == cf2) { |
369 | | - continue; |
370 | | - } |
371 | | - api cf1a = cf1.getAnnotation(api.class); |
372 | | - api cf2a = cf2.getAnnotation(api.class); |
373 | | - if(cf1a == null || cf2a == null) { |
374 | | - continue; |
375 | | - } |
376 | | - if(!Arrays.equals(cf1a.platform(), cf2a.platform())) { |
377 | | - continue; |
378 | | - } |
379 | | - Function f1 = ReflectionUtils.instantiateUnsafe(cf1); |
380 | | - Function f2 = ReflectionUtils.instantiateUnsafe(cf2); |
381 | | - if(f1.getName().equals(f2.getName())) { |
382 | | - uhohs.add(f1.getName() + " is implemented in two places, " + cf1 + " and " + cf2); |
383 | | - } |
| 367 | + |
| 368 | + // Iterate over all function classes, adding a message to "uhohs" if they are double defined. |
| 369 | + Map<String, Class<Function>> funcMap = new HashMap<>(); |
| 370 | + for(Class<Function> funcClass : set) { |
| 371 | + |
| 372 | + // Ignore non-api functions. |
| 373 | + api funcClassApi = funcClass.getAnnotation(api.class); |
| 374 | + if(funcClassApi == null) { |
| 375 | + continue; |
| 376 | + } |
| 377 | + |
| 378 | + // Get the function name. |
| 379 | + String funcName = ReflectionUtils.instantiateUnsafe(funcClass).getName(); |
| 380 | + |
| 381 | + // Create an identifier string of the function name and its platforms. |
| 382 | + // Format: "funcName\tplatform1\tplatform2\t...platformN". Platforms are sorted to 'compare as sets'. |
| 383 | + StringBuilder idStr = new StringBuilder(funcName); |
| 384 | + Platforms[] platforms = funcClassApi.platform(); |
| 385 | + Arrays.sort(platforms, (Platforms p1, Platforms p2) -> p1.toString().compareTo(p2.toString())); |
| 386 | + for(Platforms platform : platforms) { |
| 387 | + idStr.append("\t").append(platform.toString()); |
| 388 | + } |
| 389 | + |
| 390 | + // Store the function in the map by its identifier, adding an message if it is double defined. |
| 391 | + Class<Function> replacedFuncClass = funcMap.put(idStr.toString(), funcClass); |
| 392 | + if(replacedFuncClass != null) { |
| 393 | + uhohs.add(funcName + " is implemented in two places, " + funcClass + " and " + replacedFuncClass); |
384 | 394 | } |
385 | 395 | } |
| 396 | + |
| 397 | + // Fail if a function was double defined. |
386 | 398 | if(!uhohs.isEmpty()) { |
387 | 399 | fail(StringUtils.Join(uhohs, "\n")); |
388 | 400 | } |
|
0 commit comments