Skip to content

Commit

Permalink
AnnotationBear: Return precise string/comment info
Browse files Browse the repository at this point in the history
Earlier the return used to be either a tuple
of source ranges of strings/comments now it
is a tuple of namedtuples with fields
"start_delimiter_range end_delimiter_range
content_range full_range" of singleline
strings/multiline strings/singleline
comments/multiline comments.
Also, It modifies KeywordBear,  QuotesBear,
IndentationBear and their tests to adapt to
AnnotationBear changes.
  • Loading branch information
aptrishu committed Jan 29, 2017
1 parent a70176d commit 2b2deff
Show file tree
Hide file tree
Showing 7 changed files with 319 additions and 171 deletions.
262 changes: 177 additions & 85 deletions bears/general/AnnotationBear.py

Large diffs are not rendered by default.

44 changes: 25 additions & 19 deletions bears/general/IndentationBear.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,12 @@ def run(self,
"""
lang_settings_dict = LanguageDefinition(
language, coalang_dir=coalang_dir)
annotation_dict = dependency_results[AnnotationBear.name][0].contents
dep_contents = dependency_results[AnnotationBear.name][0].contents
annotation_dict = {}
annotation_dict['strings'] = (dep_contents['singleline strings'] +
dep_contents['multiline strings'])
annotation_dict['comments'] = (dep_contents['singleline comments'] +
dep_contents['multiline comments'])
# sometimes can't convert strings with ':' to dict correctly
if ':' in dict(lang_settings_dict['indent_types']).keys():
indent_types = dict(lang_settings_dict['indent_types'])
Expand Down Expand Up @@ -168,7 +173,7 @@ def get_absolute_indent_of_range(self,
:param encaps_pos: A tuple ofSourceRanges of code regions
trapped in between a matching pair of
encapsulators.
:param annotation_dict: A dictionary containing sourceranges of all the
:param annotation_dict: A dictionary containing namedtuples of all the
strings and comments within a file.
:return: A tuple of tuples with first element as the
range of encapsulator and second element as the
Expand Down Expand Up @@ -196,7 +201,7 @@ def get_indent_levels(self,
:param filename: Name of the file that needs to be checked.
:param indent_types: A dictionary with keys as start of indent and
values as their corresponding closing indents.
:param annotation_dict: A dictionary containing sourceranges of all the
:param annotation_dict: A dictionary containing namedtuples of all the
strings and comments within a file.
:param encapsulators: A tuple of sourceranges of all encapsulators of
a language.
Expand Down Expand Up @@ -255,7 +260,7 @@ def get_specified_block_range(self,
block has begun.
:param close_specifier: A character or string indicating that the block
has ended.
:param annotation_dict: A dictionary containing sourceranges of all the
:param annotation_dict: A dictionary containing namedtuples of all the
strings and comments within a file.
:return: A tuple whith the first source range being
the range of the outermost indentation while
Expand Down Expand Up @@ -324,7 +329,7 @@ def get_unspecified_block_range(self,
:param filename: Name of the file that needs to be checked.
:param indent_specifier: A character or string indicating that the
indentation should begin.
:param annotation_dict: A dictionary containing sourceranges of all the
:param annotation_dict: A dictionary containing namedtuples of all the
strings and comments within a file.
:param encapsulators: A tuple of sourceranges of all encapsulators of
a language.
Expand Down Expand Up @@ -372,7 +377,7 @@ def get_valid_sequences(file,
:param file: File that needs to be checked in the form of
a list of strings.
:param sequence: Sequence whose validity is to be checked.
:param annotation_dict: A dictionary containing sourceranges of all the
:param annotation_dict: A dictionary containing namedtuples of all the
strings and comments within a file.
:param encapsulators: A tuple of SourceRanges of code regions
trapped in between a matching pair of
Expand All @@ -394,22 +399,23 @@ def get_valid_sequences(file,

# ignore if within string
for string in annotation_dict['strings']:
if(gt_eq(sequence_position, string.start) and
lt_eq(sequence_position, string.end)):
if(gt_eq(sequence_position, string['full_range'].start) and
lt_eq(sequence_position, string['full_range'].end)):
valid = False

# ignore if within comments
for comment in annotation_dict['comments']:
if(gt_eq(sequence_position, comment.start) and
lt_eq(sequence_position, comment.end)):
if(gt_eq(sequence_position, comment['full_range'].start) and
lt_eq(sequence_position, comment['full_range'].end)):
valid = False

if(comment.start.line == sequence_position.line and
comment.end.line == sequence_position.line and
check_ending):
sequence_line_text = sequence_line_text[
:comment.start.column - 1] + sequence_line_text[
comment.end.column-1:]
if(comment['full_range'].start.line == sequence_position.line
and comment['full_range'].end.line ==
sequence_position.line and check_ending):
sequence_line_text = (sequence_line_text[
:comment['full_range'].start.column - 1] +
sequence_line_text[comment['full_range'].end.column-1:
])

if encapsulators:
for encapsulator in encapsulators:
Expand Down Expand Up @@ -462,7 +468,7 @@ def get_first_unindent(indent,
:param file: A tuple of strings.
:param start_line: The line from where to start searching for
unindent.
:param annotation_dict: A dictionary containing sourceranges of all the
:param annotation_dict: A dictionary containing namedtuples of all the
strings and comments within a file.
:param encapsulators: A tuple of SourceRanges of code regions trapped in
between a matching pair of encapsulators.
Expand All @@ -476,8 +482,8 @@ def get_first_unindent(indent,
valid = True

for comment in annotation_dict['comments']:
if(comment.start.line < line_nr + 1 and
comment.end.line >= line_nr + 1):
if(comment['full_range'].start.line < line_nr + 1 and
comment['full_range'].end.line >= line_nr + 1):
valid = False

first_char = file[line_nr].lstrip()[0] if file[line_nr].strip()\
Expand Down
7 changes: 6 additions & 1 deletion bears/general/KeywordBear.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,12 @@ def _get_comments(dependency_results):
if isinstance(result.contents, str):
logging.error(result.contents)
else:
yield from result.contents.get('comments', [])
dep_contents = result.contents
annotation_dict = {}
annotation_dict['comments'] = \
(dep_contents.get('singleline comments', []) +
dep_contents.get('multiline comments', []))
yield from annotation_dict['comments']


def generate_diff(comments, file, filename,
Expand Down
24 changes: 16 additions & 8 deletions bears/general/QuotesBear.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,21 +62,29 @@ def run(self, filename, file, dependency_results,
:param preferred_quotation: Your preferred quotation character, e.g.
``"`` or ``'``.
"""
if not isinstance(dependency_results[AnnotationBear.name][0],
HiddenResult):
if not dependency_results or \
not isinstance(dependency_results[AnnotationBear.name],
HiddenResult):
return
if isinstance(dependency_results[AnnotationBear.name][0].contents,
if isinstance(dependency_results[AnnotationBear.name].contents,
str):
self.err(dependency_results[AnnotationBear.name][0].contents)
self.err(dependency_results[AnnotationBear.name].contents)
return

ranges = dependency_results[AnnotationBear.name][0].contents['strings']
dep_contents = dependency_results[AnnotationBear.name].contents
annotation_dict = {}
s_a = 'singleline strings'
s_b = 'multiline strings'
annotation_dict['strings'] = (dep_contents[s_a] +
dep_contents[s_b])
ranges = annotation_dict['strings']

for string_range in ranges:
if (file[string_range.start.line-1][string_range.start.column-1] ==
temp_range = string_range.full_range
if (file[temp_range.start.line-1][temp_range.start.column-1] ==
preferred_quotation):
continue

if string_range.start.line == string_range.end.line:
if temp_range.start.line == temp_range.end.line:
yield from self.correct_single_line_str(
filename, file, string_range, preferred_quotation)
filename, file, temp_range, preferred_quotation)
104 changes: 65 additions & 39 deletions tests/general/AnnotationBearTest.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from queue import Queue
from collections import namedtuple
import unittest

from bears.general.AnnotationBear import AnnotationBear
Expand All @@ -22,47 +23,62 @@ def setUp(self):

def test_single_line_string(self):
text = ["'from start till the end with #comments'\n", ]
compare = (SourceRange.from_absolute_position(
'F',
AbsolutePosition(text, 0),
AbsolutePosition(text, len(text[0]) - 2)),)
compare = SourceRange.from_absolute_position(
'F',
AbsolutePosition(text, 0),
AbsolutePosition(text, len(text[0]) - 2))
with execute_bear(self.python_uut, 'F', text) as result:
self.assertEqual(result[0].contents['strings'], compare)
self.assertEqual(result[0].contents['comments'], ())
for _result in result[0].contents['singleline strings']:
self.assertEqual(_result['full_range'], compare)
self.assertEqual(result[0].contents['singleline comments'], ())

text = ["a'\n", "b'\n"]
with execute_bear(self.python_uut, 'F', text) as result:
self.assertEqual(result[0].message, "' has no closure")

def test_empty_string(self):
text = ["''\n", ]
compare = SourceRange.from_absolute_position(
'F',
AbsolutePosition(text, 0),
AbsolutePosition(text, len(text[0]) - 2))
with execute_bear(self.python_uut, 'F', text) as result:
for _result in result[0].contents['singleline strings']:
self.assertEqual(_result['full_range'], compare)
self.assertEqual(result[0].contents['singleline comments'], ())

def test_multiline_string(self):
text = ["'''multiline string, #comment within it'''\n"]
compare = (SourceRange.from_absolute_position(
'F',
AbsolutePosition(text, 0),
AbsolutePosition(text, len(text[0])-2)),)
compare = SourceRange.from_absolute_position(
'F',
AbsolutePosition(text, 0),
AbsolutePosition(text, len(text[0])-2))
with execute_bear(self.python_uut, 'F', text) as result:
self.assertEqual(result[0].contents['strings'], compare)
self.assertEqual(result[0].contents['comments'], ())
for _result in result[0].contents['multiline strings']:
self.assertEqual(_result['full_range'], compare)
self.assertEqual(result[0].contents['singleline comments'], ())

def test_single_line_comment(self):
text = ["some #coment with 'string'\n", 'and next line']
compare = (SourceRange.from_absolute_position(
'F',
AbsolutePosition(text, text[0].find('#')),
AbsolutePosition(text, len(text[0]) - 1)),)
compare = SourceRange.from_absolute_position(
'F',
AbsolutePosition(text, text[0].find('#')),
AbsolutePosition(text, len(text[0]) - 1))
with execute_bear(self.python_uut, 'F', text) as result:
self.assertEqual(result[0].contents['strings'], ())
self.assertEqual(result[0].contents['comments'], compare)
self.assertEqual(result[0].contents['singleline strings'], ())
for _result in result[0].contents['singleline comments']:
self.assertEqual(_result['full_range'], compare)

def test_multiline_comment(self):
text = ['some string /*within \n', "'multiline comment'*/"]
compare = (SourceRange.from_absolute_position(
'F',
AbsolutePosition(text, text[0].find('/*')),
AbsolutePosition(text, len(''.join(text)) - 1)),)
compare = SourceRange.from_absolute_position(
'F',
AbsolutePosition(text, text[0].find('/*')),
AbsolutePosition(text, len(''.join(text)) - 1))
with execute_bear(self.c_uut, 'F', text) as result:
self.assertEqual(result[0].contents['strings'], ())
self.assertEqual(result[0].contents['comments'], compare)
self.assertEqual(result[0].contents['singleline strings'], ())
for _result in result[0].contents['multiline comments']:
self.assertEqual(_result['full_range'], compare)

text = ['/*Multiline which does not end']
with execute_bear(self.c_uut, 'F', text) as result:
Expand All @@ -74,17 +90,19 @@ def test_string_with_comments(self):
comment_end = len(text[0]) - 1
string_start = ''.join(text).find("'")
string_end = ''.join(text).find("'", string_start + 1)
compare = [(SourceRange.from_absolute_position(
'F',
AbsolutePosition(text, string_start),
AbsolutePosition(text, string_end)),),
(SourceRange.from_absolute_position(
'F',
AbsolutePosition(text, comment_start),
AbsolutePosition(text, comment_end)),)]
compare = [SourceRange.from_absolute_position(
'F',
AbsolutePosition(text, string_start),
AbsolutePosition(text, string_end)),
SourceRange.from_absolute_position(
'F',
AbsolutePosition(text, comment_start),
AbsolutePosition(text, comment_end))]
with execute_bear(self.python_uut, 'F', text) as result:
self.assertEqual(result[0].contents['strings'], compare[0])
self.assertEqual(result[0].contents['comments'], compare[1])
for _result in result[0].contents['singleline strings']:
self.assertEqual(_result['full_range'], compare[0])
for _result in result[0].contents['singleline comments']:
self.assertEqual(_result['full_range'], compare[1])

def test_combined_strings(self):
file_text = ['"some string #with comment"\n',
Expand Down Expand Up @@ -116,10 +134,15 @@ def test_combined_strings(self):
AbsolutePosition(file_text, string3_start),
AbsolutePosition(file_text, string3_end))
with execute_bear(self.python_uut, 'F', file_text) as results:
self.assertIn(string1, results[0].contents['strings'])
self.assertIn(string2, results[0].contents['strings'])
self.assertIn(string3, results[0].contents['strings'])
self.assertEqual(results[0].contents['comments'], ())
full_ranges = []
for _result in (results[0].contents['singleline strings'] +
results[0].contents['multiline strings']):
full_ranges.append(_result['full_range'])
self.assertIn(string1, full_ranges)
self.assertIn(string2, full_ranges)
self.assertIn(string3, full_ranges)
self.assertEqual(results[0].contents['multiline comments'], ())
self.assertEqual(results[0].contents['singleline comments'], ())

def test_no_coalang(self):
self.section1.append(Setting('language', 'Valyrian'))
Expand All @@ -136,8 +159,11 @@ def test_escape_strings(self):
'F',
AbsolutePosition(text, 0),
AbsolutePosition(text, text[0].find("'", 4)))

with execute_bear(uut, 'F', text) as result:
self.assertEqual(result[0].contents['strings'], (test_range,))
self.assertEqual(
result[0].contents['singleline strings'][0]['full_range'],
test_range)

text = ['''
""""quoting inside quoting"
Expand Down
Loading

0 comments on commit 2b2deff

Please sign in to comment.