Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .release-notes/fix-lsp-definition-ranges.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## Fix LSP definition and type-definition ranges

`textDocument/definition` and `textDocument/typeDefinition` responses now return a range that covers the full declaration — from the opening keyword to the end of the body. Previously the range covered only the declaration keyword (`class`, `fun`, etc.).

Range computation now also correctly handles the last type declaration in a file. Previously the compiler's synthesized default constructors could cause the final entity's range to extend to an incorrect position; this no longer occurs.
5 changes: 5 additions & 0 deletions .release-notes/lsp-symbol-range.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## Fix LSP symbol ranges

LSP clients that use `textDocument/documentSymbol` (the outline/breadcrumb view in most editors) could produce a "selectionRange must be contained in range" error, causing the entire symbol list to be rejected. This is now fixed.

In addition, symbol ranges across both `textDocument/documentSymbol` and `workspace/symbol` now correctly cover the full declaration — from the opening keyword to the end of the body. Previously, `textDocument/documentSymbol` ranges covered only the declaration keyword (`class`, `fun`, etc.), and `workspace/symbol` ranges covered only the identifier. Highlighting a symbol or jumping to it now selects the whole declaration.
7 changes: 0 additions & 7 deletions src/libponyc/codegen/codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,6 @@ static void init_runtime(compile_t* c)
LLVM_MEMORYEFFECTS_ARG(LLVM_MEMORYEFFECTS_READWRITE) |
LLVM_MEMORYEFFECTS_INACCESSIBLEMEM(LLVM_MEMORYEFFECTS_READWRITE));
LLVM_DECLARE_ATTRIBUTEREF(noalias_attr, noalias, 0);
LLVM_DECLARE_ATTRIBUTEREF(noreturn_attr, noreturn, 0);
LLVM_DECLARE_ATTRIBUTEREF(deref_actor_attr, dereferenceable,
PONY_ACTOR_PAD_SIZE + align_value);
LLVM_DECLARE_ATTRIBUTEREF(align_attr, align, align_value);
Expand Down Expand Up @@ -607,12 +606,6 @@ static void init_runtime(compile_t* c)
LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr);
LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, memory_readonly);

// void pony_error()
type = LLVMFunctionType(c->void_type, NULL, 0, false);
value = LLVMAddFunction(c->module, "pony_error", type);

LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, noreturn_attr);

// i32 memcmp(i8*, i8*, intptr)
params[0] = c->ptr;
params[1] = c->ptr;
Expand Down
5 changes: 2 additions & 3 deletions src/libponyc/codegen/gencall.c
Original file line number Diff line number Diff line change
Expand Up @@ -1057,10 +1057,9 @@ LLVMValueRef gen_call(compile_t* c, ast_t* ast)
{
r = c->none_instance;
}

if(c_m->try_return_info.return_type != TRYRETURNTYPE_NONE)
else if(c_m->try_return_info.return_type != TRYRETURNTYPE_NONE)
{
r = unwrap_try_return_value(c, &c_m->try_return_info, r, m->result);
r = unwrap_try_return_value_jump_if_error(c, &c_m->try_return_info, r);
}

if(return_by_value)
Expand Down
10 changes: 4 additions & 6 deletions src/libponyc/codegen/gencontrol.c
Original file line number Diff line number Diff line change
Expand Up @@ -621,20 +621,19 @@ LLVMValueRef gen_return(compile_t* c, ast_t* ast)
partial_ret = c_m->try_return_info.return_type != TRYRETURNTYPE_NONE;
}

if(LLVMGetTypeKind(r_type) || partial_ret)
if(LLVMGetTypeKind(r_type) != LLVMVoidTypeKind)
{
if(partial_ret)
{
compile_type_t* ret_c_t = (compile_type_t*)c->frame->m->result->c_type;
r_type = ret_c_t->use_type;
r_type = get_try_return_unwrapped_type(&c_m->try_return_info);
}
ast_t* type = deferred_reify(c->frame->reify, ast_type(expr), c->opt);
LLVMValueRef ret = gen_assign_cast(c, r_type, value, type);
ast_free_unattached(type);

if(partial_ret)
{
ret = wrap_try_return_success(c, &c_m->try_return_info, ret, c->frame->m->result);
ret = wrap_try_return_success(c, &c_m->try_return_info, ret);
}

codegen_scope_lifetime_end(c);
Expand Down Expand Up @@ -720,7 +719,6 @@ LLVMValueRef gen_try(compile_t* c, ast_t* ast)
return NULL;

gen_expr(c, then_clause);

else_block = LLVMGetInsertBlock(c->builder);
LLVMBuildBr(c->builder, post_block);
}
Expand Down Expand Up @@ -947,7 +945,7 @@ LLVMValueRef gen_error(compile_t* c, ast_t* ast)

