2 * tm_parser.c - this file is part of Geany, a fast and lightweight IDE
4 * Copyright 2016 The Geany contributors
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 #include "tm_parser.h"
33 /* Allows remapping a subparser tag type to another type if there's a clash with
34 * the master parser tag type. Only subparser tag types explicitly listed within
35 * TMSubparserMapEntry maps are added to tag manager - tags with types not listed
36 * are discarded to prevent uncontrolled merging of tags from master parser and
42 } TMSubparserMapEntry
;
45 static GHashTable
*subparser_map
= NULL
;
48 {'d', tm_tag_macro_t}, \
49 {'e', tm_tag_enumerator_t}, \
50 {'f', tm_tag_function_t}, \
51 {'g', tm_tag_enum_t}, \
52 {'m', tm_tag_member_t}, \
53 {'p', tm_tag_prototype_t}, \
54 {'s', tm_tag_struct_t}, \
55 {'t', tm_tag_typedef_t}, \
56 {'u', tm_tag_union_t}, \
57 {'v', tm_tag_variable_t}, \
58 {'x', tm_tag_externvar_t},
60 /* Old C parser, also used by GLSL and Ferite */
61 static TMParserMapEntry map_C_old_parser
[] = {
63 {'c', tm_tag_class_t
},
64 {'n', tm_tag_namespace_t
},
67 # define COMMON_C_NEW_PARSER \
68 {'h', tm_tag_undef_t}, \
69 {'l', tm_tag_undef_t}, \
70 {'z', tm_tag_undef_t}, \
71 {'L', tm_tag_undef_t}, \
72 {'D', tm_tag_undef_t},
74 static TMParserMapEntry map_C
[] = {
79 static TMParserMapEntry map_CPP
[] = {
83 {'c', tm_tag_class_t
},
84 {'n', tm_tag_namespace_t
},
85 {'A', tm_tag_undef_t
},
86 {'N', tm_tag_undef_t
},
87 {'U', tm_tag_undef_t
},
88 {'Z', tm_tag_undef_t
},
91 static TMParserMapEntry map_JAVA
[] = {
92 {'c', tm_tag_class_t
},
93 {'f', tm_tag_field_t
},
94 {'i', tm_tag_interface_t
},
95 {'m', tm_tag_method_t
},
96 {'p', tm_tag_package_t
},
97 {'e', tm_tag_enumerator_t
},
101 static TMParserMapEntry map_MAKEFILE
[] = {
102 {'m', tm_tag_macro_t
},
103 {'t', tm_tag_function_t
},
104 {'I', tm_tag_undef_t
},
107 static TMParserMapEntry map_PASCAL
[] = {
108 {'f', tm_tag_function_t
},
109 {'p', tm_tag_function_t
},
112 static TMParserMapEntry map_PERL
[] = {
113 {'c', tm_tag_enum_t
},
114 {'f', tm_tag_other_t
},
115 {'l', tm_tag_macro_t
},
116 {'p', tm_tag_package_t
},
117 {'s', tm_tag_function_t
},
118 {'d', tm_tag_prototype_t
},
119 {'M', tm_tag_undef_t
},
122 static TMParserMapEntry map_PHP
[] = {
123 {'c', tm_tag_class_t
},
124 {'d', tm_tag_macro_t
},
125 {'f', tm_tag_function_t
},
126 {'i', tm_tag_interface_t
},
127 {'l', tm_tag_undef_t
},
128 {'n', tm_tag_namespace_t
},
129 {'t', tm_tag_struct_t
},
130 {'v', tm_tag_variable_t
},
131 {'a', tm_tag_undef_t
},
134 static TMParserMapEntry map_PYTHON
[] = {
135 {'c', tm_tag_class_t
},
136 {'f', tm_tag_function_t
},
137 {'m', tm_tag_method_t
},
138 {'v', tm_tag_variable_t
},
139 /* defined as externvar to get those excluded as forward type in symbols.c:goto_tag()
140 * so we can jump to the real implementation (if known) instead of to the import statement */
141 {'x', tm_tag_externvar_t
},
144 /* different parser than tex.c from universal-ctags */
145 static TMParserMapEntry map_LATEX
[] = {
146 {'f', tm_tag_function_t
},
147 {'c', tm_tag_class_t
},
148 {'m', tm_tag_member_t
},
149 {'d', tm_tag_macro_t
},
150 {'v', tm_tag_variable_t
},
151 {'n', tm_tag_namespace_t
},
152 {'s', tm_tag_struct_t
},
154 static TMParserMapEntry map_BIBTEX
[] = {
155 {'a', tm_tag_function_t
},
156 {'b', tm_tag_class_t
},
157 {'B', tm_tag_class_t
},
158 {'c', tm_tag_member_t
},
159 {'i', tm_tag_macro_t
},
160 {'I', tm_tag_macro_t
},
161 {'j', tm_tag_member_t
},
162 {'m', tm_tag_other_t
},
163 {'M', tm_tag_variable_t
},
164 {'n', tm_tag_other_t
},
165 {'p', tm_tag_variable_t
},
166 {'P', tm_tag_class_t
},
167 {'s', tm_tag_namespace_t
},
168 {'t', tm_tag_other_t
},
169 {'u', tm_tag_externvar_t
},
172 static TMParserMapEntry map_ASM
[] = {
173 {'d', tm_tag_macro_t
},
174 {'l', tm_tag_namespace_t
},
175 {'m', tm_tag_function_t
},
176 {'t', tm_tag_struct_t
},
177 {'s', tm_tag_undef_t
},
180 /* not in universal-ctags */
181 static TMParserMapEntry map_CONF
[] = {
182 {'s', tm_tag_namespace_t
},
183 {'k', tm_tag_macro_t
},
186 static TMParserMapEntry map_SQL
[] = {
187 {'c', tm_tag_undef_t
},
188 {'d', tm_tag_prototype_t
},
189 {'f', tm_tag_function_t
},
190 {'E', tm_tag_field_t
},
191 {'l', tm_tag_undef_t
},
192 {'L', tm_tag_undef_t
},
193 {'P', tm_tag_package_t
},
194 {'p', tm_tag_namespace_t
},
195 {'r', tm_tag_undef_t
},
196 {'s', tm_tag_undef_t
},
197 {'t', tm_tag_class_t
},
198 {'T', tm_tag_macro_t
},
199 {'v', tm_tag_variable_t
},
200 {'i', tm_tag_struct_t
},
201 {'e', tm_tag_undef_t
},
202 {'U', tm_tag_undef_t
},
203 {'R', tm_tag_undef_t
},
204 {'D', tm_tag_undef_t
},
205 {'V', tm_tag_member_t
},
206 {'n', tm_tag_undef_t
},
207 {'x', tm_tag_undef_t
},
208 {'y', tm_tag_undef_t
},
209 {'z', tm_tag_undef_t
},
210 {'C', tm_tag_undef_t
},
213 /* not in universal-ctags */
214 static TMParserMapEntry map_DOCBOOK
[] = {
215 {'f', tm_tag_function_t
},
216 {'c', tm_tag_class_t
},
217 {'m', tm_tag_member_t
},
218 {'d', tm_tag_macro_t
},
219 {'v', tm_tag_variable_t
},
220 {'s', tm_tag_struct_t
},
223 static TMParserMapEntry map_ERLANG
[] = {
224 {'d', tm_tag_macro_t
},
225 {'f', tm_tag_function_t
},
226 {'m', tm_tag_undef_t
},
227 {'r', tm_tag_struct_t
},
228 {'t', tm_tag_typedef_t
},
231 static TMParserMapEntry map_CSS
[] = {
232 {'c', tm_tag_class_t
},
233 {'s', tm_tag_struct_t
},
234 {'i', tm_tag_variable_t
},
237 static TMParserMapEntry map_RUBY
[] = {
238 {'c', tm_tag_class_t
},
239 {'f', tm_tag_method_t
},
240 {'m', tm_tag_namespace_t
},
241 {'S', tm_tag_member_t
},
242 {'C', tm_tag_undef_t
},
243 {'A', tm_tag_undef_t
},
244 {'a', tm_tag_undef_t
},
245 {'L', tm_tag_undef_t
},
248 static TMParserMapEntry map_TCL
[] = {
249 {'c', tm_tag_class_t
},
250 {'m', tm_tag_member_t
},
251 {'p', tm_tag_function_t
},
252 {'n', tm_tag_namespace_t
},
255 static TMParserMapEntry map_SH
[] = {
256 {'f', tm_tag_function_t
},
259 static TMParserMapEntry map_D
[] = {
260 {'c', tm_tag_class_t
},
261 {'e', tm_tag_enumerator_t
},
262 {'f', tm_tag_function_t
},
263 {'g', tm_tag_enum_t
},
264 {'i', tm_tag_interface_t
},
265 {'m', tm_tag_member_t
},
266 {'n', tm_tag_namespace_t
},
267 {'p', tm_tag_prototype_t
},
268 {'s', tm_tag_struct_t
},
269 {'t', tm_tag_typedef_t
},
270 {'u', tm_tag_union_t
},
271 {'v', tm_tag_variable_t
},
272 {'x', tm_tag_externvar_t
},
275 static TMParserMapEntry map_DIFF
[] = {
276 {'m', tm_tag_function_t
},
277 {'n', tm_tag_function_t
},
278 {'d', tm_tag_function_t
},
279 {'h', tm_tag_undef_t
},
282 /* different parser than in universal-ctags */
283 static TMParserMapEntry map_VHDL
[] = {
284 {'c', tm_tag_variable_t
},
285 {'t', tm_tag_typedef_t
},
286 {'v', tm_tag_variable_t
},
287 {'a', tm_tag_undef_t
},
288 {'s', tm_tag_variable_t
},
289 {'f', tm_tag_function_t
},
290 {'p', tm_tag_function_t
},
291 {'k', tm_tag_member_t
},
292 {'l', tm_tag_namespace_t
},
293 {'m', tm_tag_member_t
},
294 {'n', tm_tag_class_t
},
295 {'o', tm_tag_struct_t
},
296 {'u', tm_tag_undef_t
},
297 {'b', tm_tag_member_t
},
298 {'A', tm_tag_typedef_t
},
301 static TMParserMapEntry map_LUA
[] = {
302 {'f', tm_tag_function_t
},
303 {'X', tm_tag_undef_t
},
306 static TMParserMapEntry map_JAVASCRIPT
[] = {
307 {'f', tm_tag_function_t
},
308 {'c', tm_tag_class_t
},
309 {'m', tm_tag_method_t
},
310 {'p', tm_tag_member_t
},
311 {'C', tm_tag_macro_t
},
312 {'v', tm_tag_variable_t
},
313 {'g', tm_tag_function_t
},
314 {'G', tm_tag_undef_t
},
315 {'S', tm_tag_undef_t
},
316 {'M', tm_tag_undef_t
},
319 static TMParserMapEntry map_HASKELL
[] = {
320 {'t', tm_tag_typedef_t
},
321 {'c', tm_tag_macro_t
},
322 {'f', tm_tag_function_t
},
323 {'m', tm_tag_namespace_t
},
326 static TMParserMapEntry map_CSHARP
[] = {
327 {'c', tm_tag_class_t
},
328 {'d', tm_tag_macro_t
},
329 {'e', tm_tag_enumerator_t
},
330 {'E', tm_tag_undef_t
},
331 {'f', tm_tag_field_t
},
332 {'g', tm_tag_enum_t
},
333 {'i', tm_tag_interface_t
},
334 {'l', tm_tag_undef_t
},
335 {'m', tm_tag_method_t
},
336 {'n', tm_tag_namespace_t
},
337 {'p', tm_tag_undef_t
},
338 {'s', tm_tag_struct_t
},
339 {'t', tm_tag_typedef_t
},
342 static TMParserMapEntry map_FREEBASIC
[] = {
343 {'c', tm_tag_macro_t
},
344 {'f', tm_tag_function_t
},
345 {'l', tm_tag_namespace_t
},
346 {'t', tm_tag_struct_t
},
347 {'v', tm_tag_variable_t
},
348 {'g', tm_tag_externvar_t
},
351 static TMParserMapEntry map_HAXE
[] = {
352 {'m', tm_tag_method_t
},
353 {'c', tm_tag_class_t
},
354 {'e', tm_tag_enum_t
},
355 {'v', tm_tag_variable_t
},
356 {'i', tm_tag_interface_t
},
357 {'t', tm_tag_typedef_t
},
360 static TMParserMapEntry map_REST
[] = {
361 {'c', tm_tag_namespace_t
},
362 {'s', tm_tag_member_t
},
363 {'S', tm_tag_macro_t
},
364 {'t', tm_tag_variable_t
},
365 {'C', tm_tag_undef_t
},
366 {'T', tm_tag_undef_t
},
367 {'d', tm_tag_undef_t
},
370 static TMParserMapEntry map_HTML
[] = {
371 {'a', tm_tag_member_t
},
372 {'c', tm_tag_undef_t
},
373 {'h', tm_tag_namespace_t
},
374 {'i', tm_tag_class_t
},
375 {'j', tm_tag_variable_t
},
376 {'C', tm_tag_undef_t
},
377 {'I', tm_tag_undef_t
},
378 {'J', tm_tag_undef_t
},
381 static TMSubparserMapEntry subparser_HTML_javascript_map
[] = {
382 {tm_tag_function_t
, tm_tag_function_t
},
385 static TMParserMapEntry map_F77
[] = {
386 {'b', tm_tag_undef_t
},
387 {'c', tm_tag_macro_t
},
388 {'e', tm_tag_undef_t
},
389 {'f', tm_tag_function_t
},
390 {'i', tm_tag_interface_t
},
391 {'k', tm_tag_member_t
},
392 {'l', tm_tag_undef_t
},
393 {'L', tm_tag_undef_t
},
394 {'m', tm_tag_namespace_t
},
395 {'n', tm_tag_undef_t
},
396 {'p', tm_tag_struct_t
},
397 {'s', tm_tag_method_t
},
398 {'t', tm_tag_class_t
},
399 {'v', tm_tag_variable_t
},
400 {'E', tm_tag_enum_t
},
401 {'N', tm_tag_enumerator_t
},
404 #define map_FORTRAN map_F77
406 /* different parser than in universal-ctags */
407 static TMParserMapEntry map_MATLAB
[] = {
408 {'f', tm_tag_function_t
},
409 {'s', tm_tag_struct_t
},
412 #define map_GLSL map_C_old_parser
414 /* not in universal-ctags */
415 static TMParserMapEntry map_VALA
[] = {
416 {'c', tm_tag_class_t
},
417 {'d', tm_tag_macro_t
},
418 {'e', tm_tag_enumerator_t
},
419 {'f', tm_tag_field_t
},
420 {'g', tm_tag_enum_t
},
421 {'i', tm_tag_interface_t
},
422 {'l', tm_tag_undef_t
},
423 {'m', tm_tag_method_t
},
424 {'n', tm_tag_namespace_t
},
425 {'p', tm_tag_undef_t
},
426 {'S', tm_tag_undef_t
},
427 {'s', tm_tag_struct_t
},
430 /* not in universal-ctags */
431 static TMParserMapEntry map_ACTIONSCRIPT
[] = {
432 {'f', tm_tag_function_t
},
433 {'c', tm_tag_class_t
},
434 {'i', tm_tag_interface_t
},
435 {'P', tm_tag_package_t
},
436 {'m', tm_tag_method_t
},
437 {'p', tm_tag_member_t
},
438 {'v', tm_tag_variable_t
},
439 {'l', tm_tag_variable_t
},
440 {'C', tm_tag_macro_t
},
441 {'I', tm_tag_externvar_t
},
442 {'x', tm_tag_other_t
},
445 static TMParserMapEntry map_NSIS
[] = {
446 {'s', tm_tag_namespace_t
},
447 {'f', tm_tag_function_t
},
448 {'v', tm_tag_variable_t
},
449 {'d', tm_tag_undef_t
},
450 {'m', tm_tag_undef_t
},
451 {'S', tm_tag_undef_t
},
452 {'p', tm_tag_undef_t
},
453 {'l', tm_tag_undef_t
},
454 {'i', tm_tag_undef_t
},
457 /* not in universal-ctags */
458 static TMParserMapEntry map_MARKDOWN
[] = {
459 {'v', tm_tag_variable_t
},
462 static TMParserMapEntry map_TXT2TAGS
[] = {
463 {'s', tm_tag_member_t
},
466 static TMParserMapEntry map_ABC
[] = {
467 {'s', tm_tag_member_t
},
470 static TMParserMapEntry map_VERILOG
[] = {
471 {'c', tm_tag_variable_t
},
472 {'e', tm_tag_typedef_t
},
473 {'f', tm_tag_function_t
},
474 {'m', tm_tag_class_t
},
475 {'n', tm_tag_variable_t
},
476 {'p', tm_tag_variable_t
},
477 {'r', tm_tag_variable_t
},
478 {'t', tm_tag_function_t
},
481 static TMParserMapEntry map_R
[] = {
482 {'f', tm_tag_function_t
},
483 {'l', tm_tag_other_t
},
484 {'s', tm_tag_other_t
},
487 static TMParserMapEntry map_COBOL
[] = {
488 {'d', tm_tag_variable_t
},
489 {'D', tm_tag_interface_t
},
490 {'f', tm_tag_function_t
},
491 {'g', tm_tag_struct_t
},
492 {'p', tm_tag_macro_t
},
493 {'P', tm_tag_class_t
},
494 {'s', tm_tag_namespace_t
},
495 {'S', tm_tag_externvar_t
},
498 static TMParserMapEntry map_OBJC
[] = {
499 {'i', tm_tag_interface_t
},
500 {'I', tm_tag_undef_t
},
501 {'P', tm_tag_undef_t
},
502 {'m', tm_tag_method_t
},
503 {'c', tm_tag_class_t
},
504 {'v', tm_tag_variable_t
},
505 {'E', tm_tag_field_t
},
506 {'f', tm_tag_function_t
},
507 {'p', tm_tag_undef_t
},
508 {'t', tm_tag_typedef_t
},
509 {'s', tm_tag_struct_t
},
510 {'e', tm_tag_enum_t
},
511 {'M', tm_tag_macro_t
},
512 {'C', tm_tag_undef_t
},
515 static TMParserMapEntry map_ASCIIDOC
[] = {
516 {'c', tm_tag_namespace_t
},
517 {'s', tm_tag_member_t
},
518 {'S', tm_tag_macro_t
},
519 {'t', tm_tag_variable_t
},
520 {'T', tm_tag_struct_t
},
521 {'u', tm_tag_undef_t
},
522 {'a', tm_tag_undef_t
},
525 static TMParserMapEntry map_ABAQUS
[] = {
526 {'p', tm_tag_class_t
},
527 {'a', tm_tag_member_t
},
528 {'s', tm_tag_interface_t
},
531 static TMParserMapEntry map_RUST
[] = {
532 {'n', tm_tag_namespace_t
},
533 {'s', tm_tag_struct_t
},
534 {'i', tm_tag_interface_t
},
535 {'c', tm_tag_class_t
},
536 {'f', tm_tag_function_t
},
537 {'g', tm_tag_enum_t
},
538 {'t', tm_tag_typedef_t
},
539 {'v', tm_tag_variable_t
},
540 {'M', tm_tag_macro_t
},
541 {'m', tm_tag_field_t
},
542 {'e', tm_tag_enumerator_t
},
543 {'P', tm_tag_method_t
},
546 static TMParserMapEntry map_GO
[] = {
547 {'p', tm_tag_namespace_t
},
548 {'f', tm_tag_function_t
},
549 {'c', tm_tag_macro_t
},
550 {'t', tm_tag_typedef_t
},
551 {'v', tm_tag_variable_t
},
552 {'s', tm_tag_struct_t
},
553 {'i', tm_tag_interface_t
},
554 {'m', tm_tag_member_t
},
555 {'M', tm_tag_undef_t
},
556 {'n', tm_tag_undef_t
},
557 {'u', tm_tag_undef_t
},
558 {'P', tm_tag_undef_t
},
559 {'a', tm_tag_undef_t
},
560 {'R', tm_tag_undef_t
},
563 static TMParserMapEntry map_JSON
[] = {
564 {'o', tm_tag_member_t
},
565 {'a', tm_tag_member_t
},
566 {'n', tm_tag_member_t
},
567 {'s', tm_tag_member_t
},
568 {'b', tm_tag_member_t
},
569 {'z', tm_tag_member_t
},
572 /* Zephir, same as PHP */
573 #define map_ZEPHIR map_PHP
575 /* not in universal-ctags */
576 static TMParserMapEntry map_POWERSHELL
[] = {
577 {'f', tm_tag_function_t
},
578 {'v', tm_tag_variable_t
},
581 static TMParserMapEntry map_JULIA
[] = {
582 {'c', tm_tag_variable_t
},
583 {'f', tm_tag_function_t
},
584 {'g', tm_tag_member_t
},
585 {'m', tm_tag_macro_t
},
586 {'n', tm_tag_namespace_t
},
587 {'s', tm_tag_struct_t
},
588 {'t', tm_tag_typedef_t
},
589 /* defined as externvar to get those excluded as forward type in symbols.c:goto_tag()
590 * so we can jump to the real implementation (if known) instead of to the import statement */
591 {'x', tm_tag_externvar_t
},
594 static TMParserMapEntry map_CPREPROCESSOR
[] = {
595 {'d', tm_tag_undef_t
},
596 {'h', tm_tag_undef_t
},
597 {'D', tm_tag_undef_t
},
599 static TMParserMapEntry map_GDSCRIPT
[] = {
600 {'c', tm_tag_class_t
},
601 {'m', tm_tag_method_t
},
602 {'v', tm_tag_variable_t
},
603 {'C', tm_tag_variable_t
},
604 {'g', tm_tag_enum_t
},
605 {'e', tm_tag_variable_t
},
606 {'z', tm_tag_other_t
},
607 {'l', tm_tag_other_t
},
608 {'s', tm_tag_variable_t
},
613 TMParserMapEntry
*entries
;
617 #define MAP_ENTRY(lang) [TM_PARSER_##lang] = {map_##lang, G_N_ELEMENTS(map_##lang)}
619 /* keep in sync with TM_PARSER_* definitions in the header */
620 static TMParserMap parser_map
[] = {
646 MAP_ENTRY(JAVASCRIPT
),
649 MAP_ENTRY(FREEBASIC
),
657 MAP_ENTRY(ACTIONSCRIPT
),
672 MAP_ENTRY(POWERSHELL
),
674 MAP_ENTRY(CPREPROCESSOR
),
676 /* make sure the parser map is consistent and complete */
677 G_STATIC_ASSERT(G_N_ELEMENTS(parser_map
) == TM_PARSER_COUNT
);
680 TMTagType
tm_parser_get_tag_type(gchar kind
, TMParserType lang
)
682 TMParserMap
*map
= &parser_map
[lang
];
685 for (i
= 0; i
< map
->size
; i
++)
687 TMParserMapEntry
*entry
= &map
->entries
[i
];
689 if (entry
->kind
== kind
)
692 return tm_tag_undef_t
;
696 gchar
tm_parser_get_tag_kind(TMTagType type
, TMParserType lang
)
698 TMParserMap
*map
= &parser_map
[lang
];
701 for (i
= 0; i
< map
->size
; i
++)
703 TMParserMapEntry
*entry
= &map
->entries
[i
];
705 if (entry
->type
== type
)
712 static void add_subparser(TMParserType lang
, TMParserType sublang
, TMSubparserMapEntry
*map
, guint map_size
)
716 GHashTable
*lang_map
= g_hash_table_lookup(subparser_map
, GINT_TO_POINTER(lang
));
720 lang_map
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
721 g_hash_table_insert(subparser_map
, GINT_TO_POINTER(lang
), lang_map
);
724 mapping
= g_ptr_array_new();
725 for (i
= 0; i
< map_size
; i
++)
726 g_ptr_array_add(mapping
, &map
[i
]);
728 g_hash_table_insert(lang_map
, GINT_TO_POINTER(sublang
), mapping
);
732 #define SUBPARSER_MAP_ENTRY(lang, sublang, map) add_subparser(TM_PARSER_##lang, TM_PARSER_##sublang, map, G_N_ELEMENTS(map))
734 static void init_subparser_map(void)
736 SUBPARSER_MAP_ENTRY(HTML
, JAVASCRIPT
, subparser_HTML_javascript_map
);
740 TMTagType
tm_parser_get_subparser_type(TMParserType lang
, TMParserType sublang
, TMTagType type
)
743 GHashTable
*lang_map
;
748 subparser_map
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
749 init_subparser_map();
752 lang_map
= g_hash_table_lookup(subparser_map
, GINT_TO_POINTER(lang
));
754 return tm_tag_undef_t
;
756 mapping
= g_hash_table_lookup(lang_map
, GINT_TO_POINTER(sublang
));
758 return tm_tag_undef_t
;
760 for (i
= 0; i
< mapping
->len
; i
++)
762 TMSubparserMapEntry
*entry
= mapping
->pdata
[i
];
763 if (entry
->orig_type
== type
)
764 return entry
->new_type
;
767 return tm_tag_undef_t
;
771 void tm_parser_verify_type_mappings(void)
775 if (TM_PARSER_COUNT
> tm_ctags_get_lang_count())
776 g_error("More parsers defined in Geany than in ctags");
778 for (lang
= 0; lang
< TM_PARSER_COUNT
; lang
++)
780 const gchar
*kinds
= tm_ctags_get_lang_kinds(lang
);
781 TMParserMap
*map
= &parser_map
[lang
];
782 gchar presence_map
[256];
785 if (! map
->entries
|| map
->size
< 1)
786 g_error("No tag types in TM for %s, is the language listed in parser_map?",
787 tm_ctags_get_lang_name(lang
));
789 if (map
->size
!= strlen(kinds
))
790 g_error("Different number of tag types in TM (%d) and ctags (%d) for %s",
791 map
->size
, (int)strlen(kinds
), tm_ctags_get_lang_name(lang
));
793 memset(presence_map
, 0, sizeof(presence_map
));
794 for (i
= 0; i
< map
->size
; i
++)
796 gboolean ctags_found
= FALSE
;
797 gboolean tm_found
= FALSE
;
800 for (j
= 0; j
< map
->size
; j
++)
802 /* check that for every type in TM there's a type in ctags */
803 if (map
->entries
[i
].kind
== kinds
[j
])
805 /* check that for every type in ctags there's a type in TM */
806 if (map
->entries
[j
].kind
== kinds
[i
])
808 if (ctags_found
&& tm_found
)
812 g_error("Tag type '%c' found in TM but not in ctags for %s",
813 map
->entries
[i
].kind
, tm_ctags_get_lang_name(lang
));
815 g_error("Tag type '%c' found in ctags but not in TM for %s",
816 kinds
[i
], tm_ctags_get_lang_name(lang
));
818 presence_map
[(unsigned char) map
->entries
[i
].kind
]++;
821 for (i
= 0; i
< sizeof(presence_map
); i
++)
823 if (presence_map
[i
] > 1)
824 g_error("Duplicate tag type '%c' found for %s",
825 (gchar
)i
, tm_ctags_get_lang_name(lang
));
831 /* When the suffix of 'str' is an operator that should trigger scope
832 * autocompletion, this function should return the length of the operator,
834 gint
tm_parser_scope_autocomplete_suffix(TMParserType lang
, const gchar
*str
)
836 const gchar
*sep
= tm_parser_scope_separator(lang
);
838 if (g_str_has_suffix(str
, sep
))
845 if (g_str_has_suffix(str
, "."))
847 else if (g_str_has_suffix(str
, "->"))
849 else if (lang
== TM_PARSER_CPP
&& g_str_has_suffix(str
, "->*"))
858 /* Get the name of constructor method. Arguments of this method will be used
859 * for calltips when creating an object using the class name
860 * (e.g. after the opening brace in 'c = MyClass()' in Python) */
861 const gchar
*tm_parser_get_constructor_method(TMParserType lang
)
867 case TM_PARSER_PYTHON
:
875 /* determine anonymous tags from tag names only when corresponding
876 * ctags information is not available */
877 gboolean
tm_parser_is_anon_name(TMParserType lang
, gchar
*name
)
882 if (sscanf(name
, "__anon%u%c", &i
, &dummy
) == 1) /* uctags tags files */
884 else if (lang
== TM_PARSER_C
|| lang
== TM_PARSER_CPP
) /* legacy Geany tags files */
885 return sscanf(name
, "anon_%*[a-z]_%u%c", &i
, &dummy
) == 1;
886 else if (lang
== TM_PARSER_FORTRAN
|| lang
== TM_PARSER_F77
) /* legacy Geany tags files */
888 return sscanf(name
, "Structure#%u%c", &i
, &dummy
) == 1 ||
889 sscanf(name
, "Interface#%u%c", &i
, &dummy
) == 1 ||
890 sscanf(name
, "Enum#%u%c", &i
, &dummy
) == 1;
896 static gchar
*replace_string_if_present(gchar
*haystack
, gchar
*needle
, gchar
*subst
)
898 if (strstr(haystack
, needle
))
900 gchar
**split
= g_strsplit(haystack
, needle
, -1);
901 gchar
*ret
= g_strjoinv(subst
, split
);
909 /* return updated scope or original scope if no change needed */
910 gchar
*tm_parser_update_scope(TMParserType lang
, gchar
*scope
)
915 case TM_PARSER_ZEPHIR
:
916 /* PHP parser uses two different scope separators but this would
917 * complicate things in Geany so make sure there's just one type */
918 return replace_string_if_present(scope
, "\\", "::");
924 /* whether or not to enable ctags roles for the given language and kind */
925 gboolean
tm_parser_enable_role(TMParserType lang
, gchar kind
)
929 case TM_PARSER_GDSCRIPT
:
930 return kind
== 'c' ? FALSE
: TRUE
;
932 /* 'p' is used both for package definition tags and imported package
933 * tags and we can't tell which is which just by kind. By disabling
934 * roles for this kind, we only get package definition tags. */
935 return kind
== 'p' ? FALSE
: TRUE
;
941 /* whether or not to enable ctags kinds for the given language */
942 gboolean
tm_parser_enable_kind(TMParserType lang
, gchar kind
)
947 if (lang
>= TM_PARSER_COUNT
)
948 /* Fatal error but tm_parser_verify_type_mappings() will provide
949 * better message later */
952 map
= &parser_map
[lang
];
953 for (i
= 0; i
< map
->size
; i
++)
955 if (map
->entries
[i
].kind
== kind
)
956 return map
->entries
[i
].type
!= tm_tag_undef_t
;
962 gchar
*tm_parser_format_variable(TMParserType lang
, const gchar
*name
, const gchar
*type
)
970 return g_strconcat(name
, " ", type
, NULL
);
971 case TM_PARSER_PASCAL
:
972 case TM_PARSER_PYTHON
:
973 return g_strconcat(name
, ": ", type
, NULL
);
975 return g_strconcat(type
, " ", name
, NULL
);
980 gchar
*tm_parser_format_function(TMParserType lang
, const gchar
*fname
, const gchar
*args
,
981 const gchar
*retval
, const gchar
*scope
)
985 if (!args
) /* not a function */
988 str
= g_string_new(NULL
);
992 g_string_append(str
, scope
);
993 g_string_append(str
, tm_parser_scope_separator_printable(lang
));
995 g_string_append(str
, fname
);
996 g_string_append_c(str
, ' ');
997 g_string_append(str
, args
);
1003 case TM_PARSER_GDSCRIPT
:
1005 case TM_PARSER_PASCAL
:
1006 case TM_PARSER_PYTHON
:
1008 /* retval after function */
1012 case TM_PARSER_PASCAL
:
1015 case TM_PARSER_GDSCRIPT
:
1016 case TM_PARSER_PYTHON
:
1023 g_string_append(str
, sep
);
1024 g_string_append(str
, retval
);
1028 /* retval before function */
1029 g_string_prepend_c(str
, ' ');
1030 g_string_prepend(str
, retval
);
1035 return g_string_free(str
, FALSE
);
1039 const gchar
*tm_parser_scope_separator(TMParserType lang
)
1043 case TM_PARSER_C
: /* for C++ .h headers or C structs */
1045 case TM_PARSER_GLSL
: /* for structs */
1047 case TM_PARSER_POWERSHELL
:
1048 case TM_PARSER_RUST
:
1049 case TM_PARSER_ZEPHIR
:
1052 case TM_PARSER_TXT2TAGS
:
1055 /* these parsers don't report nested scopes but default "." for scope separator
1056 * might appear in the text so use something more improbable */
1057 case TM_PARSER_ASCIIDOC
:
1058 case TM_PARSER_CONF
:
1059 case TM_PARSER_REST
:
1068 const gchar
*tm_parser_scope_separator_printable(TMParserType lang
)
1072 case TM_PARSER_TXT2TAGS
:
1073 case TM_PARSER_ASCIIDOC
:
1074 case TM_PARSER_CONF
:
1075 case TM_PARSER_REST
:
1079 return tm_parser_scope_separator(lang
);
1084 gboolean
tm_parser_has_full_scope(TMParserType lang
)
1088 /* These parsers include full hierarchy in the tag scope, separated by tm_parser_scope_separator() */
1089 case TM_PARSER_ACTIONSCRIPT
:
1092 case TM_PARSER_CSHARP
:
1093 case TM_PARSER_COBOL
:
1095 case TM_PARSER_GDSCRIPT
:
1096 case TM_PARSER_GLSL
:
1098 case TM_PARSER_JAVA
:
1099 case TM_PARSER_JAVASCRIPT
:
1100 case TM_PARSER_JSON
:
1103 case TM_PARSER_POWERSHELL
:
1104 case TM_PARSER_PYTHON
:
1105 case TM_PARSER_RUBY
:
1106 case TM_PARSER_RUST
:
1108 case TM_PARSER_TXT2TAGS
:
1109 case TM_PARSER_VALA
:
1110 case TM_PARSER_ZEPHIR
:
1113 /* These make use of the scope, but don't include nested hierarchy
1114 * (either as a parser limitation or a language semantic) */
1115 case TM_PARSER_ASCIIDOC
:
1116 case TM_PARSER_CONF
:
1117 case TM_PARSER_ERLANG
:
1119 case TM_PARSER_FORTRAN
:
1120 case TM_PARSER_OBJC
:
1121 case TM_PARSER_REST
:
1122 /* Other parsers don't use scope at all (or should be somewhere above) */
1129 gboolean
tm_parser_langs_compatible(TMParserType lang
, TMParserType other
)
1131 if (lang
== TM_PARSER_NONE
|| other
== TM_PARSER_NONE
)
1135 /* Accept CPP tags for C lang and vice versa */
1136 else if (lang
== TM_PARSER_C
&& other
== TM_PARSER_CPP
)
1138 else if (lang
== TM_PARSER_CPP
&& other
== TM_PARSER_C
)