Skip to content
← Back

src/semantic/symbol_definition_locations.ghul

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