Skip to content

Commit

Permalink
Re-enable and fix up document symbol support
Browse files Browse the repository at this point in the history
  • Loading branch information
kralicky committed Jan 5, 2024
1 parent 29be66f commit 33fcbfd
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 152 deletions.
149 changes: 0 additions & 149 deletions pkg/lsp/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -841,155 +841,6 @@ func (c *Cache) computeImportHints(doc protocol.TextDocumentIdentifier, rng prot
return hints
}

func (c *Cache) DocumentSymbolsForFile(doc protocol.TextDocumentIdentifier) ([]protocol.DocumentSymbol, error) {
c.resultsMu.RLock()
defer c.resultsMu.RUnlock()

f, err := c.FindResultByURI(doc.URI)
if err != nil {
return nil, err
}

var symbols []protocol.DocumentSymbol

fn := f.AST()
ast.Walk(fn, &ast.SimpleVisitor{
// DoVisitImportNode: func(node *ast.ImportNode) error {
// slog.Debug("found import", "name", string(node.Name.AsString()))
// symbols = append(symbols, protocol.DocumentSymbol{
// Name: string(node.Name.AsString()),
// Kind: protocol.SymbolKindNamespace,
// Range: posToRange(fn.NodeInfo(node)),
// SelectionRange: posToRange(fn.NodeInfo(node.Name)),
// })
// return nil
// },
DoVisitServiceNode: func(node *ast.ServiceNode) error {
service := protocol.DocumentSymbol{
Name: string(node.Name.AsIdentifier()),
Kind: protocol.Interface,
Range: toRange(fn.NodeInfo(node)),
SelectionRange: toRange(fn.NodeInfo(node.Name)),
}

ast.Walk(node, &ast.SimpleVisitor{
DoVisitRPCNode: func(node *ast.RPCNode) error {
var detail string
switch {
case node.Input.Stream != nil && node.Output.Stream != nil:
detail = "stream (bidirectional)"
case node.Input.Stream != nil:
detail = "stream (client)"
case node.Output.Stream != nil:
detail = "stream (server)"
default:
detail = "unary"
}
rpc := protocol.DocumentSymbol{
Name: string(node.Name.AsIdentifier()),
Detail: detail,
Kind: protocol.Method,
Range: toRange(fn.NodeInfo(node)),
SelectionRange: toRange(fn.NodeInfo(node.Name)),
}

ast.Walk(node, &ast.SimpleVisitor{
DoVisitRPCTypeNode: func(node *ast.RPCTypeNode) error {
rpcType := protocol.DocumentSymbol{
Name: string(node.MessageType.AsIdentifier()),
Kind: protocol.Class,
Range: toRange(fn.NodeInfo(node)),
SelectionRange: toRange(fn.NodeInfo(node.MessageType)),
}
rpc.Children = append(rpc.Children, rpcType)
return nil
},
})
service.Children = append(service.Children, rpc)
return nil
},
})
symbols = append(symbols, service)
return nil
},
DoVisitMessageNode: func(node *ast.MessageNode) error {
sym := protocol.DocumentSymbol{
Name: string(node.Name.AsIdentifier()),
Kind: protocol.Class,
Range: toRange(fn.NodeInfo(node)),
SelectionRange: toRange(fn.NodeInfo(node.Name)),
}
ast.Walk(node, &ast.SimpleVisitor{
DoVisitFieldNode: func(node *ast.FieldNode) error {
sym.Children = append(sym.Children, protocol.DocumentSymbol{
Name: string(node.Name.AsIdentifier()),
Detail: string(node.FldType.AsIdentifier()),
Kind: protocol.Field,
Range: toRange(fn.NodeInfo(node)),
SelectionRange: toRange(fn.NodeInfo(node.Name)),
})
return nil
},
DoVisitMapFieldNode: func(node *ast.MapFieldNode) error {
sym.Children = append(sym.Children, protocol.DocumentSymbol{
Name: string(node.Name.AsIdentifier()),
Detail: fmt.Sprintf("map<%s, %s>", string(node.KeyField().Ident.AsIdentifier()), string(node.ValueField().Ident.AsIdentifier())),
Kind: protocol.Field,
Range: toRange(fn.NodeInfo(node)),
SelectionRange: toRange(fn.NodeInfo(node.Name)),
})
return nil
},
})
symbols = append(symbols, sym)
return nil
},
DoVisitEnumNode: func(node *ast.EnumNode) error {
sym := protocol.DocumentSymbol{
Name: string(node.Name.AsIdentifier()),
Kind: protocol.Enum,
Range: toRange(fn.NodeInfo(node)),
SelectionRange: toRange(fn.NodeInfo(node.Name)),
}
ast.Walk(node, &ast.SimpleVisitor{
DoVisitEnumValueNode: func(node *ast.EnumValueNode) error {
sym.Children = append(sym.Children, protocol.DocumentSymbol{
Name: string(node.Name.AsIdentifier()),
Kind: protocol.EnumMember,
Range: toRange(fn.NodeInfo(node)),
SelectionRange: toRange(fn.NodeInfo(node.Name)),
})
return nil
},
})
symbols = append(symbols, sym)
return nil
},
DoVisitExtendNode: func(node *ast.ExtendNode) error {
sym := protocol.DocumentSymbol{
Name: string(node.Extendee.AsIdentifier()),
Kind: protocol.Class,
Range: toRange(fn.NodeInfo(node)),
SelectionRange: toRange(fn.NodeInfo(node.Extendee)),
}
ast.Walk(node, &ast.SimpleVisitor{
DoVisitFieldNode: func(node *ast.FieldNode) error {
sym.Children = append(sym.Children, protocol.DocumentSymbol{
Name: string(node.Name.AsIdentifier()),
Kind: protocol.Field,
Range: toRange(fn.NodeInfo(node)),
SelectionRange: toRange(fn.NodeInfo(node.Name)),
})
return nil
},
})
symbols = append(symbols, sym)
return nil
},
})
return symbols, nil
}

