C++, full support for parallel builds.

Fixes sphinx-doc/sphinx#2130.
This commit is contained in:
Jakob Lykke Andersen 2015-11-29 15:19:45 +01:00
parent 03cc72eea0
commit 9ac166d326

View File

@ -2013,7 +2013,6 @@ class ASTDeclaration(ASTBase):
self.declaration = declaration self.declaration = declaration
self.symbol = None self.symbol = None
self.declarationScope = None # set by Symbol.add_declaration
@property @property
def name(self): def name(self):
@ -2056,9 +2055,6 @@ class ASTDeclaration(ASTBase):
parentNode.pop() parentNode.pop()
assert self.symbol assert self.symbol
if not self.declarationScope:
raise NotImplementedError("hmm, a bug? %s" % text_type(self))
assert self.declarationScope
if self.templatePrefix: if self.templatePrefix:
self.templatePrefix.describe_signature(parentNode, mode, env, self.templatePrefix.describe_signature(parentNode, mode, env,
symbol=self.symbol) symbol=self.symbol)
@ -2140,6 +2136,28 @@ class Symbol(object):
nn = ASTNestedName([nne], rooted=False) nn = ASTNestedName([nne], rooted=False)
self._add_symbols(nn, [], decl, docname) self._add_symbols(nn, [], decl, docname)
def _fill_empty(self, declaration, docname):
self._assert_invariants()
assert not self.declaration
assert not self.docname
assert declaration
assert docname
self.declaration = declaration
self.declaration.symbol = self
self.docname = docname
self._assert_invariants()
def clear_doc(self, docname):
newChildren = []
for sChild in self.children:
sChild.clear_doc(docname)
if sChild.declaration and sChild.docname == docname:
sChild.declaration = None
sChild.docname = None
if sChild.declaration or len(sChild.children) > 0:
newChildren.append(sChild)
self.children = newChildren
def get_all_symbols(self): def get_all_symbols(self):
yield self yield self
for sChild in self.children: for sChild in self.children:
@ -2225,7 +2243,6 @@ class Symbol(object):
if nestedName.rooted: if nestedName.rooted:
while parentSymbol.parent: while parentSymbol.parent:
parentSymbol = parentSymbol.parent parentSymbol = parentSymbol.parent
declarationScope = parentSymbol
names = nestedName.names names = nestedName.names
iTemplateDecl = 0 iTemplateDecl = 0
for name in names[:-1]: for name in names[:-1]:
@ -2286,11 +2303,7 @@ class Symbol(object):
# .. namespace:: Test # .. namespace:: Test
# .. namespace:: nullptr # .. namespace:: nullptr
# .. class:: Test # .. class:: Test
symbol.declaration = declaration symbol._fill_empty(declaration, docname)
symbol.docname = docname
declaration.symbol = symbol
declaration.declarationScope = declarationScope
symbol._assert_invariants()
return symbol return symbol
# it may simply be a functin overload # it may simply be a functin overload
# TODO: it could be a duplicate but let's just insert anyway # TODO: it could be a duplicate but let's just insert anyway
@ -2300,17 +2313,55 @@ class Symbol(object):
templateArgs=templateArgs, templateArgs=templateArgs,
declaration=declaration, declaration=declaration,
docname=docname) docname=docname)
declaration.declarationScope = declarationScope
else: else:
symbol = Symbol(parent=parentSymbol, identifier=identifier, symbol = Symbol(parent=parentSymbol, identifier=identifier,
templateParams=templateParams, templateParams=templateParams,
templateArgs=templateArgs, templateArgs=templateArgs,
declaration=declaration, declaration=declaration,
docname=docname) docname=docname)
if declaration:
declaration.declarationScope = declarationScope
return symbol return symbol
def merge_with(self, other, docnames, env):
assert other is not None
for otherChild in other.children:
if not otherChild.identifier:
if not otherChild.declaration:
print("WTF?")
print(otherChild.dump(0))
print(other.dump(0))
assert otherChild.declaration
operator = otherChild.declaration.name.names[-1]
assert operator.is_operator()
else:
operator = None
ourChild = self._find_named_symbol(otherChild.identifier,
otherChild.templateParams,
otherChild.templateArgs,
operator,
templateShorthand=False,
matchSelf=False)
if ourChild is None:
# TODO: hmm, should we prune by docnames?
self.children.append(otherChild)
otherChild.parent = self
otherChild._assert_invariants()
continue
if otherChild.declaration and otherChild.docname in docnames:
if not ourChild.declaration:
ourChild._fill_empty(otherChild.declaration, otherChild.docname)
elif ourChild.docname != otherChild.docname:
name = text_type(ourChild.declaration)
msg = "Duplicate declaration, also defined in '%s'.\n"
msg += "Declaration is '%s'."
msg = msg % (ourChild.docname, name)
env.warn(otherChild.docname, msg)
else:
# Both have declarations, and in the same docname.
# This can apparently happen, it should be safe to
# just ignore it, right?
pass
ourChild.merge_with(otherChild, docnames, env)
def add_name(self, nestedName, templatePrefix=None): def add_name(self, nestedName, templatePrefix=None):
if templatePrefix: if templatePrefix:
templateDecls = templatePrefix.templates templateDecls = templatePrefix.templates
@ -2320,6 +2371,8 @@ class Symbol(object):
declaration=None, docname=None) declaration=None, docname=None)
def add_declaration(self, declaration, docname): def add_declaration(self, declaration, docname):
assert declaration
assert docname
nestedName = declaration.name nestedName = declaration.name
if declaration.templatePrefix: if declaration.templatePrefix:
templateDecls = declaration.templatePrefix.templates templateDecls = declaration.templatePrefix.templates
@ -2425,22 +2478,34 @@ class Symbol(object):
parentSymbol = symbol parentSymbol = symbol
assert False # should have returned in the loop assert False # should have returned in the loop
def dump(self, indent): def to_string(self, indent):
self._assert_invariants()
res = ['\t'*indent] res = ['\t'*indent]
if self.identifier: if not self.parent:
res.append('::')
else:
if self.templateParams: if self.templateParams:
res.append(text_type(self.templateParams)) res.append(text_type(self.templateParams))
res.append('\n') res.append('\n')
res.append('\t'*indent) res.append('\t'*indent)
res.append(text_type(self.identifier)) if self.identifier:
res.append(text_type(self.identifier))
else:
res.append(text_type(self.declaration))
if self.templateArgs: if self.templateArgs:
res.append(text_type(self.templateArgs)) res.append(text_type(self.templateArgs))
if self.declaration: if self.declaration:
res.append(": ") res.append(": ")
res.append(text_type(self.declaration)) res.append(text_type(self.declaration))
else: if self.docname:
res.append('::') res.append('\t(')
res.append(self.docname)
res.append(')')
res.append('\n') res.append('\n')
return ''.join(res)
def dump(self, indent):
res = [self.to_string(indent)]
for c in self.children: for c in self.children:
res.append(c.dump(indent + 1)) res.append(c.dump(indent + 1))
return ''.join(res) return ''.join(res)
@ -3715,28 +3780,30 @@ class CPPDomain(Domain):
def clear_doc(self, docname): def clear_doc(self, docname):
rootSymbol = self.data['rootSymbol'] rootSymbol = self.data['rootSymbol']
for symbol in rootSymbol.get_all_symbols(): rootSymbol.clear_doc(docname)
if not symbol.declaration:
continue
if symbol.docname != docname:
continue
symbol.declaration = None
symbol.docname = None
for name, nDocname in list(self.data['names'].items()): for name, nDocname in list(self.data['names'].items()):
if nDocname == docname: if nDocname == docname:
del self.data['names'][name] del self.data['names'][name]
def process_doc(self, env, docname, document): def process_doc(self, env, docname, document):
# just for debugging # just for debugging
# print(docname)
# print(self.data['rootSymbol'].dump(0)) # print(self.data['rootSymbol'].dump(0))
pass pass
def merge_domaindata(self, docnames, otherdata): def merge_domaindata(self, docnames, otherdata):
theirRoot = self.data['rootSymbol'] self.data['rootSymbol'].merge_with(otherdata['rootSymbol'],
assert theirRoot is not None docnames, self.env)
if theirRoot.parent is not None: ourNames = self.data['names']
raise NotImplementedError() for name, docname in otherdata['names'].items():
# TODO: do the actual merging if docname in docnames:
if name in ourNames:
msg = "Duplicate declaration, also defined in '%s'.\n"
msg += "Name of declaration is '%s'."
msg = msg % (ourNames[name], name)
self.env.warn(docname, msg)
else:
ourNames[name] = docname
def _resolve_xref_inner(self, env, fromdocname, builder, def _resolve_xref_inner(self, env, fromdocname, builder,
target, node, contnode, emitWarnings=True): target, node, contnode, emitWarnings=True):