Skip to content

Commit f15ff61

Browse files
cmaglieFederico Fissore
authored and
Federico Fissore
committed
Refactoring: ctags parser now uses a CTag structure
Signed-off-by: Cristian Maglie <[email protected]>
1 parent 90ba6d5 commit f15ff61

8 files changed

+300
-271
lines changed

Diff for: src/arduino.cc/builder/collect_ctags_from_sketch_files.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,10 @@ func (s *CollectCTagsFromSketchFiles) Run(context map[string]interface{}) error
4242
sketch := context[constants.CTX_SKETCH].(*types.Sketch)
4343
sketchFileNames := collectSketchFileNamesFrom(sketch)
4444

45-
ctags := context[constants.CTX_CTAGS_OF_PREPROC_SOURCE].([]map[string]string)
46-
ctagsOfSketch := []map[string]string{}
45+
ctags := context[constants.CTX_CTAGS_OF_PREPROC_SOURCE].([]*CTag)
46+
ctagsOfSketch := []*CTag{}
4747
for _, ctag := range ctags {
48-
if utils.SliceContains(sketchFileNames, strings.Replace(ctag[FIELD_FILENAME], "\\\\", "\\", -1)) {
48+
if utils.SliceContains(sketchFileNames, strings.Replace(ctag.Filename, "\\\\", "\\", -1)) {
4949
ctagsOfSketch = append(ctagsOfSketch, ctag)
5050
}
5151
}

Diff for: src/arduino.cc/builder/compare_prototypes_from_source_and_preproc_source.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,10 @@ import (
3636
type ComparePrototypesFromSourceAndPreprocSource struct{}
3737

3838
func (s *ComparePrototypesFromSourceAndPreprocSource) Run(context map[string]interface{}) error {
39-
ctagsOfSource := context[constants.CTX_CTAGS_OF_SOURCE].([]map[string]string)
40-
ctagsOfPreprocSource := context[constants.CTX_CTAGS_OF_PREPROC_SOURCE].([]map[string]string)
39+
ctagsOfSource := context[constants.CTX_CTAGS_OF_SOURCE].([]*CTag)
40+
ctagsOfPreprocSource := context[constants.CTX_CTAGS_OF_PREPROC_SOURCE].([]*CTag)
4141

42-
actualCTags := []map[string]string{}
42+
actualCTags := []*CTag{}
4343
for _, ctagOfPreprocSource := range ctagsOfPreprocSource {
4444
if sliceContainsCTag(ctagsOfSource, ctagOfPreprocSource) {
4545
actualCTags = append(actualCTags, ctagOfPreprocSource)
@@ -51,9 +51,9 @@ func (s *ComparePrototypesFromSourceAndPreprocSource) Run(context map[string]int
5151
return nil
5252
}
5353

54-
func sliceContainsCTag(slice []map[string]string, target map[string]string) bool {
54+
func sliceContainsCTag(slice []*CTag, target *CTag) bool {
5555
for _, value := range slice {
56-
if value[FIELD_FUNCTION_NAME] == target[FIELD_FUNCTION_NAME] {
56+
if value.FunctionName == target.FunctionName {
5757
return true
5858
}
5959
}

Diff for: src/arduino.cc/builder/ctags_parser.go

+103-70
Original file line numberDiff line numberDiff line change
@@ -39,44 +39,52 @@ import (
3939
"strings"
4040
)
4141

42-
const FIELD_KIND = "kind"
43-
const FIELD_LINE = "line"
44-
const FIELD_SIGNATURE = "signature"
45-
const FIELD_RETURNTYPE = "returntype"
46-
const FIELD_CODE = "code"
47-
const FIELD_CLASS = "class"
48-
const FIELD_STRUCT = "struct"
49-
const FIELD_NAMESPACE = "namespace"
50-
const FIELD_FILENAME = "filename"
51-
const FIELD_SKIP = "skipMe"
52-
const FIELD_FUNCTION_NAME = "functionName"
53-
5442
const KIND_PROTOTYPE = "prototype"
5543
const KIND_FUNCTION = "function"
56-
const KIND_PROTOTYPE_MODIFIERS = "prototype_modifiers"
44+
45+
//const KIND_PROTOTYPE_MODIFIERS = "prototype_modifiers"
5746

5847
const TEMPLATE = "template"
5948
const STATIC = "static"
60-
const TRUE = "true"
6149

62-
var FIELDS = map[string]bool{"kind": true, "line": true, "typeref": true, "signature": true, "returntype": true, "class": true, "struct": true, "namespace": true}
63-
var KNOWN_TAG_KINDS = map[string]bool{"prototype": true, "function": true}
64-
var FIELDS_MARKING_UNHANDLED_TAGS = []string{FIELD_CLASS, FIELD_STRUCT, FIELD_NAMESPACE}
50+
var KNOWN_TAG_KINDS = map[string]bool{
51+
"prototype": true,
52+
"function": true,
53+
}
6554

6655
type CTagsParser struct{}
6756

57+
type CTag struct {
58+
FunctionName string
59+
Kind string
60+
Line int
61+
Signature string
62+
Returntype string
63+
Code string
64+
Class string
65+
Struct string
66+
Namespace string
67+
Filename string
68+
Typeref string
69+
SkipMe bool
70+
71+
Prototype string
72+
Function string
73+
PrototypeModifiers string
74+
}
75+
6876
func (s *CTagsParser) Run(context map[string]interface{}) error {
6977
rows := strings.Split(context[constants.CTX_CTAGS_OUTPUT].(string), "\n")
7078

7179
rows = removeEmpty(rows)
7280

73-
var tags []map[string]string
81+
var tags []*CTag
7482
for _, row := range rows {
7583
tags = append(tags, parseTag(row))
7684
}
7785

7886
skipTagsWhere(tags, tagIsUnknown, context)
79-
skipTagsWithField(tags, FIELDS_MARKING_UNHANDLED_TAGS, context)
87+
skipTagsWhere(tags, tagIsUnhandled, context)
8088
skipTagsWhere(tags, signatureContainsDefaultArg, context)
8189
addPrototypes(tags)
8290
removeDefinedProtypes(tags, context)
@@ -88,90 +96,90 @@ func (s *CTagsParser) Run(context map[string]interface{}) error {
8896
return nil
8997
}
9098

91-
func addPrototypes(tags []map[string]string) {
99+
func addPrototypes(tags []*CTag) {
92100
for _, tag := range tags {
93-
if tag[FIELD_SKIP] != TRUE {
94-
addPrototype(tag)
101+
if !tag.SkipMe {
102+
tag.AddPrototype()
95103
}
96104
}
97105
}
98106

99-
func addPrototype(tag map[string]string) {
100-
if strings.Index(tag[FIELD_RETURNTYPE], TEMPLATE) == 0 || strings.Index(tag[FIELD_CODE], TEMPLATE) == 0 {
101-
code := tag[FIELD_CODE]
107+
func (tag *CTag) AddPrototype() {
108+
if strings.Index(tag.Returntype, TEMPLATE) == 0 || strings.Index(tag.Code, TEMPLATE) == 0 {
109+
code := tag.Code
102110
if strings.Contains(code, "{") {
103111
code = code[:strings.Index(code, "{")]
104112
} else {
105113
code = code[:strings.LastIndex(code, ")")+1]
106114
}
107-
tag[KIND_PROTOTYPE] = code + ";"
115+
tag.Prototype = code + ";"
108116
return
109117
}
110118

111-
tag[KIND_PROTOTYPE] = tag[FIELD_RETURNTYPE] + " " + tag[FIELD_FUNCTION_NAME] + tag[FIELD_SIGNATURE] + ";"
119+
tag.Prototype = tag.Returntype + " " + tag.FunctionName + tag.Signature + ";"
112120

113-
tag[KIND_PROTOTYPE_MODIFIERS] = ""
114-
if strings.Index(tag[FIELD_CODE], STATIC+" ") != -1 {
115-
tag[KIND_PROTOTYPE_MODIFIERS] = tag[KIND_PROTOTYPE_MODIFIERS] + " " + STATIC
121+
tag.PrototypeModifiers = ""
122+
if strings.Index(tag.Code, STATIC+" ") != -1 {
123+
tag.PrototypeModifiers = tag.PrototypeModifiers + " " + STATIC
116124
}
117-
tag[KIND_PROTOTYPE_MODIFIERS] = strings.TrimSpace(tag[KIND_PROTOTYPE_MODIFIERS])
125+
tag.PrototypeModifiers = strings.TrimSpace(tag.PrototypeModifiers)
118126
}
119127

120-
func removeDefinedProtypes(tags []map[string]string, context map[string]interface{}) {
128+
func removeDefinedProtypes(tags []*CTag, context map[string]interface{}) {
121129
definedPrototypes := make(map[string]bool)
122130
for _, tag := range tags {
123-
if tag[FIELD_KIND] == KIND_PROTOTYPE {
124-
definedPrototypes[tag[KIND_PROTOTYPE]] = true
131+
if tag.Kind == KIND_PROTOTYPE {
132+
definedPrototypes[tag.Prototype] = true
125133
}
126134
}
127135

128136
for _, tag := range tags {
129-
if definedPrototypes[tag[KIND_PROTOTYPE]] {
137+
if definedPrototypes[tag.Prototype] {
130138
if utils.DebugLevel(context) >= 10 {
131-
utils.Logger(context).Fprintln(os.Stderr, constants.MSG_SKIPPING_TAG_ALREADY_DEFINED, tag[FIELD_FUNCTION_NAME])
139+
utils.Logger(context).Fprintln(os.Stderr, constants.MSG_SKIPPING_TAG_ALREADY_DEFINED, tag.FunctionName)
132140
}
133-
tag[FIELD_SKIP] = TRUE
141+
tag.SkipMe = true
134142
}
135143
}
136144
}
137145

138-
func removeDuplicate(tags []map[string]string) {
146+
func removeDuplicate(tags []*CTag) {
139147
definedPrototypes := make(map[string]bool)
140148

141149
for _, tag := range tags {
142-
if !definedPrototypes[tag[KIND_PROTOTYPE]] {
143-
definedPrototypes[tag[KIND_PROTOTYPE]] = true
150+
if !definedPrototypes[tag.Prototype] {
151+
definedPrototypes[tag.Prototype] = true
144152
} else {
145-
tag[FIELD_SKIP] = TRUE
153+
tag.SkipMe = true
146154
}
147155
}
148156
}
149157

150-
type skipFuncType func(tag map[string]string) bool
158+
type skipFuncType func(tag *CTag) bool
151159

152-
func skipTagsWhere(tags []map[string]string, skipFunc skipFuncType, context map[string]interface{}) {
160+
func skipTagsWhere(tags []*CTag, skipFunc skipFuncType, context map[string]interface{}) {
153161
for _, tag := range tags {
154-
if tag[FIELD_SKIP] != TRUE {
162+
if !tag.SkipMe {
155163
skip := skipFunc(tag)
156164
if skip && utils.DebugLevel(context) >= 10 {
157-
utils.Logger(context).Fprintln(os.Stderr, constants.MSG_SKIPPING_TAG_WITH_REASON, tag[FIELD_FUNCTION_NAME], runtime.FuncForPC(reflect.ValueOf(skipFunc).Pointer()).Name())
165+
utils.Logger(context).Fprintln(os.Stderr, constants.MSG_SKIPPING_TAG_WITH_REASON, tag.FunctionName, runtime.FuncForPC(reflect.ValueOf(skipFunc).Pointer()).Name())
158166
}
159-
tag[FIELD_SKIP] = strconv.FormatBool(skip)
167+
tag.SkipMe = skip
160168
}
161169
}
162170
}
163171

164-
func signatureContainsDefaultArg(tag map[string]string) bool {
165-
return strings.Contains(tag[FIELD_SIGNATURE], "=")
172+
func signatureContainsDefaultArg(tag *CTag) bool {
173+
return strings.Contains(tag.Signature, "=")
166174
}
167175

168-
func prototypeAndCodeDontMatch(tag map[string]string) bool {
169-
if tag[FIELD_SKIP] == TRUE {
176+
func prototypeAndCodeDontMatch(tag *CTag) bool {
177+
if tag.SkipMe {
170178
return true
171179
}
172180

173-
code := removeSpacesAndTabs(tag[FIELD_CODE])
174-
prototype := removeSpacesAndTabs(tag[KIND_PROTOTYPE])
181+
code := removeSpacesAndTabs(tag.Code)
182+
prototype := removeSpacesAndTabs(tag.Prototype)
175183
prototype = removeTralingSemicolon(prototype)
176184

177185
return strings.Index(code, prototype) == -1
@@ -187,41 +195,66 @@ func removeSpacesAndTabs(s string) string {
187195
return s
188196
}
189197

190-
func skipTagsWithField(tags []map[string]string, fields []string, context map[string]interface{}) {
191-
for _, tag := range tags {
192-
if field, skip := utils.TagHasAtLeastOneField(tag, fields); skip {
193-
if utils.DebugLevel(context) >= 10 {
194-
utils.Logger(context).Fprintln(os.Stderr, constants.MSG_SKIPPING_TAG_BECAUSE_HAS_FIELD, field)
195-
}
196-
tag[FIELD_SKIP] = TRUE
197-
}
198+
func tagIsUnhandled(tag *CTag) bool {
199+
return !tag.IsHandled()
200+
}
201+
202+
func (tag *CTag) IsHandled() bool {
203+
if tag.Class != "" {
204+
return false
205+
}
206+
if tag.Struct != "" {
207+
return false
208+
}
209+
if tag.Namespace != "" {
210+
return false
198211
}
212+
return true
199213
}
200214

201-
func tagIsUnknown(tag map[string]string) bool {
202-
return !KNOWN_TAG_KINDS[tag[FIELD_KIND]]
215+
func tagIsUnknown(tag *CTag) bool {
216+
return !KNOWN_TAG_KINDS[tag.Kind]
203217
}
204218

205-
func parseTag(row string) map[string]string {
206-
tag := make(map[string]string)
219+
func parseTag(row string) *CTag {
220+
tag := &CTag{}
207221
parts := strings.Split(row, "\t")
208222

209-
tag[FIELD_FUNCTION_NAME] = parts[0]
210-
tag[FIELD_FILENAME] = parts[1]
223+
tag.FunctionName = parts[0]
224+
tag.Filename = parts[1]
211225

212226
parts = parts[2:]
213227

214228
for _, part := range parts {
215229
if strings.Contains(part, ":") {
216-
field := part[:strings.Index(part, ":")]
217-
if FIELDS[field] {
218-
tag[field] = strings.TrimSpace(part[strings.Index(part, ":")+1:])
230+
colon := strings.Index(part, ":")
231+
field := part[:colon]
232+
value := strings.TrimSpace(part[colon+1:])
233+
switch field {
234+
case "kind":
235+
tag.Kind = value
236+
case "line":
237+
val, _ := strconv.Atoi(value)
238+
// TODO: Check err from strconv.Atoi
239+
tag.Line = val
240+
case "typeref":
241+
tag.Typeref = value
242+
case "signature":
243+
tag.Signature = value
244+
case "returntype":
245+
tag.Returntype = value
246+
case "class":
247+
tag.Class = value
248+
case "struct":
249+
tag.Struct = value
250+
case "namespace":
251+
tag.Namespace = value
219252
}
220253
}
221254
}
222255

223256
if strings.Contains(row, "/^") && strings.Contains(row, "$/;") {
224-
tag[FIELD_CODE] = row[strings.Index(row, "/^")+2 : strings.Index(row, "$/;")]
257+
tag.Code = row[strings.Index(row, "/^")+2 : strings.Index(row, "$/;")]
225258
}
226259

227260
return tag

0 commit comments

Comments
 (0)