aboutsummaryrefslogtreecommitdiff
path: root/src/server/diagnostics.odin
blob: 821aa74419ca8c3f8394b3adacdeed316e9eff89 (plain)
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
package server

import "core:log"
import "core:slice"
import "core:strings"

DiagnosticType :: enum {
	Syntax,
	Unused,
	Check,
}

diagnostics: [DiagnosticType]map[string][dynamic]Diagnostic

add_diagnostics :: proc(type: DiagnosticType, uri: string, diagnostic: Diagnostic) {
	diagnostic_type := &diagnostics[type]

	if diagnostic_type == nil {
		log.errorf("Diagnostic type did not exist: %v", type)
		return
	}

	uri := uri

	when ODIN_OS == .Windows {
		uri = strings.to_lower(uri, context.temp_allocator)
	}

	diagnostic_array := &diagnostic_type[uri]

	if diagnostic_array == nil {
		diagnostic_type[strings.clone(uri)] = make([dynamic]Diagnostic)
		diagnostic_array = &diagnostic_type[uri]
	}

    diagnostic := diagnostic

    diagnostic.message = strings.clone(diagnostic.message)
    diagnostic.code = strings.clone(diagnostic.code)

    append(diagnostic_array, diagnostic)
}

remove_diagnostics :: proc(type: DiagnosticType, uri: string) {
	diagnostic_type := &diagnostics[type]

	if diagnostic_type == nil {
		log.errorf("Diagnostic type did not exist: %v", type)
		return
	}

	uri := uri

	when ODIN_OS == .Windows {
		uri = strings.to_lower(uri, context.temp_allocator)
	}

	diagnostic_array := &diagnostic_type[uri]

	if diagnostic_array == nil {
		return
	}

	for diagnostic in diagnostic_array {
		delete(diagnostic.message)
		delete(diagnostic.code)
	}

	clear(diagnostic_array)
}

clear_diagnostics :: proc(type: DiagnosticType) {
	diagnostic_type := &diagnostics[type]

	if diagnostic_type == nil {
		log.errorf("Diagnostic type did not exist: %v", type)
		return
	}

	for _, &diagnostic_array in diagnostic_type {
		for diagnostic in diagnostic_array {
			delete(diagnostic.message)
			delete(diagnostic.code)
		}
		clear(&diagnostic_array)
	}
}

push_diagnostics :: proc(writer: ^Writer) {
	merged_diagnostics := make(map[string][dynamic]Diagnostic, context.temp_allocator)

	for diagnostic_type in diagnostics {
		for k, v in diagnostic_type {
			diagnostic_array := &merged_diagnostics[k]

			if diagnostic_array == nil {
				merged_diagnostics[k] = make([dynamic]Diagnostic, context.temp_allocator)
				diagnostic_array = &merged_diagnostics[k]
			}

			append(diagnostic_array, ..v[:])
		}
	}

	for k, v in merged_diagnostics {
		//Find the unique diagnostics, since some poor profile settings make the checker check the same file multiple times
		unique := slice.unique(v[:])

		params := NotificationPublishDiagnosticsParams {
			uri         = k,
			diagnostics = unique,
		}

		notifaction := Notification {
			jsonrpc = "2.0",
			method  = "textDocument/publishDiagnostics",
			params  = params,
		}

		if writer != nil {
			send_notification(notifaction, writer)
		}
	}

}