Skip to content

Commit 396b2a0

Browse files
committed
Fix multiline prototype issue
This time it should also work with all the functions with return type and signature on different lines
1 parent aad7534 commit 396b2a0

File tree

1 file changed

+84
-1
lines changed

1 file changed

+84
-1
lines changed

src/arduino.cc/builder/ctags/ctags_has_issues.go

+84-1
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,90 @@ func (p *CTagsParser) prototypeAndCodeDontMatch(tag *types.CTag) bool {
9696
prototype := removeSpacesAndTabs(tag.Prototype)
9797
prototype = removeTralingSemicolon(prototype)
9898

99-
return strings.Index(code, prototype) == -1
99+
// Prototype matches exactly with the code?
100+
ret := strings.Index(code, prototype)
101+
102+
if ret == -1 {
103+
// If the definition is multiline ctags uses the function name as line number
104+
// Try to match functions in the form
105+
// void
106+
// foo() {}
107+
108+
// Add to code n non-whitespace non-comments tokens before the code line
109+
110+
code = removeEverythingAfterClosingRoundBracket(code)
111+
// Get how many characters are "missing"
112+
n := strings.Index(prototype, code)
113+
// Add these characters to "code" string
114+
code = getFunctionProtoWithNPreviousCharacters(tag, code, n)
115+
// Check again for perfect matching
116+
ret = strings.Index(code, prototype)
117+
}
118+
119+
return ret == -1
120+
}
121+
122+
func removeEverythingAfterClosingRoundBracket(s string) string {
123+
n := strings.Index(s, ")")
124+
return s[0 : n+1]
125+
}
126+
127+
func getFunctionProtoWithNPreviousCharacters(tag *types.CTag, code string, n int) string {
128+
129+
/* FIXME I'm ugly */
130+
expectedPrototypeLen := len(code) + n
131+
132+
file, err := os.Open(tag.Filename)
133+
if err == nil {
134+
defer file.Close()
135+
136+
scanner := bufio.NewScanner(file)
137+
line := 0
138+
multilinecomment := false
139+
var textBuffer []string
140+
141+
// buffer lines until we get to the start of this tag
142+
for scanner.Scan() && line < (tag.Line-1) {
143+
line++
144+
text := scanner.Text()
145+
textBuffer = append(textBuffer, text)
146+
}
147+
148+
for line > 0 && len(code) < expectedPrototypeLen {
149+
150+
line = line - 1
151+
text := textBuffer[line]
152+
153+
// Remove C++ style comments
154+
if strings.Index(text, "//") != -1 {
155+
text = text[0:strings.Index(text, "//")]
156+
}
157+
158+
// Remove C style comments
159+
if strings.Index(text, "*/") != -1 {
160+
if strings.Index(text, "/*") != -1 {
161+
// C style comments on the same line
162+
text = text[0:strings.Index(text, "/*")] + text[strings.Index(text, "*/")+1:len(text)-1]
163+
} else {
164+
text = text[strings.Index(text, "*/")+1 : len(text)-1]
165+
multilinecomment = true
166+
}
167+
}
168+
169+
if multilinecomment {
170+
if strings.Index(text, "/*") != -1 {
171+
text = text[0:strings.Index(text, "/*")]
172+
multilinecomment = false
173+
} else {
174+
text = ""
175+
}
176+
}
177+
178+
code = text + code
179+
code = removeSpacesAndTabs(code)
180+
}
181+
}
182+
return code
100183
}
101184

102185
/* This function scans the source files searching for "extern C" context

0 commit comments

Comments
 (0)