diff options
| author | DanielGavin <danielgavin5@hotmail.com> | 2020-11-07 15:44:30 +0100 |
|---|---|---|
| committer | DanielGavin <danielgavin5@hotmail.com> | 2020-11-07 15:44:30 +0100 |
| commit | 6ec424ed8d34cf8a5f51e277a20429741b33ee96 (patch) | |
| tree | 6d0eed732e01d19effbae5cc525a9c2f6e28534f | |
| parent | 3f1027bd4003cdb9fdc80665548181df2fb60810 (diff) | |
complete refractor of the project into packages
| -rw-r--r-- | src/common/config.odin (renamed from src/config.odin) | 3 | ||||
| -rw-r--r-- | src/common/position.odin (renamed from src/position.odin) | 25 | ||||
| -rw-r--r-- | src/common/types.odin | 26 | ||||
| -rw-r--r-- | src/common/uri.odin (renamed from src/uri.odin) | 2 | ||||
| -rw-r--r-- | src/index/build.odin | 86 | ||||
| -rw-r--r-- | src/index/file_index.odin | 7 | ||||
| -rw-r--r-- | src/index/indexer.odin (renamed from src/index.odin) | 51 | ||||
| -rw-r--r-- | src/index/memory_index.odin | 29 | ||||
| -rw-r--r-- | src/index/symbol.odin | 66 | ||||
| -rw-r--r-- | src/main.odin | 27 | ||||
| -rw-r--r-- | src/server/analysis.odin (renamed from src/analysis.odin) | 33 | ||||
| -rw-r--r-- | src/server/documents.odin (renamed from src/documents.odin) | 79 | ||||
| -rw-r--r-- | src/server/log.odin (renamed from src/log.odin) | 2 | ||||
| -rw-r--r-- | src/server/reader.odin (renamed from src/reader.odin) | 4 | ||||
| -rw-r--r-- | src/server/requests.odin (renamed from src/requests.odin) | 32 | ||||
| -rw-r--r-- | src/server/response.odin (renamed from src/response.odin) | 2 | ||||
| -rw-r--r-- | src/server/types.odin (renamed from src/types.odin) | 55 | ||||
| -rw-r--r-- | src/server/unmarshal.odin (renamed from src/unmarshal.odin) | 2 | ||||
| -rw-r--r-- | src/server/workspace.odin | 1 | ||||
| -rw-r--r-- | src/server/writer.odin (renamed from src/writer.odin) | 2 | ||||
| -rw-r--r-- | src/workspace.odin | 1 | ||||
| -rw-r--r-- | tests/tests.odin | 18 |
22 files changed, 351 insertions, 202 deletions
diff --git a/src/config.odin b/src/common/config.odin index b4df050..cdbe4fd 100644 --- a/src/config.odin +++ b/src/common/config.odin @@ -1,9 +1,10 @@ -package main +package common Config :: struct { workspace_folders: [dynamic] WorkspaceFolder, completion_support_md: bool, hover_support_md: bool, collections: map [string] string, + running: bool, }; diff --git a/src/position.odin b/src/common/position.odin index 3278f10..7eb4173 100644 --- a/src/position.odin +++ b/src/common/position.odin @@ -1,4 +1,4 @@ -package main +package common import "core:strings" import "core:unicode/utf8" @@ -9,6 +9,22 @@ import "core:odin/ast" This file handles the conversion between utf-16 and utf-8 offsets in the text document */ +Position :: struct { + line: int, + character: int, +}; + +Range :: struct { + start: Position, + end: Position, +}; + +Location :: struct { + uri: string, + range: Range, +}; + + AbsoluteRange :: struct { start: int, end: int, @@ -59,12 +75,15 @@ get_token_range :: proc(node: ast.Node, document_text: [] u8) -> Range { return index+1; } - offset := go_backwards_to_endline(node.pos.offset, document_text); + pos_offset := min(len(document_text)-1, node.pos.offset); + end_offset := min(len(document_text)-1, node.end.offset); + + offset := go_backwards_to_endline(pos_offset, document_text); range.start.line = node.pos.line-1; range.start.character = get_character_offset_u8_to_u16(node.pos.column-1, document_text[offset:]); - offset = go_backwards_to_endline(node.end.offset, document_text); + offset = go_backwards_to_endline(end_offset, document_text); range.end.line = node.end.line-1; range.end.character = get_character_offset_u8_to_u16(node.end.column-1, document_text[offset:]); diff --git a/src/common/types.odin b/src/common/types.odin new file mode 100644 index 0000000..08bd8c2 --- /dev/null +++ b/src/common/types.odin @@ -0,0 +1,26 @@ +package common + + +Error :: enum { + None = 0, + + // Defined by JSON RPC + ParseError = -32700, + InvalidRequest = -32600, + MethodNotFound = -32601, + InvalidParams = -32602, + InternalError = -32603, + serverErrorStart = -32099, + serverErrorEnd = -32000, + ServerNotInitialized = -32002, + UnknownErrorCode = -32001, + + // Defined by the protocol. + RequestCancelled = -32800, + ContentModified = -32801, +}; + +WorkspaceFolder :: struct { + name: string, + uri: string, +}; diff --git a/src/uri.odin b/src/common/uri.odin index 8a59e4c..f8bee9e 100644 --- a/src/uri.odin +++ b/src/common/uri.odin @@ -1,4 +1,4 @@ -package main +package common import "core:mem" import "core:strings" diff --git a/src/index/build.odin b/src/index/build.odin new file mode 100644 index 0000000..d52cbca --- /dev/null +++ b/src/index/build.odin @@ -0,0 +1,86 @@ +package index + +import "core:path/filepath" +import "core:os" +import "core:fmt" +import "core:odin/parser" +import "core:odin/ast" +import "core:odin/tokenizer" + +import "shared:common" + +/* + Not fully sure how to handle rebuilding, but one thing is for sure, dynamic indexing has to have a background thread + rebuilding every minute or less to fight against stale information + */ + + +//test version for static indexing + +symbol_collection: SymbolCollection; + +build_static_index :: proc(allocator := context.allocator, config: ^common.Config) { + + //right now just collect the symbols from core + + core_path := config.collections["core"]; + + + symbol_collection = make_symbol_collection(allocator); + + walk_static_index_build := proc(info: os.File_Info, in_err: os.Errno) -> (err: os.Errno, skip_dir: bool) { + + if info.is_dir { + return 0, false; + } + + //fmt.println(info.fullpath); + + //bit worried about using temp allocator here since we might overwrite all our temp allocator budget + data, ok := os.read_entire_file(info.fullpath, context.allocator); + + if !ok { + fmt.println("failed to read"); + return 1, false; + } + + p := parser.Parser { + err = no_error_handler, + warn = no_warning_handler, + }; + + file := ast.File { + fullpath = info.fullpath, + src = data, + }; + + parser.parse_file(&p, &file); + + uri := common.create_uri(info.fullpath, context.temp_allocator); + + collect_symbols(&symbol_collection, file, uri.uri); + + delete(data); + + + return 0, false; + }; + + filepath.walk(core_path, walk_static_index_build); + + indexer.static_index = make_memory_index(symbol_collection); +} + + +no_error_handler :: proc(pos: tokenizer.Pos, msg: string, args: ..any) { + +} + +no_warning_handler :: proc(pos: tokenizer.Pos, msg: string, args: ..any) { + +} + + + + + diff --git a/src/index/file_index.odin b/src/index/file_index.odin new file mode 100644 index 0000000..fe787e5 --- /dev/null +++ b/src/index/file_index.odin @@ -0,0 +1,7 @@ +package index + +/* + This is indexer for static files operating on a file database to index symbols and files. + + NOTE(Daniel, Let's be honest probably will not be made any time soon) + */
\ No newline at end of file diff --git a/src/index.odin b/src/index/indexer.odin index 7d2774f..46a2192 100644 --- a/src/index.odin +++ b/src/index/indexer.odin @@ -1,4 +1,4 @@ -package main +package index import "core:odin/ast" import "core:fmt" @@ -38,58 +38,17 @@ import "core:strings" TODO(Daniel, Look into data structure for fuzzy searching) */ -BaseSymbol :: struct { - range: Range, - uri: ^Uri, -}; -ProcedureSymbol :: struct { - using symbolbase: BaseSymbol, -}; - -Symbol :: union { - ProcedureSymbol, -}; Indexer :: struct { - symbol_table: map [string] Symbol, + static_index: MemoryIndex, }; indexer: Indexer; -index_document :: proc(document: ^Document) -> Error { - - for decl in document.ast.decls { - - if value_decl, ok := decl.derived.(ast.Value_Decl); ok { - - name := string(document.text[value_decl.names[0].pos.offset:value_decl.names[0].end.offset]); - - if len(value_decl.values) == 1 { - - if proc_lit, ok := value_decl.values[0].derived.(ast.Proc_Lit); ok { - symbol: ProcedureSymbol; - - symbol.range = get_token_range(proc_lit, document.text); - symbol.uri = &document.uri; - - indexer.symbol_table[strings.concatenate({document.package_name, name}, context.temp_allocator)] = symbol; - - //fmt.println(proc_lit.type); - - } - - } - - } - } - - //fmt.println(indexer.symbol_table); - - return .None; +lookup :: proc(id: string) -> (Symbol, bool) { + return memory_index_lookup(&indexer.static_index, id); } -indexer_get_symbol :: proc(id: string) -> (Symbol, bool) { - return indexer.symbol_table[id]; -} +//indexer_fuzzy_search :: proc(name: string, scope: [] string, ) diff --git a/src/index/memory_index.odin b/src/index/memory_index.odin new file mode 100644 index 0000000..c5ce416 --- /dev/null +++ b/src/index/memory_index.odin @@ -0,0 +1,29 @@ +package index + +import "core:hash" + +/* + This is a in memory index designed for the dynamic indexing of symbols and files. + Designed for few files and should be fast at rebuilding. + + Right now the implementation is quite naive. + */ +MemoryIndex :: struct { + collection: SymbolCollection, +}; + + +make_memory_index :: proc(collection: SymbolCollection) -> MemoryIndex { + + return MemoryIndex { + collection = collection, + }; + +} + +memory_index_lookup :: proc(index: ^MemoryIndex, id: string) -> (Symbol, bool) { + + hashed := hash.murmur64(transmute([]u8)id); + + return index.collection.symbols[hashed]; +}
\ No newline at end of file diff --git a/src/index/symbol.odin b/src/index/symbol.odin new file mode 100644 index 0000000..2cbd58c --- /dev/null +++ b/src/index/symbol.odin @@ -0,0 +1,66 @@ +package index + +import "core:odin/ast" +import "core:hash" +import "core:strings" +import "core:mem" + +import "shared:common" + +Symbol :: struct { + id: u64, + range: common.Range, + uri: string, +}; + +SymbolCollection :: struct { + allocator: mem.Allocator, + symbols: map[u64] Symbol, + unique_strings: map[u64] string, +}; + +make_symbol_collection :: proc(allocator := context.allocator) -> SymbolCollection { + return SymbolCollection { + allocator = allocator, + symbols = make(map[u64] Symbol, 16, allocator), + unique_strings = make(map[u64] string, 16, allocator), + }; +} + +collect_symbols :: proc(collection: ^SymbolCollection, file: ast.File, uri: string) -> common.Error { + + for decl in file.decls { + + if value_decl, ok := decl.derived.(ast.Value_Decl); ok { + + name := string(file.src[value_decl.names[0].pos.offset:value_decl.names[0].end.offset]); + + if len(value_decl.values) == 1 { + + if proc_lit, ok := value_decl.values[0].derived.(ast.Proc_Lit); ok { + + symbol: Symbol; + + symbol.range = common.get_token_range(proc_lit, file.src); + + uri_id := hash.murmur64(transmute([]u8)uri); + + if _, ok := collection.unique_strings[uri_id]; !ok { + collection.unique_strings[uri_id] = strings.clone(uri); + } + + symbol.uri = collection.unique_strings[uri_id]; + + id := hash.murmur64(transmute([]u8)strings.concatenate({file.pkg_name, name}, context.temp_allocator)); + + collection.symbols[id] = symbol; + + } + + } + + } + } + + return .None; +} diff --git a/src/main.odin b/src/main.odin index 382fd31..62c75f6 100644 --- a/src/main.odin +++ b/src/main.odin @@ -9,6 +9,10 @@ import "core:slice" import "core:strconv" import "core:encoding/json" +import "shared:index" +import "shared:server" +import "shared:common" + running: bool; os_read :: proc(handle: rawptr, data: [] byte) -> (int, int) @@ -23,9 +27,9 @@ os_write :: proc(handle: rawptr, data: [] byte) -> (int, int) //Note(Daniel, Should look into handling errors without crashing from parsing) -run :: proc(reader: ^Reader, writer: ^Writer) { +run :: proc(reader: ^server.Reader, writer: ^server.Writer) { - config: Config; + config: common.Config; //temporary collections being set manually, need to get client configuration set up. config.collections = make(map [string] string); @@ -34,11 +38,14 @@ run :: proc(reader: ^Reader, writer: ^Writer) { log.info("Starting Odin Language Server"); - running = true; + index.build_static_index(context.allocator, &config); + + + config.running = true; - for running { + for config.running { - header, success := read_and_parse_header(reader); + header, success := server.read_and_parse_header(reader); if(!success) { log.error("Failed to read and parse header"); @@ -47,14 +54,14 @@ run :: proc(reader: ^Reader, writer: ^Writer) { value: json.Value; - value, success = read_and_parse_body(reader, header); + value, success = server.read_and_parse_body(reader, header); if(!success) { log.error("Failed to read and parse body"); return; } - success = handle_request(value, &config, writer); + success = server.handle_request(value, &config, writer); if(!success) { log.error("Unrecoverable handle request"); @@ -74,10 +81,10 @@ end :: proc() { main :: proc() { - reader := make_reader(os_read, cast(rawptr)os.stdin); - writer := make_writer(os_write, cast(rawptr)os.stdout); + reader := server.make_reader(os_read, cast(rawptr)os.stdin); + writer := server.make_writer(os_write, cast(rawptr)os.stdout); - context.logger = create_lsp_logger(&writer); + context.logger = server.create_lsp_logger(&writer); run(&reader, &writer); } diff --git a/src/analysis.odin b/src/server/analysis.odin index 23f18ae..e88532f 100644 --- a/src/analysis.odin +++ b/src/server/analysis.odin @@ -1,4 +1,4 @@ -package main +package server import "core:odin/parser" import "core:odin/ast" @@ -8,6 +8,10 @@ import "core:log" import "core:strings" import "core:path" +import "shared:common" +import "shared:index" + + DocumentPositionContextDottedValue :: struct { prefix: string, @@ -37,14 +41,15 @@ tokenizer_error_handler :: proc(pos: tokenizer.Pos, msg: string, args: ..any) { } + /* Figure out what exactly is at the given position and whether it is in a function, struct, etc. */ -get_document_position_context :: proc(document: ^Document, position: Position) -> (DocumentPositionContext, bool) { +get_document_position_context :: proc(document: ^Document, position: common.Position) -> (DocumentPositionContext, bool) { position_context: DocumentPositionContext; - absolute_position, ok := get_absolute_position(position, document.text); + absolute_position, ok := common.get_absolute_position(position, document.text); if !ok { return position_context, false; @@ -86,9 +91,6 @@ get_document_position_context :: proc(document: ^Document, position: Position) - } - //fmt.println(current_token.text); - //fmt.println(); - if current_token.pos.offset+len(current_token.text) >= absolute_position { break; } @@ -119,9 +121,12 @@ get_document_position_context :: proc(document: ^Document, position: Position) - } -get_definition_location :: proc(document: ^Document, position: Position) -> (Location, bool) { +get_definition_location :: proc(document: ^Document, position: common.Position) -> (common.Location, bool) { + + + location: common.Location; + - location: Location; position_context, ok := get_document_position_context(document, position); @@ -129,11 +134,11 @@ get_definition_location :: proc(document: ^Document, position: Position) -> (Loc return location, false; } - symbol: Symbol; + symbol: index.Symbol; #partial switch v in position_context.value { case DocumentPositionContextDottedValue: - symbol, ok = indexer_get_symbol(strings.concatenate({v.prefix, v.postfix}, context.temp_allocator)); + symbol, ok = index.lookup(strings.concatenate({v.prefix, v.postfix}, context.temp_allocator)); case: return location, false; } @@ -144,11 +149,9 @@ get_definition_location :: proc(document: ^Document, position: Position) -> (Loc return location, false; } - switch v in symbol { - case ProcedureSymbol: - location.range = v.range; - location.uri = v.uri.uri; - } + location.range = symbol.range; + location.uri = symbol.uri; + return location, true; } diff --git a/src/documents.odin b/src/server/documents.odin index bda7c21..59eeadd 100644 --- a/src/documents.odin +++ b/src/server/documents.odin @@ -1,4 +1,4 @@ -package main +package server import "core:strings" import "core:fmt" @@ -9,6 +9,8 @@ import "core:odin/ast" import "core:odin/tokenizer" import "core:path" +import "shared:common" + ParserError :: struct { message: string, line: int, @@ -23,12 +25,11 @@ Package :: struct { }; Document :: struct { - uri: Uri, + uri: common.Uri, text: [] u8, used_text: int, //allow for the text to be reallocated with more data than needed client_owned: bool, diagnosed_errors: bool, - indexed: bool, ast: ast.File, package_name: string, imports: [] string, @@ -44,7 +45,7 @@ document_storage: DocumentStorage; document_get :: proc(uri_string: string) -> ^Document { - uri, parsed_ok := parse_uri(uri_string, context.temp_allocator); + uri, parsed_ok := common.parse_uri(uri_string, context.temp_allocator); if !parsed_ok { return nil; @@ -61,11 +62,11 @@ document_get :: proc(uri_string: string) -> ^Document { /* Server opens a new document with text from filesystem */ -document_new :: proc(path: string, config: ^Config) -> Error { +document_new :: proc(path: string, config: ^common.Config) -> common.Error { text, ok := os.read_entire_file(path); - uri := create_uri(path); + uri := common.create_uri(path); if !ok { log.error("Failed to parse uri"); @@ -75,23 +76,12 @@ document_new :: proc(path: string, config: ^Config) -> Error { document := Document { uri = uri, text = transmute([] u8)text, - client_owned = true, + client_owned = false, used_text = len(text), }; - if err := document_refresh(&document, config, nil, false); err != .None { - log.error("Failed to refresh new document"); - return err; - } - - document_storage.documents[path] = document; - - if err := index_document(&document_storage.documents[path]); err != .None { - log.error("Failed to index new document"); - return err; - } - + document_storage.documents[path] = document; return .None; } @@ -100,9 +90,9 @@ document_new :: proc(path: string, config: ^Config) -> Error { Client opens a document with transferred text */ -document_open :: proc(uri_string: string, text: string, config: ^Config, writer: ^Writer) -> Error { +document_open :: proc(uri_string: string, text: string, config: ^common.Config, writer: ^Writer) -> common.Error { - uri, parsed_ok := parse_uri(uri_string); + uri, parsed_ok := common.parse_uri(uri_string); log.infof("document_open: %v", uri_string); @@ -123,7 +113,7 @@ document_open :: proc(uri_string: string, text: string, config: ^Config, writer: } if len(document.uri.uri) > 0 { - delete_uri(document.uri); + common.delete_uri(document.uri); } document.uri = uri; @@ -164,9 +154,9 @@ document_open :: proc(uri_string: string, text: string, config: ^Config, writer: /* Function that applies changes to the given document through incremental syncronization */ -document_apply_changes :: proc(uri_string: string, changes: [dynamic] TextDocumentContentChangeEvent, config: ^Config, writer: ^Writer) -> Error { +document_apply_changes :: proc(uri_string: string, changes: [dynamic] TextDocumentContentChangeEvent, config: ^common.Config, writer: ^Writer) -> common.Error { - uri, parsed_ok := parse_uri(uri_string, context.temp_allocator); + uri, parsed_ok := common.parse_uri(uri_string, context.temp_allocator); if !parsed_ok { return .ParseError; @@ -181,7 +171,7 @@ document_apply_changes :: proc(uri_string: string, changes: [dynamic] TextDocume for change in changes { - absolute_range, ok := get_absolute_range(change.range, document.text[:document.used_text]); + absolute_range, ok := common.get_absolute_range(change.range, document.text[:document.used_text]); if !ok { return .ParseError; @@ -225,9 +215,9 @@ document_apply_changes :: proc(uri_string: string, changes: [dynamic] TextDocume return document_refresh(document, config, writer, true); } -document_close :: proc(uri_string: string) -> Error { +document_close :: proc(uri_string: string) -> common.Error { - uri, parsed_ok := parse_uri(uri_string, context.temp_allocator); + uri, parsed_ok := common.parse_uri(uri_string, context.temp_allocator); if !parsed_ok { return .ParseError; @@ -247,7 +237,7 @@ document_close :: proc(uri_string: string) -> Error { -document_refresh :: proc(document: ^Document, config: ^Config, writer: ^Writer, parse_imports: bool) -> Error { +document_refresh :: proc(document: ^Document, config: ^common.Config, writer: ^Writer, parse_imports: bool) -> common.Error { errors, ok := parse_document(document, config); @@ -267,12 +257,12 @@ document_refresh :: proc(document: ^Document, config: ^Config, writer: ^Writer, for error, i in errors { params.diagnostics[i] = Diagnostic { - range = Range { - start = Position { + range = common.Range { + start = common.Position { line = error.line - 1, character = 0, }, - end = Position { + end = common.Position { line = error.line, character = 0, }, @@ -316,27 +306,10 @@ document_refresh :: proc(document: ^Document, config: ^Config, writer: ^Writer, } - if parse_imports { - - /* - go through the imports from this document and see if we need to load them into memory(not owned by client), - and also refresh them if needed - */ - for imp in document.imports { - - if err := document_load_package(imp, config); err != .None { - return err; - } - - } - - } - - return .None; } -document_load_package :: proc(package_directory: string, config: ^Config) -> Error { +document_load_package :: proc(package_directory: string, config: ^common.Config) -> common.Error { fd, err := os.open(package_directory); @@ -376,7 +349,7 @@ parser_warning_handler :: proc(pos: tokenizer.Pos, msg: string, args: ..any) { } -parse_document :: proc(document: ^Document, config: ^Config) -> ([] ParserError, bool) { +parse_document :: proc(document: ^Document, config: ^common.Config) -> ([] ParserError, bool) { p := parser.Parser { err = parser_error_handler, @@ -392,6 +365,11 @@ parse_document :: proc(document: ^Document, config: ^Config) -> ([] ParserError, parser.parse_file(&p, &document.ast); + /* + if document.imports != nil { + delete(document.imports); + delete(document.package_name); + } document.imports = make([]string, len(document.ast.imports)); document.package_name = document.ast.pkg_name; @@ -418,6 +396,7 @@ parse_document :: proc(document: ^Document, config: ^Config) -> ([] ParserError, } } + */ return current_errors[:], true; }
\ No newline at end of file diff --git a/src/log.odin b/src/server/log.odin index 82a52a4..5ed007e 100644 --- a/src/log.odin +++ b/src/server/log.odin @@ -1,4 +1,4 @@ -package main +package server import "core:fmt"; import "core:strings"; diff --git a/src/reader.odin b/src/server/reader.odin index 31019a5..f421d67 100644 --- a/src/reader.odin +++ b/src/server/reader.odin @@ -1,4 +1,4 @@ -package main +package server import "core:os" import "core:mem" @@ -46,7 +46,7 @@ read_until_delimiter :: proc(reader: ^Reader, delimiter: u8, builder: ^strings.B } } - return true; + return true; } read_sized :: proc(reader: ^Reader, data: []u8) -> bool { diff --git a/src/requests.odin b/src/server/requests.odin index 182772a..cd8e734 100644 --- a/src/requests.odin +++ b/src/server/requests.odin @@ -1,4 +1,4 @@ -package main +package server import "core:fmt" import "core:log" @@ -9,6 +9,8 @@ import "core:slice" import "core:strconv" import "core:encoding/json" +import "shared:common" + Header :: struct { content_length: int, @@ -129,7 +131,7 @@ read_and_parse_body :: proc(reader: ^Reader, header: Header) -> (json.Value, boo } -handle_request :: proc(request: json.Value, config: ^Config, writer: ^Writer) -> bool { +handle_request :: proc(request: json.Value, config: ^common.Config, writer: ^Writer) -> bool { root, ok := request.value.(json.Object); @@ -156,7 +158,7 @@ handle_request :: proc(request: json.Value, config: ^Config, writer: ^Writer) -> method := root["method"].value.(json.String); - call_map : map [string] proc(json.Value, RequestId, ^Config, ^Writer) -> Error = + call_map : map [string] proc(json.Value, RequestId, ^common.Config, ^Writer) -> common.Error = {"initialize" = request_initialize, "initialized" = request_initialized, "shutdown" = request_shutdown, @@ -167,7 +169,7 @@ handle_request :: proc(request: json.Value, config: ^Config, writer: ^Writer) -> "textDocument/didSave" = notification_did_save, "textDocument/definition" = request_definition }; - fn: proc(json.Value, RequestId, ^Config, ^Writer) -> Error; + fn: proc(json.Value, RequestId, ^common.Config, ^Writer) -> common.Error; fn, ok = call_map[method]; @@ -197,7 +199,7 @@ handle_request :: proc(request: json.Value, config: ^Config, writer: ^Writer) -> return true; } -request_initialize :: proc(params: json.Value, id: RequestId, config: ^Config, writer: ^Writer) -> Error { +request_initialize :: proc(params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error { params_object, ok := params.value.(json.Object); @@ -211,7 +213,7 @@ request_initialize :: proc(params: json.Value, id: RequestId, config: ^Config, w return .ParseError; } - config.workspace_folders = make([dynamic]WorkspaceFolder); + config.workspace_folders = make([dynamic]common.WorkspaceFolder); for s in initialize_params.workspaceFolders { append_elem(&config.workspace_folders, s); @@ -238,11 +240,11 @@ request_initialize :: proc(params: json.Value, id: RequestId, config: ^Config, w return .None; } -request_initialized :: proc(params: json.Value, id: RequestId, config: ^Config, writer: ^Writer) -> Error { +request_initialized :: proc(params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error { return .None; } -request_shutdown :: proc(params: json.Value, id: RequestId, config: ^Config, writer: ^Writer) -> Error { +request_shutdown :: proc(params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error { response := make_response_message( params = nil, @@ -254,7 +256,7 @@ request_shutdown :: proc(params: json.Value, id: RequestId, config: ^Config, wri return .None; } -request_definition :: proc(params: json.Value, id: RequestId, config: ^Config, writer: ^Writer) -> Error { +request_definition :: proc(params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error { params_object, ok := params.value.(json.Object); @@ -293,12 +295,12 @@ request_definition :: proc(params: json.Value, id: RequestId, config: ^Config, w return .None; } -notification_exit :: proc(params: json.Value, id: RequestId, config: ^Config, writer: ^Writer) -> Error { - running = false; +notification_exit :: proc(params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error { + config.running = false; return .None; } -notification_did_open :: proc(params: json.Value, id: RequestId, config: ^Config, writer: ^Writer) -> Error { +notification_did_open :: proc(params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error { params_object, ok := params.value.(json.Object); @@ -317,7 +319,7 @@ notification_did_open :: proc(params: json.Value, id: RequestId, config: ^Config return document_open(open_params.textDocument.uri, open_params.textDocument.text, config, writer); } -notification_did_change :: proc(params: json.Value, id: RequestId, config: ^Config, writer: ^Writer) -> Error { +notification_did_change :: proc(params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error { params_object, ok := params.value.(json.Object); @@ -336,7 +338,7 @@ notification_did_change :: proc(params: json.Value, id: RequestId, config: ^Conf return .None; } -notification_did_close :: proc(params: json.Value, id: RequestId, config: ^Config, writer: ^Writer) -> Error { +notification_did_close :: proc(params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error { params_object, ok := params.value.(json.Object); @@ -353,7 +355,7 @@ notification_did_close :: proc(params: json.Value, id: RequestId, config: ^Confi return document_close(close_params.textDocument.uri); } -notification_did_save :: proc(params: json.Value, id: RequestId, config: ^Config, writer: ^Writer) -> Error { +notification_did_save :: proc(params: json.Value, id: RequestId, config: ^common.Config, writer: ^Writer) -> common.Error { diff --git a/src/response.odin b/src/server/response.odin index b9249f4..bd7a77e 100644 --- a/src/response.odin +++ b/src/server/response.odin @@ -1,4 +1,4 @@ -package main +package server import "core:fmt" diff --git a/src/types.odin b/src/server/types.odin index f8964e5..262f464 100644 --- a/src/types.odin +++ b/src/server/types.odin @@ -1,7 +1,9 @@ -package main +package server import "core:encoding/json" +import "shared:common" + /* General types */ @@ -16,7 +18,7 @@ RequestId :: union { ResponseParams :: union { ResponseInitializeParams, rawptr, - Location, + common.Location, }; ResponseMessage :: struct { @@ -31,27 +33,8 @@ ResponseMessageError :: struct { error: ResponseError, }; -Error :: enum { - None = 0, - - // Defined by JSON RPC - ParseError = -32700, - InvalidRequest = -32600, - MethodNotFound = -32601, - InvalidParams = -32602, - InternalError = -32603, - serverErrorStart = -32099, - serverErrorEnd = -32000, - ServerNotInitialized = -32002, - UnknownErrorCode = -32001, - - // Defined by the protocol. - RequestCancelled = -32800, - ContentModified = -32801, -}; - ResponseError :: struct { - code: Error, + code: common.Error, message: string, }; @@ -76,18 +59,13 @@ Notification :: struct { params: NotificationParams }; -WorkspaceFolder :: struct { - name: string, - uri: string, -}; - ResponseInitializeParams :: struct { capabilities: ServerCapabilities, }; RequestInitializeParams :: struct { trace: string, - workspaceFolders: [dynamic] WorkspaceFolder, + workspaceFolders: [dynamic] common.WorkspaceFolder, capabilities: ClientCapabilities, }; @@ -120,23 +98,8 @@ ClientCapabilities :: struct { textDocument: TextDocumentClientCapabilities, }; -Position :: struct { - line: int, - character: int, -}; - -Range :: struct { - start: Position, - end: Position, -}; - -Location :: struct { - uri: string, - range: Range, -}; - TextDocumentContentChangeEvent :: struct { - range: Range, + range: common.Range, text: string, }; @@ -166,7 +129,7 @@ DiagnosticSeverity :: enum { }; Diagnostic :: struct { - range: Range, + range: common.Range, severity: DiagnosticSeverity, code: string, message: string, @@ -187,5 +150,5 @@ DidCloseTextDocumentParams :: struct { TextDocumentPositionParams :: struct { textDocument: TextDocumentIdentifier, - position: Position, + position: common.Position, };
\ No newline at end of file diff --git a/src/unmarshal.odin b/src/server/unmarshal.odin index 297bd89..e5ca619 100644 --- a/src/unmarshal.odin +++ b/src/server/unmarshal.odin @@ -1,4 +1,4 @@ -package main +package server import "core:encoding/json" import "core:strings" diff --git a/src/server/workspace.odin b/src/server/workspace.odin new file mode 100644 index 0000000..abb4e43 --- /dev/null +++ b/src/server/workspace.odin @@ -0,0 +1 @@ +package server diff --git a/src/writer.odin b/src/server/writer.odin index ccb1762..3c82451 100644 --- a/src/writer.odin +++ b/src/server/writer.odin @@ -1,4 +1,4 @@ -package main +package server import "core:os" import "core:mem" diff --git a/src/workspace.odin b/src/workspace.odin deleted file mode 100644 index 8b13789..0000000 --- a/src/workspace.odin +++ /dev/null @@ -1 +0,0 @@ - diff --git a/tests/tests.odin b/tests/tests.odin index 619fae4..ef7e4a5 100644 --- a/tests/tests.odin +++ b/tests/tests.odin @@ -6,7 +6,9 @@ import "core:fmt" import "core:os" import "core:strings" + import src "../src" +import "shared:server" /* @@ -346,8 +348,8 @@ test_init_check_shutdown :: proc() -> bool { data = transmute([]byte) strings.join({make_request(initialize_request), make_request(shutdown_request), make_request(exit_notification)}, "", context.allocator), }; - reader := src.make_reader(test_read, &buffer); - writer := src.make_writer(src.os_write, cast(rawptr)os.stdout); + reader := server.make_reader(test_read, &buffer); + writer := server.make_writer(src.os_write, cast(rawptr)os.stdout); src.run(&reader, &writer); @@ -447,10 +449,10 @@ test_open_and_change_notification :: proc() -> bool { }; - reader := src.make_reader(test_read, &buffer); - writer := src.make_writer(src.os_write, cast(rawptr)os.stdout); + reader := server.make_reader(test_read, &buffer); + writer := server.make_writer(src.os_write, cast(rawptr)os.stdout); - context.logger = src.create_lsp_logger(&writer); + context.logger = server.create_lsp_logger(&writer); src.run(&reader, &writer); @@ -502,10 +504,10 @@ test_definition_request :: proc() -> bool { }; - reader := src.make_reader(test_read, &buffer); - writer := src.make_writer(src.os_write, cast(rawptr)os.stdout); + reader := server.make_reader(test_read, &buffer); + writer := server.make_writer(src.os_write, cast(rawptr)os.stdout); - context.logger = src.create_lsp_logger(&writer); + context.logger = server.create_lsp_logger(&writer); src.run(&reader, &writer); |