Permalink
Browse files

DocBaseClass: Add DocBaseClass

Add DocBaseClass
Merge DocumentationExtraction with DocBaseClass
Closes #2659
  • Loading branch information...
damngamerz committed Jul 22, 2017
1 parent 86f0544 commit d79e4971f2f74f5aaa43dbc569c85b0590aa7392
@@ -4,6 +4,8 @@
DocstyleDefinition)
from coalib.bearlib.languages.documentation.DocumentationComment import (
DocumentationComment)
from coalib.results.Diff import Diff
from coalib.results.TextRange import TextRange
from coalib.results.TextPosition import TextPosition
@@ -254,31 +256,81 @@ def extract_documentation_with_markers(content, docstyle_definition):
yield doc
def extract_documentation(content, language, docstyle):
class DocBaseClass:
"""
Extracts all documentation texts inside the given source-code-string using
the coala docstyle definition files.
The documentation texts are sorted by their order appearing in ``content``.
For more information about how documentation comments are identified and
extracted, see DocstyleDefinition.doctypes enumeration.
:param content: The source-code-string where to extract
documentation from. Needs to be a list or tuple
where each string item is a single line
(including ending whitespaces like ``\\n``).
:param language: The programming language used.
:param docstyle: The documentation style/tool used
(e.g. doxygen).
:raises FileNotFoundError: Raised when the docstyle definition file was not
found.
:raises KeyError: Raised when the given language is not defined in
given docstyle.
:raises ValueError: Raised when a docstyle definition setting has an
invalid format.
:return: An iterator returning each DocumentationComment
found in the content.
DocBaseClass holds important functions which will extract, parse
and generates diffs for documentation. All bears that processes
documentation should inherit from this.
"""
docstyle_definition = DocstyleDefinition.load(language, docstyle)
return extract_documentation_with_markers(content, docstyle_definition)
@staticmethod
def extract(content, language, docstyle):
"""
Extracts all documentation texts inside the given source-code-string
using the coala docstyle definition files.
The documentation texts are sorted by their order appearing in
``content``.
For more information about how documentation comments are
identified and extracted, see DocstyleDefinition.doctypes enumeration.
:param content: The source-code-string where to extract
documentation from. Needs to be a list
or tuple where each string item is a
single line(including ending whitespaces
like ``\\n``).
:param language: The programming language used.
:param docstyle: The documentation style/tool used
(e.g. doxygen).
:raises FileNotFoundError: Raised when the docstyle definition file
was not found.
:raises KeyError: Raised when the given language is not
defined in given docstyle.
:raises ValueError: Raised when a docstyle definition setting
has an invalid format.
:return: An iterator returning each
DocumentationComment found in the content.
"""
docstyle_definition = DocstyleDefinition.load(language, docstyle)
return extract_documentation_with_markers(
content, docstyle_definition)
@staticmethod
def generate_diff(file, doc_comment, new_comment):
"""
Generates diff between the original doc_comment and its fix
new_comment which are instances of DocumentationComment.
:param doc_comment:
Original instance of DocumentationComment.
:param new_comment:
Fixed instance of DocumentationComment.
:return:
Diff instance.
"""
diff = Diff(file)
# We need to update old comment positions, as `assemble()`
# prepends indentation for first line.
old_range = TextRange.from_values(
doc_comment.range.start.line,
1,
doc_comment.range.end.line,
doc_comment.range.end.column)
# Clearing cached assemble() so a fresh one is fetched.
new_comment.assemble.cache_clear()
diff.replace(old_range, new_comment.assemble())
return diff
def process_documentation(self, *args, **kwargs):
"""
Checks and handles the fixing part of documentation.
:return:
A tuple of processed documentation and warning_desc.
"""
raise NotImplementedError('This function has to be implemented for a '
'documentation bear.')
@@ -4,25 +4,28 @@
DocstyleDefinition)
from coalib.bearlib.languages.documentation.DocumentationComment import (
DocumentationComment)
from coalib.bearlib.languages.documentation.DocumentationExtraction import (
extract_documentation)
from coalib.bearlib.languages.documentation.DocBaseClass import (
DocBaseClass)
from tests.bearlib.languages.documentation.TestUtils import (
load_testdata)
from coalib.results.TextPosition import TextPosition
from coalib.results.TextRange import TextRange
from coalib.results.Diff import Diff
class DocumentationExtractionTest(unittest.TestCase):
class DocBaseClassTest(unittest.TestCase):
def test_DocBaseClass_extraction_invalid_input(self):
def test_extract_documentation_invalid_input(self):
with self.assertRaises(FileNotFoundError):
tuple(extract_documentation('', 'PYTHON', 'INVALID'))
tuple(DocBaseClass.extract('', 'PYTHON', 'INVALID'))
def test_extract_documentation_C(self):
def test_DocBaseClass_extraction_C(self):
data = load_testdata('data.c')
# No built-in documentation for C.
with self.assertRaises(KeyError):
tuple(extract_documentation(data, 'C', 'default'))
tuple(DocBaseClass.extract(data, 'C', 'default'))
docstyle_C_doxygen = DocstyleDefinition.load('C', 'doxygen')
@@ -59,31 +62,31 @@ def test_extract_documentation_C(self):
TextPosition(28, 1)))
self.assertEqual(tuple(
extract_documentation(data, 'C', 'doxygen')),
DocBaseClass.extract(data, 'C', 'doxygen')),
expected_results)
def test_extract_documentation_C_2(self):
def test_DocBaseClass_extraction_C_2(self):
data = ['/** my main description\n', ' * continues here */']
docstyle_C_doxygen = DocstyleDefinition.load('C', 'doxygen')
self.assertEqual(
list(extract_documentation(data, 'C', 'doxygen')),
list(DocBaseClass.extract(data, 'C', 'doxygen')),
[DocumentationComment(' my main description\n continues here',
docstyle_C_doxygen, '',
docstyle_C_doxygen.markers[0],
TextPosition(1, 1))])
def test_extract_documentation_CPP(self):
def test_DocBaseClass_extraction_CPP(self):
data = load_testdata('data.cpp')
# No built-in documentation for C++.
with self.assertRaises(KeyError):
tuple(extract_documentation(data, 'CPP', 'default'))
tuple(DocBaseClass.extract(data, 'CPP', 'default'))
docstyle_CPP_doxygen = DocstyleDefinition.load('CPP', 'doxygen')
self.assertEqual(tuple(extract_documentation(data, 'CPP', 'doxygen')),
self.assertEqual(tuple(DocBaseClass.extract(data, 'CPP', 'doxygen')),
(DocumentationComment(
('\n'
' This is the main function.\n'
@@ -118,20 +121,20 @@ def test_extract_documentation_CPP(self):
docstyle_CPP_doxygen.markers[4],
TextPosition(32, 1))))
def test_extract_documentation_CPP_2(self):
def test_DocBaseClass_CPP_2(self):
data = load_testdata('data2.cpp')
docstyle_CPP_doxygen = DocstyleDefinition.load('CPP', 'doxygen')
self.assertEqual(tuple(extract_documentation(data, 'CPP', 'doxygen')),
self.assertEqual(tuple(DocBaseClass.extract(data, 'CPP', 'doxygen')),
(DocumentationComment(
('module comment\n'
' hello world\n'),
docstyle_CPP_doxygen, '',
docstyle_CPP_doxygen.markers[0],
TextPosition(1, 1)),))
def test_extract_documentation_PYTHON3(self):
def test_DocBaseClass_PYTHON3(self):
data = load_testdata('data.py')
docstyle_PYTHON3_default = DocstyleDefinition.load('PYTHON3',
'default')
@@ -192,9 +195,8 @@ def test_extract_documentation_PYTHON3(self):
)
self.assertEqual(
tuple(extract_documentation(data, 'PYTHON3', 'default')),
tuple(DocBaseClass.extract(data, 'PYTHON3', 'default')),
expected)
# Change only the docstyle in expected results.
expected = list(DocumentationComment(r.documentation,
docstyle_PYTHON3_doxygen,
@@ -214,37 +216,37 @@ def test_extract_documentation_PYTHON3(self):
TextPosition(30, 1)))
self.assertEqual(
list(extract_documentation(data, 'PYTHON3', 'doxygen')),
list(DocBaseClass.extract(data, 'PYTHON3', 'doxygen')),
expected)
def test_extract_documentation_PYTHON3_2(self):
def test_DocBaseClass_extraction_PYTHON3_2(self):
data = ['\n', '""" documentation in single line """\n', 'print(1)\n']
docstyle_PYTHON3_default = DocstyleDefinition.load('PYTHON3',
'default')
self.assertEqual(
list(extract_documentation(data, 'PYTHON3', 'default')),
list(DocBaseClass.extract(data, 'PYTHON3', 'default')),
[DocumentationComment(' documentation in single line ',
docstyle_PYTHON3_default, '',
docstyle_PYTHON3_default.markers[0],
TextPosition(2, 1))])
def test_extract_documentation_PYTHON3_3(self):
def test_DocBaseClass_extraction_PYTHON3_3(self):
data = ['## documentation in single line without return at end.']
docstyle_PYTHON3_doxygen = DocstyleDefinition.load('PYTHON3',
'doxygen')
self.assertEqual(
list(extract_documentation(data, 'PYTHON3', 'doxygen')),
list(DocBaseClass.extract(data, 'PYTHON3', 'doxygen')),
[DocumentationComment(' documentation in single line without '
'return at end.',
docstyle_PYTHON3_doxygen, '',
docstyle_PYTHON3_doxygen.markers[1],
TextPosition(1, 1))])
def test_extract_documentation_PYTHON3_4(self):
def test_DocBaseClass_extraction_PYTHON3_4(self):
data = ['\n', 'triple_quote_string_test = """\n',
'This is not a docstring\n', '"""\n']
@@ -254,5 +256,35 @@ def test_extract_documentation_PYTHON3_4(self):
# Nothing is yielded as triple quote string literals are being
# ignored.
self.assertEqual(
list(extract_documentation(data, 'PYTHON3', 'default')),
list(DocBaseClass.extract(data, 'PYTHON3', 'default')),
[])
def test_generate_diff(self):
data_old = ['\n', '""" documentation in single line """\n']
for doc_comment in DocBaseClass.extract(
data_old, 'PYTHON3', 'default'):
old_doc_comment = doc_comment
old_range = TextRange.from_values(
old_doc_comment.range.start.line,
1,
old_doc_comment.range.end.line,
old_doc_comment.range.end.column)
data_new = ['\n', '"""\n documentation in single line\n"""\n']
for doc_comment in DocBaseClass.extract(
data_new, 'PYTHON3', 'default'):
new_doc_comment = doc_comment
diff = DocBaseClass.generate_diff(
data_old, old_doc_comment, new_doc_comment)
diff_expected = Diff(data_old)
diff_expected.replace(old_range, new_doc_comment.assemble())
self.assertEqual(diff, diff_expected)
def test_DocBaseClass_process_documentation_not_implemented(self):
test_object = DocBaseClass()
self.assertRaises(NotImplementedError,
test_object.process_documentation)
@@ -4,8 +4,8 @@
DocstyleDefinition)
from coalib.bearlib.languages.documentation.DocumentationComment import (
DocumentationComment)
from coalib.bearlib.languages.documentation.DocumentationExtraction import (
extract_documentation)
from coalib.bearlib.languages.documentation.DocBaseClass import (
DocBaseClass)
from tests.bearlib.languages.documentation.TestUtils import (
load_testdata)
from coalib.results.TextPosition import TextPosition
@@ -72,7 +72,7 @@ def test_not_implemented(self):
def test_from_metadata(self):
data = load_testdata('default.py')
original = list(extract_documentation(data, 'python', 'default'))
original = list(DocBaseClass.extract(data, 'python', 'default'))
parsed_docs = [(doc.parse(), doc.marker, doc.indent, doc.position)
for doc in original]
@@ -109,7 +109,8 @@ def test_empty_docstring(self):
def test_description(self):
doc = ' description only '
self.check_docstring(doc, [self.Description(desc=' description only ')])
self.check_docstring(
doc, [self.Description(desc=' description only ')])
def test_params_default(self):
self.maxDiff = None
@@ -139,7 +140,7 @@ def test_python_default(self):
data = load_testdata('default.py')
parsed_docs = [doc.parse() for doc in
extract_documentation(data, 'python', 'default')]
DocBaseClass.extract(data, 'python', 'default')]
expected = [
[self.Description(desc='\nModule description.\n\n'
@@ -188,7 +189,7 @@ def test_python_doxygen(self):
data = load_testdata('doxygen.py')
parsed_docs = [doc.parse() for doc in
extract_documentation(data, 'python', 'doxygen')]
DocBaseClass.extract(data, 'python', 'doxygen')]
expected = [
[self.Description(desc=' @package pyexample\n Documentation for'
@@ -232,7 +233,7 @@ def test_java_default(self):
data = load_testdata('default.java')
parsed_docs = [doc.parse() for doc in
extract_documentation(data, 'java', 'default')]
DocBaseClass.extract(data, 'java', 'default')]
expected = [[self.Description(
desc='\n Returns an String that says Hello with the name'
@@ -253,7 +254,7 @@ def test_go_default(self):
data = load_testdata('default.go')
parsed_docs = [doc.parse() for doc in
extract_documentation(data, 'golang', 'golang')]
DocBaseClass.extract(data, 'golang', 'golang')]
expected = [['\n',
'Comments may span\n',
@@ -272,19 +273,19 @@ def test_python_assembly(self):
data = load_testdata('default.py')
docs = ''.join(data)
for doc in extract_documentation(data, 'python', 'default'):
for doc in DocBaseClass.extract(data, 'python', 'default'):
self.assertIn(doc.assemble(), docs)
def test_doxygen_assembly(self):
data = load_testdata('doxygen.py')
docs = ''.join(data)
for doc in extract_documentation(data, 'python', 'doxygen'):
for doc in DocBaseClass.extract(data, 'python', 'doxygen'):
self.assertIn(doc.assemble(), docs)
def test_c_assembly(self):
data = load_testdata('default.c')
docs = ''.join(data)
for doc in extract_documentation(data, 'c', 'doxygen'):
for doc in DocBaseClass.extract(data, 'c', 'doxygen'):
self.assertIn(doc.assemble(), docs)

0 comments on commit d79e497

Please sign in to comment.