diff options
| author | DanielGavin <danielgavin5@hotmail.com> | 2025-05-17 18:13:34 +0200 |
|---|---|---|
| committer | DanielGavin <danielgavin5@hotmail.com> | 2025-05-17 18:13:34 +0200 |
| commit | 07ea39ecdcf02dba84c82d90b028055463f6562c (patch) | |
| tree | 871c9659513cc053108b453411af421666b033f7 | |
| parent | 89f83305019a70d714af015aec734700dfee967c (diff) | |
Fixed issue with magic completion in call expressions.
| -rw-r--r-- | editors/vscode/package-lock.json | 18 | ||||
| -rw-r--r-- | editors/vscode/package.json | 35 | ||||
| -rw-r--r-- | editors/vscode/src/extension.ts | 21 | ||||
| -rw-r--r-- | src/server/analysis.odin | 106 | ||||
| -rw-r--r-- | src/server/completion.odin | 16 |
5 files changed, 122 insertions, 74 deletions
diff --git a/editors/vscode/package-lock.json b/editors/vscode/package-lock.json index 5f7b8c4..4b7fa77 100644 --- a/editors/vscode/package-lock.json +++ b/editors/vscode/package-lock.json @@ -1,15 +1,16 @@ { "name": "ols", - "version": "0.1.33", + "version": "0.1.35", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ols", - "version": "0.1.33", + "version": "0.1.35", "dependencies": { "adm-zip": "^0.5.9", "https-proxy-agent": "^5.0.0", + "json5": "^2.2.1", "node-fetch": "^2.6.7", "vscode-languageclient": "9.0.1" }, @@ -29,7 +30,7 @@ "vscode-test": "^1.6.1" }, "engines": { - "vscode": "^1.80.0" + "vscode": "^1.96.0" } }, "node_modules/@azure/abort-controller": { @@ -2817,6 +2818,17 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, + "node_modules/json5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/jsonc-parser": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", diff --git a/editors/vscode/package.json b/editors/vscode/package.json index 94edc88..7aa2f6c 100644 --- a/editors/vscode/package.json +++ b/editors/vscode/package.json @@ -7,7 +7,7 @@ "type": "git", "url": "git://github.com/DanielGavin/ols.git" }, - "version": "0.1.33", + "version": "0.1.36", "engines": { "vscode": "^1.96.0" }, @@ -124,8 +124,8 @@ "text.html.markdown" ], "embeddedLanguages": { - "meta.embedded.block.odin": "odin" - } + "meta.embedded.block.odin": "odin" + } } ], "breakpoints": [ @@ -136,17 +136,19 @@ "problemMatchers": [ { "name": "odin", - "owner": "odin", - "fileLocation": ["absolute"], - "pattern": { - "regexp": "^(.+)\\(([0-9]+)\\:([0-9]+)\\) ([^:]+)(.+)$", - "file": 1, - "line": 2, - "column": 3, - "severity": 4, - "message": 5 - } - } + "owner": "odin", + "fileLocation": [ + "absolute" + ], + "pattern": { + "regexp": "^(.+)\\(([0-9]+)\\:([0-9]+)\\) ([^:]+)(.+)$", + "file": 1, + "line": 2, + "column": 3, + "severity": 4, + "message": 5 + } + } ] }, "scripts": { @@ -166,16 +168,17 @@ "@types/vscode": "^1.96.0", "@typescript-eslint/eslint-plugin": "^4.33.0", "@typescript-eslint/parser": "^4.33.0", + "@vscode/vsce": "^3.2.1", "eslint": "^7.32.0", "glob": "^7.2.0", "mocha": "^10.2.0", "typescript": "^4.6.2", - "@vscode/vsce": "^3.2.1", "vscode-test": "^1.6.1" }, "dependencies": { "adm-zip": "^0.5.9", "https-proxy-agent": "^5.0.0", + "json5": "^2.2.1", "node-fetch": "^2.6.7", "vscode-languageclient": "9.0.1" }, @@ -184,4 +187,4 @@ "editor.semanticHighlighting.enabled": true } } -} +}
\ No newline at end of file diff --git a/editors/vscode/src/extension.ts b/editors/vscode/src/extension.ts index 0d1f578..da120c1 100644 --- a/editors/vscode/src/extension.ts +++ b/editors/vscode/src/extension.ts @@ -5,7 +5,7 @@ import * as vscode from 'vscode'; import * as path from "path"; import * as os from "os"; -import { promises as fs, constants, writeFileSync} from "fs"; +import { promises as fs, constants, writeFileSync } from "fs"; var AdmZip = require('adm-zip'); @@ -27,7 +27,9 @@ import { watchOlsConfigFile } from './watch'; const onDidChange: vscode.EventEmitter<void> = new vscode.EventEmitter<void>(); -const defaultConfig = JSON.stringify( +const JSON5 = require('json5') + +const defaultConfig = JSON5.stringify( { $schema: "https://raw.githubusercontent.com/DanielGavin/ols/master/misc/ols.schema.json", enable_document_symbols: true, @@ -117,7 +119,7 @@ export async function activate(context: vscode.ExtensionContext) { const userConfigPath = path.join(path.dirname(serverPath), "ols.json"); fs.access(projectConfigPath, constants.F_OK).catch(async (_e1) => { - fs.access(userConfigPath, constants.F_OK).catch( async (_e2) => { + fs.access(userConfigPath, constants.F_OK).catch(async (_e2) => { if (!config.askCreateOLS) { return; } @@ -151,7 +153,12 @@ export async function activate(context: vscode.ExtensionContext) { // parse ols file first, so we can pass it to "isOdinInstalled" // in order to check if the path to odin was defined in the ols file - await parseOlsFile(config, projectConfigPath); + try { + await parseOlsFile(config, projectConfigPath); + } + catch (error) { + log.error("Failed to parse ols configuration"); + } if (!isOdinInstalled(config)) { vscode.window.showErrorMessage("Odin cannot be found in your path environment. Please install Odin or add it into your path environment before going any further: [Install](https://odin-lang.org/docs/install/)."); @@ -170,7 +177,7 @@ export async function activate(context: vscode.ExtensionContext) { client.start(); }); - vscode.commands.registerCommand("ols.editProjectConfig", async() => { + vscode.commands.registerCommand("ols.editProjectConfig", async () => { createOrEditProjectConfig(); }); @@ -277,7 +284,7 @@ export async function parseOlsFile(config: Config, file: string) { */ await fs.readFile(file).then( (data) => { - const conf = JSON.parse(data.toString()); + const conf = JSON5.parse(data.toString()); config.collections = conf.collections; if (conf.hasOwnProperty("odin_command")) { config.odinCommand = conf.odin_command; @@ -344,7 +351,7 @@ async function getServer(config: Config, state: PersistentState): Promise<string Temp: right now it doesn't check for versions, since ols has no versioning right now */ - if (exists && state.lastCheck !== undefined && state.lastCheck + (3 * 60 * 60 * 1000) > Date.now()) { + if (exists && state.lastCheck !== undefined && state.lastCheck + (3 * 60 * 60 * 1000) > Date.now()) { return destExecutable; } diff --git a/src/server/analysis.odin b/src/server/analysis.odin index 98f44c0..7202fe2 100644 --- a/src/server/analysis.odin +++ b/src/server/analysis.odin @@ -1335,7 +1335,10 @@ internal_resolve_type_identifier :: proc(ast_context: ^AstContext, node: ast.Ide if return_symbol, ok = internal_resolve_type_expression(ast_context, v.expr); ok { if proc_value, ok := return_symbol.value.(SymbolProcedureValue); ok { if len(proc_value.return_types) >= 1 && proc_value.return_types[0].type != nil { - return_symbol, ok = internal_resolve_type_expression(ast_context, proc_value.return_types[0].type) + return_symbol, ok = internal_resolve_type_expression( + ast_context, + proc_value.return_types[0].type, + ) } } // Otherwise should be a parapoly style @@ -2748,34 +2751,34 @@ get_generic_assignment :: proc( if symbol, ok := resolve_type_expression(ast_context, v.expr); ok { #partial switch symbol_value in symbol.value { - case SymbolProcedureValue: - for ret in symbol_value.return_types { - if ret.type != nil { - calls[len(results)] = true - append(results, ret.type) - } else if ret.default_value != nil { - calls[len(results)] = true - append(results, ret.default_value) - } + case SymbolProcedureValue: + for ret in symbol_value.return_types { + if ret.type != nil { + calls[len(results)] = true + append(results, ret.type) + } else if ret.default_value != nil { + calls[len(results)] = true + append(results, ret.default_value) } - case SymbolAggregateValue: - //In case we can't resolve the proc group, just save it anyway, so it won't cause any issues further down the line. - append(results, value) - - case SymbolStructValue: - // Parametrized struct - get_generic_assignment(file, v.expr, ast_context, results, calls, flags) - case SymbolUnionValue: - // Parametrized union - get_generic_assignment(file, v.expr, ast_context, results, calls, flags) + } + case SymbolAggregateValue: + //In case we can't resolve the proc group, just save it anyway, so it won't cause any issues further down the line. + append(results, value) - case: - if ident, ok := v.expr.derived.(^ast.Ident); ok { - //TODO: Simple assumption that you are casting it the type. - type_ident := new_type(Ident, ident.pos, ident.end, ast_context.allocator) - type_ident.name = ident.name - append(results, type_ident) - } + case SymbolStructValue: + // Parametrized struct + get_generic_assignment(file, v.expr, ast_context, results, calls, flags) + case SymbolUnionValue: + // Parametrized union + get_generic_assignment(file, v.expr, ast_context, results, calls, flags) + + case: + if ident, ok := v.expr.derived.(^ast.Ident); ok { + //TODO: Simple assumption that you are casting it the type. + type_ident := new_type(Ident, ident.pos, ident.end, ast_context.allocator) + type_ident.name = ident.name + append(results, type_ident) + } } } case ^Comp_Lit: @@ -3155,25 +3158,28 @@ get_locals_for_range_stmt :: proc( if ident, ok := unwrap_ident(val); ok { expr: ^ast.Expr - if v.return_types[i].type != nil { - expr = v.return_types[i].type - } else if v.return_types[i].default_value != nil { - expr = v.return_types[i].default_value - } + if len(v.return_types) > i { - store_local( - ast_context, - ident, - expr, - ident.pos.offset, - ident.name, - ast_context.local_id, - ast_context.non_mutable_only, - false, - true, - symbol.pkg, - false, - ) + if v.return_types[i].type != nil { + expr = v.return_types[i].type + } else if v.return_types[i].default_value != nil { + expr = v.return_types[i].default_value + } + + store_local( + ast_context, + ident, + expr, + ident.pos.offset, + ident.name, + ast_context.local_id, + ast_context.non_mutable_only, + false, + true, + symbol.pkg, + false, + ) + } } } case SymbolUntypedValue: @@ -4402,6 +4408,16 @@ position_in_node :: proc(node: ^ast.Node, position: common.AbsolutePosition) -> return node != nil && node.pos.offset <= position && position <= node.end.offset } +position_in_exprs :: proc(nodes: []^ast.Expr, position: common.AbsolutePosition) -> bool { + for node in nodes { + if node != nil && node.pos.offset <= position && position <= node.end.offset { + return true + } + } + + return false +} + get_document_position_label :: proc(label: ^ast.Expr, position_context: ^DocumentPositionContext) { if label == nil { return diff --git a/src/server/completion.odin b/src/server/completion.odin index 7383785..8d61e3e 100644 --- a/src/server/completion.odin +++ b/src/server/completion.odin @@ -1831,12 +1831,22 @@ append_magic_map_completion :: proc( get_expression_string_from_position_context :: proc(position_context: ^DocumentPositionContext) -> string { src := position_context.file.src if position_context.call != nil { - return src[position_context.call.pos.offset:position_context.call.end.offset] - } else if position_context.field != nil { + if call_expr, ok := position_context.call.derived.(^ast.Call_Expr); ok { + if position_in_node(call_expr.expr, position_context.position) { + return src[position_context.call.pos.offset:position_context.call.end.offset] + } + } + + } + + if position_context.field != nil { return src[position_context.field.pos.offset:position_context.field.end.offset] - } else if position_context.selector != nil { + } + + if position_context.selector != nil { return src[position_context.selector.pos.offset:position_context.selector.end.offset] } + return "" } |