SF.net SVN: geany: [1773] trunk

ntrel at users.sourceforge.net ntrel at xxxxx
Tue Aug 7 12:36:04 UTC 2007


Revision: 1773
          http://geany.svn.sourceforge.net/geany/?rev=1773&view=rev
Author:   ntrel
Date:     2007-08-07 05:36:03 -0700 (Tue, 07 Aug 2007)

Log Message:
-----------
Parse Python global variables and class variables from assignment
statements; assignment to a tuple literal ('x, y =') not supported.

Modified Paths:
--------------
    trunk/ChangeLog
    trunk/src/symbols.c
    trunk/tagmanager/python.c

Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2007-08-05 11:29:09 UTC (rev 1772)
+++ trunk/ChangeLog	2007-08-07 12:36:03 UTC (rev 1773)
@@ -1,3 +1,10 @@
+2007-08-07  Nick Treleaven  <nick(dot)treleaven(at)btinternet(dot)com>
+
+ * src/symbols.c, tagmanager/python.c:
+   Parse Python global variables and class variables from assignment
+   statements; assignment to a tuple literal ('x, y =') not supported.
+
+
 2007-08-05  Enrico Tröger  <enrico(dot)troeger(at)uvena(dot)de>
 
  * geany.glade, src/geany.h, src/interface.c, src/keyfile.c,

Modified: trunk/src/symbols.c
===================================================================
--- trunk/src/symbols.c	2007-08-05 11:29:09 UTC (rev 1772)
+++ trunk/src/symbols.c	2007-08-07 12:36:03 UTC (rev 1773)
@@ -572,6 +572,7 @@
 				&(tv_iters.tag_class), _("Classes"), "classviewer-class",
 				&(tv_iters.tag_member), _("Methods"), "classviewer-member",
 				&(tv_iters.tag_function), _("Functions"), "classviewer-method",
+				&(tv_iters.tag_variable), _("Variables"), "classviewer-var",
 				NULL);
 				//&(tv_iters.tag_macro), _("Mixin"),
 				//&(tv_iters.tag_variable), _("Variables"),

Modified: trunk/tagmanager/python.c
===================================================================
--- trunk/tagmanager/python.c	2007-08-05 11:29:09 UTC (rev 1772)
+++ trunk/tagmanager/python.c	2007-08-07 12:36:03 UTC (rev 1773)
@@ -24,13 +24,14 @@
 *   DATA DEFINITIONS
 */
 typedef enum {
-    K_CLASS, K_FUNCTION, K_METHOD
+    K_CLASS, K_FUNCTION, K_METHOD, K_VARIABLE
 } pythonKind;
 
 static kindOption PythonKinds [] = {
     { TRUE, 'c', "class",    "classes" },
     { TRUE, 'f', "function", "functions" },
-    { TRUE, 'm', "member", "methods" }
+    { TRUE, 'm', "member", "methods" },
+    { TRUE, 'v', "variable", "variables" }
 };
 
 typedef struct _lastClass {
@@ -42,7 +43,17 @@
 *   FUNCTION DEFINITIONS
 */
 
+static boolean isIdentifierFirstCharacter (int c)
+{
+	return (boolean) (isalpha (c) || c == '_');
+}
 
+static boolean isIdentifierCharacter (int c)
+{
+	return (boolean) (isalnum (c) || c == '_');
+}
+
+
 // remove all previous classes with more indent than the current one
 static GList *clean_class_list(GList *list, gint indent)
 {
@@ -77,6 +88,9 @@
     gint indent;
     const unsigned char *line;
     boolean inMultilineString = FALSE;
+	lastClass *lastclass = NULL;
+    boolean inFunction = FALSE;
+    gint fn_indent = 0;
 
     while ((line = fileReadLine ()) != NULL)
     {
@@ -97,15 +111,50 @@
 		cp += 3;
 	    }
 
+		if (*cp == '\0')
+			break;	// at end of multiline string
+
+		// update indent-sensitive things
+		if (!inMultilineString && !isspace(*cp))
+		{
+			if (inFunction)
+			{
+				if (indent < fn_indent)
+					inFunction = FALSE;
+			}
+		    if (lastclass != NULL)
+		    {
+				if (indent <= lastclass->indent)
+				{
+					GList *last;
+
+					parents = clean_class_list(parents, indent);
+					last = g_list_last(parents);
+					if (last != NULL)
+						lastclass = last->data;
+					else
+						lastclass = NULL;
+				}
+		    }
+		}
+
 	    if (inMultilineString)
 		++cp;
 		else if (isspace ((int) *cp))
 		{
-			cp++;
 			// count indentation amount of current line
 			// the indentation has to be made with tabs only _or_ spaces only, if they are mixed
 			// the code below gets confused
-			indent++;
+			if (cp == line)
+			{
+				do
+				{
+					indent++;
+					cp++;
+				} while (isspace(*cp));
+			}
+			else
+				cp++;	// non-indent whitespace
 		}
 	    else if (*cp == '#')
 		break;
@@ -114,12 +163,8 @@
 			cp += 5;
 			if (isspace ((int) *cp))
 			{
-				GList *last = g_list_last(parents);
-				lastClass *lastclass = NULL;
 				lastClass *newclass = g_new(lastClass, 1);
 
-				if (last != NULL) lastclass = last->data;
-
 				while (isspace ((int) *cp))
 				++cp;
 				while (isalnum ((int) *cp)  ||  *cp == '_')
@@ -129,13 +174,14 @@
 				}
 				vStringTerminate (name);
 
-				parents = clean_class_list(parents, indent);
-
 				newclass->name = g_strdup(vStringValue(name));
 				newclass->indent = indent;
 				parents = g_list_append(parents, newclass);
 				makeSimpleTag (name, PythonKinds, K_CLASS);
 				vStringClear (name);
+
+				lastclass = newclass;
+				break;	// ignore rest of line so that lastclass is not reset immediately
 			}
 	    }
 	    else if (strncmp ((const char*) cp, "def", (size_t) 3) == 0)
