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