Ports tag matcher update

https://github.com/Baystation12/Baystation12/pull/12218
This commit is contained in:
Kelenius
2016-03-11 12:32:20 +03:00
parent 1cd71da6ed
commit 7fb2c0d467
2 changed files with 57 additions and 39 deletions

View File

@@ -30,7 +30,7 @@ script:
- shopt -s globstar - shopt -s globstar
- (! grep 'step_[xy]' maps/**/*.dmm) - (! grep 'step_[xy]' maps/**/*.dmm)
- (! find nano/templates/ -type f -exec md5sum {} + | sort | uniq -D -w 32 | grep nano) - (! find nano/templates/ -type f -exec md5sum {} + | sort | uniq -D -w 32 | grep nano)
- (! grep -E "<\s*span\s+class\s*=\s*('[^'>]+|[^'>]+')\s*>" **/*.dm) - (! grep -En "<\s*span\s+class\s*=\s*('[^'>]+|[^'>]+')\s*>" **/*.dm)
- awk -f tools/indentation.awk **/*.dm - awk -f tools/indentation.awk **/*.dm
- md5sum -c - <<< "88490b460c26947f5ec1ab1bb9fa9f17 *html/changelogs/example.yml" - md5sum -c - <<< "88490b460c26947f5ec1ab1bb9fa9f17 *html/changelogs/example.yml"
- (num=`grep -E '\\\\(red|blue|green|black|b|i[^mc])' **/*.dm | wc -l`; echo "$num escapes (expecting ${MACRO_COUNT} or less)"; [ $num -le ${MACRO_COUNT} ]) - (num=`grep -E '\\\\(red|blue|green|black|b|i[^mc])' **/*.dm | wc -l`; echo "$num escapes (expecting ${MACRO_COUNT} or less)"; [ $num -le ${MACRO_COUNT} ])

View File

