Skip to content

Commit

Permalink
Update tag database when file is saved
Browse files Browse the repository at this point in the history
  • Loading branch information
netmute committed Nov 26, 2024
1 parent 5668133 commit 361fec8
Showing 1 changed file with 47 additions and 8 deletions.
55 changes: 47 additions & 8 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ type ServerCapabilities struct {
type TextDocumentSyncOptions struct {
Change int `json:"change"`
OpenClose bool `json:"openClose"`
Save bool `json:"save"`
}

// CompletionOptions defines options for the completion provider
Expand Down Expand Up @@ -370,7 +371,7 @@ func handleInitialize(server *Server, req RPCRequest) {
// Convert RootURI to filesystem path
server.rootPath = uriToPath(params.RootURI)
// Load ctags entries
if err := server.loadTagsFromJSON(); err != nil {
if err := server.scanRecursiveTags(); err != nil {
sendError(req.ID, -32603, "Internal error", err.Error())
return
}
Expand All @@ -381,6 +382,7 @@ func handleInitialize(server *Server, req RPCRequest) {
TextDocumentSync: &TextDocumentSyncOptions{
Change: 1, // Full synchronization
OpenClose: true,
Save: true,
},
CompletionProvider: &CompletionOptions{
TriggerCharacters: []string{".", ":", ">", "\""},
Expand Down Expand Up @@ -462,7 +464,19 @@ func handleDidClose(server *Server, req RPCRequest) {

// handleDidSave processes the 'textDocument/didSave' notification
func handleDidSave(server *Server, req RPCRequest) {
// Currently not utilized
var params DidSaveTextDocumentParams
err := json.Unmarshal(req.Params, &params)
if err != nil {
return
}

// Get file path from URI
filePath := uriToPath(params.TextDocument.URI)

// Scan the file again
if err := server.scanSingleFileTag(filePath); err != nil {
log.Printf("Error rescanning file %s: %v", filePath, err)
}
}

// handleCompletion processes the 'textDocument/completion' request
Expand Down Expand Up @@ -646,10 +660,32 @@ func filepathToURI(path string) string {
return "file://" + filepath.ToSlash(absPath)
}

// loadTagsFromJSON executes the ctags command and parses the JSON output
func (s *Server) loadTagsFromJSON() error {
// scanRecursiveTags scans all files in the root path
func (s *Server) scanRecursiveTags() error {
cmd := exec.Command("ctags", "--output-format=json", "-R")
cmd.Dir = s.rootPath
return s.processTagsOutput(cmd)
}

// scanSingleFileTag scans a single file, removing previous entries for that file
func (s *Server) scanSingleFileTag(filePath string) error {
s.mu.Lock()
newEntries := make([]TagEntry, 0, len(s.tagEntries))
for _, entry := range s.tagEntries {
if entry.Path != filePath {
newEntries = append(newEntries, entry)
}
}
s.tagEntries = newEntries
s.mu.Unlock()

cmd := exec.Command("ctags", "--output-format=json", filePath)
cmd.Dir = s.rootPath
return s.processTagsOutput(cmd)
}

// processTagsOutput handles the ctags command execution and output processing
func (s *Server) processTagsOutput(cmd *exec.Cmd) error {
stdout, err := cmd.StdoutPipe()
if err != nil {
return fmt.Errorf("failed to get stdout from ctags command: %v", err)
Expand All @@ -660,15 +696,14 @@ func (s *Server) loadTagsFromJSON() error {
}

scanner := bufio.NewScanner(stdout)
var entries []TagEntry
for scanner.Scan() {
line := scanner.Text()
var entry TagEntry
err := json.Unmarshal([]byte(line), &entry)
if err != nil {
if err := json.Unmarshal([]byte(scanner.Text()), &entry); err != nil {
log.Printf("Failed to parse ctags JSON entry: %v", err)
continue
}
s.tagEntries = append(s.tagEntries, entry)
entries = append(entries, entry)
}

if err := scanner.Err(); err != nil {
Expand All @@ -679,6 +714,10 @@ func (s *Server) loadTagsFromJSON() error {
return fmt.Errorf("ctags command failed: %v", err)
}

s.mu.Lock()
s.tagEntries = append(s.tagEntries, entries...)
s.mu.Unlock()

return nil
}

Expand Down

0 comments on commit 361fec8

Please sign in to comment.