3 # Author: Enrico Tröger
4 # License: GPL v2 or later
6 # This script downloads the PHP tag definitions in JSON format from
7 # http://doc.php.net/downloads/json/php_manual_en.json.
8 # From those defintions all function tags are extracted and written
9 # to ../data/tags/std.php.tags (relative to the script's location, not $CWD).
13 from json
import loads
14 from os
.path
import dirname
, join
15 from urllib
.request
import urlopen
17 from create_tags_helper
import format_tag
, write_ctags_file
19 UPSTREAM_TAG_DEFINITION
= 'http://doc.php.net/downloads/json/php_manual_en.json'
20 PROTOTYPE_RE
= r
'^(?P<return_type>.*) {tag_name}(?P<arg_list>\(.*\))$'
22 # (from src/tagmanager/tm_tag.c:90)
31 KIND_FUNCTION
= 'function'
32 KIND_VARIABLE
= 'variable'
35 def normalize_name(name
):
36 """ Replace namespace separator with class separators, as Geany only
37 understands the latter """
38 return name
.replace('\\', '::')
41 def split_scope(name
):
42 """ Splits the scope from the member, and returns (scope, member).
43 Returned scope is None if the name is not a member """
44 name
= normalize_name(name
)
45 sep_pos
= name
.rfind('::')
49 return name
[:sep_pos
], name
[sep_pos
+ 2:]
52 def parse_and_create_php_tags_file():
53 # download upstream definition
54 response
= urlopen(UPSTREAM_TAG_DEFINITION
)
56 html
= response
.read()
61 definitions
= loads(html
)
65 for tag_name
, tag_definition
in definitions
.items():
66 prototype_re
= PROTOTYPE_RE
.format(tag_name
=re
.escape(tag_name
))
67 match
= re
.match(prototype_re
, tag_definition
['prototype'])
69 return_type
= normalize_name(match
.group('return_type'))
70 arg_list
= match
.group('arg_list')
72 scope
, tag_name
= split_scope(tag_name
)
73 if tag_name
[0] == '$':
78 tag_list
.append(format_tag(tag_name
, kind
, arg_list
, scope
, ('unknown', return_type
)))
79 # Also create a class tag when encountering a __construct()
80 if tag_name
== '__construct' and scope
is not None:
81 scope
, tag_name
= split_scope(scope
)
82 tag_list
.append(format_tag(tag_name
, KIND_CLASS
, arg_list
, scope
or ''))
85 script_dir
= dirname(__file__
)
86 filename
= join(script_dir
, '..', 'data', 'tags', 'std.php.tags')
87 write_ctags_file(filename
, tag_list
, sys
.argv
[0])
88 print(f
'Created: {filename} with {len(tag_list)} tags')
91 if __name__
== '__main__':
92 parse_and_create_php_tags_file()