From a308041e43ac6f130d556c5bf86901238fac4ee6 Mon Sep 17 00:00:00 2001 From: Kim K Date: Mon, 11 Nov 2019 00:09:56 +0800 Subject: [PATCH] Support auto-functions and template-functions --- Dockerfile | 15 +++------ autoload/doge/helpers.vim | 11 +++--- generators/libclang.py | 70 ++++++++++++++++++++++++++++----------- 3 files changed, 61 insertions(+), 35 deletions(-) diff --git a/Dockerfile b/Dockerfile index a1cb9a02..153791d2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,26 +1,21 @@ FROM tweekmonster/vim-testbed:latest -RUN install_vim \ - -tag v7.4.2119 -build \ - -tag v8.1.2000 -py3 -build \ - -tag neovim:v0.2.0 -py3 -build \ - -tag neovim:v0.3.8 -py3 -build +RUN install_vim -tag v7.4.2119 -py -build +RUN install_vim -tag v8.1.2000 -py3 -build +RUN install_vim -tag neovim:v0.2.0 -py3 -build +RUN install_vim -tag neovim:v0.3.8 -py3 -build # Install base dependencies. RUN apk -v --progress add bash git RUN apk -v --progress add clang=8.0.0-r0 -# Install Python3 -RUN apk -v --progress add --virtual .build-deps g++ python3-dev libffi-dev openssl-dev -RUN apk -v --progress add python3 - # Install addition python modules. RUN pip3 install --upgrade pip vim-vint==0.3.15 clang setuptools # Create a symlink to our libclang binary. RUN ln -s /usr/lib/libclang.so.8 /usr/lib/libclang.so -# Remove unnecessary files. +# Cleanup. RUN rm -rf /var/cache/apk/* /tmp/* /var/tmp/* # Install Vader. diff --git a/autoload/doge/helpers.vim b/autoload/doge/helpers.vim index 1df1aa8e..e6837d29 100644 --- a/autoload/doge/helpers.vim +++ b/autoload/doge/helpers.vim @@ -82,11 +82,12 @@ function doge#helpers#generator(path) abort let l:generator = g:doge_dir . '/generators/' . a:path if filereadable(l:generator) != v:false let l:result = doge#python#file(l:generator) - let l:json = json_decode(l:result) - if type(l:json) != v:t_dict - echoerr l:result - endif - return l:json + try + return json_decode(l:result) + catch /.*/ + echo '[DoGe] ' . a:path . ' generator failed.' + echo l:result + endtry endif return 0 endfunction diff --git a/generators/libclang.py b/generators/libclang.py index 1025b8f7..7b362ed9 100755 --- a/generators/libclang.py +++ b/generators/libclang.py @@ -32,15 +32,25 @@ The libclang binary its location should be defined in the $LD_LIBRARY_PATH. """ -from clang.cindex import Index, CursorKind +from clang.cindex import Index, CursorKind, Cursor +import sys import json import vim import os import tempfile +from typing import Union -func = {} +FUNCTION = {} -def get_token(node, key): + +def get_next_token(node: Cursor, key: str) -> Union[str, None]: + """ + Get the next token from a node. + + :param node clang.cindex.Cursor: The node itself. + :param key str: The key to get from the next token. + :rtype str/none: The requested token or None otherwise. + """ try: token = next(node.get_tokens()) return getattr(token, key) @@ -48,25 +58,29 @@ def get_token(node, key): return None -def find_func(node, line): +def find_node(node: Cursor, line: int) -> Union[Cursor, bool]: + """ + Find a node based on a given line number. + + :param node clang.cindex.Cursor: The node itself. + :param line int: The line number where the node is located at. + :rtype clang.cindex.Cursor/bool: The found node or False otherwise. + """ if node.location.line == line: - if node.kind in [CursorKind.CXX_METHOD, CursorKind.FUNCTION_DECL]: - if 'parameters' not in func.keys(): - func['parameters'] = [] - func['name'] = node.spelling - func['returnType'] = get_token(node, 'spelling') - elif node.kind == CursorKind.PARM_DECL: - func['parameters'].append({ - 'name': node.spelling, - }) + return node for child in node.get_children(): - find_func(child, line) + result = find_node(child, line) + if result: + return result + return False def main(): - ext = vim.eval("&filetype") - lines = vim.eval("getline(line(0), line('$'))") - line = int(vim.eval("line('.')")) + file_ext = vim.eval("expand('%:p:e')") + ext = file_ext if file_ext else vim.eval('&filetype') + + lines = vim.eval("getline(line(1), line('$'))") + current_line = int(vim.eval("line('.')")) # Save the lines to a temp file and parse that file. fd, filename = tempfile.mkstemp('.{}'.format(ext)) @@ -77,9 +91,25 @@ def main(): index = Index.create() tu = index.parse(filename) if tu: - find_func(tu.cursor, line) - if len(func.keys()) > 0: - print(json.dumps(func)) + node = find_node(tu.cursor, current_line) + while node: + if node.kind in [CursorKind.TEMPLATE_NON_TYPE_PARAMETER, CursorKind.TEMPLATE_TYPE_PARAMETER]: + current_line += 1 + node = find_node(tu.cursor, current_line) + elif node.kind in [CursorKind.CXX_METHOD, CursorKind.FUNCTION_DECL, CursorKind.FUNCTION_TEMPLATE]: + FUNCTION['name'] = node.spelling + FUNCTION['returnType'] = get_next_token(node, 'spelling') + if 'parameters' not in FUNCTION.keys(): + FUNCTION['parameters'] = [] + for child in node.get_children(): + if child.kind == CursorKind.PARM_DECL: + FUNCTION['parameters'].append({ + 'name': child.spelling, + }) + print(json.dumps(FUNCTION)) + break + else: + break except Exception as e: print(e) finally: