aboutsummaryrefslogtreecommitdiff
path: root/src/server/diagnostics.odin
blob: 411ffbca1dde21b7ee11cf45a5c60d10a41cd436 (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
126
package server

import "core:log"
import "core:slice"
import "core:strings"
import "src:common"

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)
		}
	}

}