final PsiElement stringNode = parameters.getOriginalPosition();
assert stringNode != null;
final int offset = parameters.getOffset();
- if (file.findReferenceAt(offset) != null) {
- return;
- }
final DocStringFormat format = DocStringUtil.getConfiguredDocStringFormat(file);
if (!(format == DocStringFormat.GOOGLE || format == DocStringFormat.NUMPY)) {
return;
}
+ // Numpy docstring format is ambiguous. Because parameters have the same indentation as section headers,
+ // beginning of section header can be parsed as parameter reference
+ if (format == DocStringFormat.GOOGLE && file.findReferenceAt(offset) != null) {
+ return;
+ }
final Document document = parameters.getEditor().getDocument();
final TextRange linePrefixRange = new TextRange(document.getLineStartOffset(document.getLineNumber(offset)), offset);
final String prefix = StringUtil.trimLeading(document.getText(linePrefixRange));
return Pair.create(null, lineNum);
}
+ @Override
+ protected int getSectionIndentationThreshold(int sectionIndent) {
+ // For Numpy we want to let section content has the same indent as section header
+ return sectionIndent - 1;
+ }
+
@Override
protected Pair<SectionField, Integer> parseSectionField(int lineNum,
int sectionIndent,
@NotNull
protected Pair<SectionField, Integer> parseGenericField(int lineNum, int sectionIndent) {
- // We want to let section content has the same indent as section header, in particular for Numpy
- final Pair<List<Substring>, Integer> pair = parseIndentedBlock(lineNum, Math.max(sectionIndent - 1, 0));
+ final Pair<List<Substring>, Integer> pair = parseIndentedBlock(lineNum, getSectionIndentationThreshold(sectionIndent));
final Substring firstLine = ContainerUtil.getFirstItem(pair.getFirst());
final Substring lastLine = ContainerUtil.getLastItem(pair.getFirst());
if (firstLine != null && lastLine != null) {
protected boolean isSectionBreak(int lineNum, int curSectionIndent) {
return lineNum >= getLineCount() ||
// note that field may have the same indent as its containing section
- (!isEmpty(lineNum) && getLineIndentSize(lineNum) < curSectionIndent) ||
+ (!isEmpty(lineNum) && getLineIndentSize(lineNum) <= getSectionIndentationThreshold(curSectionIndent)) ||
isSectionStart(lineNum);
}
return Pair.create(myLines.subList(lineNum, blockEnd), blockEnd);
}
+ /**
+ * Inside section any indentation that is equal or smaller to returned one signals about section break.
+ * It's safe to return negative value, because it's used only for comparisons.
+ *
+ * @see #isSectionBreak(int, int)
+ * @see #parseGenericField(int, int)
+ */
+ protected int getSectionIndentationThreshold(int sectionIndent) {
+ return sectionIndent;
+ }
+
@Override
protected boolean isBlockEnd(int lineNum) {
return isSectionStart(lineNum);
--- /dev/null
+def f(x):
+ """
+ Args:
+ x:
+
+ Ret<caret>:
+ """
\ No newline at end of file
--- /dev/null
+def f(x, y):
+ """
+ Args:
+ x (int): foo
+
+ Args:
+ y (int): bar
+
+ Examples:
+ first line
+ second line
+ third line
+ """
\ No newline at end of file
assertEquals(firstField.getDescription(), "description");
}
+ // PY-16991
+ public void testGoogleMandatoryIndentationInsideSection() {
+ final GoogleCodeStyleDocString docString = findAndParseGoogleStyleDocString();
+ assertSize(3, docString.getSections());
+ assertEmpty(docString.getSections().get(0).getFields());
+ assertSize(1, docString.getSections().get(1).getFields());
+ final Section thirdSection = docString.getSections().get(2);
+ assertSize(1, thirdSection.getFields());
+ final SectionField firstExample = thirdSection.getFields().get(0);
+ assertEmpty(firstExample.getName());
+ assertEmpty(firstExample.getType());
+ assertEquals("first line\n" +
+ "second line", firstExample.getDescription());
+ }
+
@Override
protected String getTestDataPath() {
return super.getTestDataPath() + "/docstrings";
});
}
+ // PY-16991
+ public void testSecondSectionNameInGoogleDocstring() {
+ runWithDocStringFormat(DocStringFormat.GOOGLE, new Runnable() {
+ @Override
+ public void run() {
+ final List<String> variants = doTestByFile();
+ assertNotNull(variants);
+ assertContainsElements(variants, "Return", "Returns");
+ }
+ });
+ }
+
// PY-16877
public void testTwoWordsSectionNameInGoogleDocstring() throws Exception {
runWithDocStringFormat(DocStringFormat.GOOGLE, new Runnable() {