-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathast.go
196 lines (186 loc) · 5.83 KB
/
ast.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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
// Parse the go source files to extract info about them
// HanishKVC, 2022
package main
import (
"fmt"
"go/ast"
"go/parser"
"go/token"
"os"
"path/filepath"
"reflect"
"regexp"
"strings"
)
const gbPrependPkgBasePath bool = true
func test_dbsymbols_update() {
aMap := map[string]DBSymbolInfo{"t100": {"doct of t100", "X"}}
//bMap := DBSymbols{}
dbsymbols_update(aMap, "t1", DBSymbolInfo{"doc for t1", ""}, true)
fmt.Printf("%v:INFO:T MAPSTRUCT2: aMap:%v\n", PRG_TAG, aMap)
dbsymbols_update(aMap, "t1", DBSymbolInfo{"doc for t1", ""}, true)
dbsymbols_update(aMap, "t2", DBSymbolInfo{"doc for t2", ""}, true)
fmt.Printf("%v:INFO:T MAPSTRUCT2: aMap after updates:%v\n", PRG_TAG, aMap)
}
type IdentyStats struct {
identCnt uint
funcCnt uint
valueCnt uint
typeCnt uint
}
var gIdentyStats IdentyStats
func (is IdentyStats) String() string {
return fmt.Sprintf("{ i:%v f:%v v:%v t:%v }", is.identCnt, is.funcCnt, is.valueCnt, is.typeCnt)
}
func (is *IdentyStats) delta_summary() int {
return (int(is.identCnt - (is.funcCnt + is.typeCnt + is.valueCnt)))
}
func pkgname_with_basepath(pkgName string, sFile string, srcBasePath string, bPrependPkgBasePath bool) string {
if !bPrependPkgBasePath {
return pkgName
}
sbpLen := len(srcBasePath)
if sbpLen > 0 {
lastChar := srcBasePath[sbpLen-1]
if lastChar == os.PathSeparator {
srcBasePath = srcBasePath[:sbpLen-1]
}
}
sTheFile := sFile[len(srcBasePath):]
re := regexp.MustCompile(fmt.Sprintf("(.*?)%v%v.*", string(os.PathSeparator), pkgName))
sMatchs := re.FindStringSubmatch(sTheFile)
if giDEBUG > 1 {
fmt.Printf("%v:DBUG:AST:%v:%v:%v:%v\n", PRG_TAG, re.String(), sTheFile, pkgName, sMatchs)
}
if len(sMatchs) > 1 {
sPkgPrefix := sMatchs[1]
pkgName = filepath.Join(sPkgPrefix, pkgName)
} else {
sDir, _ := filepath.Split(sTheFile)
if len(sDir) > 0 {
pkgName = filepath.Join(sDir, pkgName)
}
}
if (len(pkgName) > 1) && (pkgName[0] == os.PathSeparator) {
pkgName = pkgName[1:]
}
return filepath.ToSlash(pkgName)
}
// Retreive info about the go source file specified
// It returns
// the package name to which the file belongs
// all the comments in the file
// map of exported / all identifiers defined by the file
func gosrc_info(sFile string) (string, string, DBSymbols) {
tfs := token.NewFileSet()
astF, err := parser.ParseFile(tfs, sFile, nil, parser.ParseComments)
if err != nil {
fmt.Printf("%v:ERRR:AST: %v\n", PRG_TAG, err)
return "", "", nil
}
pkgName := ""
fileCmts := ""
theIdents := DBSymbols{}
genDeclCmt := ""
genDeclType := "?"
ast.Inspect(astF, func(n ast.Node) bool {
bDigDeeper := true
if n == nil {
if giDEBUG > 6 {
fmt.Printf("%v:INFO:AST: n:nil:: %v\n", PRG_TAG, n)
}
bDigDeeper = false // true or false may not matter here, but still
return bDigDeeper
}
sType := "???"
sExtra := ""
switch t := n.(type) {
/* Commenting out, bcas this path traps for both own as well as other packages' identifiers used by go source file being inspected
case *ast.Ident: // This gives names of vars, consts, types and funcs also
sType = "Identifier"
sExtra = t.Name
identsmap_update(theIdents, t.Name, "", t.IsExported())
gIdentyStats.identCnt += 1
*/
case *ast.ValueSpec: // Through GenDecl
sType = "ConstOrVar"
sCmt := ":Cmt:" + t.Comment.Text() + ":Doc:" + t.Doc.Text()
valCmt := genDeclCmt + "\n" + t.Comment.Text() + "\n" + t.Doc.Text()
saExtra := []string{}
for _, ident := range t.Names {
saExtra = append(saExtra, ident.Name)
dbsymbols_update(theIdents, ident.Name, DBSymbolInfo{valCmt, genDeclType}, ident.IsExported())
gIdentyStats.valueCnt += 1
}
sExtra = "<" + strings.Join(saExtra, ",") + "> " + sCmt
case *ast.TypeSpec: // Through GenDecl
sType = "Type"
sCmt := ":Cmt:" + t.Comment.Text() + ":Doc:" + t.Doc.Text()
typeCmt := genDeclCmt + "\n" + t.Comment.Text() + "\n" + t.Doc.Text()
sExtra = "<" + t.Name.Name + "> " + sCmt
dbsymbols_update(theIdents, t.Name.Name, DBSymbolInfo{typeCmt, "T"}, t.Name.IsExported())
gIdentyStats.typeCnt += 1
case *ast.GenDecl:
sType = "ImpTypeConstVar"
genDeclType = "*"
switch t.Tok {
case token.IMPORT:
sType = "GenDecl:Import"
genDeclType = "I"
bDigDeeper = false
case token.CONST:
sType = "GenDecl:Const"
genDeclType = "C"
case token.TYPE:
sType = "GenDecl:Type"
genDeclType = "T"
case token.VAR:
sType = "GenDecl:Var"
genDeclType = "V"
}
/*
for _, spec := range t.Specs {
fmt.Printf("%v:DBUG:AST GenDecl:%v\n", PRG_TAG, spec.Doc.Text())
}
*/
sExtra = t.Doc.Text()
genDeclCmt = t.Doc.Text()
case *ast.FuncDecl:
sType = "Function"
sExtra = t.Name.Name + ", :Doc:" + t.Doc.Text()
dbsymbols_update(theIdents, t.Name.Name, DBSymbolInfo{t.Doc.Text(), "F"}, t.Name.IsExported())
gIdentyStats.funcCnt += 1
case *ast.Package: // Working on individual Go src files doesnt seem to encounter this type
sType = "Package"
sExtra = t.Name
pkgName = t.Name
case *ast.File: // This could give useful info
sType = "File"
sExtra = t.Name.Name
pkgName = t.Name.Name
//fmt.Printf("%v:INFO:AST: File.Scope: %v\n", PRG_TAG, t.Scope)
for _, cmtG := range t.Comments {
fileCmts += cmtG.Text()
}
sExtra += (", " + fileCmts)
default:
if giDEBUG > 6 {
sType = "?" + reflect.TypeOf(t).String() + "?"
//sExtra = t1.Name() + ";" + t1.Elem().Name()
sExtra = reflect.ValueOf(t).String()
}
}
if giDEBUG > 6 {
fmt.Printf("%v:INFO:AST: n:%v:%v: %v\n", PRG_TAG, sType, sExtra, n)
}
return bDigDeeper
})
if giDEBUG > 5 {
fmt.Printf("%v:INFO:AST: GoFile:%v:%v\n", PRG_TAG, pkgName, theIdents)
}
if giDEBUG > 20 {
fmt.Printf("%v:DBUG:AST: GoFile:%v:%v:%v\n", PRG_TAG, sFile, gIdentyStats, gIdentyStats.delta_summary())
}
pkgName = pkgname_with_basepath(pkgName, sFile, gBasePath, gbPrependPkgBasePath)
return pkgName, fileCmts, theIdents
}