@Override
 public void startElement(String uri, String localName, String qName, Attributes attributes)
     throws SAXException {
   if ("item".equals(qName)) {
     externalName = attributes.getValue("name");
   } else if ("annotation".equals(qName)) {
     annotationFQN = attributes.getValue("name");
     arguments = new StringBuilder();
   } else if ("val".equals(qName)) {
     if (arguments.length() != 0) {
       arguments.append(",");
     }
     String name = attributes.getValue("name");
     if (name != null) {
       arguments.append(name);
       arguments.append("=");
     }
     arguments.append(attributes.getValue("val"));
   }
 }
 @Override
 public void endElement(String uri, String localName, String qName) throws SAXException {
   if ("item".equals(qName)) {
     externalName = null;
   } else if ("annotation".equals(qName)) {
     if (externalName != null && annotationFQN != null) {
       String argumentsString = arguments.length() == 0 ? "" : intern(arguments.toString());
       for (AnnotationData existingData : data.get(externalName)) {
         if (existingData.annotationClassFqName.equals(annotationFQN)) {
           duplicateError(file, externalName, "Duplicate annotation '" + annotationFQN + "' ");
         }
       }
       AnnotationData annData =
           internAnnotationData(new AnnotationData(annotationFQN, argumentsString));
       data.add(externalName, annData);
       annotationFQN = null;
       arguments = null;
     }
   }
 }
  @NotNull
  @Override
  public PsiTypeParameter createTypeParameter(String name, PsiClassType[] superTypes) {
    @NonNls StringBuilder builder = new StringBuilder();
    builder.append("public <").append(name);
    if (superTypes.length > 1
        || superTypes.length == 1
            && !superTypes[0].equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) {
      builder.append(" extends ");
      for (PsiClassType type : superTypes) {
        if (type.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) continue;
        builder.append(type.getCanonicalText()).append('&');
      }

      builder.delete(builder.length() - 1, builder.length());
    }
    builder.append("> void foo(){}");
    try {
      return createMethodFromText(builder.toString(), null).getTypeParameters()[0];
    } catch (RuntimeException e) {
      throw new IncorrectOperationException("type parameter text: " + builder.toString());
    }
  }
 @NotNull
 @Override
 public PsiDocTag createParamTag(
     @NotNull final String parameterName, @NonNls final String description)
     throws IncorrectOperationException {
   @NonNls final StringBuilder builder = new StringBuilder();
   builder.append(" * @param ");
   builder.append(parameterName);
   builder.append(" ");
   final String[] strings = description.split("\\n");
   for (int i = 0; i < strings.length; i++) {
     if (i > 0) builder.append("\n * ");
     builder.append(strings[i]);
   }
   return createDocTagFromText(builder.toString());
 }
 @NotNull
 @Override
 public PsiReferenceList createReferenceList(
     @NotNull final PsiJavaCodeReferenceElement[] references) throws IncorrectOperationException {
   @NonNls final StringBuilder builder = new StringBuilder();
   builder.append("void method()");
   if (references.length > 0) {
     builder.append(" throws ");
     for (int i = 0; i < references.length; i++) {
       if (i > 0) builder.append(", ");
       builder.append(references[i].getCanonicalText());
     }
   }
   builder.append(';');
   return createMethodFromText(builder.toString(), null).getThrowsList();
 }
 @NotNull
 @Override
 public PsiParameterList createParameterList(
     @NotNull final String[] names, @NotNull final PsiType[] types)
     throws IncorrectOperationException {
   @NonNls StringBuilder builder = new StringBuilder();
   builder.append("void method(");
   for (int i = 0; i < names.length; i++) {
     if (i > 0) builder.append(", ");
     builder.append(types[i].getCanonicalText()).append(' ').append(names[i]);
   }
   builder.append(");");
   return createMethodFromText(builder.toString(), null).getParameterList();
 }
 // This method is used for legacy reasons.
 // Old external annotations sometimes are bad XML: they have "<" and ">" characters in attributes
 // values. To prevent SAX parser from
 // failing, we escape attributes values.
 @NotNull
 private static String escapeAttributes(@NotNull String invalidXml) {
   // We assume that XML has single- and double-quote characters only for attribute values,
   // therefore we don't any complex parsing,
   // just have binary inAttribute state
   StringBuilder buf = new StringBuilder(invalidXml.length());
   boolean inAttribute = false;
   for (int i = 0; i < invalidXml.length(); i++) {
     char c = invalidXml.charAt(i);
     if (inAttribute && c == '<') {
       buf.append("&lt;");
     } else if (inAttribute && c == '>') {
       buf.append("&gt;");
     } else if (c == '\"' || c == '\'') {
       buf.append('\"');
       inAttribute = !inAttribute;
     } else {
       buf.append(c);
     }
   }
   return buf.toString();
 }