forked from coala/coala-bears
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
181 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
from coalib.bears.LocalBear import LocalBear | ||
from bears.general.AnnotationBear import AnnotationBear | ||
from coalib.results.Diff import Diff | ||
from coalib.results.HiddenResult import HiddenResult | ||
from coalib.results.Result import Result | ||
|
||
|
||
class QuotesBear(LocalBear): | ||
|
||
BEAR_DEPS = {AnnotationBear} | ||
AUTHORS = {'The coala developers'} | ||
AUTHORS_EMAILS = {'[email protected]'} | ||
LICENSE = 'AGPL-3.0' | ||
CAN_DETECT = {'Formatting'} | ||
|
||
def correct_single_line_str(self, filename, file, sourcerange, | ||
preferred_quotation): | ||
""" | ||
Corrects a given single line string assuming it does not use the | ||
preferred quotation. If the preferred quotation mark is used inside the | ||
string, no correction will be made. | ||
This function will yield one or no Result objects. | ||
:param filename: | ||
The filename of the file to correct the line in. | ||
:param file: | ||
The file contents as list of lines. | ||
:param sourcerange: | ||
The sourcerange indicating where to find the string. | ||
:param preferred_quotation: | ||
``'`` or ``"`` respectively. | ||
""" | ||
str_contents = file[sourcerange.start.line - 1][ | ||
sourcerange.start.column:sourcerange.end.column-1] | ||
|
||
if preferred_quotation in str_contents: | ||
return | ||
|
||
before = file[sourcerange.start.line - 1][:sourcerange.start.column-1] | ||
after = file[sourcerange.end.line - 1][sourcerange.end.column:] | ||
|
||
replacement = (before + preferred_quotation + str_contents + | ||
preferred_quotation + after) | ||
|
||
diff = Diff(file) | ||
diff.change_line(sourcerange.start.line, | ||
file[sourcerange.start.line - 1], | ||
replacement) | ||
yield Result(self, 'You do not use the preferred quotation marks.', | ||
diff.affected_code(filename), diffs={filename: diff}) | ||
|
||
def run(self, filename, file, dependency_results, | ||
preferred_quotation: str='"'): | ||
""" | ||
Checks and corrects your quotation style. | ||
For all single line strings, this bear will correct the quotation to | ||
your preferred quotation style if that kind of quote is not included | ||
within the string. Multi line strings are not supported. | ||
:param preferred_quotation: Your preferred quotation character, e.g. | ||
``"`` or ``'``. | ||
""" | ||
if not isinstance(dependency_results[AnnotationBear.name][0], | ||
HiddenResult): | ||
return | ||
if isinstance(dependency_results[AnnotationBear.name][0].contents, | ||
str): | ||
self.err(dependency_results[AnnotationBear.name][0].contents) | ||
return | ||
|
||
ranges = dependency_results[AnnotationBear.name][0].contents['strings'] | ||
|
||
for string_range in ranges: | ||
if (file[string_range.start.line-1][string_range.start.column-1] == | ||
preferred_quotation): | ||
continue | ||
|
||
if string_range.start.line == string_range.end.line: | ||
yield from self.correct_single_line_str( | ||
filename, file, string_range, preferred_quotation) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
import unittest | ||
from queue import Queue | ||
from textwrap import dedent | ||
|
||
from coalib.results.HiddenResult import HiddenResult, Result | ||
from bears.general.QuotesBear import QuotesBear | ||
from coalib.results.SourceRange import SourceRange | ||
from coalib.settings.Section import Section | ||
from coalib.testing.LocalBearTestHelper import verify_local_bear, execute_bear | ||
|
||
|
||
class QuotesBearDiffTest(unittest.TestCase): | ||
|
||
def setUp(self): | ||
self.section = Section('') | ||
self.uut = QuotesBear(self.section, Queue()) | ||
|
||
self.double_quote_file = dedent(""" | ||
''' | ||
Multiline string | ||
''' | ||
"a string with double quotes!" | ||
'A single quoted string with " in it' | ||
""").splitlines(True) | ||
|
||
self.single_quote_file = dedent(""" | ||
''' | ||
Multiline string | ||
''' | ||
'a string with single quotes!' | ||
"A double quoted string with ' in it" | ||
""").splitlines(True) | ||
|
||
self.filename = 'f' | ||
|
||
self.dep_results = { | ||
'AnnotationBear': | ||
[HiddenResult( | ||
'AnnotationBear', | ||
{'comments': (), 'strings': ( | ||
SourceRange.from_values(self.filename, 2, 1, 4, 3), | ||
SourceRange.from_values(self.filename, 5, 1, 5, 30), | ||
SourceRange.from_values(self.filename, 6, 1, 6, 37)) | ||
} | ||
)] | ||
} | ||
|
||
def test_error_handling(self): | ||
dep_results = {'AnnotationBear': [Result("test", "test")]} | ||
with execute_bear(self.uut, self.filename, self.double_quote_file, | ||
dependency_results=dep_results) as results: | ||
self.assertEqual(len(results), 0) | ||
|
||
dep_results = {'AnnotationBear': [HiddenResult('a', 'error!')]} | ||
with execute_bear(self.uut, self.filename, self.double_quote_file, | ||
dependency_results=dep_results) as results: | ||
self.assertEqual(len(results), 0) | ||
|
||
def test_valid_quotes(self): | ||
with execute_bear(self.uut, self.filename, self.double_quote_file, | ||
dependency_results=self.dep_results) as results: | ||
self.assertEqual(len(results), 0) | ||
|
||
self.section['preferred_quotation'] = "'" | ||
with execute_bear(self.uut, self.filename, self.single_quote_file, | ||
dependency_results=self.dep_results) as results: | ||
self.assertEqual(len(results), 0) | ||
|
||
def test_invalid_quotes(self): | ||
with execute_bear(self.uut, self.filename, self.single_quote_file, | ||
dependency_results=self.dep_results) as results: | ||
res_list = list(results) | ||
self.assertEqual(len(res_list), 1) | ||
self.assertEqual(res_list[0].diffs[self.filename].unified_diff, | ||
'--- \n' | ||
'+++ \n' | ||
'@@ -2,5 +2,5 @@\n' | ||
" '''\n" | ||
" Multiline string\n" | ||
" '''\n" | ||
"-'a string with single quotes!'\n" | ||
'+"a string with single quotes!"\n' | ||
' "A double quoted string with \' in it"\n') | ||
|
||
self.section['preferred_quotation'] = "'" | ||
with execute_bear(self.uut, self.filename, self.double_quote_file, | ||
dependency_results=self.dep_results) as results: | ||
res_list = list(results) | ||
self.assertEqual(len(res_list), 1) | ||
self.assertEqual(res_list[0].diffs[self.filename].unified_diff, | ||
'--- \n' | ||
'+++ \n' | ||
'@@ -2,5 +2,5 @@\n' | ||
" '''\n" | ||
" Multiline string\n" | ||
" '''\n" | ||
'-"a string with double quotes!"\n' | ||
"+'a string with double quotes!'\n" | ||
" 'A single quoted string with \" in it'\n") |