fn_anchors.py (2151B)
1 # This Source Code Form is subject to the terms of the Mozilla Public 2 # License, v. 2.0. If a copy of the MPL was not distributed with this 3 # file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 5 import json 6 import subprocess 7 from os import path 8 9 from qm_try_analysis.logging import info, warning 10 11 cached_functions = {} 12 13 14 def getMetricsJson(src_url): 15 if src_url.startswith("http"): 16 info(f"Fetching source for function extraction: {src_url}") 17 metrics = subprocess.check_output([ 18 path.join(path.dirname(path.realpath(__file__)), "fetch_fn_names.sh"), 19 src_url, 20 ]) 21 else: 22 warning(f"Skip fetching source: {src_url}") 23 metrics = "" 24 25 try: 26 return json.loads(metrics) 27 except ValueError: 28 return {"kind": "empty", "name": "anonymous", "spaces": []} 29 30 31 def getSpaceFunctionsRecursive(metrics_space): 32 functions = [] 33 if ( 34 metrics_space["kind"] == "function" 35 and metrics_space["name"] 36 and metrics_space["name"] != "<anonymous>" 37 ): 38 functions.append({ 39 "name": metrics_space["name"], 40 "start_line": int(metrics_space["start_line"]), 41 "end_line": int(metrics_space["end_line"]), 42 }) 43 for space in metrics_space["spaces"]: 44 functions += getSpaceFunctionsRecursive(space) 45 return functions 46 47 48 def getSourceFunctions(src_url): 49 if src_url not in cached_functions: 50 metrics_space = getMetricsJson(src_url) 51 cached_functions[src_url] = getSpaceFunctionsRecursive(metrics_space) 52 53 return cached_functions[src_url] 54 55 56 def getFunctionName(location): 57 location.replace("annotate", "raw-file") 58 pieces = location.split("#l") 59 src_url = pieces[0] 60 line = int(pieces[1]) 61 closest_name = f"<Unknown {line}>" 62 closest_start = 0 63 functions = getSourceFunctions(src_url) 64 for fn in functions: 65 if ( 66 fn["start_line"] > closest_start 67 and line >= fn["start_line"] 68 and line <= fn["end_line"] 69 ): 70 closest_start = fn["start_line"] 71 closest_name = fn["name"] 72 return closest_name