private static void parameters(Tree.TypeParameterList tpl, StyledString label) {
   if (tpl != null && !tpl.getTypeParameterDeclarations().isEmpty()) {
     label.append("<");
     int len = tpl.getTypeParameterDeclarations().size(), i = 0;
     for (Tree.TypeParameterDeclaration p : tpl.getTypeParameterDeclarations()) {
       label.append(name(p.getIdentifier()), TYPE_STYLER);
       if (++i < len) label.append(", ");
     }
     label.append(">");
   }
 }
 @Override
 public void visit(Tree.TypeParameterDeclaration that) {
   super.visit(that);
   if (that.getDeclarationModel() == declaration) {
     specify();
   }
 }
  static StyledString getStyledLabelFor(Node n) {
    // TODO: it would be much better to render types
    //      from the tree nodes instead of from the
    //      model nodes

    if (n instanceof Tree.TypeParameterDeclaration) {
      Tree.TypeParameterDeclaration ac = (Tree.TypeParameterDeclaration) n;
      return new StyledString(name(ac.getIdentifier()));
    }
    if (n instanceof Tree.AnyClass) {
      Tree.AnyClass ac = (Tree.AnyClass) n;
      StyledString label = new StyledString("class ", KW_STYLER);
      label.append(name(ac.getIdentifier()), TYPE_ID_STYLER);
      parameters(ac.getTypeParameterList(), label);
      parameters(ac.getParameterList(), label);
      return label;
    } else if (n instanceof Tree.AnyInterface) {
      Tree.AnyInterface ai = (Tree.AnyInterface) n;
      StyledString label = new StyledString("interface ", KW_STYLER);
      label.append(name(ai.getIdentifier()), TYPE_ID_STYLER);
      parameters(ai.getTypeParameterList(), label);
      return label;
    } else if (n instanceof Tree.ObjectDefinition) {
      Tree.ObjectDefinition ai = (Tree.ObjectDefinition) n;
      return new StyledString("object ", KW_STYLER).append(name(ai.getIdentifier()), ID_STYLER);
    } else if (n instanceof Tree.AttributeSetterDefinition) {
      Tree.AttributeSetterDefinition ai = (Tree.AttributeSetterDefinition) n;
      return new StyledString("assign ", KW_STYLER).append(name(ai.getIdentifier()), ID_STYLER);
    } else if (n instanceof Tree.TypedDeclaration) {
      Tree.TypedDeclaration td = (Tree.TypedDeclaration) n;
      String type;
      Styler styler;
      if (td.getType() instanceof Tree.VoidModifier) {
        type = "void";
        styler = KW_STYLER;
      } else {
        type = type(td.getType());
        styler = TYPE_STYLER;
      }
      StyledString label = new StyledString(type, styler);
      label.append(" ").append(name(td.getIdentifier()), ID_STYLER);
      if (n instanceof Tree.AnyMethod) {
        Tree.AnyMethod am = (Tree.AnyMethod) n;
        parameters(am.getTypeParameterList(), label);
        for (Tree.ParameterList pl : am.getParameterLists()) {
          parameters(pl, label);
        }
      }
      return label;
    } else if (n instanceof Tree.CompilationUnit) {
      Tree.CompilationUnit ai = (Tree.CompilationUnit) n;
      return new StyledString(ai.getUnit().getFilename());
    } else if (n instanceof Tree.ImportList) {
      return new StyledString("imports");
    } else if (n instanceof Tree.Import) {
      Tree.Import ai = (Tree.Import) n;
      if (ai.getImportPath() != null && !ai.getImportPath().getIdentifiers().isEmpty()) {
        return new StyledString(toPath(ai), QUALIFIER_STYLER);
      }
    } else if (n instanceof PackageNode) {
      PackageNode pn = (PackageNode) n;
      if (pn.getPackageName().isEmpty()) {
        return new StyledString("default package");
      } else {
        return new StyledString(pn.getPackageName(), QUALIFIER_STYLER);
      }
    }

    return new StyledString("<something>");
  }