private static @NotNull TypeInfo fromTypeElement(@NotNull LighterAST tree,
                                                   @NotNull LighterASTNode typeElement) {
    TypeInfo info = null;
    TypeKind derivedKind = null;
    for (LighterASTNode child : tree.getChildren(typeElement)) {
      IElementType tokenType = child.getTokenType();
      if (PRIMITIVE_TYPES.contains(tokenType)) {
        info = new SimpleTypeInfo(TEXT_TO_KIND.get(((LighterASTTokenNode)child).getText().toString()));
      }
      else if (tokenType == JavaElementType.TYPE) {
        info = fromTypeElement(tree, child);
      }
      else if (tokenType == JavaElementType.DUMMY_ELEMENT) {
        info = fromString(LightTreeUtil.toFilteredString(tree, child, null));
      }
      else if (tokenType == JavaElementType.JAVA_CODE_REFERENCE) {
        info = fromCodeReference(tree, child);
      }
      else if (tokenType == JavaTokenType.EXTENDS_KEYWORD) {
        derivedKind = TypeKind.EXTENDS;
      }
      else if (tokenType == JavaTokenType.SUPER_KEYWORD) {
        derivedKind = TypeKind.SUPER;
      }
      else if (tokenType == JavaTokenType.QUEST) {
        info = new SimpleTypeInfo(TypeKind.WILDCARD); // may be overwritten
      }
      if (tokenType == JavaTokenType.LBRACKET) {
        info = Objects.requireNonNull(info).arrayOf();
      }
      else if (tokenType == JavaTokenType.ELLIPSIS) {
        info = Objects.requireNonNull(info).arrayOf().withEllipsis();
      }
    }
    if (info == null) {
      throw new IllegalArgumentException("Malformed type: " + LightTreeUtil.toFilteredString(tree, typeElement, null));
    }
    if (derivedKind != null) {
      info = new DerivedTypeInfo(derivedKind, info);
    }
    return info;
  }
private static @NotNull TypeInfo fromTypeElement(@NotNull LighterAST tree,
                                                   @NotNull LighterASTNode typeElement)