edu.umd.cs.findbugs.TypeAnnotation.java Source code

Java tutorial

Introduction

Here is the source code for edu.umd.cs.findbugs.TypeAnnotation.java

Source

/*
 * FindBugs - Find Bugs in Java programs
 * Copyright (C) 2006, University of Maryland
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307, USA
 */
package edu.umd.cs.findbugs;

import java.io.IOException;

import org.apache.bcel.generic.Type;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;

import edu.umd.cs.findbugs.ba.AnalysisContext;
import edu.umd.cs.findbugs.ba.SignatureConverter;
import edu.umd.cs.findbugs.ba.generic.GenericObjectType;
import edu.umd.cs.findbugs.ba.generic.GenericUtilities;
import edu.umd.cs.findbugs.xml.XMLAttributeList;
import edu.umd.cs.findbugs.xml.XMLOutput;

/**
 * Bug annotation class for java types.
 * This is of lighter weight than ClassAnnotation,
 * and can be used for things like array types.
 * 
 * @see ClassAnnotation
 */
public class TypeAnnotation extends BugAnnotationWithSourceLines {
    private static final long serialVersionUID = 1L;

    public static final String DEFAULT_ROLE = "TYPE_DEFAULT";
    public static final String EXPECTED_ROLE = "TYPE_EXPECTED";
    public static final String FOUND_ROLE = "TYPE_FOUND";
    public static final String CLOSEIT_ROLE = "TYPE_CLOSEIT";
    public static final String UNHASHABLE_ROLE = "TYPE_UNHASHABLE";

    final private String descriptor; // jvm type descriptor, such as "[I"
    private String roleDescription;
    private String typeParameters;

    /**
     * constructor.
     * 
     * <p>For information on type descriptors,
     * <br>see http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html#14152
     * <br>or  http://www.murrayc.com/learning/java/java_classfileformat.shtml#TypeDescriptors
     * 
     * @param typeDescriptor a jvm type descriptor, such as "[I"
     */
    public TypeAnnotation(String typeDescriptor) {
        this(typeDescriptor, DEFAULT_ROLE);
    }

    public TypeAnnotation(Type objectType) {
        this(objectType, DEFAULT_ROLE);
    }

    public TypeAnnotation(Type objectType, String roleDescription) {
        this(objectType.getSignature(), roleDescription);
        if (objectType instanceof GenericObjectType) {
            GenericObjectType genericObjectType = (GenericObjectType) objectType;
            if (genericObjectType.getTypeCategory() == GenericUtilities.TypeCategory.PARAMETERIZED)
                typeParameters = genericObjectType.getGenericParametersAsString();
        }
    }

    public TypeAnnotation(String typeDescriptor, String roleDescription) {
        descriptor = typeDescriptor;
        this.roleDescription = roleDescription;
        if (descriptor.startsWith("L")) {
            String className = typeDescriptor.substring(1, typeDescriptor.length() - 1).replace('/', '.');
            AnalysisContext context = AnalysisContext.currentAnalysisContext();
            if (context != null) {
                this.sourceFileName = context.lookupSourceFile(className);
                this.sourceLines = ClassAnnotation.getSourceLinesForClass(className, sourceFileName);
            } else
                this.sourceFileName = SourceLineAnnotation.UNKNOWN_SOURCE_FILE;
        }
    }

    /**
     * Get the type descriptor.
     * @return the jvm type descriptor, such as "[I"
     */
    public String getTypeDescriptor() {
        return descriptor;
    }

    public void accept(BugAnnotationVisitor visitor) {
        visitor.visitTypeAnnotation(this);
    }

    public String format(String key, ClassAnnotation primaryClass) {
        String name = new SignatureConverter(descriptor).parseNext().replace("java.lang.", "");
        if (key.equals("givenClass"))
            name = ClassAnnotation.shorten(primaryClass.getPackageName(), name);
        else if (key.equals("excludingPackage"))
            name = ClassAnnotation.removePackage(name);

        if (typeParameters != null && !key.equals("hash"))
            name = name + typeParameters;
        return name;
    }

    public void setDescription(String roleDescription) {
        this.roleDescription = roleDescription.intern();
    }

    public String getDescription() {
        return roleDescription;
    }

    public void setTypeParameters(String typeParameters) {
        this.typeParameters = typeParameters;
    }

    @Override
    public int hashCode() {
        return descriptor.hashCode();
    }

    @Override
    public boolean equals(Object o) {
        if (!(o instanceof TypeAnnotation))
            return false;
        return descriptor.equals(((TypeAnnotation) o).descriptor);
    }

    public int compareTo(BugAnnotation o) {
        if (!(o instanceof TypeAnnotation)) // BugAnnotations must be Comparable with any type of BugAnnotation
            return this.getClass().getName().compareTo(o.getClass().getName());
        return descriptor.compareTo(((TypeAnnotation) o).descriptor);
        // could try to determine equivalence with ClassAnnotation, but don't see how this would be useful
    }

    @Override
    public String toString() {
        String pattern = I18N.instance().getAnnotationDescription(roleDescription);
        FindBugsMessageFormat format = new FindBugsMessageFormat(pattern);
        return format.format(new BugAnnotation[] { this }, null);
    }

    /* ----------------------------------------------------------------------
     * XML Conversion support
     * ---------------------------------------------------------------------- */

    private static final String ELEMENT_NAME = "Type";

    public void writeXML(XMLOutput xmlOutput) throws IOException {
        writeXML(xmlOutput, false, false);
    }

    public void writeXML(XMLOutput xmlOutput, boolean addMessages, boolean isPrimary) throws IOException {
        XMLAttributeList attributeList = new XMLAttributeList().addAttribute("descriptor", descriptor);

        String role = getDescription();
        if (!role.equals(DEFAULT_ROLE))
            attributeList.addAttribute("role", role);
        if (typeParameters != null)
            attributeList.addAttribute("typeParameters", typeParameters);

        BugAnnotationUtil.writeXML(xmlOutput, ELEMENT_NAME, this, attributeList, addMessages);
    }

    public boolean isSignificant() {
        return true;
    }
}