Skip to content

Commit

Permalink
Merge pull request #550 from rogerbarton/dev
Browse files Browse the repository at this point in the history
C# Support
  • Loading branch information
vermeeren authored Aug 19, 2020
2 parents 26cd84d + 6436873 commit d762cfa
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 13 deletions.
3 changes: 2 additions & 1 deletion breathe/directives.py
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,8 @@ def setup(app: Sphinx) -> None:
app.add_config_value("breathe_projects", {}, True) # Dict[str, str]
app.add_config_value("breathe_default_project", "", True) # str
# Provide reasonable defaults for domain_by_extension mapping. Can be overridden by users.
app.add_config_value("breathe_domain_by_extension", {'py': 'py'}, True) # Dict[str, str]
app.add_config_value("breathe_domain_by_extension",
{'py': 'py', 'cs': 'cs'}, True) # Dict[str, str]
app.add_config_value("breathe_domain_by_file_pattern", {}, True) # Dict[str, str]
app.add_config_value("breathe_projects_source", {}, True)
app.add_config_value("breathe_build_directory", '', True)
Expand Down
100 changes: 93 additions & 7 deletions breathe/renderer/sphinxrenderer.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@
except ImportError:
php = None

try:
from sphinx_csharp import csharp as cs # type: ignore
except ImportError:
cs = None

import re
import six
import textwrap
Expand Down Expand Up @@ -140,6 +145,55 @@ class PyClasslike(BaseObject, python.PyClasslike):
pass


# ----------------------------------------------------------------------------

if cs is not None:
class CSharpCurrentNamespace(BaseObject, cs.CSharpCurrentNamespace):
pass

class CSharpNamespacePlain(BaseObject, cs.CSharpNamespacePlain):
pass

class CSharpClass(BaseObject, cs.CSharpClass):
pass

class CSharpStruct(BaseObject, cs.CSharpStruct):
pass

class CSharpInterface(BaseObject, cs.CSharpInterface):
pass

class CSharpInherits(BaseObject, cs.CSharpInherits):
pass

class CSharpMethod(BaseObject, cs.CSharpMethod):
pass

class CSharpVariable(BaseObject, cs.CSharpVariable):
pass

class CSharpProperty(BaseObject, cs.CSharpProperty):
pass

class CSharpEvent(BaseObject, cs.CSharpEvent):
pass

class CSharpEnum(BaseObject, cs.CSharpEnum):
pass

class CSharpEnumValue(BaseObject, cs.CSharpEnumValue):
pass

class CSharpAttribute(BaseObject, cs.CSharpAttribute):
pass

class CSharpIndexer(BaseObject, cs.CSharpIndexer):
pass

class CSharpXRefRole(BaseObject, cs.CSharpXRefRole):
pass


# ----------------------------------------------------------------------------

class DomainDirectiveFactory:
Expand Down Expand Up @@ -191,6 +245,30 @@ class DomainDirectiveFactory:
'global': (php.PhpGloballevel, 'global'),
}

if cs is not None:
cs_classes = {
# 'doxygen-name': (CSharp class, key in CSharpDomain.object_types)
'namespace': (CSharpNamespacePlain, 'namespace'),

'class': (CSharpClass, 'class'),
'struct': (CSharpStruct, 'struct'),
'interface': (CSharpInterface, 'interface'),

'function': (CSharpMethod, 'function'),
'method': (CSharpMethod, 'method'),

'variable': (CSharpVariable, 'var'),
'property': (CSharpProperty, 'property'),
'event': (CSharpEvent, 'event'),

'enum': (CSharpEnum, 'enum'),
'enumvalue': (CSharpEnumValue, 'enumerator'),
'attribute': (CSharpAttribute, 'attr'),

# Fallback to cpp domain
'typedef': (CPPTypeObject, 'type'),
}