func (c *Cache) GetSyntheticFileContents(ctx context.Context, uri protocol.DocumentURI) (string, error) {
return c.resolver.SyntheticFileContents(uri)
}
Expand Down
1 change: 1 addition & 0 deletions pkg/lsp/semantic.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ const (
semanticTypeNumber
semanticTypeRegexp
semanticTypeOperator
semanticTypeDecorator
)

type tokenModifier uint32
Expand Down
4 changes: 1 addition & 3 deletions pkg/lsp/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ func (s *Server) Initialize(ctx context.Context, params *protocol.ParamInitializ
Change: protocol.Incremental,
Save: &protocol.SaveOptions{IncludeText: false},
},

HoverProvider: &protocol.Or_ServerCapabilities_hoverProvider{Value: true},
DiagnosticProvider: &protocol.Or_ServerCapabilities_diagnosticProvider{
Value: protocol.DiagnosticOptions{
Expand Down Expand Up @@ -122,7 +121,6 @@ func (s *Server) Initialize(ctx context.Context, params *protocol.ParamInitializ
// TypeDefinitionProvider: true,
ReferencesProvider: &protocol.Or_ServerCapabilities_referencesProvider{Value: true},
// WorkspaceSymbolProvider: &protocol.Or_ServerCapabilities_workspaceSymbolProvider{Value: true},

DefinitionProvider: &protocol.Or_ServerCapabilities_definitionProvider{Value: true},
SemanticTokensProvider: &protocol.SemanticTokensOptions{
Legend: protocol.SemanticTokensLegend{
Expand All @@ -132,7 +130,7 @@ func (s *Server) Initialize(ctx context.Context, params *protocol.ParamInitializ
Full: &protocol.Or_SemanticTokensOptions_full{Value: true},
Range: &protocol.Or_SemanticTokensOptions_range{Value: true},
},
// DocumentSymbolProvider: &protocol.Or_ServerCapabilities_documentSymbolProvider{Value: true},
DocumentSymbolProvider: &protocol.Or_ServerCapabilities_documentSymbolProvider{Value: true},
},

ServerInfo: &protocol.ServerInfo{
Expand Down
151 changes: 151 additions & 0 deletions pkg/lsp/symbols.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
package lsp

import (
"fmt"

"github.com/kralicky/protocompile/ast"
"github.com/kralicky/tools-lite/gopls/pkg/lsp/protocol"
)

func (c *Cache) DocumentSymbolsForFile(doc protocol.TextDocumentIdentifier) ([]protocol.DocumentSymbol, error) {
c.resultsMu.RLock()
defer c.resultsMu.RUnlock()

f, err := c.FindResultByURI(doc.URI)
if err != nil {
return nil, err
}

var symbols []protocol.DocumentSymbol

fn := f.AST()
for _, decl := range fn.Decls {
switch node := decl.(type) {
case *ast.MessageNode:
symbols = append(symbols, messageSymbols(fn, node)...)
case *ast.EnumNode:
symbols = append(symbols, enumSymbols(fn, node)...)
case *ast.ExtendNode:
symbols = append(symbols, extendSymbols(fn, node)...)
case *ast.ServiceNode:
symbols = append(symbols, serviceSymbols(fn, node)...)
}
}
return symbols, nil
}

func messageSymbols(fn *ast.FileNode, node *ast.MessageNode) []protocol.DocumentSymbol {
symbols := []protocol.DocumentSymbol{}
sym := protocol.DocumentSymbol{
Name: string(node.Name.AsIdentifier()),
Kind: protocol.Class,
Range: toRange(fn.NodeInfo(node)),
SelectionRange: toRange(fn.NodeInfo(node.Name)),
}
for _, decl := range node.Decls {
switch node := decl.(type) {
case *ast.FieldNode:
if node.IsIncomplete() {
continue
}
sym.Children = append(sym.Children, protocol.DocumentSymbol{
Name: string(node.Name.AsIdentifier()),
Detail: string(node.FldType.AsIdentifier()),
Kind: protocol.Field,
Range: toRange(fn.NodeInfo(node)),
SelectionRange: toRange(fn.NodeInfo(node.Name)),
})
case *ast.MapFieldNode:
sym.Children = append(sym.Children, protocol.DocumentSymbol{
Name: string(node.Name.AsIdentifier()),
Detail: fmt.Sprintf("map<%s, %s>", string(node.KeyField().Ident.AsIdentifier()), string(node.ValueField().Ident.AsIdentifier())),
Kind: protocol.Field,
Range: toRange(fn.NodeInfo(node)),
SelectionRange: toRange(fn.NodeInfo(node.Name)),
})
case *ast.MessageNode:
sym.Children = append(sym.Children, messageSymbols(fn, node)...)
case *ast.EnumNode:
sym.Children = append(sym.Children, enumSymbols(fn, node)...)
case *ast.ExtendNode:
sym.Children = append(sym.Children, extendSymbols(fn, node)...)
}
}
symbols = append(symbols, sym)
return symbols
}

func enumSymbols(fn *ast.FileNode, node *ast.EnumNode) []protocol.DocumentSymbol {
sym := protocol.DocumentSymbol{
Name: string(node.Name.AsIdentifier()),
Kind: protocol.Enum,
Range: toRange(fn.NodeInfo(node)),
SelectionRange: toRange(fn.NodeInfo(node.Name)),
}
for _, decl := range node.Decls {
switch node := decl.(type) {
case *ast.EnumValueNode:
sym.Children = append(sym.Children, protocol.DocumentSymbol{
Name: string(node.Name.AsIdentifier()),
Kind: protocol.EnumMember,
Range: toRange(fn.NodeInfo(node)),
SelectionRange: toRange(fn.NodeInfo(node.Name)),
})
}
}
return []protocol.DocumentSymbol{sym}
}

func extendSymbols(fn *ast.FileNode, node *ast.ExtendNode) []protocol.DocumentSymbol {
symbols := []protocol.DocumentSymbol{}
for _, decl := range node.Decls {
switch node := decl.(type) {
case *ast.FieldNode:
if node.IsIncomplete() {
continue
}
symbols = append(symbols, protocol.DocumentSymbol{
Name: string(node.Name.AsIdentifier()),
Detail: fmt.Sprintf("[%s] %s", node.Extendee.Extendee.AsIdentifier(), string(node.FldType.AsIdentifier())),
Kind: protocol.Field,
Range: toRange(fn.NodeInfo(node)),
SelectionRange: toRange(fn.NodeInfo(node.Name)),
})
}
}
return symbols
}

func serviceSymbols(fn *ast.FileNode, node *ast.ServiceNode) []protocol.DocumentSymbol {
service := protocol.DocumentSymbol{
Name: string(node.Name.AsIdentifier()),
Kind: protocol.Interface,
Range: toRange(fn.NodeInfo(node)),
SelectionRange: toRange(fn.NodeInfo(node.Name)),
}
for _, decl := range node.Decls {
switch node := decl.(type) {
case *ast.RPCNode:
var detail string
switch {
case node.Input.Stream != nil && node.Output.Stream != nil:
detail = "stream (bidirectional)"
case node.Input.Stream != nil:
detail = "stream (client)"
case node.Output.Stream != nil:
detail = "stream (server)"
default:
detail = "unary"
}
rpc := protocol.DocumentSymbol{
Name: string(node.Name.AsIdentifier()),
Detail: detail,
Kind: protocol.Method,
Range: toRange(fn.NodeInfo(node)),
SelectionRange: toRange(fn.NodeInfo(node.Name)),
}
service.Children = append(service.Children, rpc)
}
}
return []protocol.DocumentSymbol{service}
}

0 comments on commit 33fcbfd

Please sign in to comment.