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, scope_model="v2")
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(
91  lookup[filePath].items(),
92  key=lambda kv: (kv[1]['lineno'], kv[1]['col_offset']),
93  ))
94 
95  _lookupCache[cacheKey] = lookup
96  return lookup
97 
98 
99 
100 
108 def _resetCache():
109  global _analysisCache, _lookupCache
110  _analysisCache = {}
111  _lookupCache = {}
112 
113 
114 
115 
132 def _convertApiCall(callObj, projPath):
133  from Tool.callsite import makeCallsiteRecord
134 
135  resolved = callObj.resolved_func or callObj.func_name or ''
136 
137  return makeCallsiteRecord(
138  file_path=callObj.file_path,
139  call_text=callObj.expression,
140  format_api=f"{resolved}({callObj.parameters})" if resolved else callObj.expression,
141  parameters=callObj.parameters,
142  lineno=callObj.lineno,
143  col_offset=callObj.col_offset,
144  end_lineno=callObj.end_lineno or None,
145  end_col_offset=callObj.end_col_offset or None,
146  proj_path=projPath,
147  )
148 
149 
150 
151 
169 def _matchesLibname(callObj, libName):
170  deco = getattr(callObj, 'decorated_by', []) or []
171  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:190
def buildCallsiteLookup(projPath, libName)
Build a CallsiteRecord lookup table from PCResolve analysis 从PCResolve分析结果构建CallsiteRecord查找表