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 5import json 6import subprocess 7 8cached_functions = {} 9 10 11def getMetricsJson(src_url): 12 if src_url.startswith("http"): 13 print("Fetching source for function extraction: {}".format(src_url)) 14 metrics = subprocess.check_output(["./fetch_fn_names.sh", src_url]) 15 else: 16 print("Skip fetching source: {}".format(src_url)) 17 metrics = "" 18 19 try: 20 return json.loads(metrics) 21 except ValueError: 22 return {"kind": "empty", "name": "anonymous", "spaces": []} 23 24 25def getSpaceFunctionsRecursive(metrics_space): 26 functions = [] 27 if ( 28 metrics_space["kind"] == "function" 29 and metrics_space["name"] 30 and metrics_space["name"] != "<anonymous>" 31 ): 32 functions.append( 33 { 34 "name": metrics_space["name"], 35 "start_line": int(metrics_space["start_line"]), 36 "end_line": int(metrics_space["end_line"]), 37 } 38 ) 39 for space in metrics_space["spaces"]: 40 functions += getSpaceFunctionsRecursive(space) 41 return functions 42 43 44def getSourceFunctions(src_url): 45 if src_url not in cached_functions: 46 metrics_space = getMetricsJson(src_url) 47 cached_functions[src_url] = getSpaceFunctionsRecursive(metrics_space) 48 49 return cached_functions[src_url] 50 51 52def getFunctionName(location): 53 location.replace("annotate", "raw-file") 54 pieces = location.split("#l") 55 src_url = pieces[0] 56 line = int(pieces[1]) 57 closest_name = "<Unknown {}>".format(line) 58 closest_start = 0 59 functions = getSourceFunctions(src_url) 60 for fn in functions: 61 if ( 62 fn["start_line"] > closest_start 63 and line >= fn["start_line"] 64 and line <= fn["end_line"] 65 ): 66 closest_start = fn["start_line"] 67 closest_name = fn["name"] 68 return closest_name 69