Ejemplo n.º 1
0
 /*
  * Get the index of comment which contains given position. If there's no
  * matching comment, then return depends on exact parameter: = 0: return -1
  * < 0: return index of the comment before the given position > 0: return
  * index of the comment after the given position
  */
 private int getCommentIndex(int start, int position, int exact) {
   if (position == 0) {
     if (this.comments.length > 0 && this.comments[0].getStart() == 0) {
       return 0;
     }
     return -1;
   }
   int bottom = start, top = this.comments.length - 1;
   int i = 0, index = -1;
   Comment comment = null;
   while (bottom <= top) {
     i = bottom + (top - bottom) / 2;
     comment = this.comments[i];
     int commentStart = comment.getStart();
     if (position < commentStart) {
       top = i - 1;
     } else if (position >= (commentStart + comment.getLength())) {
       bottom = i + 1;
     } else {
       index = i;
       break;
     }
   }
   if (index < 0 && exact != 0) {
     comment = this.comments[i];
     if (position < comment.getStart()) {
       return exact < 0 ? i - 1 : i;
     } else {
       return exact < 0 ? i : i + 1;
     }
   }
   return index;
 }
Ejemplo n.º 2
0
  /**
   * Search and store node trailing comments. Comments are searched in position range from node end
   * position to specified next start. If one or several comment are found, returns last comment end
   * position, otherwise returns node end position.
   *
   * <p>Starts to search for first comment after node end position and return if none was found...
   *
   * <p>When first comment is found after node, goes down in comment list until one of following
   * conditions becomes true:
   *
   * <ol>
   *   <li>comment start is after next start
   *   <li>there's other than white characters between current node and comment
   *   <li>TODO there's more than 1 line between current node and comment
   * </ol>
   *
   * If at least potential comments have been found, then all of them has to be separated from
   * following node. So, remove all comments which do not verify this assumption. Note that this
   * verification is not applicable on last node.
   *
   * <p>If finally there's still trailing comments, then stores indexes of the first and last one in
   * trailing comments table.
   */
  int storeTrailingComments(ASTNode node, int nextStart, boolean lastChild, int[] parentLineRange) {

    // Init extended position
    int nodeEnd = node.getEnd() - 1;
    if (nodeEnd == nextStart) {
      // special case for last child of its parent
      if (++this.trailingPtr == 0) {
        this.trailingNodes = new ASTNode[STORAGE_INCREMENT];
        this.trailingIndexes = new long[STORAGE_INCREMENT];
        this.lastTrailingPtr = -1;
      } else if (this.trailingPtr == this.trailingNodes.length) {
        int newLength = (this.trailingPtr * 3 / 2) + STORAGE_INCREMENT;
        System.arraycopy(
            this.trailingNodes,
            0,
            this.trailingNodes = new ASTNode[newLength],
            0,
            this.trailingPtr);
        System.arraycopy(
            this.trailingIndexes,
            0,
            this.trailingIndexes = new long[newLength],
            0,
            this.trailingPtr);
      }
      this.trailingNodes[this.trailingPtr] = node;
      this.trailingIndexes[this.trailingPtr] = -1;
      return nodeEnd;
    }
    int extended = nodeEnd;

    // Get line number
    int nodeEndLine = getLineNumber(nodeEnd, parentLineRange);

    // Find comments range index
    int idx = getCommentIndex(0, nodeEnd, 1);
    if (idx == -1) {
      return nodeEnd;
    }

    // Look after potential comments
    int startIdx = idx;
    int endIdx = -1;
    int length = this.comments.length;
    int commentStart = extended + 1;
    int previousEnd = nodeEnd + 1;
    int sameLineIdx = -1;
    while (idx < length && commentStart < nextStart) {
      // get comment and leave if next starting position has been reached
      Comment comment = this.comments[idx];
      commentStart = comment.getStart();
      // verify that there's nothing else than white spaces between
      // node/comments
      if (commentStart >= nextStart) {
        // stop search on condition 1)
        break;
      } else if (previousEnd < commentStart) {
        try {
          resetTo(previousEnd, commentStart);
          this.scanner.next_token();
          String token = this.scanner.yytext();
          if (token != null && token.trim().length() > 0) {
            // stop search on condition 2)
            // if first index fails, then there's no extended
            // position in fact...
            if (idx == startIdx) {
              return nodeEnd;
            }
            // otherwise we get the last index of trailing comment
            // => break
            break;
          }
        } catch (Exception e) {
          // Should not happen, but return no extended position...
          assert false;
          return nodeEnd;
        }
      }
      // Store index if we're on the same line than node end
      int commentLine = getLineNumber(commentStart, parentLineRange);
      if (commentLine == nodeEndLine) {
        sameLineIdx = idx;
      }
      // Store previous infos
      previousEnd = commentStart + comment.getLength();
      endIdx = idx++;
    }
    if (endIdx != -1) {
      // Verify that following node start is separated
      if (!lastChild) {
        int nextLine = getLineNumber(nextStart, parentLineRange);
        int previousLine = getLineNumber(previousEnd, parentLineRange);
        if ((nextLine - previousLine) <= 1) {
          if (sameLineIdx == -1) return nodeEnd;
          endIdx = sameLineIdx;
        }
      }
      // Store trailing comments indexes
      if (++this.trailingPtr == 0) {
        this.trailingNodes = new ASTNode[STORAGE_INCREMENT];
        this.trailingIndexes = new long[STORAGE_INCREMENT];
        this.lastTrailingPtr = -1;
      } else if (this.trailingPtr == this.trailingNodes.length) {
        int newLength = (this.trailingPtr * 3 / 2) + STORAGE_INCREMENT;
        System.arraycopy(
            this.trailingNodes,
            0,
            this.trailingNodes = new ASTNode[newLength],
            0,
            this.trailingPtr);
        System.arraycopy(
            this.trailingIndexes,
            0,
            this.trailingIndexes = new long[newLength],
            0,
            this.trailingPtr);
      }
      this.trailingNodes[this.trailingPtr] = node;
      long nodeRange = (((long) startIdx) << 32) + endIdx;
      this.trailingIndexes[this.trailingPtr] = nodeRange;
      // Compute new extended end
      extended = this.comments[endIdx].getEnd() - 1;
      // Look for children unresolved extended end
      ASTNode previousNode = node;
      int ptr = this.trailingPtr - 1; // children extended end were stored
      // before
      while (ptr >= 0) {
        long range = this.trailingIndexes[ptr];
        if (range != -1) break; // there's no more unresolved nodes
        ASTNode unresolved = this.trailingNodes[ptr];
        if (previousNode != unresolved.getParent())
          break; // we're no longer in node ancestor hierarchy
        this.trailingIndexes[ptr] = nodeRange;
        previousNode = unresolved;
        ptr--; // get previous node
      }
      // Remove remaining unresolved nodes
      if (ptr > this.lastTrailingPtr) {
        int offset = ptr - this.lastTrailingPtr;
        for (int i = ptr + 1; i <= this.trailingPtr; i++) {
          this.trailingNodes[i - offset] = this.trailingNodes[i];
          this.trailingIndexes[i - offset] = this.trailingIndexes[i];
        }
        this.trailingPtr -= offset;
      }
      this.lastTrailingPtr = this.trailingPtr;
    }
    return extended;
  }
