MessageHolder (@NotNull String pattern) { MessageHolder holder = new MessageHolder(pattern); while (!holder.hasRuntimeError && holder.hasNext()) { char ch = holder.nextPool(); if (holder.getLastPart().getParsedType() == MessageFormatParsedType.STRING) { if (ch == '\'') { if (holder.hasNext() && holder.nextPeek() == '\'') { holder.addChar(ch); holder.nextPool(); } else { holder.inQuote = !holder.inQuote; holder.lastQuoteIndex = holder.current; } } else if (ch == '{') { if (holder.inQuote) { int end = findEndOfQuotedPlaceholder(pattern, holder.current); if (end != -1) { holder.addError(MessageFormatErrorType.QUOTED_PLACEHOLDER, holder.current, end); } holder.addChar(ch); } else { holder.startFormatElement(ch); } } else { holder.addChar(ch); } } else { if (holder.inQuote) { if (ch == '\'') { holder.inQuote = false; } holder.addChar(ch); } else { switch (ch) { case ',' -> { if (!holder.moveSegmentOfFormatElement()) { holder.addChar(ch); } } case '{' -> { holder.braceStack++; holder.addChar(ch); } case ' ' -> { MessageFormatPart part = holder.getLastPart(); if (!(part.getMessageFormatElement() != null && part.getMessageFormatElement().currentPart == MessageFormatElementPart.FORMAT_TYPE && part.getMessageFormatElement().formatTypeSegment.length() == 0)) { holder.addChar(ch); } } case '}' -> { if (holder.braceStack != 0) { holder.braceStack--; holder.addChar(ch); } else { holder.finishFormatElement(ch); } } case '\'' -> { holder.inQuote = true; holder.lastQuoteIndex = holder.current; holder.addChar(ch); } default -> holder.addChar(ch); } } } } MessageFormatPart lastPart = holder.getLastPart(); if (holder.inQuote) { holder.addError(MessageFormatErrorType.UNPAIRED_QUOTE, holder.lastQuoteIndex, holder.lastQuoteIndex + 1); } if (lastPart.getMessageFormatElement() != null && holder.braceStack == 0 && holder.getLastPart().parsedType != MessageFormatParsedType.STRING) { holder.addError(MessageFormatErrorType.UNMATCHED_BRACE, lastPart.getMessageFormatElement().indexSegmentStart - 1, lastPart.getMessageFormatElement().indexSegmentStart); } else if (lastPart.getMessageFormatElement() != null && !lastPart.getMessageFormatElement().finished) { holder.addError(MessageFormatErrorType.UNCLOSED_BRACE_PLACEHOLDER, lastPart.getMessageFormatElement().indexSegmentStart - 1, lastPart.getMessageFormatElement().indexSegmentStart); } return holder; } private static int findEndOfQuotedPlaceholder(@NotNull String pattern, int current) { if (!(current - 1 >= 0 && pattern.charAt(current - 1) == '\'')) { return -1; } String nextPattern = pattern.substring(current); int from = 0; int nextQuote; while (true) { nextQuote = nextPattern.indexOf('\'', from); if (nextQuote == -1) { return -1; } if (nextPattern.length() > nextQuote + 1 && nextPattern.charAt(nextQuote + 1) == '\'') { from = nextQuote + 2; continue; } break; } nextPattern = nextPattern.substring(0, nextQuote); if (nextPattern.startsWith("{") && nextPattern.endsWith("}") && nextPattern.indexOf("}") == nextPattern.length() - 1) { MessageHolder holder = parseMessageHolder(nextPattern); if (holder.errors.isEmpty()) { List<MessageFormatPart> notStrings = ContainerUtil.filter(holder.parts, t -> !(t.getParsedType() == MessageFormatParsedType.STRING && t.getText().length() == 0)); if (notStrings.size() == 1 && notStrings.get(0).getParsedType() == MessageFormatParsedType.FORMAT_ELEMENT) { return nextQuote + current; } } } return -1; }