Source code for champollion.parser.js_function

# :coding: utf-8

import re

from .helper import filter_comments
from .helper import collapse_all
from .helper import get_docstring


#: Regular Expression pattern for function expressions
_FUNCTION_PATTERN = re.compile(
    r"(?P<start_regex>(\n|^)) *(?P<export>export +)?(?P<default>default +)?"
    r"((const|var|let) (?P<data_name>[\w_-]+) *= *)?"
    r"function *(?P<generator>\* *)?(?P<function_name>[\w_-]+)? "
    r"*\([\n ]*(?P<arguments>.*?)[\n ]*\) *{",
    re.DOTALL
)

#: Regular Expression pattern for arrow functions
_FUNCTION_ARROW_PATTERN = re.compile(
    r"(?P<start_regex>(\n|^)) *(?P<export>export +)?(?P<default>default +)?"
    r"(const|let|var) (?P<function_name>\w+) *= *"
    r"(\([\n ]*(?P<arguments>.*?)[\n ]*\)|(?P<single_argument>[\w._-]+)) *"
    r"=> *",
    re.DOTALL
)

#: Regular Expression pattern for imported functions
_IMPORTED_FUNCTION_PATTERN = re.compile(
    r"(?P<start_regex>(\n|^)) *(?P<export>export +)?(?P<default>default +)?"
    r"(?P<function_name>[\w_-]+)? *\([\n ]*(?P<arguments>.*?)[\n ]*\);?",
    re.DOTALL
)


[docs]def fetch_environment(content, module_id): """Return function environment dictionary from *content*. *module_id* represent the identifier of the module. The environment is in the form of:: { "moduleName.doSomething": { "id": "moduleName.doSomething", "module_id": "moduleName", "exported": False, "default": False, "name": "doSomething", "anonymous": False, "generator": False, "arguments": ["argument1", "argument2"], "line_number": 2, "description": "Function doc.\\n\\nDetailed description." } } """ environment = {} lines = content.split("\n") content = filter_comments(content) content = collapse_all(content)[0] for match_iter in ( _FUNCTION_ARROW_PATTERN.finditer(content), _FUNCTION_PATTERN.finditer(content), _IMPORTED_FUNCTION_PATTERN.finditer(content), ): for match in match_iter: name = match.group("function_name") # In case of anonymous functions, do not allow the imported # function pattern to confuse the 'function' statement with # the name. if name == "function": continue if "data_name" in match.groupdict().keys(): _name = match.group("data_name") if _name is not None: name = _name generator = False if "generator" in match.groupdict().keys(): generator = match.group("generator") is not None if name is None: name = "__ANONYMOUS_FUNCTION__" function_id = ".".join([module_id, name]) line_number = ( content[:match.start()].count("\n") + match.group("start_regex").count("\n") + 1 ) arguments_matched = match.group("arguments") if arguments_matched is None: arguments_matched = match.group("single_argument") arguments = list(filter(lambda x: len(x), [ arg.strip() for arg in arguments_matched.split(",") ])) function_environment = { "id": function_id, "module_id": module_id, "exported": match.group("export") is not None, "default": match.group("default") is not None, "name": name, "anonymous": name == "__ANONYMOUS_FUNCTION__", "generator": generator, "arguments": arguments, "line_number": line_number, "description": get_docstring(line_number, lines) } environment[function_id] = function_environment return environment