this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

lsp/server: force-load all packages for completions within embedded files

Completions and Hover for embedded files should both behave the same
way: the embedded file is "upstream", just like an imported package, but
unlike an imported package, completions and hover are calculated by
looking at downstream - i.e. where the embedded file is actually
embedded.

Therefore, completions should also force-load all packages within the
current module for non-cue files, to identify where the file might be
embedded.

Signed-off-by: Matthew Sackman <matthew@cue.works>
Change-Id: I86dfd965baf564f32da01599c79a57deed88b83d
Reviewed-on: https://cue.gerrithub.io/c/cue-lang/cue/+/1231012
TryBot-Result: CUEcueckoo <cueckoo@cuelang.org>
Reviewed-by: Daniel Martí <mvdan@mvdan.cc>
Unity-Result: CUE porcuepine <cue.porcuepine@gmail.com>

+57 -5
+56 -4
cmd/cue/cmd/integration/workspace/embedded_test.go
··· 267 267 }) 268 268 } 269 269 270 - func TestEmbedHover(t *testing.T) { 271 - const files = ` 270 + const filesHoverComplete = ` 272 271 -- cue.mod/module.cue -- 273 272 module: "mod.example/x" 274 273 language: version: "v0.16.0" ··· 296 295 s: field: { 297 296 // does the field contain sheep? 298 297 sheep: bool 298 + horses: bool 299 299 } 300 300 -- data/file.json -- 301 301 { ··· 322 322 } 323 323 ` 324 324 325 - WithOptions(RootURIAsDefaultFolder()).Run(t, files, func(t *testing.T, env *Env) { 325 + func TestEmbedHover(t *testing.T) { 326 + WithOptions(RootURIAsDefaultFolder()).Run(t, filesHoverComplete, func(t *testing.T, env *Env) { 326 327 rootURI := env.Sandbox.Workdir.RootURI() 327 328 328 329 env.OpenFile("data/file.json") ··· 335 336 ) 336 337 337 338 mappers := make(map[string]*protocol.Mapper) 338 - for _, file := range txtar.Parse([]byte(files)).Files { 339 + for _, file := range txtar.Parse([]byte(filesHoverComplete)).Files { 339 340 mapper := protocol.NewMapper(rootURI+"/"+protocol.DocumentURI(file.Name), file.Data) 340 341 mappers[file.Name] = mapper 341 342 } ··· 383 384 qt.Assert(t, qt.Equals(got.Value, expectation), qt.Commentf("%v(+%d)", p, i)) 384 385 } 385 386 } 387 + 388 + // Calling Hover should have caused package x:a to be loaded 389 + // because that's the package which embeds the json files. 390 + env.Await( 391 + LogMatching(protocol.Debug, 1, false, `Package dirs=\[%v\] importPath=mod\.example/x@v0:a Created`, rootURI), 392 + ) 386 393 387 394 // Test that all offsets not explicitly mentioned in 388 395 // expectations, have no hovers (for the open files only). ··· 407 414 qt.Assert(t, qt.IsNil(got), qt.Commentf("%v:%v (0-based)", filename, pos)) 408 415 } 409 416 } 417 + }) 418 + } 410 419 420 + func TestEmbedCompletion(t *testing.T) { 421 + WithOptions(RootURIAsDefaultFolder()).Run(t, filesHoverComplete, func(t *testing.T, env *Env) { 422 + rootURI := env.Sandbox.Workdir.RootURI() 423 + 424 + env.OpenFile("data/file.json") 425 + env.Await( 426 + env.DoneWithOpen(), 427 + LogMatching(protocol.Debug, 1, false, `Package dirs=\[%v/data\] importPath=mod\.example/x/data@v0:_.+ Created`, rootURI), 428 + LogMatching(protocol.Debug, 1, false, `Package dirs=\[%v/data\] importPath=mod\.example/x/data@v0:_.+ Reloaded`, rootURI), 429 + NoLogMatching(protocol.Debug, `Package dirs=\[%v/data\] importPath=mod\.example/x@v0:a Created`, rootURI), 430 + ) 431 + 432 + mappers := make(map[string]*protocol.Mapper) 433 + for _, file := range txtar.Parse([]byte(filesHoverComplete)).Files { 434 + mapper := protocol.NewMapper(rootURI+"/"+protocol.DocumentURI(file.Name), file.Data) 435 + mappers[file.Name] = mapper 436 + } 437 + 438 + testCases := map[position][]string{ 439 + fln("data/file.json", 3, 1, `"`): {`"sheep"`, `"cows"`, `"horses"`}, 440 + fln("data/file.json", 6, 1, `"`): {`"field"`, `"fieldCount"`}, 441 + } 442 + 443 + for p, expectedLabels := range testCases { 444 + p.determinePos(mappers) 445 + completions := env.Completion(protocol.Location{ 446 + URI: p.mapper.URI, 447 + Range: protocol.Range{Start: p.pos}, 448 + }) 449 + qt.Assert(t, qt.IsNotNil(completions)) 450 + items := completions.Items 451 + gotLabels := make([]string, len(items)) 452 + for i, item := range items { 453 + gotLabels[i] = item.Label 454 + } 455 + qt.Assert(t, qt.ContentEquals(gotLabels, expectedLabels)) 456 + } 457 + 458 + // Calling Hover should have caused package x:a to be loaded 459 + // because that's the package which embeds the json files. 460 + env.Await( 461 + LogMatching(protocol.Debug, 1, false, `Package dirs=\[%v\] importPath=mod\.example/x@v0:a Created`, rootURI), 462 + ) 411 463 }) 412 464 } 413 465
+1 -1
internal/lsp/server/eval.go
··· 34 34 func (s *server) Completion(ctx context.Context, params *protocol.CompletionParams) (*protocol.CompletionList, error) { 35 35 uri := params.TextDocument.URI 36 36 w := s.workspace 37 - file, fe, srcMapper, err := w.FileEvaluatorForURI(uri, cache.LoadNothing) 37 + file, fe, srcMapper, err := w.FileEvaluatorForURI(uri, cache.LoadAllIfNonCue) 38 38 if file == nil || err != nil { 39 39 return nil, err 40 40 }