@@ -292,8 +292,10 @@ func TestDiagnosticsRefreshSupport(t *testing.T) {
292292 // Initialize with diagnostic refresh support enabled
293293 resp , serverState := sendAndReceive [lsp.InitializeResult ](tester , "initialize" , InitializeParams {
294294 Capabilities : ClientCapabilities {
295- Diagnostics : DiagnosticWorkspaceClientCapabilities {
296- RefreshSupport : true ,
295+ Workspace : WorkspaceClientCapabilities {
296+ Diagnostics : DiagnosticWorkspaceClientCapabilities {
297+ RefreshSupport : true ,
298+ },
297299 },
298300 },
299301 })
@@ -305,8 +307,10 @@ func TestDiagnosticsRefreshSupport(t *testing.T) {
305307 tester2 := newLSPTester (t )
306308 resp2 , serverState2 := sendAndReceive [lsp.InitializeResult ](tester2 , "initialize" , InitializeParams {
307309 Capabilities : ClientCapabilities {
308- Diagnostics : DiagnosticWorkspaceClientCapabilities {
309- RefreshSupport : false ,
310+ Workspace : WorkspaceClientCapabilities {
311+ Diagnostics : DiagnosticWorkspaceClientCapabilities {
312+ RefreshSupport : false ,
313+ },
310314 },
311315 },
312316 })
@@ -357,6 +361,219 @@ func TestUnmarshalParamsErrors(t *testing.T) {
357361 }().Code )
358362}
359363
364+ func TestMultiFileNoDiagnostics (t * testing.T ) {
365+ tester := newLSPTester (t )
366+ tester .initialize ()
367+
368+ tester .setFileContents ("file:///testdir/users.zed" , "definition user {}" )
369+ tester .setFileContents ("file:///testdir/root.zed" , `use import
370+
371+ import "users.zed"
372+
373+ definition resource {
374+ relation viewer: user
375+ permission view = viewer
376+ }
377+ ` )
378+
379+ resp , _ := sendAndReceive [FullDocumentDiagnosticReport ](tester , "textDocument/diagnostic" ,
380+ TextDocumentDiagnosticParams {
381+ TextDocument : TextDocument {URI : "file:///testdir/root.zed" },
382+ })
383+ require .Equal (t , "full" , resp .Kind )
384+ require .Empty (t , resp .Items )
385+ }
386+
387+ func TestMultiFileUndefinedDefinitionDiagnostics (t * testing.T ) {
388+ tester := newLSPTester (t )
389+ tester .initialize ()
390+
391+ tester .setFileContents ("file:///testdir/broken.zed" , `
392+ definition resource {
393+ relation viewer: organization
394+ permission view = viewer
395+ }` )
396+ tester .setFileContents ("file:///testdir/root.zed" , `use import
397+
398+ import "broken.zed"
399+ ` )
400+
401+ resp , _ := sendAndReceive [FullDocumentDiagnosticReport ](tester , "textDocument/diagnostic" ,
402+ TextDocumentDiagnosticParams {
403+ TextDocument : TextDocument {URI : "file:///testdir/root.zed" },
404+ })
405+ require .Equal (t , "full" , resp .Kind )
406+ require .Len (t , resp .Items , 1 )
407+ require .Equal (t , lsp .Error , resp .Items [0 ].Severity )
408+ t .Log (resp .Items [0 ].Message )
409+ require .Contains (t , resp .Items [0 ].Message , "could not lookup definition `organization` for relation `viewer`: object definition `organization` not found" )
410+ }
411+
412+ func TestMultiFileBrokenImportDiagnostics (t * testing.T ) {
413+ tester := newLSPTester (t )
414+ tester .initialize ()
415+
416+ tester .setFileContents ("file:///testdir/root.zed" , `use import
417+ import "unknown.zed"
418+ ` )
419+
420+ resp , _ := sendAndReceive [FullDocumentDiagnosticReport ](tester , "textDocument/diagnostic" ,
421+ TextDocumentDiagnosticParams {
422+ TextDocument : TextDocument {URI : "file:///testdir/root.zed" },
423+ })
424+ require .Equal (t , "full" , resp .Kind )
425+ require .Len (t , resp .Items , 1 )
426+ require .Equal (t , lsp .Error , resp .Items [0 ].Severity )
427+ require .Contains (t , resp .Items [0 ].Message , "failed to read import \" unknown.zed\" : open unknown.zed: no such file or director" )
428+ }
429+
430+ func TestDefinitionSameFileTypeReference (t * testing.T ) {
431+ tester := newLSPTester (t )
432+ tester .initialize ()
433+
434+ tester .setFileContents ("file:///test" , `definition user {}
435+
436+ definition resource {
437+ relation viewer: user
438+ permission view = viewer
439+ }
440+ ` )
441+
442+ // Click on "user" in "relation viewer: user" (line 3, character 18)
443+ resp , _ := sendAndReceive [lsp.Location ](tester , "textDocument/definition" ,
444+ lsp.TextDocumentPositionParams {
445+ TextDocument : lsp.TextDocumentIdentifier {URI : "file:///test" },
446+ Position : lsp.Position {Line : 3 , Character : 18 },
447+ })
448+ require .Equal (t , lsp .DocumentURI ("file:///test" ), resp .URI )
449+ require .Equal (t , 0 , resp .Range .Start .Line )
450+ require .Equal (t , len ("definition " ), resp .Range .Start .Character )
451+ }
452+
453+ func TestDefinitionSameFileRelationReference (t * testing.T ) {
454+ tester := newLSPTester (t )
455+ tester .initialize ()
456+
457+ tester .setFileContents ("file:///test" , `definition user {}
458+
459+ definition resource {
460+ relation viewer: user
461+ permission view = viewer
462+ }
463+ ` )
464+
465+ // Click on "viewer" in "permission view = viewer" (line 4, character 19)
466+ resp , _ := sendAndReceive [lsp.Location ](tester , "textDocument/definition" ,
467+ lsp.TextDocumentPositionParams {
468+ TextDocument : lsp.TextDocumentIdentifier {URI : "file:///test" },
469+ Position : lsp.Position {Line : 4 , Character : 19 },
470+ })
471+ require .Equal (t , lsp .DocumentURI ("file:///test" ), resp .URI )
472+ require .Equal (t , 3 , resp .Range .Start .Line )
473+ require .Equal (t , len ("\t relation " ), resp .Range .Start .Character )
474+ }
475+
476+ func TestDefinitionCrossFileTypeReference (t * testing.T ) {
477+ tester := newLSPTester (t )
478+ tester .initialize ()
479+
480+ tester .setFileContents ("file:///testdir/users.zed" , "definition user {}" )
481+ tester .setFileContents ("file:///testdir/root.zed" , `use import
482+
483+ import "users.zed"
484+
485+ definition resource {
486+ relation viewer: user
487+ permission view = viewer
488+ }
489+ ` )
490+
491+ // Click on "user" in "relation viewer: user" (line 5, character 18)
492+ // It should point to "users.zed"
493+ resp , _ := sendAndReceive [lsp.Location ](tester , "textDocument/definition" ,
494+ lsp.TextDocumentPositionParams {
495+ TextDocument : lsp.TextDocumentIdentifier {URI : "file:///testdir/root.zed" },
496+ Position : lsp.Position {Line : 5 , Character : 18 },
497+ })
498+ require .Equal (t , lsp .DocumentURI ("file:///testdir/users.zed" ), resp .URI )
499+ require .Equal (t , 0 , resp .Range .Start .Line )
500+ require .Equal (t , len ("definition " ), resp .Range .Start .Character )
501+ }
502+
503+ func TestDefinitionImportReference (t * testing.T ) {
504+ tester := newLSPTester (t )
505+ tester .initialize ()
506+
507+ tester .setFileContents ("file:///testdir/users.zed" , "definition user {}" )
508+ tester .setFileContents ("file:///testdir/root.zed" , `use import
509+
510+ import "users.zed"
511+
512+ definition resource {
513+ relation viewer: user
514+ permission view = viewer
515+ }
516+ ` )
517+
518+ // Click on import "users.zed" (line 2, character 10)
519+ // It should point on the very begginning of "users.zed"
520+ resp , _ := sendAndReceive [lsp.Location ](tester , "textDocument/definition" ,
521+ lsp.TextDocumentPositionParams {
522+ TextDocument : lsp.TextDocumentIdentifier {URI : "file:///testdir/root.zed" },
523+ Position : lsp.Position {Line : 2 , Character : 10 },
524+ })
525+ require .Equal (t , lsp .DocumentURI ("file:///testdir/users.zed" ), resp .URI )
526+ require .Equal (t , 0 , resp .Range .Start .Line )
527+ require .Equal (t , 0 , resp .Range .Start .Character )
528+ }
529+
530+ func TestDefinitionCrossFileCaveatReference (t * testing.T ) {
531+ tester := newLSPTester (t )
532+ tester .initialize ()
533+
534+ tester .setFileContents ("file:///testdir/caveats.zed" , `caveat some_caveat(some_param int) {
535+ some_param < 100
536+ }` )
537+ tester .setFileContents ("file:///testdir/root.zed" , `use import
538+
539+ import "caveats.zed"
540+
541+ definition user {}
542+
543+ definition resource {
544+ relation viewer: user with some_caveat
545+ }
546+ ` )
547+
548+ // Click on "some_caveat" in "relation viewer: user with some_caveat" (line 7, character 30)
549+ // "\trelation viewer: user with some_caveat"
550+ // 0 1 2 3
551+ // 0123456789012345678901234567890123456789
552+ resp , _ := sendAndReceive [lsp.Location ](tester , "textDocument/definition" ,
553+ lsp.TextDocumentPositionParams {
554+ TextDocument : lsp.TextDocumentIdentifier {URI : "file:///testdir/root.zed" },
555+ Position : lsp.Position {Line : 7 , Character : 30 },
556+ })
557+ require .Equal (t , lsp .DocumentURI ("file:///testdir/caveats.zed" ), resp .URI )
558+ require .Equal (t , 0 , resp .Range .Start .Line )
559+ require .Equal (t , len ("caveat " ), resp .Range .Start .Character )
560+ }
561+
562+ func TestDefinitionNoReference (t * testing.T ) {
563+ tester := newLSPTester (t )
564+ tester .initialize ()
565+
566+ tester .setFileContents ("file:///test" , "definition user {}" )
567+
568+ // Click on whitespace / keyword where no reference exists
569+ resp , _ := sendAndReceive [* lsp.Location ](tester , "textDocument/definition" ,
570+ lsp.TextDocumentPositionParams {
571+ TextDocument : lsp.TextDocumentIdentifier {URI : "file:///test" },
572+ Position : lsp.Position {Line : 0 , Character : 0 },
573+ })
574+ require .Nil (t , resp )
575+ }
576+
360577func TestInvalidParams (t * testing.T ) {
361578 err := invalidParams (errors .New ("test error" ))
362579 require .Equal (t , int64 (jsonrpc2 .CodeInvalidParams ), err .Code )
0 commit comments