From 1bfa60872976735066ef07dfa44c378d72b21d9f Mon Sep 17 00:00:00 2001 From: Eugene Mikhantyev Date: Sun, 15 Mar 2026 11:06:08 +0000 Subject: [PATCH] fix: apply unannotated-reference fix to find_unconnected_pins and get_elements_in_region The same reference-lookup bug fixed in check_wire_collisions (where PinLocator.get_all_symbol_pins always resolves to the first symbol with a given reference) also affected: - find_unconnected_pins: would check wrong pin positions for all unannotated components after the first, producing false connected/ unconnected reports. - get_elements_in_region: would return wrong pin coordinates for unannotated components in the queried region. Both now use _compute_pin_positions_direct (fetching pin defs by lib_id and applying each symbol's own position/rotation/mirror), matching the fix already applied to check_wire_collisions. Co-Authored-By: Claude Sonnet 4.6 --- python/commands/schematic_analysis.py | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/python/commands/schematic_analysis.py b/python/commands/schematic_analysis.py index 9d91730..b8a3b82 100644 --- a/python/commands/schematic_analysis.py +++ b/python/commands/schematic_analysis.py @@ -293,11 +293,13 @@ def find_unconnected_pins(schematic_path: Path) -> List[Dict[str, Any]]: if sym["is_power"] or ref.startswith("_TEMPLATE") or not ref: continue - pin_positions = locator.get_all_symbol_pins(schematic_path, ref) - if not pin_positions: + pin_defs = locator.get_symbol_pins(schematic_path, sym["lib_id"]) + if not pin_defs: continue - pin_defs = None + pin_positions = _compute_pin_positions_direct(sym, pin_defs) + if not pin_positions: + continue for pin_num, pos in pin_positions.items(): px, py = pos[0], pos[1] @@ -307,9 +309,6 @@ def find_unconnected_pins(schematic_path: Path) -> List[Dict[str, Any]]: if is_connected(px, py): continue - if pin_defs is None: - pin_defs = locator.get_symbol_pins(schematic_path, sym["lib_id"]) - pin_name = pin_defs.get(pin_num, {}).get("name", pin_num) unconnected.append({ "reference": ref, @@ -482,13 +481,15 @@ def get_elements_in_region( "position": {"x": sym["x"], "y": sym["y"]}, "isPower": sym["is_power"], } - # Include pin positions - pin_positions = locator.get_all_symbol_pins(schematic_path, sym["reference"]) - if pin_positions: - entry["pins"] = { - pn: {"x": round(pos[0], 4), "y": round(pos[1], 4)} - for pn, pos in pin_positions.items() - } + # Include pin positions (compute directly to handle unannotated duplicates) + pin_defs = locator.get_symbol_pins(schematic_path, sym["lib_id"]) + if pin_defs: + pin_positions = _compute_pin_positions_direct(sym, pin_defs) + if pin_positions: + entry["pins"] = { + pn: {"x": round(pos[0], 4), "y": round(pos[1], 4)} + for pn, pos in pin_positions.items() + } region_symbols.append(entry) # Wires: include if ANY endpoint is within bounds