void (@NotNull TypeInfo info, @NotNull TypeAnnotationContainer.Collector collector, @NotNull LighterAST tree, @NotNull LighterASTNode element, byte @NotNull [] prefix) { // TODO: support bounds, generics and enclosing types int arrayCount = 0; List<LighterASTNode> children = tree.getChildren(element); for (LighterASTNode child : children) { IElementType tokenType = child.getTokenType(); if (tokenType == JavaTokenType.LBRACKET) { arrayCount++; } } int nestingLevel = 0; boolean bound = false; for (LighterASTNode child : children) { IElementType tokenType = child.getTokenType(); if (tokenType == JavaTokenType.EXTENDS_KEYWORD || tokenType == JavaTokenType.SUPER_KEYWORD) { bound = true; } if (tokenType == JavaElementType.TYPE && info instanceof DerivedTypeInfo) { byte[] newPrefix; if (bound) { newPrefix = Arrays.copyOf(prefix, prefix.length + 1); newPrefix[prefix.length] = TypeAnnotationContainer.Collector.WILDCARD_BOUND; } else { newPrefix = Arrays.copyOf(prefix, prefix.length + arrayCount); Arrays.fill(newPrefix, prefix.length, newPrefix.length, TypeAnnotationContainer.Collector.ARRAY_ELEMENT); } collectAnnotations(((DerivedTypeInfo)info).child(), collector, tree, child, newPrefix); } else if (tokenType == JavaTokenType.LBRACKET) { nestingLevel++; } else if (tokenType == JavaElementType.ANNOTATION) { String anno = LightTreeUtil.toFilteredString(tree, child, null); byte[] typePath = Arrays.copyOf(prefix, prefix.length + nestingLevel); Arrays.fill(typePath, prefix.length, typePath.length, TypeAnnotationContainer.Collector.ARRAY_ELEMENT); collector.add(typePath, anno); } } }