Skip Menu |

This queue is for tickets about the syntax CPAN distribution.

Report information
The Basics
Id: 74739
Status: open
Priority: 0/
Queue: syntax

People
Owner: Nobody in particular
Requestors: perl [...] toby.ink
Cc:
AdminCc:

Bug Information
Severity: Wishlist
Broken in:
  • 0.001
  • 0.002
  • 0.003
Fixed in: (no value)



Subject: Lexical analysis of modules using 'use syntax' does not reveal true dependencies.
I hesitate to call this a bug - it's more of a general caveat for users of "syntax" that should probably be documented somewhere. If I write a package like this: { package Local::Thing; use syntax qw/ function perform /; # ... } Then tools like Module::Install::Metadata which perform lexical analysis (i.e. in practice regexps) of my source code will notice that it depends on the syntax module, but not that it depends on Syntax::Feature::Function and Syntax::Feature::Perform. As I said, this isn't a bug, but a consequence of the design of "syntax", and it really just exposes the fundamental problem with using lexical analysis to determine requirements. Nevertheless, I think it needs to be mentioned in the syntax pod, to warn people. One way to help alleviate the problem would be to bundle a script along the lines of "mo-inline" that Ingy includes with "Mo". The script would search through a Perl file, find lines like this: use syntax qw/ function perform /; And replace them with blocks like this: BEGIN # use syntax qw/ function perform /; { use Syntax::Feature::Function qw(); Syntax::Feature::Function->install(into => __PACKAGE__); use Syntax::Feature::Perform qw(); Syntax::Feature::Perform->install(into => __PACKAGE__); } Thus removing the dependency on "syntax" itself, and making the dependencies on the individual syntax features more explicit. Another solution would be to submit patches to things like Module::Install::Metadata to help them cope better with syntax.
Oh, I have thought of another way to help alleviate the problem. "Test::syntax" which tests a bunch of files, figures out which syntax plugins are used by them, and then checks that a given META.yml references them.
On 2012-02-07T10:21:38Z, TOBYINK wrote: Show quoted text
> Oh, I have thought of another way to help alleviate the problem. > "Test::syntax" which tests a bunch of files, figures out which syntax > plugins are used by them, and then checks that a given META.yml > references them.
The attached has a quick hack that works. Usage is: use Test::syntax; my $count = test_syntax { require My::Module::That::Uses::Syntax; require My::Other::Module::That::Uses::Syntax; do "bin/my-script-that-uses-syntax.pl"; } 'META.yml'; done_testing($count);
Subject: test.pl
use strict; use warnings; { package Test::syntax; use CPAN::Meta; use Test::More; use syntax; my %features; BEGIN { no warnings 'redefine'; my $old = syntax->can('_install_feature'); *syntax::_install_feature = sub { my ($class, $feature, $caller, $options, $all_params) = @_; $features{$feature} = 1; # capture feature. eval { # Restore syntax::_install_feature to prevent "use syntax" within # the syntax modules themselves being captured. local *syntax::_install_feature = $old; $class->$old($feature, $caller, $options, $all_params); }; }; } our @EXPORT; BEGIN { @EXPORT = qw/test_syntax done_testing/; } sub import { my $class = shift; my $caller = caller; no strict 'refs'; foreach (@EXPORT) { next if exists &{"$caller\::$_"}; *{"$caller\::$_"} = \&{"$class\::$_"}; } } sub test_syntax (&;$) { local $Test::Builder::Level = $Test::Builder::Level + 1; my ($coderef, $yaml) = @_; $yaml = 'META.yml' unless defined $yaml; %features = (); $coderef->(); my $meta = CPAN::Meta->load_file($yaml); my $reqs = $meta->effective_prereqs->as_string_hash; ok(exists $reqs->{runtime}{requires}{'syntax'}, "$yaml dependency on syntax itself"); foreach my $feature (keys %features) { my $name = 'Syntax::Feature::'. join '::', map ucfirst, split m{/}, join '', map ucfirst, split qr{_}, $feature; ok(exists $reqs->{runtime}{requires}{$name}, "$yaml dependency on $name"); } return 1 + (my $count = keys %features); } } { package main; BEGIN { Test::syntax->import }; my $count = test_syntax { # You put code here that loads all your script and modules # using "do $script" or "require $module". do 'eg1.pl'; do 'eg2.pl'; }; done_testing($count); }
Subject: Re: [rt.cpan.org #74739] Lexical analysis of modules using 'use syntax' does not reveal true dependencies.
Date: Tue, 07 Feb 2012 15:25:49 +0100
To: bug-syntax [...] rt.cpan.org
From: Robert Sedlacek <rs [...] 474.at>
Hi Tobi, On Tue, 2012-02-07 at 04:39 -0500, Toby Inkster via RT wrote: Show quoted text
> I hesitate to call this a bug - it's more of a general caveat for users > of "syntax" that should probably be documented somewhere. If I write a > package like this: > > { > package Local::Thing; > use syntax qw/ function perform /; > # ... > } > > Then tools like Module::Install::Metadata which perform lexical > analysis (i.e. in practice regexps) of my source code will notice that > it depends on the syntax module, but not that it depends on > Syntax::Feature::Function and Syntax::Feature::Perform.
I have [1], which is able to fetch the syntax dependencies, I just hadn't had time to release it yet. I'll need some time to think about how to best document this caveat, since it's a very generic one. Almost every library doing runtime loading of user-specified classes will have this problem. regards, Robert [1] https://github.com/phaylon/Perl-PrereqScanner-Scanner-SyntaxFeatures -- Robert 'phaylon' Sedlacek Perl 5 Consultant for Shadowcat Systems Limited - http://shadowcat.co.uk/