mirror of
				https://github.com/notepad-plus-plus/notepad-plus-plus.git
				synced 2025-11-03 21:14:08 +01:00 
			
		
		
		
	Fix Perl functions without parentheses / with attributes are not recognized in function list issue. Fix #4265, close #4266
		
			
				
	
	
		
			305 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
			
		
		
	
	
			305 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
#!/usr/bin/env perl
 | 
						|
 | 
						|
# pltags - create a tags file for Perl code, for use by vi(m)
 | 
						|
#
 | 
						|
# Distributed with Vim <http://www.vim.org/>, latest version always available
 | 
						|
# at <http://www.mscha.com/mscha.html?pltags#tools>
 | 
						|
#
 | 
						|
# Version 2.3, 28 February 2002
 | 
						|
#
 | 
						|
# Written by Michael Schaap <pltags@mscha.com>.  Suggestions for improvement
 | 
						|
# are very welcome!
 | 
						|
#
 | 
						|
# This script will not work with Perl 4 or below!
 | 
						|
#
 | 
						|
# Revision history:
 | 
						|
#  1.0  1997?     Original version, quickly hacked together
 | 
						|
#  2.0  1999?     Completely rewritten, better structured and documented,
 | 
						|
#		  support for variables, packages, Exuberant Ctags extensions
 | 
						|
#  2.1	Jun 2000  Fixed critical bug (typo in comment) ;-)
 | 
						|
#		  Support multiple level packages (e.g. Archive::Zip::Member)
 | 
						|
#  2.2	Jul 2001  'Glob' wildcards - especially useful under Windows
 | 
						|
#		  (thanks to Serge Sivkov and Jason King)
 | 
						|
#		  Bug fix: reset package name for each file
 | 
						|
#  2.21 Jul 2001  Oops... bug in variable detection (/local../ -> /^local.../)
 | 
						|
#  2.3	Feb 2002  Support variables declared with "our"
 | 
						|
#		  (thanks to Lutz Mende)
 | 
						|
 | 
						|
# Complain about undeclared variables
 | 
						|
use strict;
 | 
						|
 | 
						|
# Used modules
 | 
						|
use Getopt::Long;
 | 
						|
 | 
						|
# Options with their defaults
 | 
						|
my $do_subs = 1;    # --subs, --nosubs    include subs in tags file?
 | 
						|
my $do_vars = 1;    # --vars, --novars    include variables in tags file?
 | 
						|
my $do_pkgs = 1;    # --pkgs, --nopkgs    include packages in tags file?
 | 
						|
my $do_exts = 1;    # --extensions, --noextensions
 | 
						|
		    #			  include Exuberant Ctags extensions
 | 
						|
 | 
						|
# Global variables
 | 
						|
my $VERSION = "2.21";	# pltags version
 | 
						|
my $status = 0;		# GetOptions return value
 | 
						|
my $file = "";		# File being processed
 | 
						|
my @tags = ();		# List of produced tags
 | 
						|
my $is_pkg = 0;		# Are we tagging a package?
 | 
						|
my $has_subs = 0;	# Has this file any subs yet?
 | 
						|
my $package_name = "";	# Name of current package
 | 
						|
my $var_continues = 0;	# Variable declaration continues on last line
 | 
						|
my $line = "";		# Current line in file
 | 
						|
my $stmt = "";		# Current Perl statement
 | 
						|
my @vars = ();		# List of variables in declaration
 | 
						|
my $var = "";		# Variable in declaration
 | 
						|
my $tagline = "";	# Tag file line
 | 
						|
 | 
						|
# Create a tag file line and push it on the list of found tags
 | 
						|
