aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDanielGavin <danielgavin5@hotmail.com>2025-05-17 18:13:34 +0200
committerDanielGavin <danielgavin5@hotmail.com>2025-05-17 18:13:34 +0200
commit07ea39ecdcf02dba84c82d90b028055463f6562c (patch)
tree871c9659513cc053108b453411af421666b033f7
parent89f83305019a70d714af015aec734700dfee967c (diff)
Fixed issue with magic completion in call expressions.
-rw-r--r--editors/vscode/package-lock.json18
-rw-r--r--editors/vscode/package.json35
-rw-r--r--editors/vscode/src/extension.ts21
-rw-r--r--src/server/analysis.odin106
-rw-r--r--src/server/completion.odin16
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 ""
}