this repo has no description
0
fork

Configure Feed

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

gopls/cmd: remove unused code

All this code allowed some use of certain LSP features directly from the
command line. However, the code was bitrotted, unsupported, and in a few
cases still mentioned Go instead of CUE.

Delete it all; it can be resurrected later if necessary.

Signed-off-by: Matthew Sackman <matthew@cue.works>
Change-Id: I4df1662cc5a8c46584344b054dad6d82b5dff47b
Reviewed-on: https://cue.gerrithub.io/c/cue-lang/cue/+/1233638
Reviewed-by: Roger Peppe <rogpeppe@gmail.com>
TryBot-Result: CUEcueckoo <cueckoo@cuelang.org>

-665
-590
internal/golangorgx/gopls/cmd/cmd.go
··· 11 11 "context" 12 12 "flag" 13 13 "fmt" 14 - "log" 15 - "os" 16 - "path/filepath" 17 14 "reflect" 18 - "slices" 19 15 "sort" 20 16 "strings" 21 - "sync" 22 17 "text/tabwriter" 23 18 "time" 24 19 25 - "cuelang.org/go/internal/golangorgx/gopls/lsprpc" 26 - "cuelang.org/go/internal/golangorgx/gopls/protocol" 27 - "cuelang.org/go/internal/golangorgx/gopls/protocol/command" 28 20 "cuelang.org/go/internal/golangorgx/gopls/settings" 29 - "cuelang.org/go/internal/golangorgx/gopls/util/browser" 30 - "cuelang.org/go/internal/golangorgx/tools/diff" 31 - "cuelang.org/go/internal/golangorgx/tools/jsonrpc2" 32 21 "cuelang.org/go/internal/golangorgx/tools/tool" 33 - "cuelang.org/go/internal/lsp/cache" 34 - "cuelang.org/go/internal/lsp/server" 35 22 ) 36 23 37 24 // Application is the main application as passed to tool.Main ··· 59 46 // VeryVerbose enables a higher level of verbosity in logging output. 60 47 VeryVerbose bool `flag:"vv,veryverbose" help:"very verbose output"` 61 48 62 - // Control ocagent export of telemetry 63 - OCAgent string `flag:"ocagent" help:"the address of the ocagent (e.g. http://localhost:55678), or off"` 64 - 65 49 // PrepareOptions is called to update the options when a new view is built. 66 50 // It is primarily to allow the behavior of gopls to be modified by hooks. 67 51 PrepareOptions func(*settings.Options) 68 - 69 - // editFlags holds flags that control how file edit operations 70 - // are applied, in particular when the server makes an ApplyEdits 71 - // downcall to the client. Present only for commands that apply edits. 72 - editFlags *EditFlags 73 - } 74 - 75 - // EditFlags defines flags common to {fix,format,imports,rename} 76 - // that control how edits are applied to the client's files. 77 - // 78 - // The type is exported for flag reflection. 79 - // 80 - // The -write, -diff, and -list flags are orthogonal but any 81 - // of them suppresses the default behavior, which is to print 82 - // the edited file contents. 83 - type EditFlags struct { 84 - Write bool `flag:"w,write" help:"write edited content to source files"` 85 - Preserve bool `flag:"preserve" help:"with -write, make copies of original files"` 86 - Diff bool `flag:"d,diff" help:"display diffs instead of edited file content"` 87 - List bool `flag:"l,list" help:"display names of edited files"` 88 - } 89 - 90 - func (app *Application) verbose() bool { 91 - return app.Verbose || app.VeryVerbose 92 52 } 93 53 94 54 // New returns a new Application ready to run. 95 55 func New(options func(*settings.Options)) *Application { 96 56 app := &Application{ 97 57 options: options, 98 - OCAgent: "off", //TODO: Remove this line to default the exporter to on 99 58 100 59 Serve: Serve{ 101 60 RemoteListenTimeout: 1 * time.Minute, ··· 141 100 fmt.Fprint(w, "\t\nFeatures\t\n") 142 101 for _, c := range app.featureCommands() { 143 102 fmt.Fprintf(w, " %s\t%s\n", c.Name(), c.ShortHelp()) 144 - } 145 - if app.verbose() { 146 - fmt.Fprint(w, "\t\nInternal Use Only\t\n") 147 - for _, c := range app.internalCommands() { 148 - fmt.Fprintf(w, " %s\t%s\n", c.Name(), c.ShortHelp()) 149 - } 150 103 } 151 104 fmt.Fprint(w, "\nflags:\n") 152 105 printFlagDefaults(f) ··· 247 200 var commands []tool.Application 248 201 commands = append(commands, app.mainCommands()...) 249 202 commands = append(commands, app.featureCommands()...) 250 - commands = append(commands, app.internalCommands()...) 251 203 return commands 252 204 } 253 205 ··· 258 210 &apiJSON{app: app}, 259 211 &licenses{app: app}, 260 212 } 261 - } 262 - 263 - func (app *Application) internalCommands() []tool.Application { 264 - return []tool.Application{} 265 213 } 266 214 267 215 func (app *Application) featureCommands() []tool.Application { 268 216 return []tool.Application{ 269 - &format{app: app}, 270 217 newRemote(app), 271 218 } 272 219 } 273 - 274 - var ( 275 - internalMu sync.Mutex 276 - internalConnections = make(map[string]*connection) 277 - ) 278 - 279 - // connect creates and initializes a new in-process cuelsp session. 280 - // 281 - // If onProgress is set, it is called for each new progress notification. 282 - func (app *Application) connect(ctx context.Context, onProgress func(*protocol.ProgressParams)) (*connection, error) { 283 - switch { 284 - case app.Remote == "": 285 - client := newClient(app, onProgress) 286 - options := settings.DefaultOptions(app.options) 287 - cache, err := cache.New() 288 - if err != nil { 289 - return nil, err 290 - } 291 - server := server.New(cache, client, options) 292 - conn := newConnection(server, client) 293 - if err := conn.initialize(protocol.WithClient(ctx, client), app.options); err != nil { 294 - return nil, err 295 - } 296 - return conn, nil 297 - 298 - default: 299 - return app.connectRemote(ctx, app.Remote) 300 - } 301 - } 302 - 303 - func (app *Application) connectRemote(ctx context.Context, remote string) (*connection, error) { 304 - conn, err := lsprpc.ConnectToRemote(ctx, remote) 305 - if err != nil { 306 - return nil, err 307 - } 308 - stream := jsonrpc2.NewHeaderStream(conn) 309 - cc := jsonrpc2.NewConn(stream) 310 - server := protocol.ServerDispatcher(cc) 311 - client := newClient(app, nil) 312 - connection := newConnection(server, client) 313 - ctx = protocol.WithClient(ctx, connection.client) 314 - cc.Go(ctx, 315 - protocol.Handlers( 316 - protocol.ClientHandler(client, jsonrpc2.MethodNotFound))) 317 - return connection, connection.initialize(ctx, app.options) 318 - } 319 - 320 - func (c *connection) initialize(ctx context.Context, options func(*settings.Options)) error { 321 - wd, err := os.Getwd() 322 - if err != nil { 323 - return fmt.Errorf("finding workdir: %v", err) 324 - } 325 - params := &protocol.ParamInitialize{} 326 - params.RootURI = protocol.URIFromPath(wd) 327 - params.Capabilities.Workspace.Configuration = true 328 - 329 - // Make sure to respect configured options when sending initialize request. 330 - opts := settings.DefaultOptions(options) 331 - // If you add an additional option here, you must update the map key in connect. 332 - params.Capabilities.TextDocument.Hover = &protocol.HoverClientCapabilities{ 333 - ContentFormat: []protocol.MarkupKind{opts.PreferredContentFormat}, 334 - } 335 - params.Capabilities.TextDocument.DocumentSymbol.HierarchicalDocumentSymbolSupport = opts.HierarchicalDocumentSymbolSupport 336 - params.Capabilities.TextDocument.SemanticTokens = protocol.SemanticTokensClientCapabilities{} 337 - params.Capabilities.TextDocument.SemanticTokens.Formats = []protocol.TokenFormat{"relative"} 338 - params.Capabilities.TextDocument.SemanticTokens.Requests.Range = &protocol.Or_ClientSemanticTokensRequestOptions_range{Value: true} 339 - //params.Capabilities.TextDocument.SemanticTokens.Requests.Range.Value = true 340 - params.Capabilities.TextDocument.SemanticTokens.Requests.Full = &protocol.Or_ClientSemanticTokensRequestOptions_full{Value: true} 341 - params.Capabilities.TextDocument.SemanticTokens.TokenTypes = protocol.SemanticTypes() 342 - params.Capabilities.TextDocument.SemanticTokens.TokenModifiers = protocol.SemanticModifiers() 343 - 344 - // If the subcommand has registered a progress handler, report the progress 345 - // capability. 346 - if c.client.onProgress != nil { 347 - params.Capabilities.Window.WorkDoneProgress = true 348 - } 349 - 350 - params.InitializationOptions = map[string]interface{}{ 351 - "symbolMatcher": string(opts.SymbolMatcher), 352 - } 353 - if _, err := c.Server.Initialize(ctx, params); err != nil { 354 - return err 355 - } 356 - if err := c.Server.Initialized(ctx, &protocol.InitializedParams{}); err != nil { 357 - return err 358 - } 359 - return nil 360 - } 361 - 362 - type connection struct { 363 - protocol.Server 364 - client *cmdClient 365 - } 366 - 367 - // cmdClient defines the protocol.Client interface behavior of the cuelsp CLI tool. 368 - type cmdClient struct { 369 - app *Application 370 - onProgress func(*protocol.ProgressParams) 371 - 372 - filesMu sync.Mutex // guards files map and each cmdFile.diagnostics 373 - files map[protocol.DocumentURI]*cmdFile 374 - } 375 - 376 - type cmdFile struct { 377 - uri protocol.DocumentURI 378 - mapper *protocol.Mapper 379 - err error 380 - diagnostics []protocol.Diagnostic 381 - } 382 - 383 - func newClient(app *Application, onProgress func(*protocol.ProgressParams)) *cmdClient { 384 - return &cmdClient{ 385 - app: app, 386 - onProgress: onProgress, 387 - files: make(map[protocol.DocumentURI]*cmdFile), 388 - } 389 - } 390 - 391 - func newConnection(server protocol.Server, client *cmdClient) *connection { 392 - return &connection{ 393 - Server: server, 394 - client: client, 395 - } 396 - } 397 - 398 - func (c *cmdClient) CodeLensRefresh(context.Context) error { return nil } 399 - 400 - func (c *cmdClient) FoldingRangeRefresh(context.Context) error { return nil } 401 - 402 - func (c *cmdClient) LogTrace(context.Context, *protocol.LogTraceParams) error { return nil } 403 - 404 - func (c *cmdClient) ShowMessage(ctx context.Context, p *protocol.ShowMessageParams) error { 405 - fmt.Fprintf(os.Stderr, "%s: %s\n", p.Type, p.Message) 406 - return nil 407 - } 408 - 409 - func (c *cmdClient) ShowMessageRequest(ctx context.Context, p *protocol.ShowMessageRequestParams) (*protocol.MessageActionItem, error) { 410 - return nil, nil 411 - } 412 - 413 - func (c *cmdClient) LogMessage(ctx context.Context, p *protocol.LogMessageParams) error { 414 - // This logic causes server logging to be double-prefixed with a timestamp. 415 - // 2023/11/08 10:50:21 Error:2023/11/08 10:50:21 <actual message> 416 - // TODO(adonovan): print just p.Message, plus a newline if needed? 417 - switch p.Type { 418 - case protocol.Error: 419 - log.Print("Error:", p.Message) 420 - case protocol.Warning: 421 - log.Print("Warning:", p.Message) 422 - case protocol.Info: 423 - if c.app.verbose() { 424 - log.Print("Info:", p.Message) 425 - } 426 - case protocol.Log: 427 - if c.app.verbose() { 428 - log.Print("Log:", p.Message) 429 - } 430 - default: 431 - if c.app.verbose() { 432 - log.Print(p.Message) 433 - } 434 - } 435 - return nil 436 - } 437 - 438 - func (c *cmdClient) Event(ctx context.Context, t *interface{}) error { return nil } 439 - 440 - func (c *cmdClient) RegisterCapability(ctx context.Context, p *protocol.RegistrationParams) error { 441 - return nil 442 - } 443 - 444 - func (c *cmdClient) UnregisterCapability(ctx context.Context, p *protocol.UnregistrationParams) error { 445 - return nil 446 - } 447 - 448 - func (c *cmdClient) WorkspaceFolders(ctx context.Context) ([]protocol.WorkspaceFolder, error) { 449 - return nil, nil 450 - } 451 - 452 - func (c *cmdClient) Configuration(ctx context.Context, p *protocol.ParamConfiguration) ([]interface{}, error) { 453 - results := make([]interface{}, len(p.Items)) 454 - for i, item := range p.Items { 455 - if item.Section != "cuelsp" { 456 - continue 457 - } 458 - m := map[string]interface{}{ 459 - "analyses": map[string]any{ 460 - "fillreturns": true, 461 - "nonewvars": true, 462 - "noresultvalues": true, 463 - "undeclaredname": true, 464 - }, 465 - } 466 - if c.app.VeryVerbose { 467 - m["verboseOutput"] = true 468 - } 469 - results[i] = m 470 - } 471 - return results, nil 472 - } 473 - 474 - func (c *cmdClient) ApplyEdit(ctx context.Context, p *protocol.ApplyWorkspaceEditParams) (*protocol.ApplyWorkspaceEditResult, error) { 475 - if err := c.applyWorkspaceEdit(&p.Edit); err != nil { 476 - return &protocol.ApplyWorkspaceEditResult{FailureReason: err.Error()}, nil 477 - } 478 - return &protocol.ApplyWorkspaceEditResult{Applied: true}, nil 479 - } 480 - 481 - // applyWorkspaceEdit applies a complete WorkspaceEdit to the client's 482 - // files, honoring the preferred edit mode specified by cli.app.editMode. 483 - // (Used by rename and by ApplyEdit downcalls.) 484 - func (cli *cmdClient) applyWorkspaceEdit(edit *protocol.WorkspaceEdit) error { 485 - var orderedURIs []protocol.DocumentURI 486 - edits := map[protocol.DocumentURI][]protocol.TextEdit{} 487 - for _, c := range edit.DocumentChanges { 488 - if c.TextDocumentEdit != nil { 489 - uri := c.TextDocumentEdit.TextDocument.URI 490 - edits[uri] = append(edits[uri], protocol.AsTextEdits(c.TextDocumentEdit.Edits)...) 491 - orderedURIs = append(orderedURIs, uri) 492 - } 493 - if c.RenameFile != nil { 494 - return fmt.Errorf("client does not support file renaming (%s -> %s)", 495 - c.RenameFile.OldURI, 496 - c.RenameFile.NewURI) 497 - } 498 - } 499 - slices.Sort(orderedURIs) 500 - for _, uri := range orderedURIs { 501 - f := cli.openFile(uri) 502 - if f.err != nil { 503 - return f.err 504 - } 505 - if err := applyTextEdits(f.mapper, edits[uri], cli.app.editFlags); err != nil { 506 - return err 507 - } 508 - } 509 - return nil 510 - } 511 - 512 - // applyTextEdits applies a list of edits to the mapper file content, 513 - // using the preferred edit mode. It is a no-op if there are no edits. 514 - func applyTextEdits(mapper *protocol.Mapper, edits []protocol.TextEdit, flags *EditFlags) error { 515 - if len(edits) == 0 { 516 - return nil 517 - } 518 - newContent, renameEdits, err := protocol.ApplyEdits(mapper, edits) 519 - if err != nil { 520 - return err 521 - } 522 - 523 - filename := mapper.URI.FilePath() 524 - 525 - if flags.List { 526 - fmt.Println(filename) 527 - } 528 - 529 - if flags.Write { 530 - if flags.Preserve { 531 - if err := os.Rename(filename, filename+".orig"); err != nil { 532 - return err 533 - } 534 - } 535 - if err := os.WriteFile(filename, newContent, 0644); err != nil { 536 - return err 537 - } 538 - } 539 - 540 - if flags.Diff { 541 - unified, err := diff.ToUnified(filename+".orig", filename, string(mapper.Content), renameEdits, diff.DefaultContextLines) 542 - if err != nil { 543 - return err 544 - } 545 - fmt.Print(unified) 546 - } 547 - 548 - // No flags: just print edited file content. 549 - // TODO(adonovan): how is this ever useful with multiple files? 550 - if !(flags.List || flags.Write || flags.Diff) { 551 - os.Stdout.Write(newContent) 552 - } 553 - 554 - return nil 555 - } 556 - 557 - func (c *cmdClient) PublishDiagnostics(ctx context.Context, p *protocol.PublishDiagnosticsParams) error { 558 - // Don't worry about diagnostics without versions. 559 - if p.Version == 0 { 560 - return nil 561 - } 562 - 563 - c.filesMu.Lock() 564 - defer c.filesMu.Unlock() 565 - 566 - file := c.getFile(p.URI) 567 - file.diagnostics = append(file.diagnostics, p.Diagnostics...) 568 - 569 - // Perform a crude in-place deduplication. 570 - // TODO(golang/go#60122): replace the gopls.diagnose_files 571 - // command with support for textDocument/diagnostic, 572 - // so that we don't need to do this de-duplication. 573 - type key [6]interface{} 574 - seen := make(map[key]bool) 575 - out := file.diagnostics[:0] 576 - for _, d := range file.diagnostics { 577 - var codeHref string 578 - if desc := d.CodeDescription; desc != nil { 579 - codeHref = desc.Href 580 - } 581 - k := key{d.Range, d.Severity, d.Code, codeHref, d.Source, d.Message} 582 - if !seen[k] { 583 - seen[k] = true 584 - out = append(out, d) 585 - } 586 - } 587 - file.diagnostics = out 588 - 589 - return nil 590 - } 591 - 592 - func (c *cmdClient) Progress(_ context.Context, params *protocol.ProgressParams) error { 593 - if c.onProgress != nil { 594 - c.onProgress(params) 595 - } 596 - return nil 597 - } 598 - 599 - func (c *cmdClient) ShowDocument(ctx context.Context, params *protocol.ShowDocumentParams) (*protocol.ShowDocumentResult, error) { 600 - var success bool 601 - if params.External { 602 - // Open URI in external browser. 603 - success = browser.Open(params.URI) 604 - } else { 605 - // Open file in editor, optionally taking focus and selecting a range. 606 - // (cmdClient has no editor. Should it fork+exec $EDITOR?) 607 - log.Printf("Server requested that client editor open %q (takeFocus=%t, selection=%+v)", 608 - params.URI, params.TakeFocus, params.Selection) 609 - success = true 610 - } 611 - return &protocol.ShowDocumentResult{Success: success}, nil 612 - } 613 - 614 - func (c *cmdClient) WorkDoneProgressCreate(context.Context, *protocol.WorkDoneProgressCreateParams) error { 615 - return nil 616 - } 617 - 618 - func (c *cmdClient) DiagnosticRefresh(context.Context) error { 619 - return nil 620 - } 621 - 622 - func (c *cmdClient) InlayHintRefresh(context.Context) error { 623 - return nil 624 - } 625 - 626 - func (c *cmdClient) SemanticTokensRefresh(context.Context) error { 627 - return nil 628 - } 629 - 630 - func (c *cmdClient) InlineValueRefresh(context.Context) error { 631 - return nil 632 - } 633 - 634 - func (c *cmdClient) getFile(uri protocol.DocumentURI) *cmdFile { 635 - file, found := c.files[uri] 636 - if !found || file.err != nil { 637 - file = &cmdFile{ 638 - uri: uri, 639 - } 640 - c.files[uri] = file 641 - } 642 - if file.mapper == nil { 643 - content, err := os.ReadFile(uri.FilePath()) 644 - if err != nil { 645 - file.err = fmt.Errorf("getFile: %v: %v", uri, err) 646 - return file 647 - } 648 - file.mapper = protocol.NewMapper(uri, content) 649 - } 650 - return file 651 - } 652 - 653 - func (c *cmdClient) openFile(uri protocol.DocumentURI) *cmdFile { 654 - c.filesMu.Lock() 655 - defer c.filesMu.Unlock() 656 - return c.getFile(uri) 657 - } 658 - 659 - // TODO(adonovan): provide convenience helpers to: 660 - // - map a (URI, protocol.Range) to a MappedRange; 661 - // - parse a command-line argument to a MappedRange. 662 - func (c *connection) openFile(ctx context.Context, uri protocol.DocumentURI) (*cmdFile, error) { 663 - file := c.client.openFile(uri) 664 - if file.err != nil { 665 - return nil, file.err 666 - } 667 - 668 - p := &protocol.DidOpenTextDocumentParams{ 669 - TextDocument: protocol.TextDocumentItem{ 670 - URI: uri, 671 - LanguageID: "go", 672 - Version: 1, 673 - Text: string(file.mapper.Content), 674 - }, 675 - } 676 - if err := c.Server.DidOpen(ctx, p); err != nil { 677 - // TODO(adonovan): is this assignment concurrency safe? 678 - file.err = fmt.Errorf("%v: %v", uri, err) 679 - return nil, file.err 680 - } 681 - return file, nil 682 - } 683 - 684 - func (c *connection) semanticTokens(ctx context.Context, p *protocol.SemanticTokensRangeParams) (*protocol.SemanticTokens, error) { 685 - // use range to avoid limits on full 686 - resp, err := c.Server.SemanticTokensRange(ctx, p) 687 - if err != nil { 688 - return nil, err 689 - } 690 - return resp, nil 691 - } 692 - 693 - func (c *connection) diagnoseFiles(ctx context.Context, files []protocol.DocumentURI) error { 694 - cmd, err := command.NewDiagnoseFilesCommand("Diagnose files", command.DiagnoseFilesArgs{ 695 - Files: files, 696 - }) 697 - if err != nil { 698 - return err 699 - } 700 - _, err = c.ExecuteCommand(ctx, &protocol.ExecuteCommandParams{ 701 - Command: cmd.Command, 702 - Arguments: cmd.Arguments, 703 - }) 704 - return err 705 - } 706 - 707 - func (c *connection) terminate(ctx context.Context) { 708 - //TODO: do we need to handle errors on these calls? 709 - c.Shutdown(ctx) 710 - //TODO: right now calling exit terminates the process, we should rethink that 711 - //server.Exit(ctx) 712 - } 713 - 714 - // Implement io.Closer. 715 - func (c *cmdClient) Close() error { 716 - return nil 717 - } 718 - 719 - // -- conversions to span (UTF-8) domain -- 720 - 721 - // locationSpan converts a protocol (UTF-16) Location to a (UTF-8) span. 722 - // Precondition: the URIs of Location and Mapper match. 723 - func (f *cmdFile) locationSpan(loc protocol.Location) (span, error) { 724 - // TODO(adonovan): check that l.URI matches m.URI. 725 - return f.rangeSpan(loc.Range) 726 - } 727 - 728 - // rangeSpan converts a protocol (UTF-16) range to a (UTF-8) span. 729 - // The resulting span has valid Positions and Offsets. 730 - func (f *cmdFile) rangeSpan(r protocol.Range) (span, error) { 731 - start, end, err := f.mapper.RangeOffsets(r) 732 - if err != nil { 733 - return span{}, err 734 - } 735 - return f.offsetSpan(start, end) 736 - } 737 - 738 - // offsetSpan converts a byte-offset interval to a (UTF-8) span. 739 - // The resulting span contains line, column, and offset information. 740 - func (f *cmdFile) offsetSpan(start, end int) (span, error) { 741 - if start > end { 742 - return span{}, fmt.Errorf("start offset (%d) > end (%d)", start, end) 743 - } 744 - startPoint, err := offsetPoint(f.mapper, start) 745 - if err != nil { 746 - return span{}, fmt.Errorf("start: %v", err) 747 - } 748 - endPoint, err := offsetPoint(f.mapper, end) 749 - if err != nil { 750 - return span{}, fmt.Errorf("end: %v", err) 751 - } 752 - return newSpan(f.mapper.URI, startPoint, endPoint), nil 753 - } 754 - 755 - // offsetPoint converts a byte offset to a span (UTF-8) point. 756 - // The resulting point contains line, column, and offset information. 757 - func offsetPoint(m *protocol.Mapper, offset int) (point, error) { 758 - if !(0 <= offset && offset <= len(m.Content)) { 759 - return point{}, fmt.Errorf("invalid offset %d (want 0-%d)", offset, len(m.Content)) 760 - } 761 - line, col8 := m.OffsetLineCol8(offset) 762 - return newPoint(line, col8, offset), nil 763 - } 764 - 765 - // -- conversions from span (UTF-8) domain -- 766 - 767 - // spanLocation converts a (UTF-8) span to a protocol (UTF-16) range. 768 - // Precondition: the URIs of spanLocation and Mapper match. 769 - func (f *cmdFile) spanLocation(s span) (protocol.Location, error) { 770 - rng, err := f.spanRange(s) 771 - if err != nil { 772 - return protocol.Location{}, err 773 - } 774 - return f.mapper.RangeLocation(rng), nil 775 - } 776 - 777 - // spanRange converts a (UTF-8) span to a protocol (UTF-16) range. 778 - // Precondition: the URIs of span and Mapper match. 779 - func (f *cmdFile) spanRange(s span) (protocol.Range, error) { 780 - // Assert that we aren't using the wrong mapper. 781 - // We check only the base name, and case insensitively, 782 - // because we can't assume clean paths, no symbolic links, 783 - // case-sensitive directories. The authoritative answer 784 - // requires querying the file system, and we don't want 785 - // to do that. 786 - if !strings.EqualFold(filepath.Base(string(f.mapper.URI)), filepath.Base(string(s.URI()))) { 787 - return protocol.Range{}, fmt.Errorf("mapper is for file %q instead of %q", f.mapper.URI, s.URI()) 788 - } 789 - start, err := pointPosition(f.mapper, s.Start()) 790 - if err != nil { 791 - return protocol.Range{}, fmt.Errorf("start: %w", err) 792 - } 793 - end, err := pointPosition(f.mapper, s.End()) 794 - if err != nil { 795 - return protocol.Range{}, fmt.Errorf("end: %w", err) 796 - } 797 - return protocol.Range{Start: start, End: end}, nil 798 - } 799 - 800 - // pointPosition converts a valid span (UTF-8) point to a protocol (UTF-16) position. 801 - func pointPosition(m *protocol.Mapper, p point) (protocol.Position, error) { 802 - if p.HasPosition() { 803 - return m.LineCol8Position(p.Line(), p.Column()) 804 - } 805 - if p.HasOffset() { 806 - return m.OffsetPosition(p.Offset()) 807 - } 808 - return protocol.Position{}, fmt.Errorf("point has neither offset nor line/column") 809 - }
-75
internal/golangorgx/gopls/cmd/format.go
··· 1 - // Copyright 2019 The Go Authors. All rights reserved. 2 - // Use of this source code is governed by a BSD-style 3 - // license that can be found in the LICENSE file. 4 - 5 - package cmd 6 - 7 - import ( 8 - "context" 9 - "flag" 10 - "fmt" 11 - 12 - "cuelang.org/go/internal/golangorgx/gopls/protocol" 13 - ) 14 - 15 - // format implements the format verb for cuelsp. 16 - type format struct { 17 - EditFlags 18 - app *Application 19 - } 20 - 21 - func (c *format) Name() string { return "format" } 22 - func (c *format) Parent() string { return c.app.Name() } 23 - func (c *format) Usage() string { return "[format-flags] <filerange>" } 24 - func (c *format) ShortHelp() string { return "format the code according to the go standard" } 25 - func (c *format) DetailedHelp(f *flag.FlagSet) { 26 - fmt.Fprint(f.Output(), ` 27 - The arguments supplied may be simple file names, or ranges within files. 28 - 29 - Example: reformat this file: 30 - 31 - $ cuelsp format -w internal/cmd/check.go 32 - 33 - format-flags: 34 - `) 35 - printFlagDefaults(f) 36 - } 37 - 38 - // Run performs the check on the files specified by args and prints the 39 - // results to stdout. 40 - func (c *format) Run(ctx context.Context, args ...string) error { 41 - if len(args) == 0 { 42 - return nil 43 - } 44 - c.app.editFlags = &c.EditFlags 45 - conn, err := c.app.connect(ctx, nil) 46 - if err != nil { 47 - return err 48 - } 49 - defer conn.terminate(ctx) 50 - for _, arg := range args { 51 - spn := parseSpan(arg) 52 - file, err := conn.openFile(ctx, spn.URI()) 53 - if err != nil { 54 - return err 55 - } 56 - loc, err := file.spanLocation(spn) 57 - if err != nil { 58 - return err 59 - } 60 - if loc.Range.Start != loc.Range.End { 61 - return fmt.Errorf("only full file formatting supported") 62 - } 63 - p := protocol.DocumentFormattingParams{ 64 - TextDocument: protocol.TextDocumentIdentifier{URI: loc.URI}, 65 - } 66 - edits, err := conn.Formatting(ctx, &p) 67 - if err != nil { 68 - return fmt.Errorf("%v: %v", spn, err) 69 - } 70 - if err := applyTextEdits(file.mapper, edits, c.app.editFlags); err != nil { 71 - return err 72 - } 73 - } 74 - return nil 75 - }