|
7 | 7 | "slices"
|
8 | 8 | "strings"
|
9 | 9 |
|
| 10 | + gopast "github.com/goplus/gop/ast" |
| 11 | + goptoken "github.com/goplus/gop/token" |
10 | 12 | "github.com/goplus/goxlsw/gop"
|
11 | 13 | "github.com/goplus/goxlsw/internal/analysis"
|
12 | 14 | "github.com/goplus/goxlsw/internal/vfs"
|
@@ -242,25 +244,26 @@ func (s *Server) handleNotification(n *jsonrpc2.Notification) error {
|
242 | 244 | if err := UnmarshalJSON(n.Params(), ¶ms); err != nil {
|
243 | 245 | return fmt.Errorf("failed to parse didOpen params: %w", err)
|
244 | 246 | }
|
245 |
| - return errors.New("TODO") |
| 247 | + |
| 248 | + return s.didOpen(¶ms) |
246 | 249 | case "textDocument/didChange":
|
247 | 250 | var params DidChangeTextDocumentParams
|
248 | 251 | if err := UnmarshalJSON(n.Params(), ¶ms); err != nil {
|
249 | 252 | return fmt.Errorf("failed to parse didChange params: %w", err)
|
250 | 253 | }
|
251 |
| - return errors.New("TODO") |
| 254 | + return s.didChange(¶ms) |
252 | 255 | case "textDocument/didSave":
|
253 | 256 | var params DidSaveTextDocumentParams
|
254 | 257 | if err := UnmarshalJSON(n.Params(), ¶ms); err != nil {
|
255 | 258 | return fmt.Errorf("failed to parse didSave params: %w", err)
|
256 | 259 | }
|
257 |
| - return errors.New("TODO") |
| 260 | + return s.didSave(¶ms) |
258 | 261 | case "textDocument/didClose":
|
259 | 262 | var params DidCloseTextDocumentParams
|
260 | 263 | if err := UnmarshalJSON(n.Params(), ¶ms); err != nil {
|
261 | 264 | return fmt.Errorf("failed to parse didClose params: %w", err)
|
262 | 265 | }
|
263 |
| - return errors.New("TODO") |
| 266 | + return s.didClose(¶ms) |
264 | 267 | }
|
265 | 268 | return nil
|
266 | 269 | }
|
@@ -333,3 +336,40 @@ func (s *Server) fromDocumentURI(documentURI DocumentURI) (string, error) {
|
333 | 336 | func (s *Server) toDocumentURI(path string) DocumentURI {
|
334 | 337 | return DocumentURI(string(s.workspaceRootURI) + path)
|
335 | 338 | }
|
| 339 | + |
| 340 | +// fromPosition converts a token.Position to an LSP Position. |
| 341 | +func (s *Server) fromPosition(astFile *gopast.File, position goptoken.Position) Position { |
| 342 | + tokenFile := s.getProj().Fset.File(astFile.Pos()) |
| 343 | + |
| 344 | + line := position.Line |
| 345 | + lineStart := int(tokenFile.LineStart(line)) |
| 346 | + relLineStart := lineStart - tokenFile.Base() |
| 347 | + lineContent := astFile.Code[relLineStart : relLineStart+position.Column-1] |
| 348 | + utf16Offset := utf8OffsetToUTF16(string(lineContent), position.Column-1) |
| 349 | + |
| 350 | + return Position{ |
| 351 | + Line: uint32(position.Line - 1), |
| 352 | + Character: uint32(utf16Offset), |
| 353 | + } |
| 354 | +} |
| 355 | + |
| 356 | +// rangeForASTFilePosition returns a [Range] for the given position in an AST file. |
| 357 | +func (s *Server) rangeForASTFilePosition(astFile *gopast.File, position goptoken.Position) Range { |
| 358 | + p := s.fromPosition(astFile, position) |
| 359 | + return Range{Start: p, End: p} |
| 360 | +} |
| 361 | + |
| 362 | +// rangeForPos returns the [Range] for the given position. |
| 363 | +func (s *Server) rangeForPos(pos goptoken.Pos) Range { |
| 364 | + return s.rangeForASTFilePosition(s.posASTFile(pos), s.getProj().Fset.Position(pos)) |
| 365 | +} |
| 366 | + |
| 367 | +// posASTFile returns the AST file for the given position. |
| 368 | +func (s *Server) posASTFile(pos goptoken.Pos) *gopast.File { |
| 369 | + return getASTPkg(s.getProj()).Files[s.posFilename(pos)] |
| 370 | +} |
| 371 | + |
| 372 | +// posFilename returns the filename for the given position. |
| 373 | +func (s *Server) posFilename(pos goptoken.Pos) string { |
| 374 | + return s.getProj().Fset.Position(pos).Filename |
| 375 | +} |
0 commit comments