@@ -18,6 +18,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
''' '''
import argparse, re, sys import argparse, re, sys
from collections import defaultdict
from os import path, walk from os import path, walk
opt = argparse.ArgumentParser() opt = argparse.ArgumentParser()
@@ -37,66 +38,83 @@ tag_tuples = [ ('<span>', re.compile('<span(.*?)>', re.IGNORECASE), re.compile('
('<i>', re.compile('<i>', re.IGNORECASE), re.compile('</i>', re.IGNORECASE))] ('<i>', re.compile('<i>', re.IGNORECASE), re.compile('</i>', re.IGNORECASE))]
# The keys of this dictionary will be the file path of each parsed *.dm file # The keys of this dictionary will be the file path of each parsed *.dm file
# The values of this dictionary will be in the format provided by populate_match_list(). # The values of this dictionary is a another dictionary with the key/value pair: tag/list of unmatched lines
matches = { } mismatches_by_file = { }
# Support def for setting up a dictionary, populating it with all defined tuple names as key with each being assigned the value 0. # Loops over all defined tag tuples and returns a dictionary with the key/value pair: tag/mismatch_count (positive means excess of opening tag, negative means excess of closing tags)
# One such dictionary is created for each parsed file. def get_tag_matches(line):
def populate_match_list(): mismatch_count_by_tag = { }
match_list = { }
for tag_tuple in tag_tuples: for tag_tuple in tag_tuples:
match_list[tag_tuple[0]] = 0 mismatch_count = 0
return match_list mismatch_count += len(tag_tuple[1].findall(line))
mismatch_count -= len(tag_tuple[2].findall(line))
if mismatch_count != 0:
mismatch_count_by_tag[tag_tuple[0]] = mismatch_count
return mismatch_count_by_tag
# This def shall be provided by a dictionary in the format given by populate_match_list() and a line of text. # Support def that simply checks if a given dictionary in the format tag/list of unmatched lines has mismatch entries.
# It loops over all defined tag tuples, adding the number of open tags found and subtracting the number of close tag found to the corresponding tuple name in the match list.
# This def is currently run with the same match_list for a given file and for all lines of that file.
def get_tag_matches(match_list, line):
for tag_tuple in tag_tuples:
match_list[tag_tuple[0]] += len(tag_tuple[1].findall(line))
match_list[tag_tuple[0]] -= len(tag_tuple[2].findall(line))
return
# Support def that simply checks if a given dictionary in the format given by populate_match_list() contains any value that is non-zero.
# That is, a tag which had a non-equal amount of open/closing tags.
def has_mismatch(match_list): def has_mismatch(match_list):
for tag, match_number in match_list.iteritems(): for tag, list_of_mismatched_lines in match_list.iteritems():
if(match_number != 0): if(len(list_of_mismatched_lines) > 0):
return 1 return 1
return 0 return 0
def arrange_mismatches(mismatches_by_tag, mismatch_line, mismatch_counts):
for tag, mismatch_count in mismatch_counts.iteritems():
stack_of_existing_mismatches = mismatches_by_tag[tag]
for i in range(0, abs(mismatch_count)):
if len(stack_of_existing_mismatches) == 0:
if(mismatch_count > 0):
stack_of_existing_mismatches.append(mismatch_line)
else:
stack_of_existing_mismatches.append(-mismatch_line)
else:
if stack_of_existing_mismatches[0] > 0:
if mismatch_count > 0:
stack_of_existing_mismatches.append(mismatch_line)
else:
stack_of_existing_mismatches.pop()
else:
if mismatch_count < 0:
stack_of_existing_mismatches.append(-mismatch_line)
else:
stack_of_existing_mismatches.pop()
# This section parses all *.dm files in the given directory, recursively. # This section parses all *.dm files in the given directory, recursively.
for root, subdirs, files in walk(args.dir): for root, subdirs, files in walk(args.dir):
for filename in files: for filename in files:
if filename.endswith('.dm'): if filename.endswith('.dm'):
file_path = path.join(root, filename) file_path = path.join(root, filename)
with open(file_path, 'r') as f: with open(file_path, 'r') as file:
# For each file, generate the match dictionary. mismatches_by_file[file_path] = defaultdict(list)
matches[file_path] = populate_match_list() for line_number, line in enumerate(file, 1):
for x in f:
# Then for each line in the file, conduct the tuple open/close matching. # Then for each line in the file, conduct the tuple open/close matching.
get_tag_matches(matches[file_path], x) mismatches_by_tag = get_tag_matches(line)
arrange_mismatches(mismatches_by_file[file_path], line_number, mismatches_by_tag)
# Pretty printing section. # Pretty printing section.
# Loops over all matches and checks if there is a mismatch of tags. # Loops over all matches and checks if there is a mismatch of tags.
# If so, then and only then is the corresponding file path printed along with the number of unmatched open/close tags. # If so, then and only then is the corresponding file path printed along with the number of unmatched open/close tags.
total_mismatch = 0 total_mismatches = 0
for file, match_list in matches.iteritems(): for file, mismatches_by_tag in mismatches_by_file.iteritems():
if(has_mismatch(match_list)): if has_mismatch(mismatches_by_tag):
print(file) print(file)
for tag, match_number in match_list.iteritems(): for tag, mismatch_list in mismatches_by_tag.iteritems():
# A positive number means an excess of opening tag, a negative number means an excess of closing tags. # A positive number means an excess of opening tag, a negative number means an excess of closing tags.
if(match_number > 0): total_mismatches += len(mismatch_list)
total_mismatch += match_number if len(mismatch_list) > 0:
print('\t{0} - Excess of {1} opening tag(s)'.format(tag, match_number)) if mismatch_list[0] > 0:
elif (match_number < 0): print('\t{0} - Excess of {1} opening tag(s)'.format(tag, len(mismatch_list)))
total_mismatch -= match_number elif mismatch_list[0] < 0:
print('\t{0} - Excess of {1} closing tag(s)'.format(tag, -match_number)) print('\t{0} - Excess of {1} closing tag(s)'.format(tag, len(mismatch_list)))
for mismatch_line in sorted(set(mismatch_list)):
print('\t\tLine {0}'.format(abs(mismatch_line)))
# Simply prints the total number of mismatches found and if so returns 1 to, for example, fail Travis builds. # Simply prints the total number of mismatches found and if so returns 1 to, for example, fail Travis builds.
if(total_mismatch == 0): if(total_mismatches == 0):
print('No mismatches found.') print('No mismatches found.')
else: else:
print('') print('')
print('Total number of mismatches: {0}'.format(total_mismatch)) print('Total number of mismatches: {0}'.format(total_mismatches))
sys.exit(1) sys.exit(1)