Iterates through entries in the given map and matches together parent and child classes. @param mappings @return
(MappedClass mc, Map<String, MappedClass> mappings)
| 249 | * @return |
| 250 | */ |
| 251 | public static Map<String, MappedClass> linkMappings(MappedClass mc, Map<String, MappedClass> mappings) { |
| 252 | // Setting up parent structure |
| 253 | if (!mc.hasParent()) { |
| 254 | // No parent, check to see if one can be found |
| 255 | MappedClass parentMappedClass = mappings.get(mc.getNode().superName); |
| 256 | if (parentMappedClass != null) { |
| 257 | mappings = linkMappings(parentMappedClass, mappings); |
| 258 | parentMappedClass.addChild(mc); |
| 259 | mc.setParent(parentMappedClass); |
| 260 | } |
| 261 | } |
| 262 | // Adding interfaces |
| 263 | if (mc.getInterfaces().size() == 0) { |
| 264 | for (String interfaze : mc.getNode().interfaces) { |
| 265 | MappedClass mappedInterface = mappings.get(interfaze); |
| 266 | if (mappedInterface != null) { |
| 267 | mappings = linkMappings(mappedInterface, mappings); |
| 268 | mc.addInterface(mappedInterface); |
| 269 | mappedInterface.addChild(mc); |
| 270 | } |
| 271 | } |
| 272 | } |
| 273 | // Setting up outer/inner class structure |
| 274 | if (mc.getOuterClass() == null) { |
| 275 | boolean outerClassASM = mc.getNode().outerClass != null; |
| 276 | boolean outerClassName = mc.getOriginalName().contains("$"); |
| 277 | String outerClass = null; |
| 278 | if (outerClassASM) { |
| 279 | outerClass = mc.getNode().outerClass; |
| 280 | } else if (outerClassName) { |
| 281 | outerClass = mc.getOriginalName().substring(0, mc.getOriginalName().indexOf("$")); |
| 282 | if (outerClass.endsWith("/")) { |
| 283 | // TODO: Do this better, account for obfuscations that |
| 284 | // purposefully put $'s in names |
| 285 | // The name starts with the $ so probably not actually an |
| 286 | // outer class. Just obfuscation. |
| 287 | outerClass = null; |
| 288 | } |
| 289 | } else { |
| 290 | int synths = 0, synthID = -1; |
| 291 | for (int fieldKey = 0; fieldKey < mc.getFields().size(); fieldKey++) { |
| 292 | // Check for synthetic fields |
| 293 | FieldNode fn = mc.getFields().get(fieldKey).getFieldNode(); |
| 294 | if (fn == null) { |
| 295 | continue; |
| 296 | } |
| 297 | int access = fn.access; |
| 298 | if (AccessHelper.isSynthetic(access) && AccessHelper.isFinal(access) && !AccessHelper.isPublic(access) && !AccessHelper.isPrivate(access) |
| 299 | && !AccessHelper.isProtected(access)) { |
| 300 | synths++; |
| 301 | synthID = fieldKey; |
| 302 | } |
| 303 | } |
| 304 | if (synths == 1) { |
| 305 | // If there is a single synthetic field referencing a class, |
| 306 | // it's probably an anonymous inner class. |
| 307 | FieldNode fn = mc.getFields().get(synthID).getFieldNode(); |
| 308 | if (fn != null && fn.desc.contains(";")) { |
no test coverage detected