def assertEqualIgnoreWhitespace(self, expected: str, actual: str) -> None: expected = re.sub(" *, *", ",", expected) actual = re.sub(" *, *", ",", actual) self.assertEqual( Stream( re.split(r" |\n|\t", expected)).filter(lambda x: x.strip() != "").toList(), Stream( re.split(r" |\n|\t", actual)).filter(lambda x: x.strip() != "").toList())
def move_function_parameter_type_declaration_to_body(text: str) -> str: edits: List[CodeEdit] = [] for function_declaration in re.finditer( r"^\s*\S+( |\n)+(function|subroutine)( |\n)+[^\(]+( |\n)*\(", text, re.MULTILINE): if _is_inside_string_block(function_declaration.start(), text): continue depth = 1 declaration_closing_parenthesis = None for parenthesis in re.finditer(r"(\(|\))", text[function_declaration.end():]): if text[function_declaration.end():][parenthesis.start()] == '(': depth += 1 else: depth -= 1 if depth == 0: declaration_closing_parenthesis = parenthesis.start( ) + function_declaration.end() break function_opening_curly_bracket = text.index("{", function_declaration.end()) parameter_str = text[function_declaration.end( ):declaration_closing_parenthesis] parameter_declarations: List[VariableDeclaration] = [] parameter = re.search(r"::( |\n)*[^,\) \n]+", parameter_str) while parameter: identifier = parameter_str[parameter.start() + 2:parameter.end()].strip(" \n\t") declared_type = parameter_str[:parameter.start()].strip(", \n\t") parameter_declarations.append( VariableDeclaration(declared_type, identifier)) parameter_str = parameter_str[parameter.end():] parameter = re.search(r"::( |\n)*[^,\) \n]+", parameter_str) edits.append( CodeEdit( function_declaration.start(), declaration_closing_parenthesis + 1, text[function_declaration.start():function_declaration.end()] + ",".join( Stream(parameter_declarations).map(lambda x: x.identifier)) + ")")) edits.append( CodeEdit( function_opening_curly_bracket, function_opening_curly_bracket + 1, "{\n" + "\n".join( Stream(parameter_declarations).map( lambda x: f"{x.type}::{x.identifier}")))) return apply_edits(text, edits)
def _is_inside_string_block(position: int, text: str) -> bool: for quote_symbol in ('"', "'"): quotes = re.finditer(f"\\{quote_symbol}", text[:position]) quotes_count = Stream(quotes).count() if quotes_count % 2 == 1: return True return False
def _find_symbol_declaration(symbol_name: str, text: str, usage_position: int) -> SymbolDeclaration: return Stream(reversed(list( re.finditer(r"[^:\n;]*::\s*(\w+,)*" + symbol_name + r".*$", text[:usage_position], flags=re.M)))) \ .firstMatch(lambda x: not _is_inside_string_block(x.start(), text)) \ .map(lambda x: SymbolDeclaration(symbol_name, text[x.start(): x.end()])) \ .orElseThrow(CannotFindSymbolDeclarationException(symbol_name))
def _encode_character_case(word: str) -> str: character_wise_encoding = Stream(word) \ .map(lambda x: [x] if not x.isupper() else [x.lower(), "$"]) \ .flat() \ .reduce("", lambda a, e: a + e) caps_lock_state, caps_lock_encoding = Stream(word) \ .reduce((False, ""), lambda state, el: (state[0], state[1] + el.lower()) if (state[0] is False and el.islower()) or (state[0] is True and el.isupper()) else (not state[0], f"{state[1]}{el.lower()}$$")) if caps_lock_state is True: caps_lock_encoding += "$$" return character_wise_encoding \ if len(character_wise_encoding) <= len(caps_lock_encoding) \ else caps_lock_encoding
def strip_comments(text: str) -> str: lines = text.split("\n") result = [] for line in lines: if "!" in line: comment_markers = re.finditer("!", line) first_comment_marker_index = Stream(comment_markers) \ .map(lambda matcher: matcher.start()) \ .filter(lambda pos: not _is_inside_string_block(pos, line)) \ .first() if first_comment_marker_index.isPresent(): result.append(line[:first_comment_marker_index.get()]) else: result.append(line) else: result.append(line) return "\n".join(result)
def get_object_declared_type(self) -> str: return Stream(re.finditer(r"(\w+)", self.line)) \ .first() \ .map(lambda x: x.group(1)) \ .map(lambda x: x if not "type" in x else re.search(r"type\((w+)\)", x).group(1)) \ .orElseThrow(InvalidSymbolTypeDeclarationException(self.symbol_name))
def _previous_keyword(text: str, bracket_position: int) -> str: return Stream(VALID_BLOCK_NAMES) \ .filter(lambda block: block in text[:bracket_position]) \ .map(lambda block: (block, text.rindex(block, 0, bracket_position))) \ .reduce(("", -1), lambda acc, e: acc if acc[1] > e[1] else e)[0]
def _previous_word(text: str, search_end_position: int) -> str: return Stream(reversed(list(re.finditer(r"(w+)\s*", text[:search_end_position])))) \ .firstMatch(lambda match: not _is_inside_string_block(match.start(), text)) \ .map(lambda match: match.group(1)) \ .orElse("")
def _next_word(text: str, start_position: int) -> str: return Stream(re.finditer(r"\s*(\w+)", text[start_position:])) \ .firstMatch(lambda match: not _is_inside_string_block(match.start(), text)) \ .map(lambda match: match.group(1)) \ .orElse("")
def find_imported_classes_in_imports( file, imports: List[str]) -> Tuple[str, List[str]]: classes = (Stream(imports).map(_keep_only_classes_portion_of_import_line). map(_extract_classes).flat().filter(_empty_class_name).toList()) return (file, classes)
def find_imported_packages_in_imports( file: str, imports: List[str]) -> Tuple[str, List[str]]: packages = (Stream(imports).map(_keep_only_packages_portion_of_import_line ).map(_extract_package).toList()) return (file, packages)
def remove_unused_whitespace(text: str) -> str: return "\n".join(Stream(" ".join(Stream(text.split(" ")).filter(lambda x: x != "").toList()) \ .split("\n")).filter(lambda x: x != "").toList())