Appearance
| 1 | namespace Semantic is | |
| 2 | use IO.Std; | |
| 3 | ||
| 4 | use Source; | |
| 5 | ||
| 6 | trait SymbolDefinitionListener is | |
| 7 | add_symbol_definition(location: LOCATION, symbol: Symbols.Symbol); | |
| 8 | si | |
| 9 | ||
| 10 | class SYMBOL_DEFINITION_LOCATIONS(_symbol_use_listener: SymbolUseListener): SymbolDefinitionListener is | |
| 11 | ||
| 12 | _symbol_definition_map: Collections.MAP[string,Collections.LIST[Symbols.Symbol]]; | |
| 13 | _workspace_definition_map: Collections.MAP[string,Collections.LIST[Symbols.Symbol]]; | |
| 14 | ||
| 15 | init(..) is | |
| 16 | clear(); | |
| 17 | si | |
| 18 | ||
| 19 | dump_counts() is | |
| 20 | Std.error.write_line("symbol definition map: {_symbol_definition_map.count}"); | |
| 21 | Std.error.write_line("workspace definition map: {_workspace_definition_map.count}"); | |
| 22 | si | |
| 23 | ||
| 24 | clear() is | |
| 25 | _symbol_definition_map = Collections.MAP[string,Collections.LIST[Symbols.Symbol]](); | |
| 26 | _workspace_definition_map = Collections.MAP[string,Collections.LIST[Symbols.Symbol]](); | |
| 27 | si | |
| 28 | ||
| 29 | add_symbol_definition(location: LOCATION, symbol: Symbols.Symbol) is | |
| 30 | get_symbol_list_for_file_name(location.file_name).add(symbol); | |
| 31 | ||
| 32 | if !symbol.is_internal then | |
| 33 | _symbol_use_listener.add_symbol_use(location, symbol); | |
| 34 | fi | |
| 35 | si | |
| 36 | ||
| 37 | // Reconcile one file's recorded definitions after an | |
| 38 | // interface-preserving incremental EDIT, before the body re-walk | |
| 39 | // re-declares its bodies. The body-local definitions are dropped — | |
| 40 | // the re-walk re-records them — and the interface definitions are | |
| 41 | // kept (the re-walk does not re-declare the interface; the | |
| 42 | // interface symbols' own locations are refreshed by | |
| 43 | // SYMBOL_USE_LOCATIONS.refresh_edited_file). The derived workspace | |
| 44 | // list is discarded so it rebuilds on next query. | |
| 45 | refresh_edited_file(file_name: string, body_spans: Source.BODY_SPANS) is | |
| 46 | if _symbol_definition_map.contains_key(file_name) then | |
| 47 | let kept = Collections.LIST[Symbols.Symbol](); | |
| 48 | ||
| 49 | for symbol in _symbol_definition_map[file_name] do | |
| 50 | if !body_spans.contains(symbol.location.start) then | |
| 51 | kept.add(symbol); | |
| 52 | fi | |
| 53 | od | |
| 54 | ||
| 55 | _symbol_definition_map[file_name] = kept; | |
| 56 | fi | |
| 57 | ||
| 58 | _workspace_definition_map.remove(file_name); | |
| 59 | si | |
| 60 | ||
| 61 | find_definitions_from_file(file_name: string, workspace_search: bool) -> Collections.Iterable[Symbols.Symbol] => | |
| 62 | if workspace_search then | |
| 63 | get_workspace_list_for_file_name(file_name); | |
| 64 | else | |
| 65 | get_symbol_list_for_file_name(file_name); | |
| 66 | fi; | |
| 67 | ||
| 68 | // True iff at least one definition is recorded for the file — | |
| 69 | // distinguishes "this file was already compiled and genuinely | |
| 70 | // has no visible definitions" from "no compile has run yet". | |
| 71 | // `get_symbol_list_for_file_name` lazily creates an empty list, | |
| 72 | // so `contains_key` after-the-fact isn't a safe test; check | |
| 73 | // count instead. | |
| 74 | has_definitions_for(file_name: string) -> bool => | |
| 75 | _symbol_definition_map.contains_key(file_name) /\ _symbol_definition_map[file_name].count > 0; | |
| 76 | ||
| 77 | get_symbol_list_for_file_name(file_name: string) -> Collections.LIST[Symbols.Symbol] is | |
| 78 | if _symbol_definition_map.contains_key(file_name) then | |
| 79 | return _symbol_definition_map[file_name]; | |
| 80 | fi | |
| 81 | ||
| 82 | let result = Collections.LIST[Symbols.Symbol](); | |
| 83 | ||
| 84 | _symbol_definition_map[file_name] = result; | |
| 85 | ||
| 86 | return result; | |
| 87 | si | |
| 88 | ||
| 89 | get_workspace_list_for_file_name(file_name: string) -> Collections.LIST[Symbols.Symbol] is | |
| 90 | if _workspace_definition_map.contains_key(file_name) then | |
| 91 | return _workspace_definition_map[file_name]; | |
| 92 | fi | |
| 93 | ||
| 94 | let result = Collections.LIST[Symbols.Symbol](); | |
| 95 | ||
| 96 | _workspace_definition_map[file_name] = result; | |
| 97 | ||
| 98 | for symbol in get_symbol_list_for_file_name(file_name) do | |
| 99 | if symbol.is_workspace_visible then | |
| 100 | result.add(symbol); | |
| 101 | fi | |
| 102 | od | |
| 103 | ||
| 104 | return result; | |
| 105 | si | |
| 106 | si | |
| 107 | si |