PY-16761 Both StructuredDocString#getParameters and #getParameterSubstrings return...
authorMikhail Golubev <mikhail.golubev@jetbrains.com>
Sat, 5 Sep 2015 22:59:57 +0000 (01:59 +0300)
committerMikhail Golubev <mikhail.golubev@jetbrains.com>
Sat, 5 Sep 2015 22:59:57 +0000 (01:59 +0300)
python/src/com/jetbrains/python/documentation/DocStringReferenceProvider.java
python/src/com/jetbrains/python/documentation/GoogleCodeStyleDocString.java
python/src/com/jetbrains/python/documentation/NumpyDocString.java
python/src/com/jetbrains/python/documentation/SectionBasedDocString.java
python/src/com/jetbrains/python/inspections/PyDocstringInspection.java
python/src/com/jetbrains/python/inspections/quickfix/DocstringQuickFix.java
python/testData/inspections/GoogleDocstringParametersInspection/test.py
python/testSrc/com/jetbrains/python/PyQuickFixTest.java

index 32bcbc356cd7381c44860361c9196cf6be178a34..958d43da5f613b88a6059b731e8b50c0c800bd96 100644 (file)
@@ -113,7 +113,7 @@ public class DocStringReferenceProvider extends PsiReferenceProvider {
                                                         @NotNull ReferenceType refType) {
     List<PsiReference> result = new ArrayList<PsiReference>();
     for (Substring name : paramNames) {
-      final String s = trimLeadingStars(name).toString();
+      final String s = name.toString();
       if (PyNames.isIdentifier(s)) {
         final TextRange range = name.getTextRange().shiftRight(offset);
         result.add(new DocStringParameterReference(element, range, refType));
@@ -137,7 +137,7 @@ public class DocStringReferenceProvider extends PsiReferenceProvider {
     for (SectionField field : fields) {
       final Substring nameSub = field.getNameAsSubstring();
       if (nameRefType != null && nameSub != null && !nameSub.isEmpty()) {
-        final TextRange range = trimLeadingStars(nameSub).getTextRange().shiftRight(offset);
+        final TextRange range = nameSub.getTextRange().shiftRight(offset);
         result.add(new DocStringParameterReference(element, range, nameRefType));
       }
       final Substring typeSub = field.getTypeAsSubstring();
@@ -185,13 +185,4 @@ public class DocStringReferenceProvider extends PsiReferenceProvider {
     }
     return foundTag == null ? null : new TextRange(result, result + foundTag.length());
   }
-
-  @NotNull
-  private static Substring trimLeadingStars(@NotNull Substring name) {
-    int firstNotStar = 0;
-    while (firstNotStar < name.length() && name.charAt(firstNotStar) == '*') {
-      firstNotStar++;
-    }
-    return name.substring(firstNotStar).trimLeft();
-  }
 }
index d720604ed24c43d42de5da63e8eb681459034ebe..ae02f2074e170b4e1e260b12a3d378d5a17012a3 100644 (file)
@@ -18,6 +18,7 @@ package com.jetbrains.python.documentation;
 import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.util.containers.ContainerUtil;
+import com.jetbrains.python.PyNames;
 import com.jetbrains.python.toolbox.Substring;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
@@ -99,7 +100,10 @@ public class GoogleCodeStyleDocString extends SectionBasedDocString {
       type = name;
       name = null;
     }
-    if (name != null ? !isValidFieldName(name) : type.isEmpty()) {
+    if (name != null) {
+      name = cleanUpName(name);
+    }
+    if (name != null ? !PyNames.isIdentifierString(name.toString()) : type.isEmpty()) {
       return Pair.create(null, lineNum);
     }
     description = colonSeparatedParts.get(1);
index fd18f12bee0ebfff5a8e7bbc61231b13467ed6e7..0211a068361f8f0196e73f4c4130f2120335ff14 100644 (file)
@@ -16,6 +16,7 @@
 package com.jetbrains.python.documentation;
 
 import com.intellij.openapi.util.Pair;
+import com.jetbrains.python.PyNames;
 import com.jetbrains.python.toolbox.Substring;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
@@ -82,7 +83,10 @@ public class NumpyDocString extends SectionBasedDocString {
       type = name;
       name = null;
     }
-    if (name != null? !isValidFieldName(name) : type.isEmpty()) {
+    if (name != null) {
+      name = cleanUpName(name);
+    }
+    if (name != null? !PyNames.isIdentifierString(name.toString()) : type.isEmpty()) {
       return Pair.create(null, lineNum);
     }
     final Pair<List<Substring>, Integer> parsedDescription = parseIndentedBlock(lineNum + 1, getLineIndentSize(lineNum));
index fc973a55cc79c2180f069de37d8aa34eff0f2d08..a2ee4fa2085c3753f5751b3dd8f5b3233378a1f1 100644 (file)
@@ -29,7 +29,6 @@ import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 import java.util.*;
-import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 /**
@@ -39,7 +38,6 @@ import java.util.regex.Pattern;
  * @see <a href="http://sphinxcontrib-napoleon.readthedocs.org/en/latest/index.html">Napoleon</a>
  */
 public abstract class SectionBasedDocString extends DocStringLineParser implements StructuredDocString {
-  protected static final Pattern FIELD_NAME = Pattern.compile("\\**\\s*(\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*)");
 
   /**
    * Frequently used section types
@@ -524,16 +522,12 @@ public abstract class SectionBasedDocString extends DocStringLineParser implemen
   }
 
   @NotNull
-  protected static String extractFieldName(@NotNull CharSequence s) {
-    final Matcher matcher = FIELD_NAME.matcher(s);
-    if (matcher.matches()) {
-      return matcher.group(1);
+  protected static Substring cleanUpName(@NotNull Substring name) {
+    int firstNotStar = 0;
+    while (firstNotStar < name.length() && name.charAt(firstNotStar) == '*') {
+      firstNotStar++;
     }
-    return s.toString();
-  }
-
-  public static boolean isValidFieldName(@NotNull CharSequence s) {
-    return FIELD_NAME.matcher(s).matches();
+    return name.substring(firstNotStar).trimLeft();
   }
 
   public static class Section {
@@ -600,7 +594,7 @@ public abstract class SectionBasedDocString extends DocStringLineParser implemen
 
     @NotNull
     public String getName() {
-      return myName == null ? "" : extractFieldName(myName.toString());
+      return myName == null ? "" : myName.toString();
     }
 
     @Nullable
index 5934a3876d79d0379b89127769fe82b9efbc6ab1..07ea5e06938f3887c4953e26256c7dbe29f9071f 100644 (file)
@@ -182,7 +182,7 @@ public class PyDocstringInspection extends PyInspection {
       Map<String, Substring> unexpected = Maps.newHashMap();
 
       for (Substring s : docString.getParameterSubstrings()) {
-        unexpected.put(StringUtil.trimLeading(s.getValue(), '*').trim(), s);
+        unexpected.put(s.toString(), s);
       }
 
       for (PyParameter p : realParams) {
@@ -195,12 +195,13 @@ public class PyDocstringInspection extends PyInspection {
 
     private static List<PyParameter> getMissingParams(StructuredDocString docString, PyParameter[] realParams) {
       List<PyParameter> missing = new ArrayList<PyParameter>();
+      final List<String> docStringParameters = docString.getParameters();
       for (PyParameter p : realParams) {
         if (p.isSelf() || p instanceof PySingleStarParameter || p instanceof PyTupleParameter) {
           continue;
         }
         //noinspection ConstantConditions
-        if (!docString.getParameters().contains(p.getName())) {
+        if (!docStringParameters.contains(p.getName())) {
           missing.add(p);
         }
       }
index 61661371a3be572c39846e3cae79ddaf548dd725..ed6bba3dfaa63bb0ced1b014c3fb7650c226e709 100644 (file)
@@ -21,7 +21,6 @@ import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.editor.EditorFactory;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.psi.PsiDocumentManager;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.util.PsiTreeUtil;
@@ -93,7 +92,7 @@ public class DocstringQuickFix implements LocalQuickFix {
         generator.withParam(myMissingText);
       }
       else if (myUnexpected != null) {
-        generator.withoutParam(StringUtil.trimLeading(myUnexpected, '*').trim());
+        generator.withoutParam(myUnexpected.trim());
       }
       generator.buildAndInsert();
     }
index ae5a586015da2e49e3593abcd70e68d23107af43..44a8610ab75c6ea36c7c852a33881aa843d71f8f 100644 (file)
@@ -55,8 +55,8 @@ def varagrs_defined_without_stars(x, *args, y, **kwargs):
 def varagrs_dont_exist():
   """
   Args:
-    <weak_warning descr="Unexpected parameter *args in docstring">*args</weak_warning>:
-    <weak_warning descr="Unexpected parameter **kwargs in docstring">**kwargs</weak_warning>:
+    *<weak_warning descr="Unexpected parameter args in docstring">args</weak_warning>:
+    **<weak_warning descr="Unexpected parameter kwargs in docstring">kwargs</weak_warning>:
   """
   
 def varagrs_undefined(x, <weak_warning descr="Missing parameter args in docstring">*args</weak_warning>, y, <weak_warning descr="Missing parameter kwargs in docstring">**kwargs</weak_warning>):
index bc19c886b26827eb593bca90111a88ab9d56f87f..73e48ee48d1c9f320402bea5aaec05bc91d34ace 100644 (file)
@@ -499,7 +499,7 @@ public class PyQuickFixTest extends PyTestCase {
     runWithDocStringFormat(DocStringFormat.GOOGLE, new Runnable() {
       @Override
       public void run() {
-        doInspectionTest(PyDocstringInspection.class, PyBundle.message("QFIX.docstring.remove.$0", "*args"), true, true);
+        doInspectionTest(PyDocstringInspection.class, PyBundle.message("QFIX.docstring.remove.$0", "args"), true, true);
       }
     });
   }
@@ -509,7 +509,7 @@ public class PyQuickFixTest extends PyTestCase {
     runWithDocStringFormat(DocStringFormat.GOOGLE, new Runnable() {
       @Override
       public void run() {
-        doInspectionTest(PyDocstringInspection.class, PyBundle.message("QFIX.docstring.remove.$0", "**kwargs"), true, true);
+        doInspectionTest(PyDocstringInspection.class, PyBundle.message("QFIX.docstring.remove.$0", "kwargs"), true, true);
       }
     });
   }