[geany/geany] 308041: Merge branch 'ctags/python'

Colomban Wendling git-noreply at xxxxx
Wed Feb 11 17:33:19 UTC 2015


Branch:      refs/heads/master
Author:      Colomban Wendling <ban at herbesfolles.org>
Committer:   Colomban Wendling <ban at herbesfolles.org>
Date:        Wed, 11 Feb 2015 17:33:19 UTC
Commit:      308041da8d0f7ee938a075cae5d84d90da91c5eb
             https://github.com/geany/geany/commit/308041da8d0f7ee938a075cae5d84d90da91c5eb

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).


More information about the Commits mailing list