def check_idea_usage(mod_path, output_file): ideas_added = set() ideas_checked = [] ideas_removed = [] paths = [ os.path.join(mod_path, 'events'), os.path.join(mod_path, 'common', 'decisions'), os.path.join(mod_path, 'common', 'scripted_effects'), os.path.join(mod_path, 'common', 'national_focuses'), os.path.join(mod_path, 'history', 'countries'), os.path.join(mod_path, 'common', 'on_actions') ] for path in paths: for contents, filename in files_as_strings_from_path_gen(path): for idea, line in field_contents_gen(contents, 'add_ideas'): ideas_added.add(idea) idea_using_directories = [ os.path.join(mod_path, 'events'), os.path.join(mod_path, 'common', 'decisions'), os.path.join(mod_path, 'common', 'scripted_triggers'), os.path.join(mod_path, 'common', 'national_focuses'), os.path.join(mod_path, 'common', 'scripted localisation'), os.path.join(mod_path, 'common', 'national_focuses'), os.path.join(mod_path, 'common', 'on_actions'), os.path.join(mod_path, 'common', 'ai_peace'), os.path.join(mod_path, 'common', 'ai_strategy'), os.path.join(mod_path, 'common', 'ai_strategy_plans'), os.path.join(mod_path, 'common', 'autonomous_states'), os.path.join(mod_path, 'common', 'ideas'), os.path.join(mod_path, 'common', 'technologies') ] paths = [mod_path + directory for directory in idea_using_directories] for path in paths: for contents, filename in files_as_strings_from_path_gen(path): for idea, line in field_contents_gen(contents, 'remove_ideas'): ideas_removed += [IdeaUse(idea, line, filename)] for idea, line in field_contents_gen(contents, 'has_idea'): ideas_checked += [IdeaUse(idea, line, filename)] bugs = [] for idea in ideas_checked: if idea.name not in ideas_added: bugs += [ Bug('Idea is checked but never added', idea.line_number, idea.filename) ] for idea in ideas_removed: if idea.name not in ideas_added: bugs += [ Bug('Idea is removed but never added', idea.line_number, idea.filename) ] for bug in bugs: output_file.write(bug.description + ' at line ' + str(bug.line) + ' in ' + bug.filename + '\n')
def check_mutually_exclusive_focuses(path, output_file): path = os.path.join(path, 'common', 'national_focus') focus_dict = {} for string, file in files_as_strings_from_path_gen(path): for focus, line_number in scope_gen(string, ['focus', 'shared_focus']): id, not_used = next(field_contents_gen(focus, 'id')) mutually_exclusive_focuses = [] for mutually_exclusive, index in scope_gen(focus, ['mutually_exclusive']): for focus_id, index in field_contents_gen( mutually_exclusive, 'focus'): mutually_exclusive_focuses.append(focus_id) focus = Focus(line_number, file, mutually_exclusive_focuses) focus_dict[id] = focus bugs = [] for focus_id, focus in focus_dict.items(): for mut_focus_id in focus.mutually_exclusive_with: try: if focus_id not in focus_dict[ mut_focus_id].mutually_exclusive_with: bugs.append( Bug( 'Focus is listed by another focus as mutually exclusive but does not list the other ' 'focus as mutually exclusive', focus_dict[mut_focus_id].line_number, focus_dict[mut_focus_id].file_name)) except KeyError: pass for bug in bugs: output_file.write(bug.description + ' at line ' + str(bug.line) + ' in ' + bug.filename + '\n')
def check_endlines(path, output_file): def check_newlines_in_string(filename, string): within_quotes = False current_line = 1 for i in range(0, len(string)): if string[i] == "\"": within_quotes = not within_quotes if not within_quotes: if string[i] == '\n': current_line += 1 if within_quotes: if string[i:i + 2] == '/n' or string[i:i + 2] == '\\N': yield Bug('Improper newline', current_line, filename) if string[i:i + 2] == '\\n': if string[i - 1] == ' ': yield Bug('Space before newline', current_line, filename) if i < len(string) - 1: if string[i + 2] == ' ': yield Bug('Space after newline', current_line, filename) bugs = [] path = os.path.join(path, "localisation") for string, filename in files_as_strings_from_path_gen(path): bugs += [bug for bug in check_newlines_in_string(filename, string)] for bug in bugs: output_file.write(bug.description + ' at line ' + str(bug.line) + ' in ' + bug.filename + '\n')
def check_events(mod_path, output_file, optionsdict): if optionsdict['check_ai_chance_usage'] or optionsdict['check_events_for_graphics'] or optionsdict['check_events_for_titles'] or optionsdict['check_events_for_descriptions'] or optionsdict['check_events_for_options'] or optionsdict['check_load_oob_usage'] or optionsdict['check_for_duplicate_options_loc'] or optionsdict['check_hidden_events']: bugs = [] path = os.path.join(mod_path,"events") for contents, filename in files_as_strings_from_path_gen(path): for event, start_line in scope_gen(contents, ['news_event', 'country_event']): if optionsdict['check_ai_chance_usage']: if 'ai_chance' in event and event.count('option =') == 1: bugs.append(Bug('\"ai_chance\" with only one option in event', start_line, filename)) if 'hidden = yes' not in event: if optionsdict['check_events_for_graphics']: if 'picture =' not in event: bugs.append(Bug('No picture for event', start_line, filename)) if optionsdict['check_events_for_titles']: if 'title =' not in event: bugs.append(Bug('No title for event', start_line, filename)) if optionsdict['check_events_for_descriptions']: if 'desc =' not in event: bugs.append(Bug('No description for event', start_line, filename)) if optionsdict['check_events_for_options']: if 'option =' not in event: bugs.append(Bug('No options for event', start_line, filename)) if optionsdict['check_load_oob_usage']: if 'load_oob' in event and 'custom_effect_tooltip' not in event: bugs.append(Bug('\"load_oob\" is an effect but there is no \"custom_effect_tooltip\" in event', start_line, filename)) if optionsdict['check_for_duplicate_options_loc']: option_locs = [] for option, option_start_line in scope_gen(event, ['option']): try: loc, loc_line = next(field_contents_gen(option, 'name')) if loc in option_locs: bugs.append(Bug('Duplicate option localization in event', start_line+option_start_line+1, filename)) option_locs.append(loc) except StopIteration: pass if optionsdict['check_hidden_events']: if 'hidden = yes' in event: if 'picture =' in event: bugs.append(Bug('Picture in hidden event', start_line, filename)) if 'title =' in event: bugs.append(Bug('Title in hidden event', start_line, filename)) if 'desc =' in event: bugs.append(Bug('Description in hidden event', start_line, filename)) if 'option =' in event: bugs.append(Bug('Options in hidden event', start_line, filename)) for bug in bugs: output_file.write(bug.description + ' at line ' + str(bug.line) + ' in ' + bug.filename + '\n')
def check_missing_equals(mod_path, output_file): bugs = [] directories = [ os.path.join(mod_path, 'events'), os.path.join(mod_path, 'common', 'national_focus'), os.path.join(mod_path, 'interface'), os.path.join(mod_path, 'history') ] for directory in directories: for contents, filename in files_as_strings_from_path_gen(directory): if "credits.txt" not in filename: bugs += [bug for bug in missing_equals_gen(contents, filename)] for bug in bugs: output_file.write(bug.description + ' at line ' + str(bug.line) + ' in ' + bug.filename + '\n')
def check_duplicate_ids(mod_path, output_file): bugs = [] id_set = set() directories = [ os.path.join("events"), os.path.join(mod_path, "common", "national_focus") ] for path in directories: for contents, filename in files_as_strings_from_path_gen(path): for id_tag, line_number in duplicate_ids_gen(contents): if id_tag in id_set: bugs += [ Bug('Duplicate ID in scope', line_number + 1, filename) ] else: id_set.add(id_tag) for bug in bugs: output_file.write(bug.description + ' at line ' + str(bug.line) + ' in ' + bug.filename + '\n')
def check_alive_check(path, output_file): path = os.path.join(path, "events") for string, filename in files_as_strings_from_path_gen(path): for bug in missing_alive_check_gen(string, filename): output_file.write(bug.description + ' at line ' + str(bug.line) + ' in ' + bug.filename + '\n')
def check_event_usage(mod_path, output_file): non_mtth_events = [] event_ids = [] called_ids = [] called_events = [] events_directory = '/events/' path = os.path.join(mod_path, "events") for contents, filename in files_as_strings_from_path_gen(path): for event, start_line in scope_gen(contents, ['news_event', 'country_event']): event_id = find_contents_of_field(event, 'id') if event_id: event_ids += [event_id] if 'mean_time_to_happen' not in event: non_mtth_events += [Event(event_id, start_line, filename)] for called_event, called_event_start_line in scope_gen( event, ['news_event', 'country_event']): called_event_id = find_contents_of_field(called_event, 'id') if called_event_id: called_ids += [called_event_id] called_events += [ Event(called_event_id, called_event_start_line + start_line - 1, events_directory + filename) ] directories_that_can_call_events = [ os.path.join('common', 'national_focus'), os.path.join('common', 'on_actions'), 'history', os.path.join('common', 'decisions'), ] for subdir in directories_that_can_call_events: path = os.path.join(mod_path, subdir) for contents, filename in files_as_strings_from_path_gen(path): for event, start_line in scope_gen( contents, ['news_event', 'country_event']): called_event_id = find_contents_of_field(event, 'id') if called_event_id: called_ids += [called_event_id] called_events += [ Event(find_contents_of_field(event, 'id'), start_line, 'common/' + subdir + filename) ] bugs = [] called_ids_set = set(called_ids) for event in non_mtth_events: if event.id not in called_ids_set: bugs += [ Bug('Non-MTTH event is not called', event.start_line, event.filename) ] event_ids_set = set(event_ids) for event in called_events: if event.id not in event_ids_set: bugs += [ Bug('Event is called but not defined', event.start_line, event.filename) ] for bug in bugs: output_file.write(bug.description + ' at line ' + str(bug.line) + ' in ' + bug.filename + '\n')
def check_flag_usage(mod_path, output_file): global_flags_set = [] global_flags_modified = [] global_flags_checked = [] global_flags_cleared = [] country_flags_set = [] country_flags_modified = [] country_flags_checked = [] country_flags_cleared = [] state_flags_set = [] state_flags_modified = [] state_flags_checked = [] state_flags_cleared = [] commonpath = os.path.join(mod_path, 'common') paths = [os.path.join(mod_path, 'events'), os.path.join(commonpath,'decisions'), os.path.join(commonpath,'scripted_effects'), os.path.join(commonpath,'national_focuses'), os.path.join(mod_path, 'history','countries'), os.path.join(commonpath,'on_actions')] for path in paths: for contents, filename in files_as_strings_from_path_gen(path): for flag, start_line in field_contents_gen(contents, 'set_global_flag'): if flag not in global_flags_set: global_flags_set += [Flag(flag, start_line, filename)] for modify_flag, start_line in scope_gen(contents, ['modify_global_flag']): flag, line_offset = next(field_contents_gen(modify_flag, 'flag')) if flag not in global_flags_modified: global_flags_modified += [Flag(flag, start_line+line_offset-1, filename)] for flag, start_line in field_contents_gen(contents, 'clr_global_flag'): if flag not in global_flags_cleared: global_flags_cleared += [Flag(flag, start_line, filename)] for flag, start_line in field_contents_gen(contents, 'set_country_flag'): if flag not in country_flags_set: country_flags_set += [Flag(flag, start_line, filename)] for modify_flag, start_line in scope_gen(contents, ['modify_country_flag']): flag, line_offset = next(field_contents_gen(modify_flag, 'flag')) if flag not in country_flags_modified: country_flags_modified += [Flag(flag, start_line+line_offset-1, filename)] for flag, start_line in field_contents_gen(contents, 'clr_country_flag'): if flag not in country_flags_cleared: country_flags_cleared += [Flag(flag, start_line, filename)] for flag, start_line in field_contents_gen(contents, 'set_state_flag'): if flag not in state_flags_set: state_flags_set += [Flag(flag, start_line, filename)] for modify_flag, start_line in scope_gen(contents, ['modify_state_flag']): flag, line_offset = next(field_contents_gen(modify_flag, 'flag')) if flag not in state_flags_modified: state_flags_modified += [Flag(flag, start_line+line_offset-1, filename)] for flag, start_line in field_contents_gen(contents, 'clr_state_flag'): if flag not in state_flags_cleared: state_flags_cleared += [Flag(flag, start_line, filename)] paths = [os.path.join(mod_path, 'events'), os.path.join(commonpath,'decisions'), os.path.join(commonpath,'scripted_triggers'), os.path.join(commonpath,'scripted localisation'), os.path.join(commonpath,'national_focuses'), os.path.join(commonpath,'on_actions'), os.path.join(commonpath,'ai_peace'), os.path.join(commonpath,'ai_strategy'), os.path.join(commonpath,'ai_strategy_plans'), os.path.join(commonpath,'autonomous_states'), os.path.join(commonpath,'ideas'), os.path.join(commonpath, 'technologies')] for path in paths: for contents, filename in files_as_strings_from_path_gen(path): for flag, start_line in field_contents_gen(contents, 'has_global_flag'): if flag not in global_flags_checked: global_flags_checked += [Flag(flag, start_line, filename)] for flag, start_line in field_contents_gen(contents, 'has_country_flag'): if flag not in country_flags_checked: country_flags_checked += [Flag(flag, start_line, filename)] if filename != "_Ministers_ideas.txt": for flag, start_line in field_contents_gen(contents, 'has_state_flag'): if flag not in state_flags_checked: state_flags_checked += [Flag(flag, start_line, filename)] global_flags_set_names = set() for flag in global_flags_set: global_flags_set_names.add(flag.name) global_flags_checked_names = set() for flag in global_flags_checked: global_flags_checked_names.add(flag.name) country_flags_set_names = set() for flag in country_flags_set: country_flags_set_names.add(flag.name) country_flags_checked_names = set() for flag in country_flags_checked: country_flags_checked_names.add(flag.name) state_flags_set_names = set() for flag in state_flags_set: state_flags_set_names.add(flag.name) state_flags_checked_names = set() for flag in state_flags_checked: state_flags_checked_names.add(flag.name) bugs = [] for flag in global_flags_set: if flag.name not in global_flags_checked_names: bugs += [Bug('Flag is set but never checked', flag.start_line, flag.filename)] for flag in global_flags_modified: if flag.name not in global_flags_set_names: bugs += [Bug('Flag is modified but never set', flag.start_line, flag.filename)] for flag in global_flags_checked: if flag.name not in global_flags_set_names: bugs += [Bug('Flag is checked but never set', flag.start_line, flag.filename)] for flag in global_flags_cleared: if flag.name not in global_flags_set_names: bugs += [Bug('Flag is cleared but never set', flag.start_line, flag.filename)] for flag in country_flags_set: if flag.name not in country_flags_checked_names: bugs += [Bug('Flag is set but never checked', flag.start_line, flag.filename)] for flag in country_flags_modified: if flag.name not in country_flags_set_names: bugs += [Bug('Flag is modified but never set', flag.start_line, flag.filename)] for flag in country_flags_checked: if flag.name not in country_flags_set_names: bugs += [Bug('Flag is checked but never set', flag.start_line, flag.filename)] for flag in country_flags_cleared: if flag.name not in country_flags_set_names: bugs += [Bug('Flag is cleared but never set', flag.start_line, flag.filename)] for flag in state_flags_set: if flag.name not in state_flags_checked_names: bugs += [Bug('Flag is set but never checked', flag.start_line, flag.filename)] for flag in state_flags_modified: if flag.name not in state_flags_set_names: bugs += [Bug('Flag is modified but never set', flag.start_line, flag.filename)] for flag in state_flags_checked: if flag.name not in state_flags_set_names: bugs += [Bug('Flag is checked but never set', flag.start_line, flag.filename)] for flag in state_flags_cleared: if flag.name not in state_flags_set_names: bugs += [Bug('Flag is cleared but never set', flag.start_line, flag.filename)] for bug in bugs: output_file.write(bug.description + ' at line ' + str(bug.line) + ' in ' + bug.filename + '\n')