PY-16766 Fix recognition of Google code style docstrings from docstring content

We should try all possible section headers inside docstring and confirm
Google code style once at least one of them turns out to be known.

Also I replaced predefined "\s" character group in internal regular
expressions intended for matching on single line with explicit [ \t],
because otherwise they match section headers with surrounding empty
lines.
This commit is contained in:
Mikhail Golubev
2015-09-02 15:04:13 +03:00
parent 7a22acb8d3
commit dffddee659
4 changed files with 25 additions and 12 deletions
@@ -38,7 +38,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.regex.Matcher;
/**
* User: catherine
@@ -124,12 +123,12 @@ public class DocStringUtil {
}
public static boolean isGoogleDocString(@NotNull String text) {
final Matcher matcher = GoogleCodeStyleDocString.SECTION_HEADER_RE.matcher(text);
if (!matcher.find()) {
return false;
for (@NonNls String title : StringUtil.findMatches(text, GoogleCodeStyleDocString.SECTION_HEADER, 1)) {
if (SectionBasedDocString.SECTION_NAMES.contains(title.toLowerCase())) {
return true;
}
}
@NonNls final String foundName = matcher.group(1).trim();
return SectionBasedDocString.SECTION_NAMES.contains(foundName.toLowerCase());
return false;
}
public static boolean isNumpyDocstring(@NotNull String text) {
@@ -31,8 +31,8 @@ import java.util.regex.Pattern;
* @see <a href="http://google-styleguide.googlecode.com/svn/trunk/pyguide.html?showone=Comments#Comments">Google Python Style: Docstrings</a>
*/
public class GoogleCodeStyleDocString extends SectionBasedDocString {
public static final Pattern SECTION_HEADER_RE = Pattern.compile("\\s*([\\w\\s]+):\\s*", Pattern.MULTILINE);
private static final Pattern FIELD_NAME_AND_TYPE_RE = Pattern.compile("\\s*(.+?)\\s*\\(\\s*(.*?)\\s*\\)\\s*");
public static final Pattern SECTION_HEADER = Pattern.compile("^[ \t]*([\\w \t]+):[ \t]*$", Pattern.MULTILINE);
private static final Pattern FIELD_NAME_AND_TYPE = Pattern.compile("^[ \t]*(.+?)[ \t]*\\([ \t]*(.*?)[ \t]*\\)[ \t]*$", Pattern.MULTILINE);
public GoogleCodeStyleDocString(@NotNull Substring text) {
super(text);
@@ -87,7 +87,7 @@ public class GoogleCodeStyleDocString extends SectionBasedDocString {
final Substring textBeforeColon = colonSeparatedParts.get(0);
name = textBeforeColon.trim();
if (mayHaveType) {
final Matcher matcher = FIELD_NAME_AND_TYPE_RE.matcher(textBeforeColon);
final Matcher matcher = FIELD_NAME_AND_TYPE.matcher(textBeforeColon);
if (matcher.matches()) {
name = textBeforeColon.getMatcherGroup(matcher, 1).trim();
type = textBeforeColon.getMatcherGroup(matcher, 2).trim();
@@ -115,7 +115,7 @@ public class GoogleCodeStyleDocString extends SectionBasedDocString {
@Override
protected Pair<Substring, Integer> parseSectionHeader(int lineNum) {
final Substring line = getLine(lineNum);
final Matcher matcher = SECTION_HEADER_RE.matcher(line);
final Matcher matcher = SECTION_HEADER.matcher(line);
if (matcher.matches()) {
@NonNls final Substring title = line.getMatcherGroup(matcher, 1).trim();
if (SECTION_NAMES.contains(title.toString().toLowerCase())) {
@@ -29,8 +29,8 @@ import java.util.regex.Pattern;
* @see <a href="http://sphinxcontrib-napoleon.readthedocs.org/en/latest/example_numpy.html#example-numpy">Napoleon: Example NumPy Style Python Docstrings</a>
*/
public class NumpyDocString extends SectionBasedDocString {
private static final Pattern SIGNATURE = Pattern.compile("^\\s*([\\w., ]+=)?\\s*[\\w\\.]+\\(.*\\)\\s*$", Pattern.MULTILINE);
public static final Pattern SECTION_HEADER = Pattern.compile("^\\s*[-=]{2,}\\s*$", Pattern.MULTILINE);
private static final Pattern SIGNATURE = Pattern.compile("^[ \t]*([\\w., ]+=)?[ \t]*[\\w\\.]+\\(.*\\)[ \t]*$", Pattern.MULTILINE);
public static final Pattern SECTION_HEADER = Pattern.compile("^[ \t]*[-=]{2,}[ \t]*$", Pattern.MULTILINE);
private Substring mySignature;
public NumpyDocString(@NotNull Substring text) {
@@ -18,6 +18,7 @@ package com.jetbrains.python;
import com.intellij.psi.PsiElement;
import com.intellij.psi.search.PsiElementProcessor;
import com.intellij.psi.util.PsiTreeUtil;
import com.jetbrains.python.documentation.DocStringUtil;
import com.jetbrains.python.documentation.GoogleCodeStyleDocString;
import com.jetbrains.python.documentation.NumpyDocString;
import com.jetbrains.python.documentation.SectionBasedDocString;
@@ -290,6 +291,19 @@ public class PySectionBasedDocStringTest extends PyTestCase {
assertEquals("keyword arguments", docString.getSections().get(0).getNormalizedTitle());
}
// PY-16766
public void testGoogleDocStringContentDetection() {
assertTrue(DocStringUtil.isGoogleDocString(
"\n" +
" My Section:\n" +
" some user defined section\n" +
" \n" +
" Parameters:\n" +
" param1: \n" +
"\n" +
" Returns:\n"));
}
@Override
protected String getTestDataPath() {
return super.getTestDataPath() + "/docstrings";