/
funcreturn.go
117 lines (96 loc) · 2.99 KB
/
funcreturn.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package goextractors
import (
"context"
"go/ast"
"time"
"github.com/vorlif/xspreak/extract/etype"
"github.com/vorlif/xspreak/extract/extractors"
"github.com/vorlif/xspreak/result"
"github.com/vorlif/xspreak/util"
)
type funcReturnExtractor struct{}
func NewFuncReturnExtractor() extractors.Extractor {
return &funcReturnExtractor{}
}
func (e *funcReturnExtractor) Run(_ context.Context, extractCtx *extractors.Context) ([]result.Issue, error) {
util.TrackTime(time.Now(), "extract func return values")
var issues []result.Issue
extractCtx.Inspector.WithStack([]ast.Node{&ast.FuncDecl{}}, func(rawNode ast.Node, push bool, stack []ast.Node) (proceed bool) {
proceed = true
if !push {
return
}
node := rawNode.(*ast.FuncDecl)
if node.Body == nil || node.Type == nil || node.Type.Results == nil || len(node.Type.Results.List) == 0 {
return
}
// Extract the return types if from the localise package
extractedResults := make([]etype.Token, len(node.Type.Results.List))
var foundType bool
for i, res := range node.Type.Results.List {
tok, _ := extractCtx.SearchIdentAndToken(res)
if tok == etype.None {
extractedResults[i] = etype.None
continue
}
extractedResults[i] = tok
foundType = true
}
if !foundType {
return
}
pkg, _ := extractCtx.GetType(node.Name)
if pkg == nil {
return
}
// Extract the values from the return statements
ast.Inspect(node.Body, func(node ast.Node) bool {
if node == nil {
return true
}
retNode, isReturn := node.(*ast.ReturnStmt)
if !isReturn || len(retNode.Results) != len(extractedResults) {
return true
}
collector := newSearchCollector()
collector.ExtraNodes = append(collector.ExtraNodes, node)
for i, extractedResult := range extractedResults {
foundResults := extractCtx.SearchStrings(retNode.Results[i])
if len(foundResults) == 0 {
continue
}
switch extractedResult {
case etype.Singular, etype.Key, etype.PluralKey:
collector.AddSingulars(extractedResult, foundResults)
case etype.Plural:
collector.Plurals = append(collector.Plurals, foundResults...)
case etype.Context:
collector.Contexts = append(collector.Contexts, foundResults...)
case etype.Domain:
collector.Domains = append(collector.Domains, foundResults...)
}
}
collector.CheckMissingMessageID(extractCtx)
for i, singularResult := range collector.Singulars {
issue := result.Issue{
FromExtractor: e.Name(),
IDToken: collector.SingularType[i],
MsgID: singularResult.Raw,
Domain: collector.GetDomain(),
Context: collector.GetContext(),
PluralID: collector.GetPlural(),
Comments: extractCtx.GetComments(pkg, singularResult.Node),
Pkg: pkg,
Pos: extractCtx.GetPosition(singularResult.Node.Pos()),
}
issues = append(issues, issue)
}
return true
})
return
})
return issues, nil
}
func (e *funcReturnExtractor) Name() string {
return "func_return"
}