Home | History | Annotate | Download | only in check
      1 /*******************************************************************************
      2  * Copyright (c) 2009, 2017 Mountainminds GmbH & Co. KG and Contributors
      3  * All rights reserved. This program and the accompanying materials
      4  * are made available under the terms of the Eclipse Public License v1.0
      5  * which accompanies this distribution, and is available at
      6  * http://www.eclipse.org/legal/epl-v10.html
      7  *
      8  * Contributors:
      9  *    Marc R. Hoffmann - initial API and implementation
     10  *
     11  *******************************************************************************/
     12 package org.jacoco.report.check;
     13 
     14 import java.util.ArrayList;
     15 import java.util.Collection;
     16 
     17 import org.jacoco.core.analysis.IBundleCoverage;
     18 import org.jacoco.core.analysis.IClassCoverage;
     19 import org.jacoco.core.analysis.ICoverageNode;
     20 import org.jacoco.core.analysis.IMethodCoverage;
     21 import org.jacoco.core.analysis.IPackageCoverage;
     22 import org.jacoco.core.analysis.ISourceFileCoverage;
     23 import org.jacoco.report.ILanguageNames;
     24 
     25 /**
     26  * Internal class to check a list of rules against a {@link IBundleCoverage}
     27  * instance.
     28  */
     29 class BundleChecker {
     30 
     31 	private final ILanguageNames names;
     32 	private final IViolationsOutput output;
     33 
     34 	private final Collection<Rule> bundleRules;
     35 	private final Collection<Rule> packageRules;
     36 	private final Collection<Rule> classRules;
     37 	private final Collection<Rule> sourceFileRules;
     38 	private final Collection<Rule> methodRules;
     39 
     40 	private final boolean traversePackages;
     41 	private final boolean traverseClasses;
     42 	private final boolean traverseSourceFiles;
     43 	private final boolean traverseMethods;
     44 
     45 	public BundleChecker(final Collection<Rule> rules,
     46 			final ILanguageNames names, final IViolationsOutput output) {
     47 		this.names = names;
     48 		this.output = output;
     49 		this.bundleRules = new ArrayList<Rule>();
     50 		this.packageRules = new ArrayList<Rule>();
     51 		this.classRules = new ArrayList<Rule>();
     52 		this.sourceFileRules = new ArrayList<Rule>();
     53 		this.methodRules = new ArrayList<Rule>();
     54 		for (final Rule rule : rules) {
     55 			switch (rule.getElement()) {
     56 			case BUNDLE:
     57 				bundleRules.add(rule);
     58 				break;
     59 			case PACKAGE:
     60 				packageRules.add(rule);
     61 				break;
     62 			case CLASS:
     63 				classRules.add(rule);
     64 				break;
     65 			case SOURCEFILE:
     66 				sourceFileRules.add(rule);
     67 				break;
     68 			case METHOD:
     69 				methodRules.add(rule);
     70 				break;
     71 			}
     72 		}
     73 		traverseMethods = !methodRules.isEmpty();
     74 		traverseClasses = !classRules.isEmpty() || traverseMethods;
     75 		traverseSourceFiles = !sourceFileRules.isEmpty();
     76 		traversePackages = !packageRules.isEmpty() || traverseClasses
     77 				|| traverseSourceFiles;
     78 	}
     79 
     80 	public void checkBundle(final IBundleCoverage bundleCoverage) {
     81 		final String name = bundleCoverage.getName();
     82 		checkRules(bundleCoverage, bundleRules, "bundle", name);
     83 		if (traversePackages) {
     84 			for (final IPackageCoverage p : bundleCoverage.getPackages()) {
     85 				check(p);
     86 			}
     87 		}
     88 	}
     89 
     90 	private void check(final IPackageCoverage packageCoverage) {
     91 		final String name = names.getPackageName(packageCoverage.getName());
     92 		checkRules(packageCoverage, packageRules, "package", name);
     93 		if (traverseClasses) {
     94 			for (final IClassCoverage c : packageCoverage.getClasses()) {
     95 				check(c);
     96 			}
     97 		}
     98 		if (traverseSourceFiles) {
     99 			for (final ISourceFileCoverage s : packageCoverage.getSourceFiles()) {
    100 				check(s);
    101 			}
    102 		}
    103 	}
    104 
    105 	private void check(final IClassCoverage classCoverage) {
    106 		final String name = names
    107 				.getQualifiedClassName(classCoverage.getName());
    108 		checkRules(classCoverage, classRules, "class", name);
    109 		if (traverseMethods) {
    110 			for (final IMethodCoverage m : classCoverage.getMethods()) {
    111 				check(m, classCoverage.getName());
    112 			}
    113 		}
    114 	}
    115 
    116 	private void check(final ISourceFileCoverage sourceFile) {
    117 		final String name = sourceFile.getPackageName() + "/"
    118 				+ sourceFile.getName();
    119 		checkRules(sourceFile, sourceFileRules, "source file", name);
    120 	}
    121 
    122 	private void check(final IMethodCoverage method, final String className) {
    123 		final String name = names.getQualifiedMethodName(className,
    124 				method.getName(), method.getDesc(), method.getSignature());
    125 		checkRules(method, methodRules, "method", name);
    126 	}
    127 
    128 	private void checkRules(final ICoverageNode node,
    129 			final Collection<Rule> rules, final String typename,
    130 			final String elementname) {
    131 		for (final Rule rule : rules) {
    132 			if (rule.matches(elementname)) {
    133 				for (final Limit limit : rule.getLimits()) {
    134 					checkLimit(node, typename, elementname, rule, limit);
    135 				}
    136 			}
    137 		}
    138 	}
    139 
    140 	private void checkLimit(final ICoverageNode node, final String elementtype,
    141 			final String typename, final Rule rule, final Limit limit) {
    142 		final String message = limit.check(node);
    143 		if (message != null) {
    144 			output.onViolation(node, rule, limit, String.format(
    145 					"Rule violated for %s %s: %s", elementtype, typename,
    146 					message));
    147 		}
    148 	}
    149 
    150 }
    151