int (int lineno, String tagPrefix) { final Substring lineWithPrefix = getLine(lineno).trimLeft(); if (lineWithPrefix.startsWith(tagPrefix)) { final Substring line = lineWithPrefix.substring(tagPrefix.length()); final Matcher strictTagMatcher = RE_STRICT_TAG_LINE.matcher(line); final Matcher looseTagMatcher = RE_LOOSE_TAG_LINE.matcher(line); Matcher tagMatcher = null; if (strictTagMatcher.matches()) { tagMatcher = strictTagMatcher; } else if (looseTagMatcher.matches()) { tagMatcher = looseTagMatcher; } if (tagMatcher != null) { final Substring tagName = line.getMatcherGroup(tagMatcher, 1); Substring argName = line.getMatcherGroup(tagMatcher, 2).trim(); final TextRange firstArgLineRange = line.getMatcherGroup(tagMatcher, 3).trim().getTextRange(); final int linesCount = getLineCount(); final int argStart = firstArgLineRange.getStartOffset(); int argEnd = firstArgLineRange.getEndOffset(); while (lineno + 1 < linesCount) { final Substring nextLine = getLine(lineno + 1).trim(); if (nextLine.isEmpty() || nextLine.startsWith(tagPrefix)) { break; } argEnd = nextLine.getTextRange().getEndOffset(); lineno++; } final Substring argValue = new Substring(argName.getSuperString(), argStart, argEnd); final String tagNameString = tagName.toString(); if (argName.isEmpty()) { mySimpleTagValues.put(tagNameString, argValue); } else { if ("param".equals(tagNameString) || "parameter".equals(tagNameString) || "arg".equals(tagNameString) || "argument".equals(tagNameString)) { // Process declarations that combine type and description, e.g. ":param int foo: bar" // as if there were both ":param foo: bar" and ":type foo: int" final Matcher argTypeMatcher = RE_ARG_TYPE.matcher(argName); if (argTypeMatcher.matches()) { final Substring argType = argName.getMatcherGroup(argTypeMatcher, 1).trim(); argName = argName.getMatcherGroup(argTypeMatcher, 2); getTagValuesMap(TYPE).put(argName, argType); } } getTagValuesMap(tagNameString).put(argName, argValue); } } } return lineno; }