mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
C++, fixes to id generation.
New ids are prefixed with "_CPPv1". Replacing the prefix with "_Z" should yield a valid mangled name following the Itanium C++ ABI, except for expressions, which are currently not handled.
This commit is contained in:
parent
f4cf30b95e
commit
fb3a524a90
@ -189,7 +189,6 @@ _operator_re = re.compile(r'''(?x)
|
|||||||
# Id v1 constants
|
# Id v1 constants
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
|
|
||||||
_id_prefix_v1 = '_CPP'
|
|
||||||
_id_fundamental_v1 = {
|
_id_fundamental_v1 = {
|
||||||
'char': 'c',
|
'char': 'c',
|
||||||
'signed char': 'c',
|
'signed char': 'c',
|
||||||
@ -264,7 +263,7 @@ _id_operator_v1 = {
|
|||||||
# Id v2 constants
|
# Id v2 constants
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
|
|
||||||
_id_prefix_v2 = '_CPP'
|
_id_prefix_v2 = '_CPPv2'
|
||||||
_id_fundamental_v2 = {
|
_id_fundamental_v2 = {
|
||||||
# not all of these are actually parsed as fundamental types, TODO: do that
|
# not all of these are actually parsed as fundamental types, TODO: do that
|
||||||
'void': 'v',
|
'void': 'v',
|
||||||
@ -517,6 +516,9 @@ class ASTNestedNameElement(ASTBase):
|
|||||||
res = []
|
res = []
|
||||||
if self.identifier == "std":
|
if self.identifier == "std":
|
||||||
res.append(u'St')
|
res.append(u'St')
|
||||||
|
elif self.identifier[0] == "~":
|
||||||
|
# a destructor, just use an arbitrary version of dtors
|
||||||
|
res.append("D0")
|
||||||
else:
|
else:
|
||||||
res.append(text_type(len(self.identifier)))
|
res.append(text_type(len(self.identifier)))
|
||||||
res.append(self.identifier)
|
res.append(self.identifier)
|
||||||
@ -591,13 +593,14 @@ class ASTNestedName(ASTBase):
|
|||||||
res.append(n.get_id_v1())
|
res.append(n.get_id_v1())
|
||||||
return u'::'.join(res)
|
return u'::'.join(res)
|
||||||
|
|
||||||
def get_id_v2(self):
|
def get_id_v2(self, modifiers=""):
|
||||||
res = []
|
res = []
|
||||||
if len(self.names) > 1:
|
if len(self.names) > 1 or len(modifiers) > 0:
|
||||||
res.append('N')
|
res.append('N')
|
||||||
|
res.append(modifiers)
|
||||||
for n in self.names:
|
for n in self.names:
|
||||||
res.append(n.get_id_v2())
|
res.append(n.get_id_v2())
|
||||||
if len(self.names) > 1:
|
if len(self.names) > 1 or len(modifiers) > 0:
|
||||||
res.append('E')
|
res.append('E')
|
||||||
return u''.join(res)
|
return u''.join(res)
|
||||||
|
|
||||||
@ -867,6 +870,17 @@ class ASTDeclSpecsSimple(ASTBase):
|
|||||||
self.volatile = volatile
|
self.volatile = volatile
|
||||||
self.const = const
|
self.const = const
|
||||||
|
|
||||||
|
def mergeWith(self, other):
|
||||||
|
if not other:
|
||||||
|
return self
|
||||||
|
return ASTDeclSpecsSimple(self.storage or other.storage,
|
||||||
|
self.inline or other.inline,
|
||||||
|
self.virtual or other.virtual,
|
||||||
|
self.explicit or other.explicit,
|
||||||
|
self.constexpr or other.constexpr,
|
||||||
|
self.volatile or other.volatile,
|
||||||
|
self.const or other.const)
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
res = []
|
res = []
|
||||||
if self.storage:
|
if self.storage:
|
||||||
@ -905,12 +919,16 @@ class ASTDeclSpecsSimple(ASTBase):
|
|||||||
if self.const:
|
if self.const:
|
||||||
_add(modifiers, 'const')
|
_add(modifiers, 'const')
|
||||||
|
|
||||||
|
|
||||||
class ASTDeclSpecs(ASTBase):
|
class ASTDeclSpecs(ASTBase):
|
||||||
def __init__(self, outer, visibility, leftSpecs, rightSpecs, trailing):
|
def __init__(self, outer, visibility, leftSpecs, rightSpecs, trailing):
|
||||||
|
# leftSpecs and rightSpecs are used for output
|
||||||
|
# allSpecs are used for id generation
|
||||||
self.outer = outer
|
self.outer = outer
|
||||||
self.visibility = visibility
|
self.visibility = visibility
|
||||||
self.leftSpecs = leftSpecs
|
self.leftSpecs = leftSpecs
|
||||||
self.rightSpecs = rightSpecs
|
self.rightSpecs = rightSpecs
|
||||||
|
self.allSpecs = self.leftSpecs.mergeWith(self.rightSpecs)
|
||||||
self.trailingTypeSpec = trailing
|
self.trailingTypeSpec = trailing
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -920,9 +938,9 @@ class ASTDeclSpecs(ASTBase):
|
|||||||
def get_id_v1(self):
|
def get_id_v1(self):
|
||||||
res = []
|
res = []
|
||||||
res.append(self.trailingTypeSpec.get_id_v1())
|
res.append(self.trailingTypeSpec.get_id_v1())
|
||||||
if self.leftSpecs.volatile or self.rightSpecs.volatile:
|
if self.allSpecs.volatile:
|
||||||
res.append('V')
|
res.append('V')
|
||||||
if self.leftSpecs.const or self.rightSpecs.const:
|
if self.allSpecs.const:
|
||||||
res.append('C')
|
res.append('C')
|
||||||
return u''.join(res)
|
return u''.join(res)
|
||||||
|
|
||||||
@ -986,6 +1004,7 @@ class ASTDeclSpecs(ASTBase):
|
|||||||
for m in modifiers:
|
for m in modifiers:
|
||||||
signode += m
|
signode += m
|
||||||
|
|
||||||
|
|
||||||
class ASTPtrOpPtr(ASTBase):
|
class ASTPtrOpPtr(ASTBase):
|
||||||
def __init__(self, volatile, const):
|
def __init__(self, volatile, const):
|
||||||
self.volatile = volatile
|
self.volatile = volatile
|
||||||
@ -1194,8 +1213,8 @@ class ASTType(ASTBase):
|
|||||||
if self.objectType: # needs the name
|
if self.objectType: # needs the name
|
||||||
res.append(_id_prefix_v2)
|
res.append(_id_prefix_v2)
|
||||||
if self.objectType == 'function': # also modifiers
|
if self.objectType == 'function': # also modifiers
|
||||||
res.append(self.decl.get_modifiers_id_v2())
|
modifiers = self.decl.get_modifiers_id_v2()
|
||||||
res.append(self.prefixedName.get_id_v2())
|
res.append(self.prefixedName.get_id_v2(modifiers))
|
||||||
res.append(self.decl.get_param_id_v2())
|
res.append(self.decl.get_param_id_v2())
|
||||||
elif self.objectType == 'type': # just the name
|
elif self.objectType == 'type': # just the name
|
||||||
res.append(self.prefixedName.get_id_v2())
|
res.append(self.prefixedName.get_id_v2())
|
||||||
@ -1225,6 +1244,7 @@ class ASTType(ASTBase):
|
|||||||
signode += nodes.Text(' ')
|
signode += nodes.Text(' ')
|
||||||
self.decl.describe_signature(signode, mode, env)
|
self.decl.describe_signature(signode, mode, env)
|
||||||
|
|
||||||
|
|
||||||
class ASTTypeWithInit(ASTBase):
|
class ASTTypeWithInit(ASTBase):
|
||||||
def __init__(self, type, init):
|
def __init__(self, type, init):
|
||||||
self.objectType = None
|
self.objectType = None
|
||||||
@ -1939,7 +1959,7 @@ class CPPObject(ObjectDescription):
|
|||||||
ast.get_id_v2(),
|
ast.get_id_v2(),
|
||||||
ast.get_id_v1()
|
ast.get_id_v1()
|
||||||
]
|
]
|
||||||
theid = ids[1] # TODO: change to [0] before final version
|
theid = ids[0]
|
||||||
name = text_type(ast.prefixedName)
|
name = text_type(ast.prefixedName)
|
||||||
if theid not in self.state.document.ids:
|
if theid not in self.state.document.ids:
|
||||||
# if the name is not unique, the first one will win
|
# if the name is not unique, the first one will win
|
||||||
|
@ -15,6 +15,8 @@ from util import raises
|
|||||||
|
|
||||||
from sphinx.domains.cpp import DefinitionParser, DefinitionError
|
from sphinx.domains.cpp import DefinitionParser, DefinitionError
|
||||||
|
|
||||||
|
ids = []
|
||||||
|
|
||||||
def parse(name, string):
|
def parse(name, string):
|
||||||
parser = DefinitionParser(string)
|
parser = DefinitionParser(string)
|
||||||
res = getattr(parser, "parse_" + name + "_object")()
|
res = getattr(parser, "parse_" + name + "_object")()
|
||||||
@ -37,10 +39,12 @@ def check(name, input, output=None):
|
|||||||
print("Expected: ", output)
|
print("Expected: ", output)
|
||||||
raise DefinitionError("")
|
raise DefinitionError("")
|
||||||
ast.describe_signature([], 'lastIsName', None)
|
ast.describe_signature([], 'lastIsName', None)
|
||||||
ast.prefixedName = ast.name # otherwise the get_id fails, it would be set
|
# Artificially set the prefixedName, otherwise the get_id fails.
|
||||||
# in handle_signarue
|
# It would usually have been set in handle_signarue.
|
||||||
|
ast.prefixedName = ast.name
|
||||||
ast.get_id_v1()
|
ast.get_id_v1()
|
||||||
ast.get_id_v2()
|
ast.get_id_v2()
|
||||||
|
ids.append(ast.get_id_v2())
|
||||||
#print ".. %s:: %s" % (name, input)
|
#print ".. %s:: %s" % (name, input)
|
||||||
|
|
||||||
def test_type_definitions():
|
def test_type_definitions():
|
||||||
@ -79,6 +83,9 @@ def test_type_definitions():
|
|||||||
check('member', 'module::myclass foo[n]')
|
check('member', 'module::myclass foo[n]')
|
||||||
|
|
||||||
check('function', 'operator bool() const')
|
check('function', 'operator bool() const')
|
||||||
|
check('function', 'A::operator bool() const')
|
||||||
|
check('function', 'A::operator bool() volatile const &')
|
||||||
|
check('function', 'A::operator bool() volatile const &&')
|
||||||
check('function', 'bool namespaced::theclass::method(arg1, arg2)')
|
check('function', 'bool namespaced::theclass::method(arg1, arg2)')
|
||||||
x = 'std::vector<std::pair<std::string, int>> &module::test(register ' \
|
x = 'std::vector<std::pair<std::string, int>> &module::test(register ' \
|
||||||
'foo, bar, std::string baz = "foobar, blah, bleh") const = 0'
|
'foo, bar, std::string baz = "foobar, blah, bleh") const = 0'
|
||||||
@ -99,6 +106,7 @@ def test_type_definitions():
|
|||||||
check('function', 'static constexpr int get_value()')
|
check('function', 'static constexpr int get_value()')
|
||||||
check('function', 'int get_value() const noexcept')
|
check('function', 'int get_value() const noexcept')
|
||||||
check('function', 'int get_value() const noexcept = delete')
|
check('function', 'int get_value() const noexcept = delete')
|
||||||
|
check('function', 'int get_value() volatile const')
|
||||||
check('function', 'MyClass::MyClass(MyClass::MyClass&&) = default')
|
check('function', 'MyClass::MyClass(MyClass::MyClass&&) = default')
|
||||||
check('function', 'virtual MyClass::a_virtual_function() const override')
|
check('function', 'virtual MyClass::a_virtual_function() const override')
|
||||||
check('function', 'A B() override')
|
check('function', 'A B() override')
|
||||||
@ -142,3 +150,9 @@ def test_operators():
|
|||||||
check('function', 'void operator bool() const', 'void operator bool() const')
|
check('function', 'void operator bool() const', 'void operator bool() const')
|
||||||
for op in '*-+=/%!':
|
for op in '*-+=/%!':
|
||||||
check('function', 'void operator %s ()' % op, 'void operator%s()' % op)
|
check('function', 'void operator %s ()' % op, 'void operator%s()' % op)
|
||||||
|
|
||||||
|
#def test_print():
|
||||||
|
# # used for getting all the ids out for checking
|
||||||
|
# for a in ids:
|
||||||
|
# print(a)
|
||||||
|
# raise DefinitionError("")
|
Loading…
Reference in New Issue
Block a user