// Completion provider for the ƿit LSP. // CompletionItemKind constants (LSP spec) def KIND_FUNCTION = 3 def KIND_VARIABLE = 6 def KIND_KEYWORD = 14 def KIND_CONSTANT = 21 // All intrinsic function names def intrinsic_functions = [ "abs", "apply", "array", "ceiling", "character", "codepoint", "ends_with", "every", "extract", "fallback", "filter", "find", "floor", "format", "fraction", "is_array", "is_blob", "is_character", "is_data", "is_digit", "is_false", "is_fit", "is_function", "is_integer", "is_letter", "is_logical", "is_lower", "is_null", "is_number", "is_object", "is_pattern", "is_stone", "is_text", "is_true", "is_upper", "is_whitespace", "length", "logical", "lower", "max", "min", "modulo", "neg", "normalize", "not", "number", "parallel", "print", "race", "record", "reduce", "remainder", "replace", "reverse", "round", "search", "sequence", "sign", "some", "sort", "starts_with", "stone", "text", "trim", "trunc", "upper", "whole", "meme", "proto", "isa", "splat", "use" ] // Keywords that can be completed def keywords = [ "var", "def", "if", "else", "for", "while", "do", "function", "return", "go", "break", "continue", "disrupt", "disruption", "delete", "in", "this", "null", "true", "false" ] // Actor intrinsics (only in .ce files) def actor_intrinsics = [ "$me", "$send", "$start", "$stop", "$delay", "$receiver", "$clock", "$portal", "$contact", "$couple", "$unneeded", "$connection", "$time_limit" ] // Walk AST scopes to find variables visible at a position. var collect_scope_vars = function(doc, line, col) { var vars = [] var ast = doc.ast var _i = 0 var _j = 0 var scope = null var v = null if (ast == null || ast.scopes == null) { return vars } // Collect variables from all scopes (simplified: return all declared vars) while (_i < length(ast.scopes)) { scope = ast.scopes[_i] if (scope.vars != null) { _j = 0 while (_j < length(scope.vars)) { v = scope.vars[_j] if (v.name != null) { vars[] = { label: v.name, kind: (v.is_const == true) ? KIND_CONSTANT : KIND_VARIABLE, detail: (v.is_const == true) ? "def" : "var" } } _j = _j + 1 } } _i = _i + 1 } return vars } // Provide completions for a document at a position. var complete = function(doc, line, col) { var items = [] var _i = 0 var is_actor = ends_with(doc.uri, ".ce") // Intrinsic functions _i = 0 while (_i < length(intrinsic_functions)) { items[] = { label: intrinsic_functions[_i], kind: KIND_FUNCTION, detail: "intrinsic" } _i = _i + 1 } // Keywords _i = 0 while (_i < length(keywords)) { items[] = { label: keywords[_i], kind: KIND_KEYWORD, detail: "keyword" } _i = _i + 1 } // Actor intrinsics (only for .ce files) if (is_actor) { _i = 0 while (_i < length(actor_intrinsics)) { items[] = { label: actor_intrinsics[_i], kind: KIND_FUNCTION, detail: "actor intrinsic" } _i = _i + 1 } } // Variables from scope analysis var scope_vars = collect_scope_vars(doc, line, col) _i = 0 while (_i < length(scope_vars)) { items[] = scope_vars[_i] _i = _i + 1 } return items } return { complete: complete }