Skip to content
← Back

src/semantic/name_display.ghul

1
namespace Semantic is
2
use Symbols.Symbol;
3
4
// Decides the scope that symbol names render relative to. By default
5
// that is the scope currently being compiled (read on demand from the
6
// symbol table, so it stays correct however the scope stack is
7
// unwound), which is why a diagnostic reads relative to where it is
8
// reported. An override replaces that default for the duration of a
9
// language-service render (targeting the cursor's scope) or a region
10
// that needs scope-independent output (`with_scope(null)` forces fully
11
// qualified names, e.g. for a canonical ordering).
12
class NAME_DISPLAY is
13
_override_scope: Scope?;
14
_has_override: bool;
15
16
init() is
17
si
18
19
render_scope: Scope? =>
20
if _has_override then
21
_override_scope;
22
else
23
_current_build_scope;
24
fi;
25
26
_current_build_scope: Scope? is
27
let symbol_table = IoC.CONTAINER.instance.symbol_table;
28
29
return symbol_table.current_scope;
30
si
31
32
name_for(symbol: Symbol) -> string =>
33
symbol.render_name(render_scope);
34
35
// The scope-relative name without its type-argument suffix — for
36
// rendering a constructed generic's head, which then appends its own
37
// actual arguments.
38
bare_name_for(symbol: Symbol) -> string =>
39
symbol._render_scope_relative_name(render_scope);
40
41
// Render relative to `scope` (null forces fully qualified) until the
42
// returned holder is disposed. Consume with `let use` so the
43
// previous render scope is restored on every exit path, including
44
// when rendering throws.
45
with_scope(scope: Scope?) -> RENDER_SCOPE_HOLDER is
46
let holder = RENDER_SCOPE_HOLDER(self, _override_scope, _has_override);
47
48
_override_scope = scope;
49
_has_override = true;
50
51
return holder;
52
si
53
54
restore_override(scope: Scope?, has_override: bool) is
55
_override_scope = scope;
56
_has_override = has_override;
57
si
58
si
59
60
struct RENDER_SCOPE_HOLDER: Disposable is
61
_display: NAME_DISPLAY?;
62
_previous_scope: Scope?;
63
_previous_has_override: bool;
64
65
init(display: NAME_DISPLAY, previous_scope: Scope?, previous_has_override: bool) is
66
_display = display;
67
_previous_scope = previous_scope;
68
_previous_has_override = previous_has_override;
69
si
70
71
dispose() is
72
// A value-type disposable must be safe on its default value:
73
// `let use` disposal null-checks reference types before calling
74
// dispose but not value types, so an early return past the
75
// `let use` hands dispose a zero-initialized holder. A null
76
// display means the holder was never constructed and so set no
77
// override to restore.
78
let display = _display;
79
80
if display? then
81
display.restore_override(_previous_scope, _previous_has_override);
82
fi
83
si
84
si
85
si