sub MakeTag($$$$$)
 | 
						|
{
 | 
						|
    my ($tag,		# Tag name
 | 
						|
	$type,		# Type of tag
 | 
						|
	$is_static,	# Is this a static tag?
 | 
						|
	$file,		# File in which tag appears
 | 
						|
	$line) = @_;	# Line in which tag appears
 | 
						|
 | 
						|
    my $tagline = "";   # Created tag line
 | 
						|
 | 
						|
    # Only process tag if not empty
 | 
						|
    if ($tag)
 | 
						|
    {
 | 
						|
	# Get rid of \n, and escape / and \ in line
 | 
						|
	chomp $line;
 | 
						|
	$line =~ s/\\/\\\\/g;
 | 
						|
	$line =~ s/\//\\\//g;
 | 
						|
 | 
						|
	# Create a tag line
 | 
						|
	$tagline = "$tag\t$file\t/^$line\$/";
 | 
						|
 | 
						|
	# If we're told to do so, add extensions
 | 
						|
	if ($do_exts)
 | 
						|
	{
 | 
						|
	    $tagline .= ";\"\t$type"
 | 
						|
			    . ($is_static ? "\tfile:" : "")
 | 
						|
			    . ($package_name ? "\tclass:$package_name" : "");
 | 
						|
	}
 | 
						|
 | 
						|
	# Push it on the stack
 | 
						|
	push (@tags, $tagline);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
# Parse package name from statement
 | 
						|
sub PackageName($)
 | 
						|
{
 | 
						|
    my ($stmt) = @_;    # Statement
 | 
						|
 | 
						|
    # Look for the argument to "package".  Return it if found, else return ""
 | 
						|
    if ($stmt =~ /^package\s+([\w:]+)/)
 | 
						|
    {
 | 
						|
	my $pkgname = $1;
 | 
						|
 | 
						|
	# Remove any parent package name(s)
 | 
						|
	$pkgname =~ s/.*://;
 | 
						|
	return $pkgname;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
	return "";
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
# Parse sub name from statement
 | 
						|
sub SubName($)
 | 
						|
{
 | 
						|
    my ($stmt) = @_;    # Statement
 | 
						|
 | 
						|
    # Look for the argument to "sub".  Return it if found, else return ""
 | 
						|
    if ($stmt =~ /^sub\s+([\w:]+)/)
 | 
						|
    {
 | 
						|
	my $subname = $1;
 | 
						|
 | 
						|
	# Remove any parent package name(s)
 | 
						|
	$subname =~ s/.*://;
 | 
						|
	return $subname;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
	return "";
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
# Parse all variable names from statement
 | 
						|
sub VarNames($)
 | 
						|
{
 | 
						|
    my ($stmt) = @_;
 | 
						|
 | 
						|
    # Remove my or local from statement, if present
 | 
						|
    $stmt =~ s/^(my|our|local)\s+//;
 | 
						|
 | 
						|
    # Remove any assignment piece
 | 
						|
    $stmt =~ s/\s*=.*//;
 | 
						|
 | 
						|
    # Now find all variable names, i.e. "words" preceded by $, @ or %
 | 
						|
    @vars = ($stmt =~ /[\$\@\%]([\w:]+)\b/g);
 | 
						|
 | 
						|
    # Remove any parent package name(s)
 | 
						|
    map(s/.*://, @vars);
 | 
						|
 | 
						|
    return (@vars);
 | 
						|
}
 | 
						|
 | 
						|
sub functionNoParentheses {
 | 
						|
    return 1
 | 
						|
}
 | 
						|
 | 
						|
############### Start ###############
 | 
						|
 | 
						|
print "\npltags $VERSION by Michael Schaap <mscha\@mscha.com>\n\n";
 | 
						|
 | 
						|
# Get options
 | 
						|
$status = GetOptions("subs!" => \$do_subs,
 | 
						|
		     "vars!" => \$do_vars,
 | 
						|
		     "pkgs!" => \$do_pkgs,
 | 
						|
		     "extensions!" => \$do_exts);
 | 
						|
 | 
						|
# Usage if error in options or no arguments given
 | 
						|
unless ($status && @ARGV)
 | 
						|
{
 | 
						|
    print "\n" unless ($status);
 | 
						|
    print "  Usage: $0 [options] filename ...\n\n";
 | 
						|
    print "  Where options can be:\n";
 | 
						|
    print "    --subs (--nosubs)     (don't) include sub declarations in tag file\n";
 | 
						|
    print "    --vars (--novars)     (don't) include variable declarations in tag file\n";
 | 
						|
    print "    --pkgs (--nopkgs)     (don't) include package declarations in tag file\n";
 | 
						|
    print "    --extensions (--noextensions)\n";
 | 
						|
    print "                          (don't) include Exuberant Ctags / Vim style\n";
 | 
						|
    print "                          extensions in tag file\n\n";
 | 
						|
    print "  Default options: ";
 | 
						|
    print ($do_subs ? "--subs " : "--nosubs ");
 | 
						|
    print ($do_vars ? "--vars " : "--novars ");
 | 
						|
    print ($do_pkgs ? "--pkgs " : "--nopkgs ");
 | 
						|
    print ($do_exts ? "--extensions\n\n" : "--noextensions\n\n");
 | 
						|
    print "  Example: $0 *.pl *.pm ../shared/*.pm\n\n";
 | 
						|
    exit;
 | 
						|
}
 | 
						|
 | 
						|
# Loop through files on command line - 'glob' any wildcards, since Windows
 | 
						|
# doesn't do this for us
 | 
						|
foreach $file (map { glob } @ARGV)
 | 
						|
{
 | 
						|
    # Skip if this is not a file we can open.  Also skip tags files and backup
 | 
						|
    # files
 | 
						|
    next unless ((-f $file) && (-r $file) && ($file !~ /tags$/)
 | 
						|
		 && ($file !~ /~$/));
 | 
						|
 | 
						|
    print "Tagging file $file...\n";
 | 
						|
 | 
						|
    $is_pkg = 0;
 | 
						|
    $package_name = "";
 | 
						|
    $has_subs = 0;
 | 
						|
    $var_continues = 0;
 | 
						|
 | 
						|
    open (IN, $file) or die "Can't open file '$file': $!";
 | 
						|
 | 
						|
    # Loop through file
 | 
						|
    foreach $line (<IN>)
 | 
						|
    {
 | 
						|
	# Statement is line with comments and whitespace trimmed
 | 
						|
	($stmt = $line) =~ s/#.*//;
 | 
						|
	$stmt =~ s/^\s*//;
 | 
						|
	$stmt =~ s/\s*$//;
 | 
						|
 | 
						|
	# Nothing left? Never mind.
 | 
						|
	next unless ($stmt);
 | 
						|
 | 
						|
	# This is a variable declaration if one was started on the previous
 | 
						|
	# line, or if this line starts with my or local
 | 
						|
	if ($var_continues or ($stmt =~/^my\b/)
 | 
						|
			    or ($stmt =~/^our\b/) or ($stmt =~/^local\b/))
 | 
						|
	{
 | 
						|
	    # The declaration continues if the line does not end with ;
 | 
						|
	    $var_continues = ($stmt !~ /;$/);
 | 
						|
 | 
						|
	    # Loop through all variable names in the declaration
 | 
						|
	    foreach $var (VarNames($stmt))
 | 
						|
	    {
 | 
						|
		# Make a tag for this variable unless we're told not to.  We
 | 
						|
		# assume that a variable is always static, unless it appears
 | 
						|
		# in a package before any sub.	(Not necessarily true, but
 | 
						|
		# it's ok for most purposes and Vim works fine even if it is
 | 
						|
		# incorrect)
 | 
						|
		if ($do_vars)
 | 
						|
		{
 | 
						|
		    MakeTag($var, "v", (!$is_pkg or $has_subs), $file, $line);
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	}
 | 
						|
 | 
						|
	# This is a package declaration if the line starts with package
 | 
						|
	elsif ($stmt =~/^package\b/)
 | 
						|
	{
 | 
						|
	    # Get name of the package
 | 
						|
	    $package_name = PackageName($stmt);
 | 
						|
 | 
						|
	    if ($package_name)
 | 
						|
	    {
 | 
						|
		# Remember that we're doing a package
 | 
						|
		$is_pkg = 1;
 | 
						|
 | 
						|
		# Make a tag for this package unless we're told not to.  A
 | 
						|
		# package is never static.
 | 
						|
		if ($do_pkgs)
 | 
						|
		{
 | 
						|
		    MakeTag($package_name, "p", 0, $file, $line);
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	}
 | 
						|
 | 
						|
	# This is a sub declaration if the line starts with sub
 | 
						|
	elsif ($stmt =~/^sub\b/)
 | 
						|
	{
 | 
						|
	    # Remember that this file has subs
 | 
						|
	    $has_subs = 1;
 | 
						|
 | 
						|
	    # Make a tag for this sub unless we're told not to.  We assume
 | 
						|
	    # that a sub is static, unless it appears in a package.  (Not
 | 
						|
	    # necessarily true, but it's ok for most purposes and Vim works
 | 
						|
	    # fine even if it is incorrect)
 | 
						|
	    if ($do_subs)
 | 
						|
	    {
 | 
						|
		MakeTag(SubName($stmt), "s", (!$is_pkg), $file, $line);
 | 
						|
	    }
 | 
						|
	}
 | 
						|
    }
 | 
						|
    close (IN);
 | 
						|
}
 | 
						|
 | 
						|
# Do we have any tags?  If so, write them to the tags file
 | 
						|
if (@tags)
 | 
						|
{
 | 
						|
    # Add some tag file extensions if we're told to
 | 
						|
    if ($do_exts)
 | 
						|
    {
 | 
						|
	push (@tags, "!_TAG_FILE_FORMAT\t2\t/extended format/");
 | 
						|
	push (@tags, "!_TAG_FILE_SORTED\t1\t/0=unsorted, 1=sorted/");
 | 
						|
	push (@tags, "!_TAG_PROGRAM_AUTHOR\tMichael Schaap\t/mscha\@mscha.com/");
 | 
						|
	push (@tags, "!_TAG_PROGRAM_NAME\tpltags\t//");
 | 
						|
	push (@tags, "!_TAG_PROGRAM_VERSION\t$VERSION\t/supports multiple tags and extended format/");
 | 
						|
    }
 | 
						|
 | 
						|
    print "\nWriting tags file.\n";
 | 
						|
 | 
						|
    open (OUT, ">tags") or die "Can't open tags file: $!";
 | 
						|
 | 
						|
    foreach $tagline (sort @tags)
 | 
						|
    {
 | 
						|
	print OUT "$tagline\n";
 | 
						|
    }
 | 
						|
 | 
						|
    close (OUT);
 | 
						|
}
 | 
						|
else
 | 
						|
{
 | 
						|
    print "\nNo tags found.\n";
 | 
						|
}
 |