package net.king2500.plugins.PhpAdvancedAutoComplete.reference; import com.intellij.openapi.util.TextRange; import com.intellij.util.containers.hash.HashMap; import net.king2500.plugins.PhpAdvancedAutoComplete.PhpCompletionTokens; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Arrays; import java.util.List; /** * @author Thomas Schulz <[email protected]> */ class PhpPackFormatSpecificationParser { private PhpPackFormatSpecificationParser() { } static HashMap<Integer, PackSpecification> parseFormat(@NotNull String expression, boolean singleQuote, int parametersCount) { int index = 0; int num = 0; HashMap<Integer, PackSpecification> result = new HashMap<>(); List<String> codesList = Arrays.asList(PhpCompletionTokens.packCodes); while (index < expression.length()) { char c = expression.charAt(index); // Cancel when we hit variables inside string if (!singleQuote && charAtEqualsToAny(expression, index, '$')) { return result; } if (!codesList.contains(Character.toString(c)) || charAtEqualsToAny(expression, index, 'x', 'X')) { ++index; continue; } int endIndex = index; int repeater = 1; TextRange width = parseUnsignedInt(expression, index+1); if (width != null && !charAtEqualsToAny(expression, index, 'a', 'A', 'h', 'H')) { endIndex = width.getEndOffset() - 1; repeater = Integer.parseUnsignedInt(width.substring(expression)); } boolean repeatToEnd = charAtEqualsToAny(expression, index + 1, '*'); if (repeatToEnd) { ++endIndex; repeater = parametersCount - num; } TextRange range = TextRange.create(index, endIndex + 1); result.put(num, new PackSpecification(range, repeater)); if (repeatToEnd) { return result; } ++num; ++index; } return result; } private static boolean charAtEqualsToAny(@NotNull String s, int index, char... chars) { if (index >= 0 && index < s.length()) { for (char c : chars) { if (c == s.charAt(index)) { return true; } } } return false; } @Nullable private static TextRange parseUnsignedInt(@NotNull String expression, int from) { if (!isDigit(expression, from)) { return null; } else { int start; start = from; while (isDigit(expression, from)) { ++from; } return TextRange.create(start, from); } } private static boolean isDigit(@NotNull String expression, int index) { return index >= 0 && index < expression.length() && Character.isDigit(expression.charAt(index)); } public static class PackSpecification { @NotNull private final TextRange myRange; private final int myRepeater; private PackSpecification(@NotNull TextRange range, int repeater) { this.myRange = range; this.myRepeater = repeater; } public TextRange getRangeInElement() { return this.myRange; } public int getRepeater() { return this.myRepeater; } } }