org.jacoco.core.internal.analysis.ClassAnalyzer.java Source code

Java tutorial

Introduction

Here is the source code for org.jacoco.core.internal.analysis.ClassAnalyzer.java

Source

/*******************************************************************************
 * Copyright (c) 2009, 2013 Mountainminds GmbH & Co. KG and Contributors
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Marc R. Hoffmann - initial API and implementation
 *    
 *******************************************************************************/
package org.jacoco.core.internal.analysis;

import org.jacoco.core.analysis.IMethodCoverage;
import org.jacoco.core.internal.flow.ClassProbesVisitor;
import org.jacoco.core.internal.flow.MethodProbesVisitor;
import org.jacoco.core.internal.instr.InstrSupport;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Opcodes;

/**
 * Analyzes the structure of a class.
 */
public class ClassAnalyzer extends ClassProbesVisitor {

    private final long classid;
    private final boolean probes[];
    private final StringPool stringPool;

    private ClassCoverageImpl coverage;

    /**
     * Creates a new analyzer that builds coverage data for a class.
     * 
     * @param classid
     *            id of the class
     * @param probes
     *            execution data for this class or <code>null</code>
     * @param stringPool
     *            shared pool to minimize the number of {@link String} instances
     */
    public ClassAnalyzer(final long classid, final boolean[] probes, final StringPool stringPool) {
        this.classid = classid;
        this.probes = probes;
        this.stringPool = stringPool;
    }

    /**
     * Returns the coverage data for this class after this visitor has been
     * processed.
     * 
     * @return coverage data for this class
     */
    public ClassCoverageImpl getCoverage() {
        return coverage;
    }

    @Override
    public void visit(final int version, final int access, final String name, final String signature,
            final String superName, final String[] interfaces) {
        this.coverage = new ClassCoverageImpl(stringPool.get(name), classid, stringPool.get(signature),
                stringPool.get(superName), stringPool.get(interfaces));
    }

    @Override
    public void visitSource(final String source, final String debug) {
        this.coverage.setSourceFileName(stringPool.get(source));
    }

    @Override
    public MethodProbesVisitor visitMethod(final int access, final String name, final String desc,
            final String signature, final String[] exceptions) {

        InstrSupport.assertNotInstrumented(name, coverage.getName());

        // TODO: Use filter hook
        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
            return null;
        }

        return new MethodAnalyzer(stringPool.get(name), stringPool.get(desc), stringPool.get(signature), probes) {
            @Override
            public void visitEnd() {
                super.visitEnd();
                final IMethodCoverage methodCoverage = getCoverage();
                if (methodCoverage.getInstructionCounter().getTotalCount() > 0) {
                    // Only consider methods that actually contain code
                    coverage.addMethod(methodCoverage);
                }
            }
        };
    }

    @Override
    public FieldVisitor visitField(final int access, final String name, final String desc, final String signature,
            final Object value) {
        InstrSupport.assertNotInstrumented(name, coverage.getName());
        return super.visitField(access, name, desc, signature, value);
    }

    @Override
    public void visitTotalProbeCount(final int count) {
        // nothing to do
    }

}