PCART  v1.4
Automated Repair of Python API Parameter Compatibility Issues
pcresolveBridge.py
Go to the documentation of this file.
1 
13 
14 try:
15  from pcresolve import analyze_project as _pcresolveAnalyze
16 except ImportError:
17  _pcresolveAnalyze = None
18 
19 _analysisCache = {}
20 _lookupCache = {}
21 
22 
23 
24 
25 
40 def buildCallsiteLookup(projPath, libName):
41  global _analysisCache, _lookupCache
42  cacheKey = (projPath, libName)
43  if cacheKey in _lookupCache:
44  return _lookupCache[cacheKey]
45 
46  if _pcresolveAnalyze is None:
47  _lookupCache[cacheKey] = {}
48  return _lookupCache[cacheKey]
49 
50  # Two-layer cache: raw analysis (projPath) → filtered lookup (projPath, libName)
51  # 双层缓存:原始分析(projPath)→ 过滤查找(projPath, libName)
52  if projPath in _analysisCache:
53  result = _analysisCache[projPath]
54  else:
55  try:
56  result = _pcresolveAnalyze(projPath)
57  except Exception:
58  _analysisCache[projPath] = None
59  _lookupCache[cacheKey] = {}
60  return _lookupCache[cacheKey]
61  _analysisCache[projPath] = result
62 
63  if result is None:
64  _lookupCache[cacheKey] = {}
65  return _lookupCache[cacheKey]
66 
67  # Seed empty entries for every file PCResolve analyzed, so that
68  # "0 target calls" is distinguishable from "not analyzed" in
69  # getCallFunction — avoids falling back to the old extractor for
70  # files that PCResolve already determined have no target library calls.
71  # 为所有已分析的文件初始化空记录,"0调用"与"未分析"可由getCallFunction
72  # 区分——避免对PCResolve已判无目标库调用的文件回退到旧提取器。
73  lookup = {}
74  for fileResult in result.files:
75  lookup[fileResult.file_path] = {}
76 
77  for call in result.all_api_calls:
78  if not _matchesLibname(call, libName):
79  continue
80 
81  record = _convertApiCall(call, projPath)
82  key = call.file_path
83  if key not in lookup:
84  lookup[key] = {}
85  lookup[key][record['id']] = record
86 
87  # Sort by source position within each file, matching getCallFunction ordering
88  # 在每个文件内按源码位置排序,与getCallFunction排序一致
89  for filePath in lookup:
90  lookup[filePath] = dict(sorted(lookup[filePath].items(),key=lambda kv: (kv[1]['lineno'], kv[1]['col_offset'])))
91 
92  _lookupCache[cacheKey] = lookup
93  return lookup
94 
95 
96 
97 
105 def _resetCache():
106  global _analysisCache, _lookupCache
107  _analysisCache = {}
108  _lookupCache = {}
109 
110 
111 
112 
129 def _convertApiCall(callObj, projPath):
130  from Tool.callsite import makeCallsiteRecord
131 
132  resolved = callObj.resolved_func or callObj.func_name or ''
133 
134  return makeCallsiteRecord(file_path=callObj.file_path,call_text=callObj.expression,format_api=f"{resolved}({callObj.parameters})" if resolved else callObj.expression,parameters=callObj.parameters,lineno=callObj.lineno,col_offset=callObj.col_offset,end_lineno=callObj.end_lineno or None,end_col_offset=callObj.end_col_offset or None,proj_path=projPath)
135 
136 
137 
138 
156 def _matchesLibname(callObj, libName):
157  deco = getattr(callObj, 'decorated_by', []) or []
158  return callObj.top_library == libName or libName in deco
def makeCallsiteRecord(file_path, call_text, format_api, parameters, lineno, col_offset, end_lineno=None, end_col_offset=None, proj_path=None)
Make callsite record 构造调用点记录
Definition: callsite.py:186
def buildCallsiteLookup(projPath, libName)
Build a CallsiteRecord lookup table from PCResolve analysis 从PCResolve分析结果构建CallsiteRecord查找表