All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.bordertech.wcomponents.qa.findbugs.CheckComponentModelDefinition Maven / Gradle / Ivy

There is a newer version: 1.5.14
Show newest version
package com.github.bordertech.wcomponents.qa.findbugs;

import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.BugReporter;
import edu.umd.cs.findbugs.BytecodeScanningDetector;
import edu.umd.cs.findbugs.ba.ClassContext;
import edu.umd.cs.findbugs.ba.XMethod;
import edu.umd.cs.findbugs.classfile.IClassConstants;
import org.apache.bcel.classfile.Attribute;
import org.apache.bcel.classfile.InnerClass;
import org.apache.bcel.classfile.InnerClasses;
import org.apache.bcel.classfile.JavaClass;

/**
 * A FindBugs detector to ensure that ComponentModels are declared correctly.
 *
 * @author Yiannis Paschalidis
 * @since 1.0.0
 */
public class CheckComponentModelDefinition extends BytecodeScanningDetector {

	/**
	 * The utility instance for this detector.
	 */
	private final Util util;

	/**
	 * Creates a CheckWComponentFields detector.
	 *
	 * @param bugReporter the reporter used to report bugs.
	 */
	public CheckComponentModelDefinition(final BugReporter bugReporter) {
		util = new Util(bugReporter);
	}

	/**
	 * Override this as we're only interested in WComponent classes.
	 *
	 * @param obj the java class to check.
	 * @return true if the class is a WComponent.
	 */
	@Override
	public boolean shouldVisit(final JavaClass obj) {
		return util.isComponentModel(obj);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void visitClassContext(final ClassContext classContext) {
		if (!util.isComponentModel(classContext.getJavaClass())) {
			return;
		}

		// TODO: This is nasty, but classContext.getXClass().isStatic() returns FALSE for static inner classes.
		boolean isStatic = false;

		if (classContext.getXClass().getImmediateEnclosingClass() != null) {
			for (Attribute attribute : classContext.getJavaClass().getAttributes()) {
				if (attribute instanceof InnerClasses) {
					InnerClass inner = ((InnerClasses) attribute).getInnerClasses()[0];
					isStatic = (inner.getInnerAccessFlags() & IClassConstants.ACC_STATIC) != 0;
					break;
				}
			}
		}

		if (!classContext.getXClass().isPublic() || classContext.getClassDescriptor().isAnonymousClass()) {
			reportBug(classContext);
		} else if (classContext.getXClass().getImmediateEnclosingClass() != null && !isStatic) {
			reportBug(classContext);
		} else {
			boolean foundPublicNoArgsConstructor = false;
			boolean foundConstructor = false;

			for (XMethod method : classContext.getXClass().getXMethods()) {
				if ("".equals(method.getMethodDescriptor().getName())) {
					foundConstructor = true;

					if (method.isPublic() && method.getNumParams() == 0) {
						foundPublicNoArgsConstructor = true;
						break;
					}
				}
			}

			if (foundConstructor && !foundPublicNoArgsConstructor) {
				reportBug(classContext);
			}
		}
	}

	/**
	 * Reports a bug against the definition of the ComponentModel.
	 *
	 * @param classContext the class to report against.
	 */
	private void reportBug(final ClassContext classContext) {
		util.getBugReporter().reportBug(new BugInstance(this, "WCCM_NO_PUBLIC_CONSTRUCTOR",
				HIGH_PRIORITY)
				.addClass(classContext.getClassDescriptor()));
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy