@@ -3,6 +3,7 @@ use anyhow::Error;
3
3
use anyhow:: Result ;
4
4
use anyhow:: bail;
5
5
use biome_deserialize:: Merge ;
6
+ use biome_deserialize:: StringSet ;
6
7
use futures:: Sink ;
7
8
use futures:: SinkExt ;
8
9
use futures:: Stream ;
@@ -1326,7 +1327,6 @@ async fn multiple_projects() -> Result<()> {
1326
1327
} )
1327
1328
. await ?
1328
1329
. unwrap ( ) ;
1329
- println ! ( "{:?}" , res_ws_two) ;
1330
1330
1331
1331
// only the first one has a db connection and should return completion items
1332
1332
assert ! ( !match res_ws_one {
@@ -1343,3 +1343,203 @@ async fn multiple_projects() -> Result<()> {
1343
1343
1344
1344
Ok ( ( ) )
1345
1345
}
1346
+
1347
+ #[ tokio:: test]
1348
+ async fn extends_config ( ) -> Result < ( ) > {
1349
+ let factory = ServerFactory :: default ( ) ;
1350
+ let mut fs = MemoryFileSystem :: default ( ) ;
1351
+ let test_db = get_new_test_db ( ) . await ;
1352
+
1353
+ let setup = r#"
1354
+ create table public.extends_config_test (
1355
+ id serial primary key,
1356
+ name varchar(255) not null
1357
+ );
1358
+ "# ;
1359
+
1360
+ test_db
1361
+ . execute ( setup)
1362
+ . await
1363
+ . expect ( "Failed to setup test database" ) ;
1364
+
1365
+ // shared config with default db connection
1366
+ let conf_with_db = PartialConfiguration :: init ( ) ;
1367
+ fs. insert (
1368
+ url ! ( "postgrestools.jsonc" ) . to_file_path ( ) . unwrap ( ) ,
1369
+ serde_json:: to_string_pretty ( & conf_with_db) . unwrap ( ) ,
1370
+ ) ;
1371
+
1372
+ // test_one extends the shared config but sets our test db
1373
+ let mut conf_with_db = PartialConfiguration :: init ( ) ;
1374
+ conf_with_db. merge_with ( PartialConfiguration {
1375
+ extends : Some ( StringSet :: from_iter ( [ "../postgrestools.jsonc" . to_string ( ) ] ) ) ,
1376
+ db : Some ( PartialDatabaseConfiguration {
1377
+ database : Some (
1378
+ test_db
1379
+ . connect_options ( )
1380
+ . get_database ( )
1381
+ . unwrap ( )
1382
+ . to_string ( ) ,
1383
+ ) ,
1384
+ ..Default :: default ( )
1385
+ } ) ,
1386
+ ..Default :: default ( )
1387
+ } ) ;
1388
+ fs. insert (
1389
+ url ! ( "test_one/postgrestools.jsonc" ) . to_file_path ( ) . unwrap ( ) ,
1390
+ serde_json:: to_string_pretty ( & conf_with_db) . unwrap ( ) ,
1391
+ ) ;
1392
+
1393
+ // test_two extends it but keeps the default one
1394
+ let mut conf_without_db = PartialConfiguration :: init ( ) ;
1395
+ conf_without_db. merge_with ( PartialConfiguration {
1396
+ extends : Some ( StringSet :: from_iter ( [ "../postgrestools.jsonc" . to_string ( ) ] ) ) ,
1397
+ ..Default :: default ( )
1398
+ } ) ;
1399
+ fs. insert (
1400
+ url ! ( "test_two/postgrestools.jsonc" ) . to_file_path ( ) . unwrap ( ) ,
1401
+ serde_json:: to_string_pretty ( & conf_without_db) . unwrap ( ) ,
1402
+ ) ;
1403
+
1404
+ let ( service, client) = factory
1405
+ . create_with_fs ( None , DynRef :: Owned ( Box :: new ( fs) ) )
1406
+ . into_inner ( ) ;
1407
+
1408
+ let ( stream, sink) = client. split ( ) ;
1409
+ let mut server = Server :: new ( service) ;
1410
+
1411
+ let ( sender, _) = channel ( CHANNEL_BUFFER_SIZE ) ;
1412
+ let reader = tokio:: spawn ( client_handler ( stream, sink, sender) ) ;
1413
+
1414
+ server. initialize_workspaces ( ) . await ?;
1415
+ server. initialized ( ) . await ?;
1416
+
1417
+ server. load_configuration ( ) . await ?;
1418
+
1419
+ server
1420
+ . open_named_document (
1421
+ "select from public.extends_config_test;\n " ,
1422
+ url ! ( "test_one/document.sql" ) ,
1423
+ "sql" ,
1424
+ )
1425
+ . await ?;
1426
+
1427
+ server
1428
+ . change_named_document (
1429
+ url ! ( "test_one/document.sql" ) ,
1430
+ 3 ,
1431
+ vec ! [ TextDocumentContentChangeEvent {
1432
+ range: Some ( Range {
1433
+ start: Position {
1434
+ line: 0 ,
1435
+ character: 7 ,
1436
+ } ,
1437
+ end: Position {
1438
+ line: 0 ,
1439
+ character: 7 ,
1440
+ } ,
1441
+ } ) ,
1442
+ range_length: Some ( 0 ) ,
1443
+ text: " " . to_string( ) ,
1444
+ } ] ,
1445
+ )
1446
+ . await ?;
1447
+
1448
+ let res_ws_one = server
1449
+ . get_completion ( CompletionParams {
1450
+ work_done_progress_params : WorkDoneProgressParams :: default ( ) ,
1451
+ partial_result_params : PartialResultParams :: default ( ) ,
1452
+ context : None ,
1453
+ text_document_position : TextDocumentPositionParams {
1454
+ text_document : TextDocumentIdentifier {
1455
+ uri : url ! ( "test_one/document.sql" ) ,
1456
+ } ,
1457
+ position : Position {
1458
+ line : 0 ,
1459
+ character : 8 ,
1460
+ } ,
1461
+ } ,
1462
+ } )
1463
+ . await ?
1464
+ . unwrap ( ) ;
1465
+
1466
+ server
1467
+ . open_named_document (
1468
+ "select from public.users;\n " ,
1469
+ url ! ( "test_two/document.sql" ) ,
1470
+ "sql" ,
1471
+ )
1472
+ . await ?;
1473
+
1474
+ server
1475
+ . change_named_document (
1476
+ url ! ( "test_two/document.sql" ) ,
1477
+ 3 ,
1478
+ vec ! [ TextDocumentContentChangeEvent {
1479
+ range: Some ( Range {
1480
+ start: Position {
1481
+ line: 0 ,
1482
+ character: 7 ,
1483
+ } ,
1484
+ end: Position {
1485
+ line: 0 ,
1486
+ character: 7 ,
1487
+ } ,
1488
+ } ) ,
1489
+ range_length: Some ( 0 ) ,
1490
+ text: " " . to_string( ) ,
1491
+ } ] ,
1492
+ )
1493
+ . await ?;
1494
+
1495
+ let res_ws_two = server
1496
+ . get_completion ( CompletionParams {
1497
+ work_done_progress_params : WorkDoneProgressParams :: default ( ) ,
1498
+ partial_result_params : PartialResultParams :: default ( ) ,
1499
+ context : None ,
1500
+ text_document_position : TextDocumentPositionParams {
1501
+ text_document : TextDocumentIdentifier {
1502
+ uri : url ! ( "test_two/document.sql" ) ,
1503
+ } ,
1504
+ position : Position {
1505
+ line : 0 ,
1506
+ character : 8 ,
1507
+ } ,
1508
+ } ,
1509
+ } )
1510
+ . await ?
1511
+ . unwrap ( ) ;
1512
+
1513
+ let items_one = match res_ws_one {
1514
+ CompletionResponse :: Array ( ref a) => a,
1515
+ CompletionResponse :: List ( ref l) => & l. items ,
1516
+ } ;
1517
+
1518
+ // test one should have our test db connection and should return the completion items for the `extends_config_test` table
1519
+ assert ! ( items_one. iter( ) . any( |item| {
1520
+ item. label_details. clone( ) . is_some_and( |details| {
1521
+ details
1522
+ . description
1523
+ . is_some_and( |desc| desc. contains( "public.extends_config_test" ) )
1524
+ } )
1525
+ } ) ) ;
1526
+
1527
+ let items_two = match res_ws_two {
1528
+ CompletionResponse :: Array ( ref a) => a,
1529
+ CompletionResponse :: List ( ref l) => & l. items ,
1530
+ } ;
1531
+
1532
+ // test two should not have a db connection and should not return the completion items for the `extends_config_test` table
1533
+ assert ! ( !items_two. iter( ) . any( |item| {
1534
+ item. label_details. clone( ) . is_some_and( |details| {
1535
+ details
1536
+ . description
1537
+ . is_some_and( |desc| desc. contains( "public.extends_config_test" ) )
1538
+ } )
1539
+ } ) ) ;
1540
+
1541
+ server. shutdown ( ) . await ?;
1542
+ reader. abort ( ) ;
1543
+
1544
+ Ok ( ( ) )
1545
+ }
0 commit comments