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.

There is a newer version: 1.49
Show newest version
/*
 * Copyright (c) 2006 Rogério Liesenfeld
 * This file is subject to the terms of the MIT license (see LICENSE.txt).
 */
package mockit.coverage.reporting.parsing;

import javax.annotation.*;

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

/**
 * 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 = ".,;()";

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

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

   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;
         }
         else if (c2 == '*') {
            endCodeElementIfPending();
            startNewElementIfNotYetStarted();
            inComments = true;
            pos += 2;

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

      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;
      }
      else {
         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 - 2024 Weber Informatics LLC | Privacy Policy