diff --git a/lib/python/mbutils.py b/lib/python/mbutils.py index 40cc1b5..955bc27 100644 --- a/lib/python/mbutils.py +++ b/lib/python/mbutils.py @@ -23,216 +23,3 @@ def find_root(filename, starting_dir=None): raise IOError('File not found in any directory') else: return find_root(filename, path.dirname(starting_dir)) - -def _parse_composer_manifest(path): - '''Parse composer.json into dict''' - with open(path, 'r') as composer_file: - manifest = json.load(composer_file) - return manifest - -def _get_package_name(manifest): - '''Return the name field from composer.json.''' - try: - return manifest['name'] - except KeyError: - return 'foo/bar' - -def _get_all_autoloaders(manifest): - '''Combine all PSR-0 and PSR-4 autoloaders''' - autoloaders = dict() - - for type in ['psr-0', 'psr-4']: - autoloaders.update(_get_autoloaders_by_type(manifest, type)) - - return dict((p, ns) for (ns, p) in autoloaders.items()) - -def _get_autoloaders_by_type(manifest, type): - '''Get one kind of autoloader''' - try: - return manifest['autoload'][type] - except KeyError: - return dict() - -def match_path(autoloaders, dirname): - '''Find namespace for a given path''' - prefixes = sorted(autoloaders.keys(), key=len) - - try: - prefix = next(p for p in prefixes if dirname.startswith(p)) - namespace = autoloaders[prefix] - remainder = dirname.replace(prefix, '', 1) - except StopIteration: - namespace = '' - remainder = dirname - - return (namespace, remainder) - -def convert_path(dirname): - '''Naively convert path to namespace''' - return dirname.replace('/', '\\') - -def get_namespace(dirname): - '''Convert dirname into namespace intelligently.''' - try: - composer_json = find_in_parent('composer.json', dirname) - except IOError: - return None - composer_manifest = _parse_composer_manifest(composer_json) - repo_root = path.dirname(composer_json) - relative_path = path.relpath(dirname, repo_root) - - autoloaders = _get_all_autoloaders(composer_manifest) - - (namespace, remainder) = match_path(autoloaders, relative_path) - - return namespace + convert_path(remainder) - -def get_package_name(dirname): - '''Find package name from current location.''' - try: - composer_json = find_in_parent('composer.json', dirname) - except IOError: - return 'foo/bar' - composer_manifest = _parse_composer_manifest(composer_json) - name = _get_package_name(composer_manifest) - return name - -def prepare_arguments(param_tags): - arguments = generate_arguments(param_tags) - -def add_argument(snip): - '''Search for the next argument list, and insert one. - - These arguments will be of the form - - TypeName $variableName - - and will come from the body the @param snippet: - - * @param Typename $variableName Description - ''' - buffer = snip.buffer - param_line_number = snip.snippet_start[0] - param_line = buffer[param_line_number] - try: - argument_line_number = find_argument_line_number(param_line_number, buffer) - except IndexError: - return - argument_line = buffer[argument_line_number] - argument = get_argument_line(param_line) - new_argument_line = insert_argument(argument, argument_line) - buffer[argument_line_number] = new_argument_line - -def insert_argument(arg, line): - insert_point = line.find(')') - - # No arguments yet, so no comma - if line[insert_point - 1] is '(': - return line[:insert_point] + arg + line[insert_point:] - else: - return line[:insert_point] + ', ' + arg + line[insert_point:] - -def find_argument_line_number(start, buffer): - for line_number, line in enumerate(buffer[start:]): - if line.endswith('*/'): - return line_number + 1 + start - else: - pass - raise IndexError('Could not find end of comment and start of method') - -def format_method(snip): - '''Convert expanded snippet into method name and args.''' - params = get_params_map(snip) - - if len(params) is 0: - return - - sorted_params = sort_params(params.values()) - - delete_param_tags(snip, params) - place_to_insert_params = snip.snippet_start[0] + list(params.keys())[0] - snip.buffer[place_to_insert_params:place_to_insert_params] = sorted_params - - arguments = generate_arguments(sorted_params) - arguments[-1] = arguments[-1].replace(',', '') - args_line = snip.snippet_end[0] - 3 - snip.buffer[args_line:args_line + 1] = arguments - -def delete_param_tags(snip, params): - '''Sort @param PHPDoc tags so optional ones come later.''' - for idx, relative_line_number in enumerate(params.keys()): - # Have to subtract idx, because we are removing a line each time. - line_number = relative_line_number + snip.snippet_start[0] - idx - snip.buffer[line_number:line_number + 1] = [] - -def get_params_map(snip): - '''Get a map of @param PHPDoc tags, line_number: line.''' - lines = get_snippet_lines(snip) - return OrderedDict([[k, v] for k, v in enumerate(lines) if '@param' in v]) - -def generate_arguments(params): - '''Generate the function arguments from PHPDoc @params.''' - return [get_argument_line(x) for x in params] - -def sort_params(params): - '''Sort params to put optional arguments at the end.''' - def sorter(left, right): - [left_is_optional, right_is_optional] = \ - [is_union_with_null(x) for x in [left, right]] - - if (left_is_optional and not right_is_optional): - return 1 - if (not left_is_optional and right_is_optional): - return -1 - - return 0 - - return sorted(params, key=cmp_to_key(sorter)) - -def get_snippet_lines(snip): - '''Get the relevant slice of a snippet buffer.''' - start_line = snip.snippet_start[0] - finish_line = snip.snippet_end[0] - return snip.buffer[start_line:finish_line] - -def get_argument_line(param): - '''Convert line from @param tag to method parameter.''' - expression = '\s*\*\s+@param\s+([^\s]+)\s+(\$[^\s]+).*' - result = re.search(expression, param) - - type = map_type(result.group(1)) - name = result.group(2) - - return format_argument_line(type, name) - -def map_type(type): - '''Convert PHPDoc type declaration into a PHP type hint.''' - if (is_union_with_null(type)): - return map_type(type.replace('|null', '')) - if (is_union_type(type)): - # PHP doesn't support union type hints yet. - return None - if (is_array_type(type)): - # PHP doesn't have complex generics yet. - return 'array' - # A plain type - return type - -def is_union_with_null(type): - '''Test if PHPDoc type has a null option.''' - return '|null' in type - -def is_union_type(type): - '''Test if PHPDoc type is any kind of union.''' - return '|' in type - -def is_array_type(type): - '''Test if PHPDoc type is an array...''' - return '[]' in type - -def format_argument_line(type, name): - if (type is None): - return name - else: - return '{} {}'.format(type, name) -