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

com.cflint.plugins.core.LiteralChecker Maven / Gradle / Ivy

Go to download

A static code analysis tool for ColdFusion (in the spirit of FindBugs and Lint). With CFLint, you are able to analyze your ColdFusion code base for code violations.

There is a newer version: 1.5.0
Show newest version
package com.cflint.plugins.core;

import java.util.HashMap;
import java.util.Map;

import com.cflint.BugInfo;
import com.cflint.BugList;
import com.cflint.plugins.CFLintScannerAdapter;
import com.cflint.plugins.Context;

import cfml.parsing.cfscript.CFExpression;
import cfml.parsing.cfscript.CFLiteral;
import cfml.parsing.cfscript.script.CFCompDeclStatement;
import cfml.parsing.cfscript.script.CFScriptStatement;
import ro.fortsoft.pf4j.Extension;

@Extension
public class LiteralChecker extends CFLintScannerAdapter {
	final String severity = "WARNING";
	final protected int REPEAT_THRESHOLD = 3;
	final protected int WARNING_THRESHOLD = 5;

	protected int threshold = REPEAT_THRESHOLD;
	protected int warningThreshold = WARNING_THRESHOLD;

	protected Map globalLiterals = new HashMap();
	protected Map functionListerals = new HashMap();

	// May want to consider resetting literal map on new components but this way
	// it
	// detects duplicated literals across files which is useful

	@Override
	public void expression(final CFExpression expression, final Context context, final BugList bugs) {
		final String repeatThreshold = getParameter("maximum");
		final String maxWarnings = getParameter("maxWarnings");
		final String warningScope = getParameter("warningScope");

		if (repeatThreshold != null) {
			threshold = Integer.parseInt(repeatThreshold);
		}

		if (maxWarnings != null) {
			warningThreshold = Integer.parseInt(maxWarnings);
		}

		if (expression instanceof CFLiteral) {
			final CFLiteral literal = (CFLiteral) expression;
			final String name = literal.Decompile(0).replace("'", "");

			if (isCommon(name)) {
				return;
			}

			final int lineNo = literal.getLine() + context.startLine() - 1;

			if (warningScope == null || warningScope.equals("global")) {
				literalCount(name, lineNo, globalLiterals, true, context, bugs);
			} else if (warningScope.equals("local")) {
				literalCount(name, lineNo, functionListerals, false, context, bugs);
			}
		}
	}

	@Override
	public void expression(final CFScriptStatement expression, final Context context, final BugList bugs) {
		if (expression instanceof CFCompDeclStatement) {
			functionListerals.clear();
		}
	}

	protected void literalCount(final String name, final int lineNo, final Map literals,
			final boolean global, final Context context, final BugList bugs) {
		int count = 1;

		if (literals.get(name) == null) {
			literals.put(name, count);
		} else {
			count = literals.get(name);
			count++;
			literals.put(name, count);
		}

		if (count > threshold && (warningThreshold == -1 || (count - threshold) <= warningThreshold)) {
			if (global) {
				magicGlobalValue(name, lineNo, context, bugs);
			} else {
				magicLocalValue(name, lineNo, context, bugs);
			}
		}
	}

	protected boolean isCommon(final String name) {
		return name.equals("1") || name.equals("0") || name.equals("") || name.equals("true") || name.equals("false");
	}

	public void magicLocalValue(final String name, final int lineNo, final Context context, final BugList bugs) {
		bugs.add(new BugInfo.BugInfoBuilder().setLine(lineNo).setMessageCode("LOCAL_LITERAL_VALUE_USED_TOO_OFTEN")
				.setSeverity(severity).setFilename(context.getFilename())
				.setMessage("Literal " + name
						+ " occurs several times in the same file. Consider giving it a name and not hard coding values.")
				.build());
	}

	public void magicGlobalValue(final String name, final int lineNo, final Context context, final BugList bugs) {
		bugs.add(new BugInfo.BugInfoBuilder().setLine(lineNo).setMessageCode("GLOBAL_LITERAL_VALUE_USED_TOO_OFTEN")
				.setSeverity(severity).setFilename(context.getFilename())
				.setMessage("Literal " + name
						+ " occurs several times in one or more files. Consider giving it a name and not hard coding values.")
				.build());
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy