mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-9795 Parse multiline summary until first empty line of the end of docstring
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jetbrains.python.documentation;
|
||||
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author Mikhail Golubev
|
||||
*/
|
||||
public class NumpyDocString extends SectionBasedDocString {
|
||||
public NumpyDocString(@NotNull String text) {
|
||||
super(text);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Pair<SectionField, Integer> parseFieldWithType(int lineNum, int sectionIndent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Pair<SectionField, Integer> parseFieldWithNameAndOptionalType(int lineNum, int sectionIndent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Pair<String, Integer> parseSectionHeader(int lineNum) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -38,6 +38,7 @@ import java.util.*;
|
||||
* @see <a href="http://sphinxcontrib-napoleon.readthedocs.org/en/latest/index.html">Napoleon</a>
|
||||
*/
|
||||
public abstract class SectionBasedDocString implements StructuredDocString {
|
||||
|
||||
/**
|
||||
* Frequently used section types
|
||||
*/
|
||||
@@ -79,31 +80,53 @@ public abstract class SectionBasedDocString implements StructuredDocString {
|
||||
|
||||
protected final List<Substring> myLines;
|
||||
|
||||
private final List<Substring> myOtherContent = new ArrayList<Substring>();
|
||||
private final Substring mySummary;
|
||||
private final List<Section> mySections = new ArrayList<Section>();
|
||||
private final String mySummary;
|
||||
private final List<Substring> myOtherContent = new ArrayList<Substring>();
|
||||
|
||||
protected SectionBasedDocString(@NotNull String text) {
|
||||
myLines = new Substring(text).splitLines();
|
||||
String summary = "";
|
||||
int lineNum = 0;
|
||||
List<Substring> summary = Collections.emptyList();
|
||||
final int startLine = parseHeader(0);
|
||||
int lineNum = skipEmptyLines(startLine);
|
||||
while (lineNum < myLines.size()) {
|
||||
Pair<Section, Integer> result = parseSection(lineNum);
|
||||
if (result.getFirst() != null) {
|
||||
mySections.add(result.getFirst());
|
||||
lineNum = result.getSecond();
|
||||
final Pair<Section, Integer> parsedSection = parseSection(lineNum);
|
||||
if (parsedSection.getFirst() != null) {
|
||||
mySections.add(parsedSection.getFirst());
|
||||
lineNum = parsedSection.getSecond();
|
||||
}
|
||||
else if (lineNum == startLine) {
|
||||
final Pair<List<Substring>, Integer> parsedSummary = parseSummary(lineNum);
|
||||
summary = parsedSummary.getFirst();
|
||||
lineNum = parsedSummary.getSecond();
|
||||
}
|
||||
else {
|
||||
if (lineNum == 0 && isEmptyOrDoesNotExist(lineNum + 1)) {
|
||||
summary = getLine(0).trim().toString();
|
||||
}
|
||||
else {
|
||||
myOtherContent.add(getLine(lineNum));
|
||||
}
|
||||
myOtherContent.add(getLine(lineNum));
|
||||
lineNum++;
|
||||
}
|
||||
lineNum = skipEmptyLines(lineNum);
|
||||
}
|
||||
mySummary = summary;
|
||||
//noinspection ConstantConditions
|
||||
mySummary = summary.isEmpty() ? null : mergeSubstrings(summary.get(0), summary.get(summary.size() - 1)).trim();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Pair<List<Substring>, Integer> parseSummary(int lineNum) {
|
||||
final List<Substring> result = new ArrayList<Substring>();
|
||||
while (!isEmptyOrDoesNotExist(lineNum)) {
|
||||
result.add(getLine(lineNum));
|
||||
lineNum++;
|
||||
}
|
||||
return Pair.create(result, lineNum);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to parse e.g. optional function signature at the beginning of NumPy-style docstring
|
||||
*
|
||||
* @return first line from which to star parsing remaining sections
|
||||
*/
|
||||
protected int parseHeader(int startLine) {
|
||||
return startLine;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -172,7 +195,7 @@ public abstract class SectionBasedDocString implements StructuredDocString {
|
||||
}
|
||||
|
||||
private boolean isEmptyOrDoesNotExist(int lineNum) {
|
||||
return lineNum >= myLines.size() - 1 || isEmpty(lineNum);
|
||||
return lineNum < 0 || lineNum >= myLines.size() || isEmpty(lineNum);
|
||||
}
|
||||
|
||||
private boolean isEmpty(int lineNum) {
|
||||
@@ -268,8 +291,13 @@ public abstract class SectionBasedDocString implements StructuredDocString {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected Substring getLine(int indent) {
|
||||
return myLines.get(indent);
|
||||
protected Substring getLine(int lineNum) {
|
||||
return myLines.get(lineNum);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected Substring getLineOrNull(int lineNum) {
|
||||
return lineNum >= 0 && lineNum < myLines.size() ? myLines.get(lineNum) : null;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -285,7 +313,7 @@ public abstract class SectionBasedDocString implements StructuredDocString {
|
||||
|
||||
@Override
|
||||
public String getSummary() {
|
||||
return mySummary.toString();
|
||||
return mySummary != null ? mySummary.concatTrimmedLines("\n") : "";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -407,6 +435,7 @@ public abstract class SectionBasedDocString implements StructuredDocString {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private SectionField getFirstFieldForKeywordArgument(@NotNull final String name) {
|
||||
return ContainerUtil.find(getKeywordArgumentFields(), new Condition<SectionField>() {
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
def func():
|
||||
"""First line
|
||||
Second line
|
||||
Third line"""
|
||||
+25
-7
@@ -19,6 +19,7 @@ import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.search.PsiElementProcessor;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.jetbrains.python.documentation.GoogleCodeStyleDocString;
|
||||
import com.jetbrains.python.documentation.NumpyDocString;
|
||||
import com.jetbrains.python.documentation.SectionBasedDocString.Section;
|
||||
import com.jetbrains.python.documentation.SectionBasedDocString.SectionField;
|
||||
import com.jetbrains.python.fixtures.PyTestCase;
|
||||
@@ -31,10 +32,10 @@ import java.util.List;
|
||||
/**
|
||||
* @author Mikhail Golubev
|
||||
*/
|
||||
public class PyGoogleCodeStyleDocStringTest extends PyTestCase {
|
||||
public class PySectionBasedDocStringTest extends PyTestCase {
|
||||
|
||||
public void testSimpleFunctionDocString() {
|
||||
final GoogleCodeStyleDocString docString = findAndParseDocString();
|
||||
final GoogleCodeStyleDocString docString = findAndParseGoogleStyleDocString();
|
||||
assertEquals("Summary", docString.getSummary());
|
||||
final List<Section> sections = docString.getSections();
|
||||
assertSize(3, sections);
|
||||
@@ -71,12 +72,22 @@ public class PyGoogleCodeStyleDocStringTest extends PyTestCase {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private GoogleCodeStyleDocString findAndParseDocString() {
|
||||
private String findAndParseDocString() {
|
||||
myFixture.configureByFile(getTestName(true) + ".py");
|
||||
final String docStringText = findFirstDocString();
|
||||
|
||||
assertNotNull(docStringText);
|
||||
return new GoogleCodeStyleDocString(docStringText);
|
||||
return docStringText;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private GoogleCodeStyleDocString findAndParseGoogleStyleDocString() {
|
||||
return new GoogleCodeStyleDocString(findAndParseDocString());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private NumpyDocString findAndParseNumpyStyleDocString() {
|
||||
return new NumpyDocString(findAndParseDocString());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -100,7 +111,7 @@ public class PyGoogleCodeStyleDocStringTest extends PyTestCase {
|
||||
}
|
||||
|
||||
public void testSectionStartAfterQuotes() {
|
||||
final GoogleCodeStyleDocString docString = findAndParseDocString();
|
||||
final GoogleCodeStyleDocString docString = findAndParseGoogleStyleDocString();
|
||||
assertEmpty(docString.getSummary());
|
||||
|
||||
assertSize(2, docString.getSections());
|
||||
@@ -125,7 +136,7 @@ public class PyGoogleCodeStyleDocStringTest extends PyTestCase {
|
||||
}
|
||||
|
||||
public void testTypeReferences() {
|
||||
final GoogleCodeStyleDocString docString = findAndParseDocString();
|
||||
final GoogleCodeStyleDocString docString = findAndParseGoogleStyleDocString();
|
||||
assertEmpty(docString.getSummary());
|
||||
assertSize(2, docString.getSections());
|
||||
|
||||
@@ -145,7 +156,7 @@ public class PyGoogleCodeStyleDocStringTest extends PyTestCase {
|
||||
}
|
||||
|
||||
public void testNestedIndentation() {
|
||||
final GoogleCodeStyleDocString docString = findAndParseDocString();
|
||||
final GoogleCodeStyleDocString docString = findAndParseGoogleStyleDocString();
|
||||
assertSize(1, docString.getSections());
|
||||
final Section section1 = docString.getSections().get(0);
|
||||
assertEquals("parameters", section1.getTitle());
|
||||
@@ -162,6 +173,13 @@ public class PyGoogleCodeStyleDocStringTest extends PyTestCase {
|
||||
" assert func(42) is None", param1.getDescription());
|
||||
}
|
||||
|
||||
public void testMultilineSummary() {
|
||||
final GoogleCodeStyleDocString docString = findAndParseGoogleStyleDocString();
|
||||
assertEquals("First line\n" +
|
||||
"Second line\n" +
|
||||
"Third line", docString.getSummary());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTestDataPath() {
|
||||
return super.getTestDataPath() + "/docstrings";
|
||||
Reference in New Issue
Block a user