Package: exuberant-ctags
Version: 1:5.7-4
I'm fixing some gedit plugins and found that the exuberant-ctags ASP
parser is unable to detect classes and is returning a wrong char
constant for constants.
Here is a transcript of how to test it:
$ctags customevent.class.asp
$vi tags
Note that although the file is a class definition, the parser is unable
note it.
customevent.class.asp content:
<%
' Class: CustomEvent
'
' This class implements a generic way to work with Custom Events in ASP.
It's
' the ASP Xtreme Evolution base for an Event-driven programming approach.
'
' Known issues:
'
' - As you can notice by the first example, CustomEvent doesn't work
well with
' the VBScript standard Class events "Class_initialize" and
"Class_terminate"
' - It's odd but getref() is unable to get the reference of a method
or class
' procedure.
'
' About:
'
' - Written by Fabio Zendhi Nagao <http://zend.lojcomm.com.br> @
January 2009
'
class CustomEvent
' Property: classType
'
' Class type.
'
' Contains:
'
' (string) - type
'
public classType
' Property: classVersion
'
' Class version.
'
' Contains:
'
' (float) - version
'
public classVersion
' Property: Owner
'
' description
'
' Contains:
'
' (Class) - Should be set with the reference of the Caller.
'
public Owner
private Handlers
' Property: Arguments
'
' Arguments to be passed to the handlers.
'
' Contains:
'
' (Scripting.Dictionary) - A collection with the callback
function arguments
'
public Arguments
private sub Class_initialize()
classType = typename(Me)
classVersion = "1.0.0"
set Handlers = Server.createObject("Scripting.Dictionary")
set Arguments = Server.createObject("Scripting.Dictionary")
end sub
private sub Class_terminate()
Handlers.removeAll()
Arguments.removeAll()
set Handlers = nothing
set Arguments = nothing
end sub
' Subroutine: addHandler
'
' Adds a handler.
'
public sub addHandler(fn)
select case typename(fn)
case "JScriptTypeInfo"
set Handlers.item(fn.toString()) = fn
case else
set Handlers.item(fn) = getRef(fn)
end select
end sub
' Subroutine: removeHandler
'
' description
'
public sub removeHandler(fn)
set Handlers.item(fn) = nothing
Handlers.remove(fn)
end sub
' Subroutine: fire
'
' Fires all handlers attached to this event.
'
' Example:
'
' (start code)
'
' class ClassWithEvents
' public classType
' public classVersion
'
' public onLoad
' public onUnload
' public onComplimentBefore
' public onComplimentAfter
'
' private sub Class_initialize()
' classType = typename(Me)
' classVersion = "1.0.0"
'
' set onLoad = new CustomEvent : set onLoad.Owner = Me
' set onUnload = new CustomEvent : set onUnload.Owner = Me
' set onComplimentBefore = new CustomEvent : set
onComplimentBefore.Owner = Me
' set onComplimentAfter = new CustomEvent : set
onComplimentAfter.Owner = Me
'
' onComplimentBefore.Arguments.item("firstname") = "Fabio"
' onComplimentBefore.Arguments.item("lastname") = "Nagao"
' onComplimentBefore.Arguments.item("nickname") = "nagaozen"
' call onLoad.fire()
' end sub
'
' private sub Class_terminate()
' call onUnload.fire()
'
' set onLoad = nothing
' set onUnload = nothing
' set onComplimentBefore = nothing
' set onComplimentAfter = nothing
' end sub
'
' public function compliment()
' call onComplimentBefore.fire()
' Response.write("Method compliment called." & vbNewline)
' call onComplimentAfter.fire()
' end function
'
' end class
'
'
'
' sub ev_onLoad(ev)
' Response.write("Event onLoad has been fired" & vbNewline)
' end sub
'
' sub ev_onUnLoad(ev)
' Response.write("Event onUnLoad has been fired" & vbNewline)
' end sub
'
' sub ev_onComplimentBefore(ev)
' Response.write("Event onComplimentBefore has been fired. I was
really expecting this method to say: 'Hello World " &
ev.Arguments.item("firstname") & " " & ev.Arguments.item("lastname") & "
(" & ev.Arguments.item("nickname") & ")'" & vbNewline)
' end sub
'
' sub ev_onComplimentAfter(ev)
' Response.write("Event onComplimentAfter has been fired" &
vbNewline)
' end sub
'
' dim CwE : set CwE = new ClassWithEvents
' call CwE.onLoad.addHandler("ev_onLoad")
' call CwE.onUnLoad.addHandler("ev_onUnLoad")
' call CwE.onComplimentBefore.addHandler("ev_onComplimentBefore")
' call CwE.onComplimentBefore.addHandler(lambda("function(ev){
Response.write('Another handler attached to Event onComplimentAfter.
This one is using a lambda function -- Yes, ' +
ev.Arguments.item('firstname') + ' ' + ev.Arguments.item('lastname') + '
(' + ev.Arguments.item('nickname') + ') has implemented it for Classic
ASP.\r\n') }"))
' call CwE.onComplimentAfter.addHandler("ev_onComplimentAfter")
' CwE.compliment()
' set CwE = nothing
'
' Response.write("As you can see, this nothing @ line 74 doesn't
work as expected. onLoad doesn't work either. But for user methods and
procedures the CustomEvent works fine." & vbNewLine)
'
' (end code)
'
public sub fire()
dim fn : for each fn in Handlers
Handlers.item(fn)(Me)
next
end sub
' Function: revealArguments
'
' Reveals the event arguments.
'
' Returns:
'
' (string) - A list of the available event arguments
'
' Example:
'
' (start code)
'
' ' Using the class defined in the example above
' dim CwE : set CwE = new ClassWithEvents
' Response.write(CwE.onComplimentBefore.revealArguments())
' set CwE = nothing
'
' (end code)
'
public function revealArguments()
revealArguments = ""
dim arg : for each arg in Arguments
revealArguments = revealArguments & ", " & arg
next
revealArguments = mid(revealArguments, 3)
end function
end class
%>
<script language="javascript" runat="server">
function lambda(f) {
if(/^function\s*\([ a-z0-9.$_,]*\)\s*{[\S\s]*}$/gim.test(f)) {
eval("f = " + f.replace(/(\r|\n)/g, ''));
return f;
} else {
return function() {};
}
}
</script>
I've also made a patch based in the ctags/trunk/asp.c to fix this issue.
Fixed asp.c:
/*
* $Id$
*
* Copyright (c) 2000, Patrick Dehne <patr...@steidle.net>
*
* This source code is released for free distribution under the terms
of the
* GNU General Public License.
*
* This module contains functions for generating tags for the ASP (Active
* Server Pages) web page scripting language.
*/
/*
* INCLUDE FILES
*/
#include "general.h" /* must always come first */
#include <string.h>
#include "parse.h"
#include "read.h"
#include "vstring.h"
/*
* DATA DEFINITIONS
*/
typedef enum {
K_CONST, K_CLASS, K_FUNCTION, K_SUB, K_DIM
} aspKind;
static kindOption AspKinds [] = {
{ TRUE, 'd', "constant", "constants"},
{ TRUE, 'c', "class", "classes"},
{ TRUE, 'f', "function", "functions"},
{ TRUE, 's', "subroutine", "subroutines"},
{ TRUE, 'v', "variable", "variables"}
};
/*
* FUNCTION DEFINITIONS
*/
static void findAspTags (void)
{
vString *name = vStringNew ();
const unsigned char *line;
while ((line = fileReadLine ()) != NULL)
{
const unsigned char *cp = line;
while (*cp != '\0')
{
/* jump over whitespace */
while (isspace ((int)*cp))
cp++;
/* jump over strings */
if (*cp == '"')
{
cp++;
while (*cp!='"' && *cp!='\0')
cp++;
}
/* jump over comments */
else if (*cp == '\'')
break;
/* jump over end function/sub lines */
else if (strncasecmp ((const char*) cp, "end", (size_t) 3)== 0)
{
cp += 3;
if (isspace ((int)*cp))
{
while (isspace ((int)*cp))
++cp;
if (strncasecmp ((const char*) cp, "function",
(size_t) 8) == 0)
{
cp+=8;
break;
}
else if (strncasecmp ((const char*) cp, "sub",
(size_t) 3) == 0)
{
cp+=3;
break;
}
}
}
/* jump over exit function/sub lines */
else if (strncasecmp ((const char*) cp, "exit", (size_t) 4)==0)
{
cp += 4;
if (isspace ((int) *cp))
{
while (isspace ((int) *cp))
++cp;
if (strncasecmp ((const char*) cp, "function",
(size_t) 8) == 0)
{
cp+=8;
break;
}
else if (strncasecmp ((const char*) cp, "sub",
(size_t) 3) == 0)
{
cp+=3;
break;
}
}
}
/* class? */
else if (strncasecmp ((const char*) cp, "class", (size_t) 5)
== 0)
{
cp += 5;
if (isspace ((int) *cp))
{
while (isspace ((int) *cp))
++cp;
while (isalnum ((int) *cp) || *cp == '_')
{
vStringPut (name, (int) *cp);
++cp;
}
vStringTerminate (name);
makeSimpleTag (name, AspKinds, K_CLASS);
vStringClear (name);
}
}
/* function? */
else if (strncasecmp ((const char*) cp, "function", (size_t)
8) == 0)
{
cp += 8;
if (isspace ((int) *cp))
{
while (isspace ((int) *cp))
++cp;
while (isalnum ((int) *cp) || *cp == '_')
{
vStringPut (name, (int) *cp);
++cp;
}
vStringTerminate (name);
makeSimpleTag (name, AspKinds, K_FUNCTION);
vStringClear (name);
}
}
/* sub? */
else if (strncasecmp ((const char*) cp, "sub", (size_t) 3) == 0)
{
cp += 3;
if (isspace ((int) *cp))
{
while (isspace ((int) *cp))
++cp;
while (isalnum ((int) *cp) || *cp == '_')
{
vStringPut (name, (int) *cp);
++cp;
}
vStringTerminate (name);
makeSimpleTag (name, AspKinds, K_SUB);
vStringClear (name);
}
}
/* dim variable? */
else if (strncasecmp ((const char*) cp, "dim", (size_t) 3) == 0)
{
cp += 3;
if (isspace ((int) *cp))
{
while (isspace ((int) *cp))
++cp;
while (isalnum ((int) *cp) || *cp == '_')
{
vStringPut (name, (int) *cp);
++cp;
}
vStringTerminate (name);
makeSimpleTag (name, AspKinds, K_DIM);
vStringClear (name);
}
}
/* const declaration? */
else if (strncasecmp ((const char*) cp, "const", (size_t) 5)
== 0)
{
cp += 5;
if (isspace ((int) *cp))
{
while (isspace ((int) *cp))
++cp;
while (isalnum ((int) *cp) || *cp == '_')
{
vStringPut (name, (int) *cp);
++cp;
}
vStringTerminate (name);
makeSimpleTag (name, AspKinds, K_CONST);
vStringClear (name);
}
}
/* nothing relevant */
else if (*cp != '\0')
cp++;
}
}
vStringDelete (name);
}
extern parserDefinition* AspParser (void)
{
static const char *const extensions [] = { "asp", "asa", NULL };
parserDefinition* def = parserNew ("Asp");
def->kinds = AspKinds;
def->kindCount = KIND_COUNT (AspKinds);
def->extensions = extensions;
def->parser = findAspTags;
return def;
}
/* vi:set tabstop=4 shiftwidth=4: */
My kernel is: Linux nagaozen-linux 2.6.28-11-generic #42-Ubuntu SMP Fri
Apr 17 01:58:03 UTC 2009 x86_64 GNU/Linux
My shared C library is: 2.9-4ubuntu6
--
To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org