Branch: refs/heads/master Author: Colomban Wendling ban@herbesfolles.org Committer: Colomban Wendling ban@herbesfolles.org Date: Wed, 11 Feb 2015 17:33:19 UTC Commit: 308041da8d0f7ee938a075cae5d84d90da91c5eb https://github.com/geany/geany/commit/308041da8d0f7ee938a075cae5d84d90da91c5...
Log Message: ----------- Merge branch 'ctags/python'
Import Python changes from https://github.com/fishman/ctags/
Modified Paths: -------------- tagmanager/ctags/python.c tests/ctags/Makefile.am tests/ctags/py-skipped-string.py tests/ctags/py-skipped-string.py.tags
Modified: tagmanager/ctags/python.c 52 lines changed, 38 insertions(+), 14 deletions(-) =================================================================== @@ -91,32 +91,49 @@ static const char *get_class_name_from_parent (const char *parent) * - http://www.python.org/dev/peps/pep-0008/#method-names-and-instance-variables * - http://www.python.org/dev/peps/pep-0008/#designing-for-inheritance */ -static pythonAccess accessFromIdentifier (const vString *const ident) +static pythonAccess accessFromIdentifier (const vString *const ident, + pythonKind kind, boolean has_parent, boolean parent_is_class) { const char *const p = vStringValue (ident); const size_t len = vStringLength (ident);
+ /* inside a function/method, private */ + if (has_parent && !parent_is_class) + return A_PRIVATE; /* not starting with "_", public */ - if (len < 1 || p[0] != '_') + else if (len < 1 || p[0] != '_') return A_PUBLIC; /* "__...__": magic methods */ - else if (len > 3 && p[1] == '_' && p[len - 2] == '_' && p[len - 1] == '_') + else if (kind == K_METHOD && parent_is_class && + len > 3 && p[1] == '_' && p[len - 2] == '_' && p[len - 1] == '_') return A_PUBLIC; /* "__...": name mangling */ - else if (len > 1 && p[1] == '_') + else if (parent_is_class && len > 1 && p[1] == '_') return A_PRIVATE; /* "_...": suggested as non-public, but easily accessible */ else return A_PROTECTED; }
+static void addAccessFields (tagEntryInfo *const entry, + const vString *const ident, pythonKind kind, + boolean has_parent, boolean parent_is_class) +{ + pythonAccess access; + + access = accessFromIdentifier (ident, kind, has_parent, parent_is_class); + entry->extensionFields.access = PythonAccesses [access]; + /* FIXME: should we really set isFileScope in addition to access? */ + if (access == A_PRIVATE) + entry->isFileScope = TRUE; +} + /* Given a string with the contents of a line directly after the "def" keyword, * extract all relevant information and create a tag. */ static void makeFunctionTag (vString *const function, vString *const parent, int is_class_parent, const char *arglist) { - pythonAccess access; tagEntryInfo tag; initTagEntry (&tag, vStringValue (function));
@@ -147,11 +164,8 @@ static void makeFunctionTag (vString *const function, } }
- access = accessFromIdentifier (function); - tag.extensionFields.access = PythonAccesses [access]; - /* FIXME: should we really set isFileScope in addition to access? */ - if (access == A_PRIVATE) - tag.isFileScope = TRUE; + addAccessFields (&tag, function, is_class_parent ? K_METHOD : K_FUNCTION, + vStringLength (parent) > 0, is_class_parent);
makeTagEntry (&tag); } @@ -180,10 +194,13 @@ static void makeClassTag (vString *const class, vString *const inheritance, } } tag.extensionFields.inheritance = vStringValue (inheritance); + addAccessFields (&tag, class, K_CLASS, vStringLength (parent) > 0, + is_class_parent); makeTagEntry (&tag); }
-static void makeVariableTag (vString *const var, vString *const parent) +static void makeVariableTag (vString *const var, vString *const parent, + boolean is_class_parent) { tagEntryInfo tag; initTagEntry (&tag, vStringValue (var)); @@ -194,6 +211,8 @@ static void makeVariableTag (vString *const var, vString *const parent) tag.extensionFields.scope [0] = PythonKinds[K_CLASS].name; tag.extensionFields.scope [1] = vStringValue (parent); } + addAccessFields (&tag, var, K_VARIABLE, vStringLength (parent) > 0, + is_class_parent); makeTagEntry (&tag); }
@@ -247,6 +266,8 @@ static const char *skipEverything (const char *cp) } if (isIdentifierFirstCharacter ((int) *cp)) return cp; + if (match) + cp--; /* avoid jumping over the character after a skipped string */ } return cp; } @@ -517,6 +538,7 @@ static char const *find_triple_start(char const *string, char const **which) } cp = skipString(cp); if (!*cp) break; + cp--; /* avoid jumping over the character after a skipped string */ } } return NULL; @@ -603,9 +625,11 @@ static const char *skipTypeDecl (const char *cp, boolean *is_class) while (*ptr && *ptr != '=' && *ptr != '(' && !isspace(*ptr)) { /* skip over e.g. 'cpdef numpy.ndarray[dtype=double, ndim=1]' */ if(*ptr == '[') { - while(*ptr && *ptr != ']') ptr++; + while (*ptr && *ptr != ']') ptr++; + if (*ptr) ptr++; + } else { + ptr++; } - ptr++; } if (!*ptr || *ptr == '=') return NULL; if (*ptr == '(') { @@ -755,7 +779,7 @@ static void findPythonTags (void) { /* skip variables in methods */ if (parent_is_class || vStringLength(parent) == 0) - makeVariableTag (name, parent); + makeVariableTag (name, parent, parent_is_class); } }
Modified: tests/ctags/Makefile.am 1 lines changed, 1 insertions(+), 0 deletions(-) =================================================================== @@ -228,6 +228,7 @@ test_sources = \ prototype.h \ pure_elem.f95 \ py_constructor_arglist.py \ + py-skipped-string.py \ qualified_types.f90 \ random.sql \ readlob.sql \
Modified: tests/ctags/py-skipped-string.py 30 lines changed, 30 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,30 @@ +# triple start string immediately after a normal string not detected + +def f1(): + ''""" + The string above was not detected as triple start string, + but the one below instead. + """ + print "f1" + +def f2(): + ''""" + The string above was then detected as end string, + and the one below as start string again. + """ + print "f2" + +def f3(): + """ + The string below is prepared so that ctags with the bug does not start a + new triple string. For a clean precondition for the next test. + ''""" + print "f3" + +# normal string immediately after a normal string not detected + +''" import os\ +" + +""' def fX():\ +'
Modified: tests/ctags/py-skipped-string.py.tags 4 lines changed, 4 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,4 @@ +# format=tagmanager +f1�16�()�0 +f2�16�()�0 +f3�16�()�0
-------------- This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).