all repos

clerk @ e0319e501d48d625d4f01e3cf44dfeca2c0a76c7

missing tooling for ledger/hledger

clerk/internal/lsp/textdocument_document_symbol.go (view raw)

Oleksandr Smirnov Oleksandr Smirnov
olexsmir@gmail.com
ast: inline leaf value+span wrapper structs, 1 month ago
1
package lsp
2
3
import (
4
	"context"
5
6
	"go.lsp.dev/protocol"
7
8
	"olexsmir.xyz/clerk/journal/ast"
9
	"olexsmir.xyz/clerk/journal/token"
10
)
11
12
func (s *server) DocumentSymbol(_ context.Context, params *protocol.DocumentSymbolParams) (protocol.DocumentSymbolResult, error) {
13
	an := s.analysisFor(params.TextDocument.URI)
14
	if an == nil {
15
		return nil, nil
16
	}
17
	pf := parsedFileFor(an, params.TextDocument.URI.Path())
18
	if pf == nil {
19
		return nil, nil
20
	}
21
	symbols := make([]protocol.DocumentSymbol, 0, len(pf.Ast.Entries)/2)
22
	for _, entry := range pf.Ast.Entries {
23
		if symbol, ok := entryDocumentSymbol(entry, pf.Src); ok {
24
			symbols = append(symbols, symbol)
25
		}
26
	}
27
	return protocol.DocumentSymbolSlice(symbols), nil
28
}
29
30
func entryDocumentSymbol(e ast.Entry, src []byte) (protocol.DocumentSymbol, bool) {
31
	var kind symbolKind
32
	var name string
33
	var sel, whole token.Span
34
	switch e := e.(type) {
35
	case *ast.Transaction:
36
		kind, name, sel, whole = symbolTransaction, transactionName(e), e.Date.Span, e.Span
37
	case *ast.PeriodicTransaction:
38
		kind, name, sel, whole = symbolTransaction, transactionName(e), e.Period.Span, e.Span
39
	case *ast.AutomatedTransaction:
40
		kind, name, sel, whole = symbolTransaction, transactionName(e), e.ExprSpan, e.Span
41
	case *ast.AccountDirective:
42
		kind, name, sel, whole = symbolAccount, e.Account.String(), e.Account.Span, e.Span
43
	case *ast.CommodityDirective:
44
		kind, name, sel, whole = symbolCommodity, e.Commodity, e.CommoditySpan, e.Span
45
	case *ast.PayeeDirective:
46
		if e.Name == "" {
47
			return protocol.DocumentSymbol{}, false
48
		}
49
		kind, name, sel, whole = symbolPayee, e.Name, e.NameSpan, e.Span
50
	case *ast.TagDirective:
51
		sp, ok := tagDirectiveSpan(string(src), e)
52
		if !ok {
53
			return protocol.DocumentSymbol{}, false
54
		}
55
		kind, name, sel, whole = symbolTag, e.Name, sp, e.Span
56
	default:
57
		return protocol.DocumentSymbol{}, false
58
	}
59
	return protocol.DocumentSymbol{
60
		Name:           name,
61
		Kind:           kind.ToProtocol(),
62
		Range:          spanRangeFromSrc(src, whole),
63
		SelectionRange: spanRangeFromSrc(src, sel),
64
	}, true
65
}