1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
package server
import "core:odin/parser"
import "core:odin/ast"
import "core:odin/tokenizer"
import "core:fmt"
import "core:log"
import "core:strings"
import "core:path"
import "core:mem"
import "core:strconv"
import "core:path/filepath"
import "core:sort"
import "core:slice"
import "shared:common"
import "shared:index"
get_hover_information :: proc(document: ^Document, position: common.Position) -> (Hover, bool) {
hover := Hover {
contents = {
kind = "plaintext",
},
};
ast_context := make_ast_context(document.ast, document.imports, document.package_name, document.uri.uri);
position_context, ok := get_document_position_context(document, position, .Hover);
get_globals(document.ast, &ast_context);
if position_context.function != nil {
get_locals(document.ast, position_context.function, &ast_context, &position_context);
}
if position_context.identifier != nil {
if ident, ok := position_context.identifier.derived.(ast.Ident); ok {
if _, ok := common.keyword_map[ident.name]; ok {
hover.contents.kind = "plaintext";
hover.range = common.get_token_range(position_context.identifier^, ast_context.file.src);
return hover, true;
}
}
}
if position_context.selector != nil && position_context.identifier != nil {
hover.range = common.get_token_range(position_context.identifier^, ast_context.file.src);
ast_context.use_locals = true;
ast_context.use_globals = true;
ast_context.current_package = ast_context.document_package;
//if the base selector is the client wants to go to.
if base, ok := position_context.selector.derived.(ast.Ident); ok && position_context.identifier != nil {
ident := position_context.identifier.derived.(ast.Ident);
if ident.name == base.name {
if resolved, ok := resolve_type_identifier(&ast_context, ident); ok {
resolved.name = ident.name;
resolved.signature = get_signature(&ast_context, ident, resolved);
if is_variable, ok := ast_context.variables[ident.name]; ok && is_variable {
resolved.pkg = ast_context.document_package;
}
hover.contents = write_hover_content(&ast_context, resolved);
return hover, true;
}
}
}
selector: index.Symbol;
selector, ok = resolve_type_expression(&ast_context, position_context.selector);
if !ok {
return hover, true;
}
field: string;
if position_context.field != nil {
switch v in position_context.field.derived {
case ast.Ident:
field = v.name;
}
}
hover.range = common.get_token_range(position_context.identifier^, document.ast.src);
#partial switch v in selector.value {
case index.SymbolStructValue:
for name, i in v.names {
if strings.compare(name, field) == 0 {
if symbol, ok := resolve_type_expression(&ast_context, v.types[i]); ok {
symbol.name = name;
symbol.pkg = selector.name;
symbol.signature = index.node_to_string(v.types[i]);
hover.contents = write_hover_content(&ast_context, symbol);
return hover, true;
}
}
}
case index.SymbolPackageValue:
if position_context.field != nil {
if ident, ok := position_context.field.derived.(ast.Ident); ok {
ast_context.current_package = selector.pkg;
if symbol, ok := resolve_type_identifier(&ast_context, ident); ok {
hover.contents = write_hover_content(&ast_context, symbol);
return hover, true;
}
}
}
}
} else if position_context.identifier != nil {
ast_context.use_locals = true;
ast_context.use_globals = true;
ast_context.current_package = ast_context.document_package;
ident := position_context.identifier.derived.(ast.Ident);
hover.range = common.get_token_range(position_context.identifier^, document.ast.src);
if resolved, ok := resolve_type_identifier(&ast_context, ident); ok {
resolved.name = ident.name;
resolved.signature = get_signature(&ast_context, ident, resolved);
if is_variable, ok := ast_context.variables[ident.name]; ok && is_variable {
resolved.pkg = ast_context.document_package;
}
hover.contents = write_hover_content(&ast_context, resolved);
return hover, true;
}
}
return hover, true;
}
|