2022-08-26 15:53:02 +01:00
const std = @import ( " std " ) ;
const zls = @import ( " zls " ) ;
2022-09-29 04:12:34 +01:00
const builtin = @import ( " builtin " ) ;
2022-08-26 15:53:02 +01:00
2022-09-18 23:47:06 +01:00
const helper = @import ( " ../helper.zig " ) ;
const Context = @import ( " ../context.zig " ) . Context ;
const ErrorBuilder = @import ( " ../ErrorBuilder.zig " ) ;
2022-08-26 15:53:02 +01:00
const types = zls . types ;
2022-09-16 01:33:49 +01:00
const offsets = zls . offsets ;
2022-08-26 15:53:02 +01:00
const allocator : std . mem . Allocator = std . testing . allocator ;
test " inlayhints - empty " {
try testInlayHints ( " " ) ;
}
test " inlayhints - function call " {
try testInlayHints (
\\fn foo(alpha: u32) void {}
\\const _ = foo(<alpha>5);
) ;
try testInlayHints (
\\fn foo(alpha: u32, beta: u64) void {}
\\const _ = foo(<alpha>5,<beta>4);
) ;
try testInlayHints (
\\fn foo(alpha: u32, beta: u64) void {}
\\const _ = foo( <alpha>3 + 2 , <beta>(3 - 2));
) ;
try testInlayHints (
\\fn foo(alpha: u32, beta: u64) void {}
\\const _ = foo(
\\ <alpha>3 + 2,
\\ <beta>(3 - 2),
\\);
) ;
}
test " inlayhints - function self parameter " {
try testInlayHints (
\\const Foo = struct { pub fn bar(self: *Foo, alpha: u32) void {} };
\\const foo: Foo = .{};
\\const _ = foo.bar(<alpha>5);
) ;
try testInlayHints (
\\const Foo = struct { pub fn bar(_: Foo, alpha: u32, beta: []const u8) void {} };
\\const foo: Foo = .{};
\\const _ = foo.bar(<alpha>5,<beta>"");
) ;
}
test " inlayhints - builtin call " {
try testInlayHints (
\\const _ = @intCast(<DestType>u32,<int>5);
) ;
try testInlayHints (
\\const _ = @memcpy(<dest>null,<source>null,<byte_count>0);
) ;
try testInlayHints (
\\const _ = @sizeOf(u32);
) ;
try testInlayHints (
\\const _ = @TypeOf(5);
) ;
}
fn testInlayHints ( source : [ ] const u8 ) ! void {
2022-09-18 23:47:06 +01:00
var phr = try helper . collectClearPlaceholders ( allocator , source ) ;
2022-08-26 15:53:02 +01:00
defer phr . deinit ( allocator ) ;
var ctx = try Context . init ( ) ;
defer ctx . deinit ( ) ;
2023-02-11 19:19:37 +00:00
const test_uri = try ctx . addDocument ( phr . new_source ) ;
2022-08-26 15:53:02 +01:00
const range = types . Range {
. start = types . Position { . line = 0 , . character = 0 } ,
2022-12-27 06:47:57 +00:00
. end = offsets . indexToPosition ( phr . new_source , phr . new_source . len , . @ " utf-16 " ) ,
2022-08-26 15:53:02 +01:00
} ;
const InlayHint = struct {
position : types . Position ,
label : [ ] const u8 ,
kind : types . InlayHintKind ,
} ;
2022-12-27 06:47:57 +00:00
const params = types . InlayHintParams {
. textDocument = . { . uri = test_uri } ,
. range = range ,
2022-08-26 15:53:02 +01:00
} ;
2022-12-27 06:47:57 +00:00
const response = try ctx . requestGetResponse ( ? [ ] InlayHint , " textDocument/inlayHint " , params ) ;
2022-09-18 23:47:06 +01:00
const hints : [ ] InlayHint = response . result orelse {
std . debug . print ( " Server returned `null` as the result \n " , . { } ) ;
return error . InvalidResponse ;
2022-08-26 15:53:02 +01:00
} ;
2023-03-21 00:33:56 +00:00
var error_builder = ErrorBuilder . init ( allocator ) ;
2022-09-18 23:47:06 +01:00
defer error_builder . deinit ( ) ;
errdefer error_builder . writeDebug ( ) ;
2022-08-26 15:53:02 +01:00
2023-03-21 00:33:56 +00:00
try error_builder . addFile ( test_uri , phr . new_source ) ;
2022-09-18 23:47:06 +01:00
var i : usize = 0 ;
outer : while ( i < phr . locations . len ) : ( i + = 1 ) {
const old_loc = phr . locations . items ( . old ) [ i ] ;
const new_loc = phr . locations . items ( . new ) [ i ] ;
2022-08-26 15:53:02 +01:00
2022-09-18 23:47:06 +01:00
const expected_name = offsets . locToSlice ( source , old_loc ) ;
const expected_label = expected_name [ 1 . . expected_name . len - 1 ] ; // convert <name> to name
2022-08-26 15:53:02 +01:00
2022-09-18 23:47:06 +01:00
const position = offsets . indexToPosition ( phr . new_source , new_loc . start , ctx . server . offset_encoding ) ;
2022-08-26 15:53:02 +01:00
for ( hints ) | hint | {
if ( position . line ! = hint . position . line or position . character ! = hint . position . character ) continue ;
2022-09-29 04:12:34 +01:00
2023-02-11 19:19:37 +00:00
if ( ! std . mem . endsWith ( u8 , hint . label , " : " ) ) {
2023-03-21 00:33:56 +00:00
try error_builder . msgAtLoc ( " label `{s}` must end with a colon! " , test_uri , new_loc , . err , . { hint . label } ) ;
2023-01-27 14:59:11 +00:00
}
2023-02-11 19:19:37 +00:00
const actual_label = hint . label [ 0 . . hint . label . len - 1 ] ;
2022-08-26 15:53:02 +01:00
2022-09-18 23:47:06 +01:00
if ( ! std . mem . eql ( u8 , expected_label , actual_label ) ) {
2023-03-21 00:33:56 +00:00
try error_builder . msgAtLoc ( " expected label `{s}` here but got `{s}`! " , test_uri , new_loc , . err , . { expected_label , actual_label } ) ;
2022-09-18 23:47:06 +01:00
}
if ( hint . kind ! = types . InlayHintKind . Parameter ) {
2023-03-21 00:33:56 +00:00
try error_builder . msgAtLoc ( " hint kind should be `{s}` but got `{s}`! " , test_uri , new_loc , . err , . { @tagName ( types . InlayHintKind . Parameter ) , @tagName ( hint . kind ) } ) ;
2022-09-18 23:47:06 +01:00
}
2022-08-26 15:53:02 +01:00
continue : outer ;
}
2023-03-21 00:33:56 +00:00
try error_builder . msgAtLoc ( " expected hint `{s}` here " , test_uri , new_loc , . err , . { expected_label } ) ;
2022-08-26 15:53:02 +01:00
}
2022-09-18 23:47:06 +01:00
if ( error_builder . hasMessages ( ) ) return error . InvalidResponse ;
2022-08-26 15:53:02 +01:00
}