Navigation Menu

Skip to content

Commit

Permalink
Add DocGrammarBear for docstrings
Browse files Browse the repository at this point in the history
This bear checks for spellings and grammatical mistakes
on the descriptions of documentation comments.
  • Loading branch information
damngamerz committed Aug 5, 2017
1 parent 92b1f28 commit 05f9d01
Show file tree
Hide file tree
Showing 6 changed files with 216 additions and 0 deletions.
110 changes: 110 additions & 0 deletions bears/documentation/DocGrammarBear.py
@@ -0,0 +1,110 @@
import shutil

from coalib.bearlib.languages.documentation.DocumentationComment import (
DocumentationComment)
from coalib.bearlib.languages.documentation.DocstyleDefinition import (
DocstyleDefinition)
from coalib.bearlib.languages.documentation.DocBaseClass import (
DocBaseClass)
from dependency_management.requirements.PipRequirement import PipRequirement
from coalib.bears.LocalBear import LocalBear
from coalib.results.Result import Result
from coalib.settings.Setting import typed_list


class DocGrammarBear(DocBaseClass, LocalBear):
LANGUAGES = {language for docstyle, language in
DocstyleDefinition.get_available_definitions()}
REQUIREMENTS = {PipRequirement('language-check', '1.0')}
AUTHORS = {'The coala developers'}
AUTHORS_EMAILS = {'coala-devel@googlegroups.com'}
LICENSE = 'AGPL-3.0'
CAN_DETECT = {'Documentation', 'Spelling', 'Grammar'}
CAN_FIX = {'Documentation', 'Spelling', 'Grammar'}

@classmethod
def check_prerequisites(cls):
if shutil.which('java') is None:
return 'java is not installed.'
else:
try:
from language_check import LanguageTool, correct
LanguageTool
correct
return True
except ImportError: # pragma: no cover
return 'Please install the `language-check` pip package.'

def process_documentation(self,
parsed,
natural_language,
languagetool_disable_rules):
"""
This fixes the parsed documentation comment.
:param parsed:
Contains parsed documentation comment.
:param natural_language:
A locale representing the language you want to have checked.
Default is set to 'en-US'.
:param languagetool_disable_rules:
List of rules to disable checks for.
:return:
A tuple of fixed parsed documentation comment and warning_desc.
"""
# Defer import so the check_prerequisites can be run without
# language_check being there.
from language_check import LanguageTool, correct

tool = LanguageTool(natural_language)
tool.disabled.update(languagetool_disable_rules)

metadata = iter(parsed)

new_metadata = []
for comment in metadata:
matches = tool.check(comment.desc)
new_desc = correct(comment.desc, matches)
new_metadata.append(comment._replace(desc=new_desc))

return (new_metadata,
'Documentation has invalid Grammar/Spelling')

def run(self, filename, file, language: str,
docstyle: str='default', natural_language: str='en-US',
languagetool_disable_rules: typed_list(str)=()):
"""
Checks the main description and comments description of documentation
with LanguageTool.
:param language:
The programming language of the file(s).
:param docstyle:
The docstyle to use. For example ``default`` or ``doxygen``.
Docstyles are language dependent, meaning not every language is
supported by a certain docstyle.
:param natural_language:
A locale representing the language you want to have checked.
Default is set to 'en-US'.
:param languagetool_disable_rules:
List of rules to disable checks for.
"""
for doc_comment in self.extract(file, language, docstyle):
parsed = doc_comment.parse()

(new_metadata, warning_desc) = self.process_documentation(
parsed, natural_language, languagetool_disable_rules)

new_comment = DocumentationComment.from_metadata(
new_metadata, doc_comment.docstyle_definition,
doc_comment.marker, doc_comment.indent, doc_comment.position)

if new_comment != doc_comment:
# Something changed, let's apply a result.
diff = self.generate_diff(file, doc_comment, new_comment)

yield Result(
origin=self,
message=warning_desc,
affected_code=(diff.range(filename),),
diffs={filename: diff})
75 changes: 75 additions & 0 deletions tests/documentation/DocGrammarBearTest.py
@@ -0,0 +1,75 @@
from queue import Queue
import os.path
import unittest
import shutil

from coalib.results.Diff import Diff
from coalib.settings.Section import Section
from coalib.testing.LocalBearTestHelper import execute_bear

from bears.documentation.DocGrammarBear import DocGrammarBear

try:
import language_check
language_check
except ImportError as err:
raise unittest.case.SkipTest(str(err))


def load_testfile(filename):
filepath = os.path.join(os.path.dirname(__file__), 'test_files',
'DocGrammarBear', filename)
with open(filepath) as fl:
return fl.read()


def test(test_file, expected_file, optional_setting=None):
def test_function(self):
test_file_content = load_testfile(test_file).splitlines(True)

arguments = {'language': 'python', 'docstyle': 'default'}
if optional_setting:
arguments.update(optional_setting)
section = Section('test-section')
for key, value in arguments.items():
section[key] = value

with execute_bear(
DocGrammarBear(section, Queue()),
test_file,
test_file_content,
**arguments) as results:

diff = Diff(test_file_content)
for result in results:
# Only the given test file should contain a patch.
self.assertEqual(len(result.diffs), 1)

diff += result.diffs[test_file]

correct_file_content = load_testfile(expected_file).splitlines(True)

self.assertEqual(correct_file_content, diff.modified)

return test_function


class DocGrammarBearTest(unittest.TestCase):

def test_check_prerequisites(self):
_shutil_which = shutil.which
try:
shutil.which = lambda *args, **kwargs: None
self.assertEqual(DocGrammarBear.check_prerequisites(),
'java is not installed.')

shutil.which = lambda *args, **kwargs: 'path/to/java'
self.assertTrue(DocGrammarBear.check_prerequisites())
finally:
shutil.which = _shutil_which

test_bad1 = test('bad_file.py.test', 'bad_file.py.test.correct')
test_good1 = test('good_file.py.test', 'good_file.py.test')
test_good2 = test(
'good_file2.py.test', 'good_file2.py.test',
{'languagetool_disable_rules': 'UPPERCASE_SENTENCE_START'})
@@ -0,0 +1,8 @@
def improper_grammar(param1):
"""
Documntation contains gramatical mistakess.DocGrammarBear doesnt check
for style.
:param param1: Contains parameter descrption.
:return: returns nothing. first letter small.
"""
return None
@@ -0,0 +1,8 @@
def improper_grammar(param1):
"""
Documentation contains grammatical mistakes. DocGrammarBear doesn't check
for style.
:param param1: Contains parameter description.
:return: Returns nothing. First letter small.
"""
return None
@@ -0,0 +1,8 @@
def docstring_grammar_correct(dummy):
"""
This documentation has the correct grammar.

:param dummy: Dummy description.
:return: Returns Nothing.
"""
return None
@@ -0,0 +1,7 @@
def check_disabled_settings(dummy):
"""
This documentation has a setting disabled. sentence starting with lowercase.

:param dummy: dummy description.
:return: Nothing.
""" return None

0 comments on commit 05f9d01

Please sign in to comment.