Branch: refs/heads/master Author: Enrico Tröger enrico.troeger@uvena.de Committer: GitHub noreply@github.com Date: Sat, 05 Aug 2023 21:06:34 UTC Commit: e806a54a9661bf39dd4af8a6c7daad5b6be8fa28 https://github.com/geany/geany/commit/e806a54a9661bf39dd4af8a6c7daad5b6be8fa...
Log Message: ----------- Merge pull request #3512 from eht16/generate_php_global_tags_in_ctags_format
Generate PHP global tags in ctags format
Modified Paths: -------------- data/tags/std.php.tags scripts/create_php_tags.py scripts/create_py_tags.py scripts/create_tags_helper.py
Modified: data/tags/std.php.tags 18624 lines changed, 9317 insertions(+), 9307 deletions(-) =================================================================== No diff available, check online
Modified: scripts/create_php_tags.py 39 lines changed, 15 insertions(+), 24 deletions(-) =================================================================== @@ -9,10 +9,12 @@ # to ../data/tags/std.php.tags (relative to the script's location, not $CWD).
import re +import sys from json import loads from os.path import dirname, join from urllib.request import urlopen
+from create_tags_helper import format_tag, write_ctags_file
UPSTREAM_TAG_DEFINITION = 'http://doc.php.net/downloads/json/php_manual_en.json' PROTOTYPE_RE = r'^(?P<return_type>.*) {tag_name}(?P<arg_list>(.*))$' @@ -23,12 +25,11 @@ TA_ARGLIST = 205 TA_SCOPE = 206 TA_VARTYPE = 207 -# TMTagType (src/tagmanager/tm_tag.h:49) -TYPE_CLASS = 1 -TYPE_FUNCTION = 16 -TYPE_MEMBER = 64 -TYPE_METHOD = 128 -TYPE_VARIABLE = 16384 + +# PHP kinds +KIND_CLASS = 'class' +KIND_FUNCTION = 'function' +KIND_VARIABLE = 'variable'
def normalize_name(name): @@ -70,31 +71,21 @@ def parse_and_create_php_tags_file():
scope, tag_name = split_scope(tag_name) if tag_name[0] == '$': - tag_type = TYPE_MEMBER if scope is not None else TYPE_VARIABLE + kind = KIND_VARIABLE else: - tag_type = TYPE_METHOD if scope is not None else TYPE_FUNCTION - tag_list.append((tag_name, tag_type, return_type, arg_list, scope)) + kind = KIND_FUNCTION + + tag_list.append(format_tag(tag_name, kind, arg_list, scope, ('unknown', return_type))) # Also create a class tag when encountering a __construct() if tag_name == '__construct' and scope is not None: scope, tag_name = split_scope(scope) - tag_list.append((tag_name, TYPE_CLASS, None, arg_list, scope or '')) + tag_list.append(format_tag(tag_name, KIND_CLASS, arg_list, scope or ''))
# write tags script_dir = dirname(__file__) - tags_file_path = join(script_dir, '..', 'data', 'tags', 'std.php.tags') - with open(tags_file_path, 'w', encoding='iso-8859-1') as tags_file: - tags_file.write('# format=tagmanager\n') - for tag_name, tag_type, return_type, arg_list, scope in sorted(tag_list): - tag_line = f'{tag_name}' - for attr, type_ in [(tag_type, TA_TYPE), - (arg_list, TA_ARGLIST), - (return_type, TA_VARTYPE), - (scope, TA_SCOPE)]: - if attr is not None: - tag_line += f'{type_:c}{attr}' - - tags_file.write(tag_line + '\n') - print(f'Created: {tags_file_path} with {len(tag_list)} tags') + filename = join(script_dir, '..', 'data', 'tags', 'std.php.tags') + write_ctags_file(filename, tag_list, sys.argv[0]) + print(f'Created: {filename} with {len(tag_list)} tags')
if __name__ == '__main__':
Modified: scripts/create_py_tags.py 31 lines changed, 5 insertions(+), 26 deletions(-) =================================================================== @@ -23,17 +23,17 @@ # docker run --rm -it --user $(id -u):$(id -g) -v $(pwd):/data --workdir /data python:3.11-alpine python scripts/create_py_tags.py #
-import datetime import importlib.util import inspect import os -import platform import re import sys import sysconfig import warnings from pathlib import Path
+from create_tags_helper import format_tag, write_ctags_file + # treat all DeprecationWarnings as errors so we can catch them to ignore the corresponding modules warnings.filterwarnings('error', category=DeprecationWarning)
@@ -56,15 +56,6 @@ TAG_REGEXP = re.compile(r'^[ \t]*(def|class)[ \t]+([a-zA-Z0-9_]+)[ \t]*((.*))[:]') OBJECT_MEMORY_ADDRESS_REGEXP = re.compile(r'<(.+?) at 0x[0-9a-f]+(?:.+)>', flags=re.IGNORECASE)
-CTAGS_FILE_HEADER = f'''!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/ -!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/ -!_TAG_OUTPUT_EXCMD mixed /number, pattern, mixed, or combineV2/ -!_TAG_OUTPUT_FILESEP slash /slash or backslash/ -!_TAG_OUTPUT_MODE u-ctags /u-ctags or e-ctags/ -!_TAG_PATTERN_LENGTH_LIMIT 96 /0 for no limit/ -!_TAG_PROGRAM_NAME scripts/create_py_tags.py Automatically generated file - do not edit (created on {datetime.datetime.now().ctime()} with Python {platform.python_version()}) -''' - # pylint: disable=no-else-return,no-self-use
@@ -89,13 +80,7 @@ def _add_tag(self, object_name, object_, kind, module_path=None, parent=''): tag_key = (module_path, parent, object_name) if tag_key not in self.tags: signature = self._create_signature(object_) if object_ is not None else None - self.tags[tag_key] = self._format_tag(object_name, kind, signature, parent) - - def _format_tag(self, tagname, kind, signature, parent): - signature_field = f'\tsignature:{signature}' if signature else '' - parent_field = f'\tclass:{parent}' if parent else '' - - return f'{tagname}\t/unknown\t1;"\tkind:{kind}{parent_field}{signature_field}\n' + self.tags[tag_key] = format_tag(object_name, kind, signature, parent)
def _get_safe_parameter_default_value(self, value): """ @@ -234,7 +219,7 @@ def _process_module_with_fallback_parser(self, module_filename):
kind = KIND_CLASS if tag_type_str == 'class' else KIND_FUNCTION signature = args.strip() - self.tags[tagname] = self._format_tag(tagname, kind, signature, parent=None) + self.tags[tagname] = format_tag(tagname, kind, signature, parent=None)
def add_builtins(self): """ @@ -253,13 +238,7 @@ def write_to_file(self, filename):
@param filename (str) """ - result = sorted(self.tags.values()) - # write them - with open(filename, 'w') as target_file: - target_file.write(CTAGS_FILE_HEADER) - for symbol in result: - if symbol != '\n': # skip empty lines - target_file.write(symbol) + write_ctags_file(filename, self.tags.values(), sys.argv[0])
def is_import(object_, module_path):
Modified: scripts/create_tags_helper.py 70 lines changed, 70 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,70 @@ +#!/usr/bin/env python3 +# +# Author: The Geany contributors +# License: GPL v2 or later +# +# This is a helper library for Python scripts to create tag files in ctags format, +# e.g. create_py_tags.py and create_php_tags.py. +# + +import datetime +import platform + + +CTAGS_FILE_HEADER = '''!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/ +!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/ +!_TAG_OUTPUT_EXCMD mixed /number, pattern, mixed, or combineV2/ +!_TAG_OUTPUT_FILESEP slash /slash or backslash/ +!_TAG_OUTPUT_MODE u-ctags /u-ctags or e-ctags/ +!_TAG_PATTERN_LENGTH_LIMIT 96 /0 for no limit/ +!_TAG_PROGRAM_NAME {program_name} Automatically generated file - do not edit (created on {timestamp} with Python {python_version}) +''' + + +def format_tag(tagname, kind, signature, parent, return_type=None): + """ + @param tagname (str) + @param kind (str) + @param signature (str) + @param parent (str) + @param return_type (tuple of two elements or None) + + """ + if signature: + signature_field = f'\tsignature:{signature}' + else: + signature_field = '' + + if parent: + parent_field = f'\tclass:{parent}' + else: + parent_field = '' + + if return_type: + return_type_field = f'\ttyperef:{return_type[0]}:{return_type[1]}' + else: + return_type_field = '' + + return f'{tagname}\t/unknown\t1;"\tkind:{kind}{parent_field}{signature_field}{return_type_field}\n' + + +def write_ctags_file(filename, tags, program_name): + """ + Sort the found tags and write them into the file specified by filename + + @param filename (str) + @param tags (list) + @param program_name (str) + """ + result = sorted(tags) + + ctags_file_header = CTAGS_FILE_HEADER.format( + program_name=program_name, + timestamp=datetime.datetime.now().ctime(), + python_version=platform.python_version()) + + with open(filename, 'w', encoding='utf-8') as target_file: + target_file.write(ctags_file_header) + for symbol in result: + if symbol != '\n': # skip empty lines + target_file.write(symbol)
-------------- This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).