@@ -96,7 +96,90 @@ func (p *CTagsParser) prototypeAndCodeDontMatch(tag *types.CTag) bool {
96
96
prototype := removeSpacesAndTabs (tag .Prototype )
97
97
prototype = removeTralingSemicolon (prototype )
98
98
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
100
183
}
101
184
102
185
/* This function scans the source files searching for "extern C" context
0 commit comments