@staticmethod
def create(domain: str, args) -> ObjectDescription:
cls = cast(Type[ObjectDescription], None)
Expand All @@ -214,6 +292,8 @@ def create(domain: str, args) -> ObjectDescription:
arg_0 = 'global'
cls, name = DomainDirectiveFactory.php_classes.get(
arg_0, (php.PhpClasslike, 'class'))
elif cs is not None and domain == 'cs':
cls, name = DomainDirectiveFactory.cs_classes[args[0]] # type: ignore
else:
domain = 'cpp'
cls, name = DomainDirectiveFactory.cpp_classes[args[0]] # type: ignore
Expand Down Expand Up @@ -827,11 +907,11 @@ def get_node_info(file_data):
return self.visit_union(node)
elif kind in ('struct', 'class', 'interface'):
dom = self.get_domain()
if not dom or dom in ('c', 'cpp', 'py'):
if not dom or dom in ('c', 'cpp', 'py', 'cs'):
return self.visit_class(node)
elif kind == 'namespace':
dom = self.get_domain()
if not dom or dom in ('c', 'cpp', 'py'):
if not dom or dom in ('c', 'cpp', 'py', 'cs'):
return self.visit_namespace(node)

self.context = cast(RenderContext, self.context)
Expand Down Expand Up @@ -924,7 +1004,7 @@ def render_signature(file_data, doxygen_target, name, kind):
# having two lists in case they fall out of sync
#
# If this list is edited, also change the sections option documentation for
# the doxygen(auto)file directive in documentation/source/autofile.rst.
# the doxygen(auto)file directive in documentation/source/file.rst.
sections = [
("user-defined", "User Defined"),
("public-type", "Public Types"),
Expand All @@ -933,8 +1013,8 @@ def render_signature(file_data, doxygen_target, name, kind):
("public-slot", "Public Slots"),
("signal", "Signals"),
("dcop-func", "DCOP Function"),
("property", "Property"),
("event", "Event"),
("property", "Properties"),
("event", "Events"),
("public-static-func", "Public Static Functions"),
("public-static-attrib", "Public Static Attributes"),
("protected-type", "Protected Types"),
Expand Down Expand Up @@ -1344,7 +1424,7 @@ def visit_linkedtext(self, node) -> List[Node]:

def visit_function(self, node) -> List[Node]:
dom = self.get_domain()
if not dom or dom in ('c', 'cpp', 'py'):
if not dom or dom in ('c', 'cpp', 'py', 'cs'):
names = self.get_qualification()
names.append(node.get_name())
name = self.join_nested_name(names)
Expand Down Expand Up @@ -1502,7 +1582,7 @@ def visit_variable(self, node) -> List[Node]:
node.get_argsstring(),
self.make_initializer(node)
])
if not dom or dom in ('c', 'cpp', 'py'):
if not dom or dom in ('c', 'cpp', 'py', 'cs'):
return self.handle_declaration(node, declaration, options=options)
else:
return self.render_declaration(node, declaration)
Expand Down Expand Up @@ -1647,6 +1727,12 @@ def dispatch_memberdef(self, node) -> List[Node]:
return self.visit_typedef(node)
if node.kind == "variable":
return self.visit_variable(node)
if node.kind == "property":
# Note: visit like variable for now
return self.visit_variable(node)
if node.kind == "event":
# Note: visit like variable for now
return self.visit_variable(node)
if node.kind == "define":
return self.visit_define(node)
if node.kind == "friend":
Expand Down
4 changes: 2 additions & 2 deletions documentation/source/file.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ The directive-specific options are documented below.
"derivedcompoundref", "Derived compound reference"
"detaileddescription", "Detailed description"
"enum", "Enumerator"
"event", "Event"
"event", "Events"
"friend", "Friend"
"func", "Function"
"innerclass", "**Must be given to show sections inside a class**"
Expand All @@ -42,7 +42,7 @@ The directive-specific options are documented below.
"private-static-attrib", "Private static attribute"
"private-static-func", "Private static function"
"private-type", "Private type"
"property", "Property"
"property", "Properties"
"protected-attrib", "Protected attribute"
"protected-func", "Protected function"
"protected-slot", "Protected slot"
Expand Down
4 changes: 1 addition & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@

import sys

import breathe

long_desc = '''
Breathe is an extension to reStructuredText and Sphinx to be able to read and
render `Doxygen <http://www.doxygen.org>`__ xml output.
Expand All @@ -24,7 +22,7 @@

setup(
name='breathe',
version=breathe.__version__,
version='4.19.2',
url='https://github.com/michaeljones/breathe',
download_url='https://github.com/michaeljones/breathe',
license='BSD',
Expand Down

0 comments on commit d762cfa

Please sign in to comment.