@@ -143,13 +189,6 @@
 		cp += 3;
 		if (isspace ((int) *cp))
 		{
-		    GList *last;
-		    lastClass *lastclass = NULL;
-
-			parents = clean_class_list(parents, indent);
-			last = g_list_last(parents);
-			if (last != NULL) lastclass = last->data;
-
 		    while (isspace ((int) *cp))
 			++cp;
 		    while (isalnum ((int) *cp)  ||  *cp == '_')
@@ -164,8 +203,62 @@
 			makeSimpleScopedTag (name, PythonKinds, K_METHOD,
 					     PythonKinds[K_CLASS].name, lastclass->name, "public");
 		    vStringClear (name);
+
+		    inFunction = TRUE;
+		    fn_indent = indent + 1;
+		    break;	// ignore rest of line so inFunction is not cancelled immediately
 		}
 	    }
+		else if (!inFunction && *(const char*)cp == '=')
+		{
+			/* Parse global and class variable names (C.x) from assignment statements.
+			 * Object attributes (obj.x) are ignored.
+			 * Assignment to a tuple 'x, y = 2, 3' not supported.
+			 * TODO: ignore duplicate tags from reassignment statements. */
+			const guchar *sp, *eq, *start;
+
+			eq = cp + 1;
+			while (*eq)
+			{
+				if (*eq == '=')
+					goto skipvar;	// ignore '==' operator and 'x=5,y=6)' function lines
+				if (*eq == '(')
+					break;	// allow 'x = func(b=2,y=2,' lines
+				eq++;
+			}
+			// go backwards to the start of the line, checking we have valid chars
+			start = cp - 1;
+			while (start >= line && isspace ((int) *start))
+				--start;
+			while (start >= line && isIdentifierCharacter ((int) *start))
+				--start;
+			if (!isIdentifierFirstCharacter(*(start + 1)))
+				goto skipvar;
+			sp = start;
+			while (sp >= line && isspace ((int) *sp))
+				--sp;
+			if ((sp + 1) != line)	// the line isn't a simple variable assignment
+				goto skipvar;
+			// the line is valid, parse the variable name
+			++start;
+			while (isIdentifierCharacter ((int) *start))
+			{
+				vStringPut (name, (int) *start);
+				++start;
+			}
+			vStringTerminate (name);
+
+			if (lastclass == NULL)
+				makeSimpleTag (name, PythonKinds, K_VARIABLE);
+			else
+				makeSimpleScopedTag (name, PythonKinds, K_VARIABLE,
+					PythonKinds[K_CLASS].name, lastclass->name, "public");	// class member variables
+
+			vStringClear (name);
+
+			skipvar:
+			++cp;
+		}
 	    else if (*cp != '\0')
 	    {
 		do


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.



More information about the Commits mailing list