Repository: bazelbuild/buildtools (go)

Issue:
Allow documentation for **kwargs in wrappers OR turn off lint warning.
Consider this wrapper method:
```
# buildifier: disable=function-docstring-args
def license(name, license_kinds = None, license_kind = None, copyright_notice = None, **kwargs):
    """Wrapper for license rule.

    Args:
      name: str target name.
      license_kinds: list(label) list of license_kind targets.
      license_kind: label a single license_kind. Only one of license_kind or license_kinds may
                    be specified
      copyright_notice: str Copyright notice associated with this package.
    """
```
First of all, the parsing must be broken, because (without the disable line) I see the lint warning
 
```
Argument "**kwargs" is not documented. 
 https://github.com/bazelbuild/buildtools/blob/master/WARNINGS.md#function-docstring-args
```

I added this to the docstring
`kwargs: additional args`

And *still* get the above warning, plus
```
Argument "kwargs" is documented but doesn't exist in the function signature. 
  https://github.com/bazelbuild/buildtools/blob/master/WARNINGS.md#function-docstring-args
```

This is a no win.

Suggested solution:  Allow this in the docstring
`kwargs: [forwarded to <other rule name>]`

The magical [fowarded to ...] would tell lint not to complain about it.
The <other rule name> could be used by Stardoc to pull up the definitions from the underlying rule, so we could document the wrapper appropriately.






Pull request description:
Improve the warning message for missing argument documentation
If a function signature contains arguments with asterisks ("*args" or "**kwargs") users often forget to include the asterisks into the documentation, which causes warnings like `Arguments "*args", "**kwargs" are not documented` and `Argument "args" is documented but doesn't exist in the function signature`. To avoid the confusion, the latter warning message is extended with `Do you mean "*args"?` (or `"**kwargs"`) if such an argument actually exists in the function signature.


Closes #768

Patch:
diff --git a/warn/warn_docstring.go b/warn/warn_docstring.go
index 2b73f3b..9d08c91 100644
--- a/warn/warn_docstring.go
+++ b/warn/warn_docstring.go
@@ -323,14 +323,23 @@ one (preferably two) space more than "Args:", for example:
 
 		// Check whether all documented arguments actually exist in the function signature.
 		for name, pos := range info.args {
-			if !paramNames[name] {
-				posEnd := pos
-				posEnd.LineRune += len(name)
-				finding := makeLinterFinding(doc, fmt.Sprintf("Argument %q is documented but doesn't exist in the function signature.", name))
-				finding.Start = pos
-				finding.End = posEnd
-				findings = append(findings, finding)
+			if paramNames[name] {
+				continue
+			}
+			msg := fmt.Sprintf("Argument %q is documented but doesn't exist in the function signature.", name)
+			// *args and **kwargs should be documented with asterisks
+			for _, asterisks := range []string{"*", "**"} {
+				if paramNames[asterisks+name] {
+					msg += fmt.Sprintf(` Do you mean "%s%s"?`, asterisks, name)
+					break
+				}
 			}
+			posEnd := pos
+			posEnd.LineRune += len(name)
+			finding := makeLinterFinding(doc, msg)
+			finding.Start = pos
+			finding.End = posEnd
+			findings = append(findings, finding)
 		}
 	}
 	return findings


Test patch:
diff --git a/warn/warn_docstring_test.go b/warn/warn_docstring_test.go
index 7fec84a..8205691 100644
--- a/warn/warn_docstring_test.go
+++ b/warn/warn_docstring_test.go
@@ -344,6 +344,26 @@ def f(x):
 `,
 		[]string{},
 		scopeEverywhere)
+
+	checkFindings(t, "function-docstring-args", `
+def f(foobar, *bar, **baz):
+  """Some function
+  
+  Args:
+    foobar: something
+    foo: something
+    bar: something
+    baz: something
+  """
+  pass
+`,
+		[]string{
+			`:2: Arguments "*bar", "**baz" are not documented.`,
+			`:6: Argument "foo" is documented but doesn't exist in the function signature.`,
+			`:7: Argument "bar" is documented but doesn't exist in the function signature. Do you mean "*bar"?`,
+			`:8: Argument "baz" is documented but doesn't exist in the function signature. Do you mean "**baz"?`,
+		},
+		scopeEverywhere)
 }
 
 func TestFunctionDocstringReturn(t *testing.T) {