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

mockit.coverage.reporting.parsing.LineParser Maven / Gradle / Ivy

Go to download

JMockit is a Java toolkit for automated developer testing. It contains APIs for the creation of the objects to be tested, for mocking dependencies, and for faking external APIs; JUnit (4 & 5) and TestNG test runners are supported. It also contains an advanced code coverage tool.

The newest version!
/*
 * Copyright (c) 2006 JMockit developers
 * This file is subject to the terms of the MIT license (see LICENSE.txt).
 */
package mockit.coverage.reporting.parsing;

import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;

import mockit.coverage.reporting.parsing.LineElement.ElementType;

import org.checkerframework.checker.index.qual.NonNegative;

/**
 * Parses a source line into one or more consecutive segments, identifying which ones contain Java code and which ones
 * contain only comments. Block comments initiated in a previous line are kept track of until the end of the block is
 * reached.
 */
public final class LineParser {
    private static final String SEPARATORS = ".,;()";

    @NonNegative
    private int lineNum;
    private String line;
    @Nullable
    private LineElement initialElement;
    private boolean inComments;

    // Helper fields:
    @Nullable
    private LineElement currentElement;
    @NonNegative
    private int lineLength;
    private int startPos;
    private boolean inCodeElement;
    @NonNegative
    private int pos;
    private int currChar;

    @NonNegative
    public int getNumber() {
        return lineNum;
    }

    public boolean isInComments() {
        return inComments;
    }

    public boolean isBlankLine() {
        int n = line.length();

        for (int i = 0; i < n; i++) {
            char c = line.charAt(i);

            if (!Character.isWhitespace(c)) {
                return false;
            }
        }

        return true;
    }

    @NonNull
    public LineElement getInitialElement() {
        assert initialElement != null;
        return initialElement;
    }

    boolean parse(@NonNull String lineToParse) {
        lineNum++;
        initialElement = null;
        currentElement = null;
        line = lineToParse;
        lineLength = lineToParse.length();
        startPos = inComments ? 0 : -1;
        inCodeElement = false;

        for (pos = 0; pos < lineLength; pos++) {
            currChar = lineToParse.codePointAt(pos);

            if (parseComment()) {
                break;
            }

            parseSeparatorsAndCode();
        }

        if (startPos >= 0) {
            addFinalElement();
        } else if (initialElement == null) {
            initialElement = new LineElement(ElementType.SEPARATOR, "");
            return false;
        }

        return !inComments && !isBlankLine();
    }

    private void parseSeparatorsAndCode() {
        boolean separator = isSeparator();

        if (separator && !inCodeElement) {
            startNewElementIfNotYetStarted();
        } else if (!separator && !inCodeElement) {
            if (startPos >= 0) {
                addElement();
            }

            inCodeElement = true;
            startPos = pos;
        } else if (separator) {
            addElement();
            inCodeElement = false;
            startPos = pos;
        }
    }

    private boolean isSeparator() {
        return Character.isWhitespace(currChar) || SEPARATORS.indexOf(currChar) >= 0;
    }

    private void startNewElementIfNotYetStarted() {
        if (startPos < 0) {
            startPos = pos;
        }
    }

    private boolean parseComment() {
        if (inComments && parseUntilEndOfLineOrEndOfComment()) {
            return true;
        }

        while (currChar == '/' && pos < lineLength - 1) {
            int c2 = line.codePointAt(pos + 1);

            if (c2 == '/') {
                endCodeElementIfPending();
                startNewElementIfNotYetStarted();
                inComments = true;
                addFinalElement();
                inComments = false;
                startPos = -1;
                return true;
            }
            if (c2 != '*') {
                break;
            }
            endCodeElementIfPending();
            startNewElementIfNotYetStarted();
            inComments = true;
            pos += 2;

            if (parseUntilEndOfLineOrEndOfComment()) {
                return true;
            }
        }

        return false;
    }

    private void endCodeElementIfPending() {
        if (inCodeElement) {
            addElement();
            startPos = pos;
            inCodeElement = false;
        }
    }

    private boolean parseUntilEndOfLineOrEndOfComment() {
        while (pos < lineLength) {
            currChar = line.codePointAt(pos);

            if (currChar == '*' && pos < lineLength - 1 && line.codePointAt(pos + 1) == '/') {
                pos += 2;
                addElement();
                startPos = -1;
                inComments = false;
                break;
            }

            pos++;
        }

        if (pos < lineLength) {
            currChar = line.codePointAt(pos);
            return false;
        }

        return true;
    }

    private void addFinalElement() {
        String text = line.substring(startPos);
        addElement(text);
    }

    private void addElement() {
        String text = pos > 0 ? line.substring(startPos, pos) : line.substring(startPos);
        addElement(text);
    }

    private void addElement(@NonNull String text) {
        ElementType type;

        if (inComments) {
            type = ElementType.COMMENT;
        } else if (inCodeElement) {
            type = ElementType.CODE;
        } else {
            type = ElementType.SEPARATOR;
        }

        LineElement newElement = new LineElement(type, text);

        if (initialElement == null) {
            initialElement = newElement;
        } else {
            assert currentElement != null;
            currentElement.setNext(newElement);
        }

        currentElement = newElement;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy