Repository: sphinx-doc/sphinx

Issue:
Parsing error when using dataclasses in Py36 without default values
Subject: sphinx build fails when using dataclasses in Py36 without default values

### Problem

Using Python 3.6.5 on Win7 inside a Pipenv venv.

When building the documentation, Sphinx is unable to parse a .py file containing a simple dataclass (see .py file below).

``` File "...sphinx\pycode\__init__.py", line 103, in parse
    raise PycodeError('parsing %r failed: %r' % (self.srcname, exc))
sphinx.errors.PycodeError: parsing ...\\agent_loop_args.py' failed: AssertionError()
```

#### Procedure to reproduce the problem
```
make html
```
(nothing fancy going on)

#### Error logs / results

https://pastebin.com/qQi0NLW4

#### Expected results

I expected Sphinx to document the dataclass, showing the attributes' expected types.

### Reproducible project / your project

```Python3
import threading
import dataclasses


@dataclasses.dataclass
class AgentLoopArgs:
    """
    Defines the parameters necessary for an Agent to run.
    """
    on_start: callable
    on_stop: callable
    target: callable
    target_args: tuple
    target_kwargs: dict
    delay: int
    name: str
    stop_event: threading.Event
```

### Environment info
- OS: Win7
- Python version: 3.6.5
- Sphinx version: 1.7.4

Extensions:
```
#   alabaster (0.7.10) 
#   sphinx.ext.autodoc (1.7.4) 
#   sphinx.ext.intersphinx (1.7.4) 
#   sphinx.ext.todo (1.7.4)
#   sphinx.ext.coverage (1.7.4)
#   sphinx.ext.mathjax (1.7.4)
#   sphinx.ext.ifconfig (1.7.4)
#   sphinx.ext.viewcode (1.7.4)
#   sphinx.ext.githubpages (1.7.4)
```

This is my first time reporting an issue here, please let me know if I've broken any guideline and I'll do my best to fix it!

EDIT: I forgot to emphasize that if I'm specifying default values like so:

```Python3
import threading
import dataclasses


@dataclasses.dataclass
class AgentLoopArgs:
    """
    Defines the parameters necessary for an Agent to run.
    """
    on_start: callable = None
    on_stop: callable = None
    ...
```

then Sphinx has no issue whatsoever building the documentation.

Discussion:

Patch:
diff --git a/CHANGES b/CHANGES
index c4bf31738..d6a531462 100644
--- a/CHANGES
+++ b/CHANGES
@@ -39,6 +39,7 @@ Bugs fixed
 * #4973: latex: glossary directive adds whitespace to each item
 * #4980: latex: Explicit labels on code blocks are duplicated
 * #4919: node.asdom() crashes if toctree has :numbered: option
+* #4914: autodoc: Parsing error when using dataclasses without default values
 
 Testing
 --------
diff --git a/sphinx/pycode/parser.py b/sphinx/pycode/parser.py
index deba48b1c..5c4291d3d 100644
--- a/sphinx/pycode/parser.py
+++ b/sphinx/pycode/parser.py
@@ -224,12 +224,13 @@ def fetch_rvalue(self):
     def parse(self):
         # type: () -> None
         """Parse the code and obtain comment after assignment."""
-        # skip lvalue (until '=' operator)
-        while self.fetch_token() != [OP, '=']:
+        # skip lvalue (or whole of AnnAssign)
+        while not self.fetch_token().match([OP, '='], NEWLINE, COMMENT):
             assert self.current
 
-        # skip rvalue
-        self.fetch_rvalue()
+        # skip rvalue (if exists)
+        if self.current == [OP, '=']:
+            self.fetch_rvalue()
 
         if self.current == COMMENT:
             self.comment = self.current.value


Test patch:
diff --git a/tests/test_pycode_parser.py b/tests/test_pycode_parser.py
index 09f1f41f5..29363e17e 100644
--- a/tests/test_pycode_parser.py
+++ b/tests/test_pycode_parser.py
@@ -100,11 +100,13 @@ def test_comment_picker_location():
 def test_annotated_assignment_py36():
     source = ('a: str = "Sphinx"  #: comment\n'
               'b: int = 1\n'
-              '"""string on next line"""')
+              '"""string on next line"""\n'
+              'c: int  #: comment')
     parser = Parser(source)
     parser.parse()
     assert parser.comments == {('', 'a'): 'comment',
-                               ('', 'b'): 'string on next line'}
+                               ('', 'b'): 'string on next line',
+                               ('', 'c'): 'comment'}
     assert parser.definitions == {}