Skip to content
← Back

src/semantic/name_display.ghul

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