Skip to content

Commit 1766b62

Browse files
committed
fix(affected.py): Fix detection when argument names don't match
1 parent dad7311 commit 1766b62

File tree

1 file changed

+76
-3
lines changed

1 file changed

+76
-3
lines changed

.github/scripts/get_affected.py

Lines changed: 76 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,80 @@ def detect_universal_ctags() -> bool:
222222
except Exception:
223223
return False
224224

225+
def normalize_function_signature(signature: str) -> str:
226+
"""
227+
Normalize a function signature by removing parameter names, keeping only types.
228+
229+
This handles cases where header declarations and implementations have different parameter names.
230+
Uses a simple heuristic: the last word in each parameter is typically the parameter name.
231+
232+
For example:
233+
- "ltoa(long val, char *s, int radix)" -> "ltoa(long,char *,int)"
234+
- "ltoa(long value, char *result, int base)" -> "ltoa(long,char *,int)"
235+
236+
Args:
237+
signature: The function signature string, e.g., "(long val, char *s, int radix)"
238+
239+
Returns:
240+
Normalized signature with parameter names removed, e.g., "(long,char *,int)"
241+
"""
242+
if not signature:
243+
return signature
244+
245+
# Normalize signatures: treat (void) and () as equivalent (both mean no parameters)
246+
if signature == "(void)":
247+
return "()"
248+
249+
if not (signature.startswith("(") and signature.endswith(")")):
250+
return signature
251+
252+
# Handle const qualifier at the end (e.g., "(int i) const")
253+
const_qualifier = ""
254+
if signature.endswith(" const"):
255+
signature = signature[:-6] # Remove " const"
256+
const_qualifier = " const"
257+
258+
# Extract parameter list without parentheses
259+
param_list = signature[1:-1]
260+
if not param_list.strip():
261+
return "()" + const_qualifier
262+
263+
# Split by comma and process each parameter
264+
params = []
265+
for param in param_list.split(","):
266+
param = param.strip()
267+
if not param:
268+
continue
269+
270+
# Handle default parameters (e.g., "int x = 5")
271+
if "=" in param:
272+
param = param.split("=")[0].strip()
273+
274+
# Simple heuristic: remove the last word (parameter name)
275+
# This works for most cases: "int x" -> "int", "char *ptr" -> "char *"
276+
tokens = param.split()
277+
if len(tokens) > 1:
278+
# Check if the last token starts with * (like *ptr) - this is a pointer parameter name
279+
if tokens[-1].startswith('*'):
280+
# Remove the last token and add * to the type
281+
type_tokens = tokens[:-1] + ['*']
282+
params.append(" ".join(type_tokens))
283+
else:
284+
# Remove the last token (parameter name)
285+
type_tokens = tokens[:-1]
286+
params.append(" ".join(type_tokens))
287+
else:
288+
# Single word - could be a type or parameter name
289+
# In C/C++, single-word parameters are rare, so we assume it's a type
290+
# This handles both basic types (int, char) and typedefs (MACType, boolean)
291+
params.append(tokens[0])
292+
293+
result = "(" + ",".join(params) + ")"
294+
if const_qualifier:
295+
result += const_qualifier
296+
297+
return result
298+
225299
def build_qname_from_tag(tag: dict) -> str:
226300
"""
227301
Compose a qualified name for a function/method using scope + name + signature.
@@ -231,9 +305,8 @@ def build_qname_from_tag(tag: dict) -> str:
231305
name = tag.get("name") or ""
232306
signature = tag.get("signature") or ""
233307

234-
# Normalize signatures: treat (void) and () as equivalent (both mean no parameters)
235-
if signature == "(void)":
236-
signature = "()"
308+
# Normalize the signature to remove parameter names
309+
signature = normalize_function_signature(signature)
237310

238311
qparts = []
239312
if scope:

0 commit comments

Comments
 (0)