Ejemplo n.º 3
0
  /**
   * Search and store node leading comments. Comments are searched in position range from previous
   * extended position to node start position. If one or several comment are found, returns first
   * comment start position, otherwise returns node start position.
   *
   * <p>Starts to search for first comment before node start position and return if none was
   * found...
   *
   * <p>When first comment is found before node, goes up in comment list until one of following
   * conditions becomes true:
   *
   * <ol>
   *   <li>comment end is before previous end
   *   <li>comment start and previous end is on the same line but not on same line of node start
   *   <li>there's other than white characters between current node and comment
   *   <li>TODO : there's more than 1 line between current node and comment
   * </ol>
   *
   * If some comment have been found, then no token should be on on the same line before, so remove
   * all comments which do not verify this assumption.
   *
   * <p>If finally there's leading still comments, then stores indexes of the first and last one in
   * leading comments table.
   */
  int storeLeadingComments(ASTNode node, int previousEnd, int[] parentLineRange) {
    // Init extended position
    int nodeStart = node.getStart();
    int extended = nodeStart;

    // Get line of node start position
    int previousEndLine = getLineNumber(previousEnd, parentLineRange);
    int nodeStartLine = getLineNumber(nodeStart, parentLineRange);

    // Find first comment index
    int idx = getCommentIndex(0, nodeStart, -1);
    if (idx == -1) {
      return nodeStart;
    }

    // Look after potential comments
    int startIdx = -1;
    int endIdx = idx;
    int previousStart = nodeStart;
    while (idx >= 0 && previousStart >= previousEnd) {
      // Verify for each comment that there's only white spaces between
      // end and start of {following comment|node}
      Comment comment = this.comments[idx];
      int commentStart = comment.getStart();
      int end = commentStart + comment.getLength() - 1;
      int commentLine = getLineNumber(commentStart, parentLineRange);
      if (end <= previousEnd || (commentLine == previousEndLine && commentLine != nodeStartLine)) {
        // stop search on condition 1) and 2)
        break;
      } else if ((end + 1) < previousStart) { // may be equals => then no
        // scan is necessary
        try {
          resetTo(end + 1, previousStart);
          this.scanner.next_token();
          String token = this.scanner.yytext();
          if (token != null && token.trim().length() > 0) {
            // stop search on condition 3)
            // if first comment fails, then there's no extended
            // position in fact
            if (idx == endIdx) {
              return nodeStart;
            }
            break;
          }
        } catch (Exception e) {
          // Should not happen, but return no extended position...
          assert false;
          return nodeStart;
        }
      }
      // Store previous infos
      previousStart = commentStart;
      startIdx = idx--;
    }
    if (startIdx != -1) {
      // Store leading comments indexes
      if (startIdx <= endIdx) {
        if (++this.leadingPtr == 0) {
          this.leadingNodes = new ASTNode[STORAGE_INCREMENT];
          this.leadingIndexes = new long[STORAGE_INCREMENT];
        } else if (this.leadingPtr == this.leadingNodes.length) {
          int newLength = (this.leadingPtr * 3 / 2) + STORAGE_INCREMENT;
          System.arraycopy(
              this.leadingNodes, 0, this.leadingNodes = new ASTNode[newLength], 0, this.leadingPtr);
          System.arraycopy(
              this.leadingIndexes,
              0,
              this.leadingIndexes = new long[newLength],
              0,
              this.leadingPtr);
        }
        this.leadingNodes[this.leadingPtr] = node;
        this.leadingIndexes[this.leadingPtr] = (((long) startIdx) << 32) + endIdx;
        extended = this.comments[endIdx].getStart();
      }
    }
    return extended;
  }