@@ -872,6 +872,68 @@ def _add_to_tree(node, top):
872
872
)
873
873
874
874
875
+ def _get_force_info (sym ):
876
+ # Returns a string indicating what's forcing a symbol's value, or None
877
+ # if the value is not being forced by select/imply.
878
+ #
879
+ # Example return values:
880
+ # " [selected by FOO]"
881
+ # " [implied by BAR, BAZ]"
882
+
883
+ if sym .orig_type not in (BOOL , TRISTATE ):
884
+ return None
885
+
886
+ origin = sym .origin
887
+ if not origin :
888
+ return None
889
+
890
+ kind , sources = origin
891
+ if kind not in ("select" , "imply" ) or not sources :
892
+ return None
893
+
894
+ # Format the force info string
895
+ prefix = "selected by" if kind == "select" else "implied by"
896
+ sym_names = _extract_controlling_symbols (sources )
897
+
898
+ if not sym_names :
899
+ return None
900
+
901
+ # Show up to 2 symbols to keep line length reasonable
902
+ if len (sym_names ) <= 2 :
903
+ return " [{} {}]" .format (prefix , ", " .join (sym_names ))
904
+
905
+ return " [{} {}, +{}]" .format (prefix , ", " .join (sym_names [:2 ]), len (sym_names ) - 2 )
906
+
907
+
908
+ def _extract_controlling_symbols (expr_list ):
909
+ # Extracts the primary controlling symbol from each expression string
910
+ # Returns a list of unique symbol names
911
+ #
912
+ # For "A && B", extracts "A" (the symbol doing the select/imply)
913
+ # For "A || B", extracts both "A" and "B"
914
+ # For simple "A", extracts "A"
915
+ #
916
+ # This avoids showing condition symbols as if they're doing the select/imply
917
+
918
+ sym_names = []
919
+ for expr in expr_list :
920
+ # Split on && first - we only want symbols before &&
921
+ # For "FOO && BAR", we want FOO (the selector), not BAR (the condition)
922
+ and_idx = expr .find (" && " )
923
+ primary = expr [:and_idx ].strip () if and_idx != - 1 else expr .strip ()
924
+
925
+ # Now handle || - all parts are equal
926
+ if " || " in primary :
927
+ for part in primary .split (" || " ):
928
+ part = part .strip ()
929
+ if part and part not in sym_names :
930
+ sym_names .append (part )
931
+ elif primary and primary not in sym_names :
932
+ sym_names .append (primary )
933
+
934
+ return sym_names
935
+
936
+
875
937
def _node_str (node ):
876
938
# Returns the string shown to the right of the image (if any) for the node
877
939
@@ -895,6 +957,11 @@ def _node_str(node):
895
957
896
958
s += " (NEW)"
897
959
960
+ # Show what's controlling this symbol if it's selected/implied
961
+ force_info = _get_force_info (sym )
962
+ if force_info :
963
+ s += force_info
964
+
898
965
elif isinstance (node .item , Symbol ):
899
966
# Symbol without prompt (can show up in show-all)
900
967
s = "<{}>" .format (node .item .name )
@@ -2216,10 +2283,27 @@ def _value_info(sym):
2216
2283
# Returns a string showing 'sym's value
2217
2284
2218
2285
# Only put quotes around the value for string symbols
2219
- return "Value: {}\n " .format (
2286
+ s = "Value: {}\n " .format (
2220
2287
'"{}"' .format (sym .str_value ) if sym .orig_type == STRING else sym .str_value
2221
2288
)
2222
2289
2290
+ # Add origin information to explain where the value comes from
2291
+ origin = sym .origin
2292
+ if origin :
2293
+ kind , sources = origin
2294
+ if kind == "select" :
2295
+ if sources :
2296
+ s += " (selected by: {})\n " .format (", " .join (sources ))
2297
+ elif kind == "imply" :
2298
+ if sources :
2299
+ s += " (implied by: {})\n " .format (", " .join (sources ))
2300
+ elif kind == "default" :
2301
+ s += " (from default)\n "
2302
+ elif kind == "assign" :
2303
+ s += " (user assigned)\n "
2304
+
2305
+ return s
2306
+
2223
2307
2224
2308
def _choice_syms_info (choice ):
2225
2309
# Returns a string listing the choice symbols in 'choice'. Adds
0 commit comments