diff options
Diffstat (limited to 'src/server')
| -rw-r--r-- | src/server/action.odin | 2 | ||||
| -rw-r--r-- | src/server/check.odin | 89 | ||||
| -rw-r--r-- | src/server/diagnostics.odin | 126 | ||||
| -rw-r--r-- | src/server/documents.odin | 52 | ||||
| -rw-r--r-- | src/server/requests.odin | 14 |
5 files changed, 181 insertions, 102 deletions
diff --git a/src/server/action.odin b/src/server/action.odin index 058ea21..d1608b5 100644 --- a/src/server/action.odin +++ b/src/server/action.odin @@ -108,8 +108,6 @@ remove_unused_imports :: proc( append(&textEdits, import_edit) } - log.error(textEdits[:]) - workspaceEdit: WorkspaceEdit workspaceEdit.changes = make(map[string][]TextEdit, 0, context.temp_allocator) workspaceEdit.changes[uri] = textEdits[:] diff --git a/src/server/check.odin b/src/server/check.odin index b8f0c7c..5b8f2a1 100644 --- a/src/server/check.odin +++ b/src/server/check.odin @@ -19,9 +19,6 @@ import "core:thread" import "src:common" -//Store uris we have reported on since last save. We use this to clear them on next save. -uris_reported: [dynamic]string - Json_Error :: struct { type: string, pos: Json_Type_Error, @@ -68,7 +65,33 @@ fallback_find_odin_directories :: proc(config: ^common.Config) -> []string { return data[:] } -check :: proc(paths: []string, uri: common.Uri, writer: ^Writer, config: ^common.Config) { +check_unused_imports :: proc(document: ^Document, config: ^common.Config) { + if !config.enable_unused_imports_reporting { + return + } + + diagnostics := make([dynamic]Diagnostic, context.temp_allocator) + + unused_imports := find_unused_imports(document, context.temp_allocator) + + remove_diagnostics(.Unused, document.uri.uri) + + for imp in unused_imports { + add_diagnostics( + .Unused, + document.uri.uri, + Diagnostic { + range = common.get_token_range(imp.import_decl, document.ast.src), + severity = DiagnosticSeverity.Hint, + code = "Unused", + message = "unused import", + tags = {.Unnecessary}, + }, + ) + } +} + +check :: proc(paths: []string, uri: common.Uri, config: ^common.Config) { paths := paths if len(paths) == 0 { @@ -138,6 +161,8 @@ check :: proc(paths: []string, uri: common.Uri, writer: ^Writer, config: ^common log.errorf("Failed to unmarshal check results: %v, %v", res, string(buffer)) } + clear_diagnostics(.Check) + for error in json_errors.errors { if len(error.msgs) == 0 { break @@ -149,12 +174,11 @@ check :: proc(paths: []string, uri: common.Uri, writer: ^Writer, config: ^common continue } - if error.pos.file not_in errors { - errors[error.pos.file] = make([dynamic]Diagnostic, context.temp_allocator) - } + uri := common.create_uri(error.pos.file, context.temp_allocator) - append( - &errors[error.pos.file], + add_diagnostics( + .Check, + uri.uri, Diagnostic { code = "checker", severity = .Error, @@ -168,51 +192,4 @@ check :: proc(paths: []string, uri: common.Uri, writer: ^Writer, config: ^common ) } } - - for uri in uris_reported { - params := NotificationPublishDiagnosticsParams { - uri = uri, - diagnostics = {}, - } - - notification := Notification { - jsonrpc = "2.0", - method = "textDocument/publishDiagnostics", - params = params, - } - - if writer != nil { - send_notification(notification, writer) - } - - delete(uri) - } - - clear(&uris_reported) - - for k, v in errors { - uri := common.create_uri(k, context.temp_allocator) - - //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 = uri.uri, - diagnostics = unique, - } - - notifaction := Notification { - jsonrpc = "2.0", - method = "textDocument/publishDiagnostics", - params = params, - } - - append(&uris_reported, strings.clone(uri.uri)) - - if writer != nil { - send_notification(notifaction, writer) - } - } - - } diff --git a/src/server/diagnostics.odin b/src/server/diagnostics.odin new file mode 100644 index 0000000..411ffbc --- /dev/null +++ b/src/server/diagnostics.odin @@ -0,0 +1,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) + } + } + +} diff --git a/src/server/documents.odin b/src/server/documents.odin index 54d995d..70584fd 100644 --- a/src/server/documents.odin +++ b/src/server/documents.odin @@ -320,18 +320,16 @@ document_refresh :: proc(document: ^Document, config: ^common.Config, writer: ^W return .None } + remove_diagnostics(.Syntax, document.uri.uri) + remove_diagnostics(.Check, document.uri.uri) + if writer != nil && !config.disable_parser_errors { document.diagnosed_errors = true - diagnostics := make([dynamic]Diagnostic, 0, len(errors), context.temp_allocator) - - params := NotificationPublishDiagnosticsParams { - uri = document.uri.uri, - } - for error, i in errors { - append( - &diagnostics, + add_diagnostics( + .Syntax, + document.uri.uri, Diagnostic { range = common.Range { start = common.Position{line = error.line - 1, character = 0}, @@ -344,33 +342,7 @@ document_refresh :: proc(document: ^Document, config: ^common.Config, writer: ^W ) } - if config.enable_unused_imports_reporting { - unused_imports := find_unused_imports(document, context.temp_allocator) - - for imp in unused_imports { - append( - &diagnostics, - Diagnostic { - range = common.get_token_range(imp.import_decl, document.ast.src), - severity = DiagnosticSeverity.Hint, - code = "Unused", - message = "unused import", - tags = {.Unnecessary}, - }, - ) - } - - } - - params.diagnostics = diagnostics[:] - - notifaction := Notification { - jsonrpc = "2.0", - method = "textDocument/publishDiagnostics", - params = params, - } - - send_notification(notifaction, writer) + push_diagnostics(writer) } return .None @@ -507,18 +479,12 @@ get_import_range :: proc(imp: ^ast.Import_Decl, src: string) -> common.Range { start := common.token_pos_to_position(imp.name.pos, src) end := start end.character += len(imp.name.text) - return { - start = start, - end = end, - } + return {start = start, end = end} } start := common.token_pos_to_position(imp.relpath.pos, src) end := start text_len := len(imp.relpath.text) end.character += text_len - return { - start = start, - end = end, - } + return {start = start, end = end} } diff --git a/src/server/requests.odin b/src/server/requests.odin index e153503..49119aa 100644 --- a/src/server/requests.odin +++ b/src/server/requests.odin @@ -1041,6 +1041,12 @@ notification_did_open :: proc( return .InternalError } + document := document_get(open_params.textDocument.uri) + + check_unused_imports(document, config) + + push_diagnostics(writer) + return .None } @@ -1135,7 +1141,13 @@ notification_did_save :: proc( corrected_uri := common.create_uri(fullpath, context.temp_allocator) - check(config.profile.checker_path[:], corrected_uri, writer, config) + check(config.profile.checker_path[:], corrected_uri, config) + + document := document_get(save_params.textDocument.uri) + + check_unused_imports(document, config) + + push_diagnostics(writer) return .None } |