diff options
author | Takeshi KOMIYA <i.tkomiya@gmail.com> | 2017-04-29 17:45:41 +0900 |
---|---|---|
committer | Takeshi KOMIYA <i.tkomiya@gmail.com> | 2017-04-29 23:22:00 +0900 |
commit | d1e8e41b5e4ffd2a4c61dbe8291b18ae22548d25 (patch) | |
tree | efae42ac259f8abaff7833f0fd338331fa50fb73 /sphinx/domains/std.py | |
parent | 9d0338777c6f42fe98654716fb654b7f52ebc0ee (diff) | |
download | sphinx-git-d1e8e41b5e4ffd2a4c61dbe8291b18ae22548d25.tar.gz |
Fix #3633: misdetect unreferenced citations
Diffstat (limited to 'sphinx/domains/std.py')
-rw-r--r-- | sphinx/domains/std.py | 42 |
1 files changed, 34 insertions, 8 deletions
diff --git a/sphinx/domains/std.py b/sphinx/domains/std.py index c08842e6c..7a81dc1ba 100644 --- a/sphinx/domains/std.py +++ b/sphinx/domains/std.py @@ -490,15 +490,16 @@ class StandardDomain(Domain): } # type: Dict[unicode, Union[RoleFunction, XRefRole]] initial_data = { - 'progoptions': {}, # (program, name) -> docname, labelid - 'objects': {}, # (type, name) -> docname, labelid - 'citations': {}, # name -> docname, labelid - 'labels': { # labelname -> docname, labelid, sectionname + 'progoptions': {}, # (program, name) -> docname, labelid + 'objects': {}, # (type, name) -> docname, labelid + 'citations': {}, # name -> docname, labelid, lineno + 'citation_refs': {}, # name -> list of docnames + 'labels': { # labelname -> docname, labelid, sectionname 'genindex': ('genindex', '', l_('Index')), 'modindex': ('py-modindex', '', l_('Module Index')), 'search': ('search', '', l_('Search Page')), }, - 'anonlabels': { # labelname -> docname, labelid + 'anonlabels': { # labelname -> docname, labelid 'genindex': ('genindex', ''), 'modindex': ('py-modindex', ''), 'search': ('search', ''), @@ -530,9 +531,14 @@ class StandardDomain(Domain): for key, (fn, _l) in list(self.data['objects'].items()): if fn == docname: del self.data['objects'][key] - for key, (fn, _l) in list(self.data['citations'].items()): + for key, (fn, _l, lineno) in list(self.data['citations'].items()): if fn == docname: del self.data['citations'][key] + for key, docnames in list(self.data['citation_refs'].items()): + if docnames == [docname]: + del self.data['citation_refs'][key] + elif docname in docnames: + docnames.pop(docname) for key, (fn, _l, _l) in list(self.data['labels'].items()): if fn == docname: del self.data['labels'][key] @@ -552,6 +558,11 @@ class StandardDomain(Domain): for key, data in otherdata['citations'].items(): if data[0] in docnames: self.data['citations'][key] = data + for key, data in otherdata['citation_refs'].items(): + citation_refs = self.data['citation_refs'].setdefault(key, []) + for docname in data: + if docname in docnames: + citation_refs.append(docname) for key, data in otherdata['labels'].items(): if data[0] in docnames: self.data['labels'][key] = data @@ -562,6 +573,7 @@ class StandardDomain(Domain): def process_doc(self, env, docname, document): # type: (BuildEnvironment, unicode, nodes.Node) -> None self.note_citations(env, docname, document) + self.note_citation_refs(env, docname, document) self.note_labels(env, docname, document) def note_citations(self, env, docname, document): @@ -572,7 +584,13 @@ class StandardDomain(Domain): path = env.doc2path(self.data['citations'][label][0]) logger.warning('duplicate citation %s, other instance in %s', label, path, location=node, type='ref', subtype='citation') - self.data['citations'][label] = (docname, node['ids'][0]) + self.data['citations'][label] = (docname, node['ids'][0], node.line) + + def note_citation_refs(self, env, docname, document): + # type: (BuildEnvironment, unicode, nodes.Node) -> None + for name, refs in iteritems(document.citation_refs): + citation_refs = self.data['citation_refs'].setdefault(name, []) + citation_refs.append(docname) def note_labels(self, env, docname, document): # type: (BuildEnvironment, unicode, nodes.Node) -> None @@ -614,6 +632,14 @@ class StandardDomain(Domain): continue labels[name] = docname, labelid, sectname + def check_consistency(self): + # type: () -> None + for name, (docname, labelid, lineno) in iteritems(self.data['citations']): + if labelid not in self.data['citation_refs']: + logger.warning('Citation [%s] is not referenced.', name, + type='ref', subtype='citation', + location=(docname, lineno)) + def build_reference_node(self, fromdocname, builder, docname, labelid, sectname, rolename, **options): # type: (unicode, Builder, unicode, unicode, unicode, unicode, Any) -> nodes.Node @@ -788,7 +814,7 @@ class StandardDomain(Domain): # type: (BuildEnvironment, unicode, Builder, unicode, unicode, nodes.Node, nodes.Node) -> nodes.Node # NOQA from sphinx.environment import NoUri - docname, labelid = self.data['citations'].get(target, ('', '')) + docname, labelid, lineno = self.data['citations'].get(target, ('', '', 0)) if not docname: if 'ids' in node: # remove ids attribute that annotated at |