pony_assert(c_m->try_return_info.return_type != TRYRETURNTYPE_NONE);

LLVMValueRef ret = wrap_try_return_error(c, &c_m->try_return_info, r_m->result);
LLVMValueRef ret = wrap_try_return_error(c, &c_m->try_return_info);
genfun_build_ret(c, ret);
}

Expand Down
12 changes: 4 additions & 8 deletions src/libponyc/codegen/gendesc.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,7 @@ static LLVMValueRef make_unbox_function(compile_t* c, reach_type_t* t,
LLVMTypeRef ret_type = NULL;
if(needs_error_wrap)
{
compile_type_t* wrapped_c_t = (compile_type_t * )c_m->try_return_info.t->c_type;
ret_type = wrapped_c_t->use_type;
ret_type = get_try_return_wrapped_type(&c_m->try_return_info);
}
else
{
Expand Down Expand Up @@ -132,7 +131,7 @@ static LLVMValueRef make_unbox_function(compile_t* c, reach_type_t* t,

if(needs_error_wrap)
{
result = wrap_try_return_success(c, &c_m->try_return_info, result, m->result);
result = wrap_try_return_success(c, &c_m->try_return_info, result);
}

genfun_build_ret(c, result);
Expand Down Expand Up @@ -217,9 +216,7 @@ static LLVMValueRef make_error_wrap_function(compile_t* c,

TryReturnInfo tr_info = init_try_return_info();

compile_type_t* ret_c_t = (compile_type_t*)m->result->c_type;
LLVMTypeRef wrapped_ret =
generate_try_return_type(c, &tr_info, m->result, ret_c_t->use_type);
LLVMTypeRef wrapped_ret = generate_try_return_type(c, &tr_info, m->result);

const char* wrap_name = genname_error_wrap(m->full_name);
LLVMTypeRef wrap_type = LLVMFunctionType(wrapped_ret, params, count, false);
Expand All @@ -236,12 +233,11 @@ static LLVMValueRef make_error_wrap_function(compile_t* c,
LLVMValueRef result = codegen_call(c, f_type, c_m->func, args, count,
m->cap != TK_AT);

result = wrap_try_return_success(c, &tr_info, result, m->result);
result = wrap_try_return_success(c, &tr_info, result);
genfun_build_ret(c, result);

codegen_finishfun(c);

delete_try_return_info(&tr_info);
ponyint_pool_free_size(buf_size, params);
ponyint_pool_free_size(args_size, args);
return wrap_fun;
Expand Down
75 changes: 35 additions & 40 deletions src/libponyc/codegen/genfun.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@

static void compile_method_free(void* p)
{
compile_method_t* c_m = (compile_method_t*)p;
delete_try_return_info(&c_m->try_return_info);
POOL_FREE(compile_method_t, p);
}

Expand Down Expand Up @@ -122,9 +120,7 @@ static void make_signature(compile_t* c, reach_type_t* t,
LLVMTypeRef partial_ret_type = NULL;
if(ast_id(ast_childidx(m->fun->ast, 5)) == TK_QUESTION)
{
compile_type_t* res_c_t = (compile_type_t*)m->result->c_type;
partial_ret_type = generate_try_return_type(c, &c_m->try_return_info, m->result,
res_c_t->use_type);
partial_ret_type = generate_try_return_type(c, &c_m->try_return_info, m->result);
}

if(m->return_by_value)
Expand Down Expand Up @@ -169,21 +165,13 @@ static void make_signature(compile_t* c, reach_type_t* t,
{
// First argument when return by value is a pointer where the
// value should be stored.
if(c_m->try_return_info.return_type != TRYRETURNTYPE_NONE)
if(m->result->underlying != TK_TUPLETYPE)
{
compile_type_t* partial_ret_c_t = (compile_type_t*)c_m->try_return_info.t->c_type;
tparams[0] = partial_ret_c_t->use_type;
tparams[0] = ((compile_type_t*)m->result->c_type)->use_type;
}
else
{
if(m->result->underlying != TK_TUPLETYPE)
{
tparams[0] = ((compile_type_t*)m->result->c_type)->use_type;
}
else
{
tparams[0] = ((compile_type_t*)m->result->c_type)->structure_ptr;
}
tparams[0] = ((compile_type_t*)m->result->c_type)->structure_ptr;
}
}
}
Expand Down Expand Up @@ -633,16 +621,8 @@ static bool genfun_fun(compile_t* c, reach_type_t* t, reach_method_t* m)

LLVMValueRef ret = NULL;

bool assign_cast = true;

if(c_m->try_return_info.return_type != TRYRETURNTYPE_NONE)
{
ret = wrap_try_return_success(c, &c_m->try_return_info, value, m->result);
}
else if(return_by_value && return_value_lowered)
if(return_by_value && return_value_lowered)
{
assign_cast = false;

if(m->result->underlying != TK_TUPLETYPE)
{
ret = load_lowered_return_value_from_ptr(c, value, r_type, m->result);
Expand All @@ -656,16 +636,24 @@ static bool genfun_fun(compile_t* c, reach_type_t* t, reach_method_t* m)
}
else
{
ret = value;
}
if(c_m->try_return_info.return_type == TRYRETURNTYPE_OTHER)
{
r_type = get_try_return_unwrapped_type(&c_m->try_return_info);
}

if(assign_cast)
{
ast_t* body_type = deferred_reify(m->fun, ast_type(body), c->opt);
ret = gen_assign_cast(c, r_type, ret, body_type);
ast_free_unattached(body_type);
if(c_m->try_return_info.return_type != TRYRETURNTYPE_BOOL)
{
ast_t* body_type = deferred_reify(m->fun, ast_type(body), c->opt);
ret = gen_assign_cast(c, r_type, value, body_type);
ast_free_unattached(body_type);

ast_free_unattached(r_result);
ast_free_unattached(r_result);
}

if(c_m->try_return_info.return_type != TRYRETURNTYPE_NONE)
{
ret = wrap_try_return_success(c, &c_m->try_return_info, ret);
}
}

if(ret == NULL)
Expand Down Expand Up @@ -756,7 +744,7 @@ static bool genfun_new(compile_t* c, reach_type_t* t, reach_method_t* m)

if(c_m->try_return_info.return_type != TRYRETURNTYPE_NONE)
{
value = wrap_try_return_success(c, &c_m->try_return_info, value, m->result);
value = wrap_try_return_success(c, &c_m->try_return_info, value);
}

// Return 'this'.
Expand Down Expand Up @@ -795,13 +783,18 @@ static bool genfun_newbe(compile_t* c, reach_type_t* t, reach_method_t* m)
if(value == NULL)
return false;

if(c_m->try_return_info.return_type != TRYRETURNTYPE_NONE)
codegen_scope_lifetime_end(c);

if(c_m->try_return_info.return_type == TRYRETURNTYPE_NONE)
{
value = wrap_try_return_success(c, &c_m->try_return_info, value, m->result);
genfun_build_ret_void(c);
}
else
{
value = wrap_try_return_success(c, &c_m->try_return_info, value);
genfun_build_ret(c, value);
}

codegen_scope_lifetime_end(c);
genfun_build_ret_void(c);
codegen_finishfun(c);

// Generate the sender.
Expand Down Expand Up @@ -841,6 +834,7 @@ static void copy_subordinate(reach_method_t* m)
compile_method_t* c_m2 = (compile_method_t*)m2->c_method;
c_m2->func_type = c_m->func_type;
c_m2->func = c_m->func;
c_m2->try_return_info = c_m->try_return_info;
m2 = m2->subordinate;
}
}
Expand Down Expand Up @@ -972,18 +966,19 @@ static bool genfun_forward(compile_t* c, reach_type_t* t,

if(c_m2->try_return_info.return_type != TRYRETURNTYPE_NONE)
{
ret = unwrap_try_return_value(c, &c_m2->try_return_info, ret, m2->result);
ret = unwrap_try_return_value_jump_if_error(c, &c_m2->try_return_info, ret);
}

ret = gen_assign_cast(c, ((compile_type_t*)m->result->c_type)->use_type, ret,
m2->result->ast_cap);

if(c_m->try_return_info.return_type != TRYRETURNTYPE_NONE)
{
ret = wrap_try_return_success(c, &c_m->try_return_info, ret, m->result);
ret = wrap_try_return_success(c, &c_m->try_return_info, ret);
}

genfun_build_ret(c, ret);

codegen_finishfun(c);
ponyint_pool_free_size(buf_size, args);

Expand Down
4 changes: 2 additions & 2 deletions src/libponyc/codegen/genprim.c
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ static void pointer_to_reftype(compile_t* c, void* data, token_id cap)

// We need to generate the TryReturnInfo here as it doesn't go through any
// make_signature
generate_try_return_type(c, &c_m->try_return_info, t, t_elem->use_type);
generate_try_return_type(c, &c_m->try_return_info, t);

start_function(c, t, m, t_elem->use_type, &c_t->use_type, 1);

Expand Down Expand Up @@ -586,7 +586,7 @@ static void nullable_pointer_apply(compile_t* c, void* data, token_id cap)

// We need to generate the TryReturnInfo here as it doesn't go through any
// make_signature
generate_try_return_type(c, &c_m->try_return_info, t, t_elem->use_type);
generate_try_return_type(c, &c_m->try_return_info, t);

start_function(c, t, m, t_elem->use_type, &c_t->use_type, 1);

Expand Down
Loading
Loading