package org.plantuml.idea.intentions; import java.util.Arrays; public class Arrow { private int caretOffset; private char[] chars; private int[] ends = new int[]{-1, -1}; /** * there are so many types of arrow, lets allow anything which contains - or . */ private boolean containsArrowBody; public static Arrow from(int caretOffset, char[] chars) { return new Arrow(caretOffset, chars).invoke(); } private Arrow(int caretOffset, char... chars) { this.caretOffset = caretOffset; this.chars = chars; } private Arrow invoke() { if (caretWithinCharArray()) { if (isArrowCharAtCaret()) { //traverse right to find the end for (int i = caretOffset; i < chars.length; i++) { if (!processPosition(i)) break; } } //traverse left to find the second end if (arrowEndsNotFound() && previousCharIsNotWhitespace()) { for (int i = caretOffset - 1; i >= 0; i--) {//must step one char left, for cases when we are on far right edge if (!processPosition(i)) break; } } } return this; } private boolean isArrowCharAtCaret() { char currentChar = chars[caretOffset]; return isNotWhitespace(currentChar); } private boolean processPosition(int position) { char currentChar = chars[position]; boolean currentIsNotWhitespace = isNotWhitespace(currentChar); boolean continueTraversing = currentIsNotWhitespace; //continue traversing when caret is in middle if (currentIsNotWhitespace && isOnEdge(position)) { continueTraversing = savePosition(position); } if (isArrowBody(currentChar)) { containsArrowBody = true; } return continueTraversing; } private boolean savePosition(int position) { boolean continueTraversing; if (ends[0] == -1) { ends[0] = position; continueTraversing = true; } else { ends[1] = position; Arrays.sort(ends); continueTraversing = false; } return continueTraversing; } private boolean isArrowBody(char currentChar) { return currentChar == '-' || currentChar == '.'; } private boolean isOnEdge(int currentPosition) { char charRight = chars.length > currentPosition + 1 ? chars[currentPosition + 1] : ' '; char charLeft = currentPosition - 1 >= 0 ? chars[currentPosition - 1] : ' '; return isWhitespace(charLeft) || isWhitespace(charRight); } private boolean isNotWhitespace(char currentChar) { return currentChar != ' '; } private boolean isWhitespace(char currentChar) { return currentChar == ' '; } private boolean arrowEndsNotFound() { return ends[0] == -1 || ends[1] == -1; } private boolean previousCharIsNotWhitespace() { return caretOffset > 0 && isNotWhitespace(chars[caretOffset - 1]); } private boolean caretWithinCharArray() { return chars.length > caretOffset; } public boolean isValid() { if (arrowEndsNotFound()) { return false; } if (!containsArrowBody) { return false; } return !(isArrowBody(chars[ends[0]]) && isArrowBody(chars[ends[1]])); } public int getStart() { return ends[0]; } public int getEnd() { return ends[1]; } @Override public String toString() { final StringBuilder sb = new StringBuilder("Arrow{"); sb.append("caretOffset=").append(caretOffset); sb.append(", chars=").append(Arrays.toString(chars)); sb.append(", ends=").append(Arrays.toString(ends)); sb.append(", containsArrowBody=").append(containsArrowBody); sb.append('}'); return sb.toString(); } }