Commit 06021f67 authored by Anthony Gauchy's avatar Anthony Gauchy
Browse files

CSharp wrapper documentation improvment

 - Update python wrapper generation to genrate LinphoneWrapper.cs with a
   full documentation.
 - Update cmake to generate a html doc site with docfx for C# wrapper
 - minor fixes in lib documentation
parent 59378aa3
......@@ -15,7 +15,7 @@
* - C++ (https://linphone.org/@LINPHONE_STATE@/docs/liblinphone/@LINPHONE_VERSION@/c++)
* - Swift (https://linphone.org/@LINPHONE_STATE@/docs/liblinphone/@LINPHONE_VERSION@/swift)
* - Java (https://linphone.org/@LINPHONE_STATE@/docs/liblinphone/@LINPHONE_VERSION@/java)
* - C# (coming soon)
* - C# (https://linphone.org/@LINPHONE_STATE@/docs/liblinphone/@LINPHONE_VERSION@/cs)
* - Python (coming soon)
*
* Liblinphone is distributed under GPLv3 (https://www.gnu.org/licenses/gpl-3.0.html). Please understand the licencing details before using it!
......
......@@ -205,8 +205,8 @@ typedef enum _LinphoneAccountCreatorStatus {
LinphoneAccountCreatorStatusPhoneNumberInvalid, /**< Error cannot send SMS */
LinphoneAccountCreatorStatusWrongActivationCode, /**< Error key doesn't match */
LinphoneAccountCreatorStatusPhoneNumberOverused, /**< Error too many SMS sent */
LinphoneAccountCreatorStatusAlgoNotSupported, /** < Error algo isn't MD5 or SHA-256 */
LinphoneAccountCreatorStatusUnexpectedError, /** < Generic error */
LinphoneAccountCreatorStatusAlgoNotSupported, /**< Error algo isn't MD5 or SHA-256 */
LinphoneAccountCreatorStatusUnexpectedError, /**< Generic error */
} LinphoneAccountCreatorStatus;
// -----------------------------------------------------------------------------
......
......@@ -22,6 +22,7 @@ import abstractapi
import logging
import metaname
import re
import sys
class ParsingError(RuntimeError):
......@@ -509,19 +510,29 @@ class Translator:
lines = []
while len(line) > width:
cutIndex = line.rfind(' ', 0, width)
if cutIndex != -1:
if cutIndex >= 0:
if self.langCode == 'Java':
# Do not break a line in the middle of a { }
while (not line[0:cutIndex].count('{') == line[0:cutIndex].count('}')) and (not line[cutIndex:].count('{') == line[cutIndex:].count('}')):
cutIndex += 1
lines.append(line[0:cutIndex])
line = line[cutIndex+1:]
if self.langCode == 'CSharp':
# Do not break a line in the middle of a xml tag
while not line[0:cutIndex].count('<') == line[0:cutIndex].count('>'):
cutIndex += 1
if line[cutIndex] == ' ':
# Don't keep a whitespace at the start of the next line if you cut on one
lines.append(line[0:cutIndex])
line = line[cutIndex+1:]
else:
lines.append(line[0:cutIndex])
line = line[cutIndex:]
else:
# Don't break http links
cutIndex = len(line) if ('http://' or 'https://') in line else width
cutIndex = len(line) if 'http://' or 'https://' in line else width
lines.append(line[0:cutIndex])
line = line[cutIndex:]
lines.append(line)
if line:
lines.append(line)
if indent:
lines = [line if line is lines[0] else '\t' + line for line in lines]
......@@ -784,15 +795,85 @@ class SphinxTranslator(Translator):
class SandCastleTranslator(Translator):
def _tag_as_brief(self, lines):
if len(lines) > 0:
lines.insert(0, '<summary>')
lines.append('</summary>')
def __init__(self, langCode):
super().__init__(langCode)
self.isEndTagPlaced = False
def translate_text(self, textpart):
text = super().translate_text(textpart)
xmlSpecialCharDict = {'<': '&lt;',
'>': '&gt;',
"'": '&apos;',
'"': '&quot;',
'&': '&amp;'}
if sys.version_info[0] >= 3:
xmlTranslationTable = str.maketrans(xmlSpecialCharDict)
else:
import string
xmlTranslationTable = string.maketrans(xmlSpecialCharDict)
return text.translate(xmlTranslationTable)
def translate_description(self, description, tagAsBrief=False):
self.isEndTagPlaced = False
translatedDoc = super().translate_description(description, tagAsBrief)
if not tagAsBrief:
if not self.isEndTagPlaced:
translatedDoc['lines'].append({'line': '</para>'})
translatedDoc['lines'].append({'line': '</summary>'})
self.isEndTagPlaced = True
return translatedDoc
def translate_function_reference(self, ref):
refStr = Translator.translate_reference(self, ref, absName=True)
return '<see cref="{0}()" />'.format(refStr)
subnResult = re.subn('(\.Get\(\))', '.Instance' , refStr)
if subnResult[1] > 0:
return '<see cref="{0}">{0}</see>'.format(subnResult[0])
subnResult = re.subn('(\.Get|\.Set)', '.' , subnResult[0])
if subnResult[1] > 0:
return '<see cref="{0}">{0}</see>'.format(subnResult[0])
return '<see cref="{0}()">{0}()</see>'.format(subnResult[0])
# In every cases we write the same value in the "see" tag value
# than in the cref value so that even if the cref is broken the
# text is displayed
def translate_class_reference(self, ref):
refStr = Translator.translate_reference(self, ref, absName=True)
return '<see cref="{0}" />'.format(refStr)
return '<see cref="{0}">{0}</see>'.format(refStr)
def _translate_parameter_list(self, parameterList):
text = ''
if not self.isEndTagPlaced:
text += '</para>\n'
text += '</summary>\n'
self.isEndTagPlaced = True
for paramDesc in parameterList.parameters:
if self.displaySelfParam or not paramDesc.is_self_parameter():
desc = self._translate_description(paramDesc.desc)
desc = desc[0] if len(desc) > 0 else ''
text += ('<param name="{0}">{1}</param>\n'.format(paramDesc.name.translate(self.nameTranslator), desc))
return text
def _translate_section(self, section):
text =''
if not self.isEndTagPlaced:
text += '</para>\n'
text += '</summary>\n'
self.isEndTagPlaced = True
if section.kind == 'return':
section.kind = '<returns>{0}</returns>'
elif section.kind == 'warning':
section.kind = '<remarks>Warning : {0}</remarks> '
elif section.kind == 'note':
section.kind = '<remarks>Note : {0}</remarks>'
elif section.kind == 'see':
section.kind = '<remarks>See : {0}</remarks>'
else:
section.kind = section.kind + " : {0}"
logging.warning('SandCastle doc translate section pointing on an unknown object ({0})'.format(section.kind))
text += section.kind.format(self._translate_paragraph(section.paragraph))
return text
......@@ -15,7 +15,7 @@
* - C++ (https://linphone.org/@LINPHONE_STATE@/docs/liblinphone/@LINPHONE_VERSION@/c++)
* - Swift (https://linphone.org/@LINPHONE_STATE@/docs/liblinphone/@LINPHONE_VERSION@/swift)
* - Java (https://linphone.org/@LINPHONE_STATE@/docs/liblinphone/@LINPHONE_VERSION@/java)
* - C# (coming soon)
* - C# (https://linphone.org/@LINPHONE_STATE@/docs/liblinphone/@LINPHONE_VERSION@/cs)
* - Python (coming soon)
*
* Liblinphone is distributed under GPLv3 (https://www.gnu.org/licenses/gpl-3.0.html). Please understand the licencing details before using it!
......
......@@ -38,3 +38,65 @@ add_custom_target(linphonecs ALL DEPENDS LinphoneWrapper.cs)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/LinphoneWrapper.cs"
DESTINATION "${CMAKE_INSTALL_DATADIR}/linphonecs/"
)
if(ENABLE_DOC AND ENABLE_CSHARP_WRAPPER)
message(CHECK_START "Generate C# wrapper html site")
find_program(
DOCFX_EXECUTABLE
NAMES docfx
)
if(DOCFX_EXECUTABLE)
file(
COPY "${CMAKE_CURRENT_SOURCE_DIR}/docfx_project"
DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/"
)
# Check git describe to see if we are on a release or not
set(LINPHONE_STATE "snapshots")
execute_process(COMMAND ${GIT_EXECUTABLE} describe OUTPUT_VARIABLE GIT_DESC)
if(NOT GIT_DESC MATCHES ".*(alpha|beta).*")
set(LINPHONE_STATE "releases")
endif()
# Replace @LINPHONE_STATE@ and @LINPHONE_VERSION@ in site main page
configure_file(
"${CMAKE_CURRENT_BINARY_DIR}/docfx_project/index.md"
"${CMAKE_CURRENT_BINARY_DIR}/docfx_project/index.md"
)
# Replace @LINPHONE_STATE@ and @LINPHONE_VERSION@ version.txt.in, this
# file will be used in doc upload
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/version.txt.in"
"${CMAKE_CURRENT_BINARY_DIR}/version.txt"
)
add_custom_command(OUTPUT "docfx_project/_site/index.html"
DEPENDS LinphoneWrapper.cs
COMMAND ${CMAKE_COMMAND} -E copy
"${CMAKE_CURRENT_BINARY_DIR}/LinphoneWrapper.cs"
"${CMAKE_CURRENT_BINARY_DIR}/docfx_project/src/LinphoneWrapper.cs"
COMMAND ${DOCFX_EXECUTABLE} "${CMAKE_CURRENT_BINARY_DIR}/docfx_project/docfx.json"
)
add_custom_target(
linphonecs-doc-site
ALL
DEPENDS linphonecs "docfx_project/_site/index.html"
)
install(
FILES "${CMAKE_CURRENT_BINARY_DIR}/version.txt"
DESTINATION "${CMAKE_INSTALL_DATADIR}/"
)
install(
DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/docfx_project/_site/"
DESTINATION "${CMAKE_INSTALL_DATADIR}/doc/liblinphone-${LINPHONE_VERSION}/cs"
)
message(CHECK_PASS "generation and copy configured")
else()
message(CHECK_FAIL "docfx wansn't found, no site generated")
endif()
endif()
# Liblinphone C# API documentation
{
"metadata": [
{
"src": [
{
"files": [
"src/**.cs"
]
}
],
"dest": "api",
"disableGitFeatures": false,
"disableDefaultFilter": false
}
],
"build": {
"content": [
{
"files": [
"api/**.yml",
"api/index.md"
]
},
{
"files": [
"toc.yml",
"*.md"
]
}
],
"dest": "_site",
"globalMetadataFiles": [],
"fileMetadataFiles": [],
"template": [
"statictoc"
],
"postProcessors": [],
"markdownEngineName": "markdig",
"noLangKeyword": false,
"keepFileLink": false,
"cleanupCacheHistory": false,
"disableGitFeatures": false
}
}
\ No newline at end of file
# Liblinphone Documentation
## What is liblinphone
Liblinphone is a high-level open source library that integrates all the SIP voice/video and instant messaging features into a single easy-to-use API. This is the VoIP SDK engine on which Linphone applications are based.
Liblinphone combines our media processing and streaming toolkit (Mediastreamer2) with our user-agent library for SIP signaling (belle-sip). Liblinphone has support for a variety of languages, each one has its own reference documentation:
- C (https://linphone.org/@LINPHONE_STATE@/docs/liblinphone/@LINPHONE_VERSION@/c)
- C++ (https://linphone.org/@LINPHONE_STATE@/docs/liblinphone/@LINPHONE_VERSION@/c++)
- Swift (https://linphone.org/@LINPHONE_STATE@/docs/liblinphone/@LINPHONE_VERSION@/swift)
- Java (https://linphone.org/@LINPHONE_STATE@/docs/liblinphone/@LINPHONE_VERSION@/java)
- C# (https://linphone.org/@LINPHONE_STATE@/docs/liblinphone/@LINPHONE_VERSION@/cs)
- Python (coming soon)
Liblinphone is distributed under GPLv3 (https://www.gnu.org/licenses/gpl-3.0.html). Please understand the licencing details before using it!
For any use of this library beyond the rights granted to you by the GPLv3 license, please [contact Belledonne Communications](https://www.linphone.org/contact).
## CSharp tutorial for liblinphone
You can find a step by step tutorial to use liblinphone in C# [here](https://gitlab.linphone.org/BC/public/tutorials)
## See also
http://www.linphone.org
- name: Api Documentation
href: api/
# Default was api/index.md but we prefer to jump directly to api/Linphone.html page
homepage: api/Linphone.html
......@@ -90,7 +90,8 @@ class CsharpTranslator:
methodDict = {}
methodDict['prototype'] = "static extern {return} {name}({params});".format(**methodElems)
methodDict['doc'] = method.briefDescription.translate(self.docTranslator, tagAsBrief=True)
methodDict['briefDoc'] = method.briefDescription.translate(self.docTranslator, tagAsBrief=True) if method.briefDescription is not None else None
methodDict['detailedDoc'] = method.detailedDescription.translate(self.docTranslator) if method.detailedDescription is not None else None
methodDict['has_impl'] = genImpl
if genImpl:
......@@ -294,6 +295,10 @@ class CsharpTranslator:
listenerDict['delegate']['params_private'] += dllImportType + " " + argName
listenerDict['delegate']["c_name_setter"] = c_name_setter
listenerDict['delegate']['briefDoc'] = method.briefDescription.translate(self.docTranslator, tagAsBrief=True) if method.briefDescription is not None else None
listenerDict['delegate']['detailedDoc'] = method.detailedDescription.translate(self.docTranslator) if method.detailedDescription is not None else None
return listenerDict
###########################################################################################################################################
......@@ -301,7 +306,8 @@ class CsharpTranslator:
def translate_enum(self, enum):
enumDict = {}
enumDict['enumName'] = enum.name.translate(self.nameTranslator)
enumDict['doc'] = enum.briefDescription.translate(self.docTranslator, tagAsBrief=True)
enumDict['briefDoc'] = enum.briefDescription.translate(self.docTranslator, tagAsBrief=True)
enumDict['detailedDoc'] = enum.detailedDescription.translate(self.docTranslator)
enumDict['values'] = []
enumDict['isFlag'] = False
i = 0
......@@ -309,7 +315,8 @@ class CsharpTranslator:
for enumValue in enum.enumerators:
enumValDict = {}
enumValDict['name'] = enumValue.name.translate(self.nameTranslator)
enumValDict['doc'] = enumValue.briefDescription.translate(self.docTranslator, tagAsBrief=True)
enumValDict['briefDoc'] = enumValue.briefDescription.translate(self.docTranslator, tagAsBrief=True)
enumValDict['detailedDoc'] = enumValue.detailedDescription.translate(self.docTranslator)
if isinstance(enumValue.value, int):
lastValue = enumValue.value
enumValDict['value'] = str(enumValue.value)
......@@ -335,7 +342,8 @@ class CsharpTranslator:
classDict['isLinphoneFactory'] = classDict['className'] == "Factory"
classDict['isLinphoneCall'] = _class.name.to_camel_case() == "Call"
classDict['isLinphoneCore'] = _class.name.to_camel_case() == "Core"
classDict['doc'] = _class.briefDescription.translate(self.docTranslator, tagAsBrief=True)
classDict['briefDoc'] = _class.briefDescription.translate(self.docTranslator, tagAsBrief=True)
classDict['detailedDoc'] = _class.detailedDescription.translate(self.docTranslator)
classDict['dllImports'] = []
islistenable = _class.listenerInterface is not None
......@@ -382,6 +390,8 @@ class CsharpTranslator:
interfaceDict['interfaceName'] = interface.name.translate(self.nameTranslator)
interfaceDict['set_user_data_name'] = interface.listenedClass.name.to_snake_case(fullName=True) + '_cbs_set_user_data'
interfaceDict['get_user_data_name'] = interface.listenedClass.name.to_snake_case(fullName=True) + '_cbs_get_user_data'
interfaceDict['briefDoc'] = interface.briefDescription.translate(self.docTranslator, tagAsBrief=True)
interfaceDict['detailedDoc'] = interface.detailedDescription.translate(self.docTranslator)
interfaceDict['methods'] = []
for method in interface.instanceMethods:
......
LINPHONE_VERSION=@LINPHONE_VERSION@
LINPHONE_STATE=@LINPHONE_STATE@
\ No newline at end of file
......@@ -288,21 +288,37 @@ namespace Linphone
#endregion
#region Enums
{{#enums}}
{{#enum}}
{{#doc}}
/// <summary>
{{#briefDoc}}
{{#lines}}
/// {{{line}}}
{{/lines}}
{{/briefDoc}}
{{#detailedDoc}}
/// <para>
{{#lines}}
/// {{{line}}}
{{/lines}}
{{/doc}}{{#isFlag}}[Flags]{{/isFlag}}
{{/detailedDoc}}
{{#isFlag}}[Flags]{{/isFlag}}
public enum {{enumName}}
{
{{#values}}
{{#doc}}
/// <summary>
{{#briefDoc}}
{{#lines}}
/// {{{line}}}
{{/lines}}
{{/briefDoc}}
{{#detailedDoc}}
/// <para>
{{#lines}}
/// {{{line}}}
{{/lines}}
{{/doc}}
{{/detailedDoc}}
{{name}} = {{{value}}},
{{/values}}
}
......@@ -314,6 +330,18 @@ namespace Linphone
#region Listeners
{{#interfaces}}
{{#interface}}
/// <summary>
{{#briefDoc}}
{{#lines}}
/// {{{line}}}
{{/lines}}
{{/briefDoc}}
{{#detailedDoc}}
/// <para>
{{#lines}}
/// {{{line}}}
{{/lines}}
{{/detailedDoc}}
[StructLayout(LayoutKind.Sequential)]
public class {{interfaceName}} : LinphoneObject
{
......@@ -342,7 +370,20 @@ namespace Linphone
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void {{name_private}}({{params_private}});
public delegate void {{name_public}}({{{params_public}}});
/// <summary>
{{#briefDoc}}
{{#lines}}
/// {{{line}}}
{{/lines}}
{{/briefDoc}}
{{#detailedDoc}}
/// <para>
{{#lines}}
/// {{{line}}}
{{/lines}}
{{/detailedDoc}}
{{#deprecated}}[Obsolete]
{{/deprecated}}public delegate void {{name_public}}({{{params_public}}});
private {{name_private}} {{var_private}};
private {{name_public}} {{var_public}};
......@@ -419,12 +460,18 @@ namespace Linphone
#region Classes
{{#classes}}
{{#_class}}
{{#doc}}
/// <summary>
{{#briefDoc}}
{{#lines}}
/// {{{line}}}
{{/lines}}
{{/doc}}
{{/briefDoc}}
{{#detailedDoc}}
/// <para>
{{#lines}}
/// {{{line}}}
{{/lines}}
{{/detailedDoc}}
[StructLayout(LayoutKind.Sequential)]
public class {{className}} : LinphoneObject
{
......@@ -554,11 +601,18 @@ namespace Linphone
{{/has_second_prototype}}
{{#has_property}}
{{#doc}}
/// <summary>
{{#briefDoc}}
{{#lines}}
/// {{{line}}}
{{/lines}}
{{/briefDoc}}
{{#detailedDoc}}
/// <para>
{{#lines}}
/// {{{line}}}
{{/lines}}
{{/doc}}
{{/detailedDoc}}
{{property_static}}public {{{property_return}}} {{property_name}}
{
{{#has_getter}}
......@@ -628,11 +682,18 @@ namespace Linphone
{{/has_property}}
{{#has_impl}}
{{#impl}}
{{#doc}}
/// <summary>
{{#briefDoc}}
{{#lines}}
/// {{{line}}}
{{/lines}}
{{/briefDoc}}
{{#detailedDoc}}
/// <para>
{{#lines}}
/// {{{line}}}
{{/lines}}
{{/doc}}
{{/detailedDoc}}
public {{static}}{{override}}{{{type}}} {{name}}({{{args}}})
{
{{#is_string}}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment