Skip to content

Commit ce77029

Browse files
committed
[sipify] debug + fix multiline in SIP_RUN
1 parent eeba0ef commit ce77029

File tree

3 files changed

+85
-31
lines changed

3 files changed

+85
-31
lines changed

scripts/sipify.pl

Lines changed: 56 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,16 @@
22
use strict;
33
use warnings;
44
use File::Basename;
5+
use Getopt::Long;
56

67
use constant PRIVATE => 0;
78
use constant PROTECTED => 1;
89
use constant PUBLIC => 2;
910

10-
# TODO add contexts for
11-
# "multiline function signatures"
12-
# docustrings for QgsFeature::QgsAttributes
11+
# read arguments
12+
my $debug = 0;
13+
GetOptions ("debug" => \$debug) or die("Error in command line arguments\n");
14+
my $headerfile = $ARGV[0];
1315

1416
sub processDoxygenLine
1517
{
@@ -38,8 +40,7 @@ sub processDoxygenLine
3840
return "$line\n";
3941
}
4042

41-
my $headerfile = $ARGV[0];
42-
43+
# read file
4344
open(my $handle, "<", $headerfile) || die "Couldn't open '".$headerfile."' for reading because: ".$!;
4445
chomp(my @lines = <$handle>);
4546
close $handle;
@@ -71,26 +72,40 @@ sub processDoxygenLine
7172
push @output, " * Do not edit manually ! Edit header and run scripts/sipify.pl again *\n";
7273
push @output, " ************************************************************************/\n";
7374

75+
# write some code in front of line to know where the output comes from
76+
$debug == 0 or push @output, "CODE SIP_RUN MultiLine\n";
77+
sub dbg
78+
{
79+
my $msg = '';
80+
$debug == 0 or $msg = sprintf("%-4s %-1d %-1d ", $_[0], $SIP_RUN, $MULTILINE_DEFINITION);
81+
return $msg;
82+
}
83+
sub dbg_info
84+
{
85+
$debug == 0 or push @output, $_[0]."\n";
86+
}
87+
88+
# main loop
7489
while ($line_idx < $line_count){
7590
$line = $lines[$line_idx];
7691
$line_idx++;
7792
#print "$line\n";
7893

7994
if ($line =~ m/^\s*SIP_FEATURE\( (\w+) \)(.*)$/){
80-
push @output, "%Feature $1$2\n";
95+
push @output, dbg("SF1")."%Feature $1$2\n";
8196
next;
8297
}
8398
if ($line =~ m/^\s*SIP_IF_FEATURE\( (\!?\w+) \)(.*)$/){
84-
push @output, "%If ($1)$2\n";
99+
push @output, dbg("SF2")."%If ($1)$2\n";
85100
next;
86101
}
87102
if ($line =~ m/^\s*SIP_CONVERT_TO_SUBCLASS_CODE(.*)$/){
88-
push @output, "%ConvertToSubClassCode$1\n";
103+
push @output, dbg("SCS")."%ConvertToSubClassCode$1\n";
89104
next;
90105
}
91106

92107
if ($line =~ m/^\s*SIP_END(.*)$/){
93-
push @output, "%End$1\n";
108+
push @output, dbg("SEN")."%End$1\n";
94109
next;
95110
}
96111

@@ -99,6 +114,7 @@ sub processDoxygenLine
99114

100115
# skip #if 0 blocks
101116
if ( $line =~ m/^\s*#if 0/){
117+
dbg_info("skipping #if 0 block");
102118
my $nesting_index = 0;
103119
while ($line_idx < $line_count){
104120
$line = $lines[$line_idx];
@@ -120,7 +136,7 @@ sub processDoxygenLine
120136
if ( $line =~ m/^\s*#ifdef SIP_RUN/){
121137
$SIP_RUN = 1;
122138
if ($ACCESS == PRIVATE){
123-
push @output, $private_section_line."\n";
139+
push @output, dbg("PRV1").$private_section_line."\n";
124140
}
125141
next;
126142
}
@@ -171,7 +187,7 @@ sub processDoxygenLine
171187
elsif ( $line =~ m/^\s*#else/ && $global_nesting_index == 0 ){
172188
# code here will be printed out
173189
if ($ACCESS == PRIVATE){
174-
push @output, $private_section_line."\n";
190+
push @output, dbg("PRV2").$private_section_line."\n";
175191
}
176192
$SIP_RUN = 1;
177193
last;
@@ -197,7 +213,7 @@ sub processDoxygenLine
197213
# TYPE HEADER CODE
198214
if ( $HEADER_CODE && $SIP_RUN == 0 ){
199215
$HEADER_CODE = 0;
200-
push @output, "%End\n";
216+
push @output, dbg("HCE")."%End\n";
201217
}
202218

203219
# Skip forward declarations
@@ -219,11 +235,13 @@ sub processDoxygenLine
219235
$opening_line = pop(@output);
220236
$#output >= 0 or die 'could not reach opening definition';
221237
}
238+
dbg_info("removed multiline definition of SIP_SKIP method");
222239
$MULTILINE_DEFINITION = 0;
223240
}
224241
# also skip method body if there is one
225242
if ($lines[$line_idx] =~ m/^\s*\{/){
226243
my $nesting_index = 0;
244+
dbg_info("skipping method body of SIP_SKIP method");
227245
while ($line_idx < $line_count){
228246
$line = $lines[$line_idx];
229247
$line_idx++;
@@ -271,7 +289,7 @@ sub processDoxygenLine
271289
$comment = '';
272290
}
273291
elsif ( $ACCESS == PRIVATE && $line =~ m/SIP_FORCE/){
274-
push @output, $private_section_line."\n";
292+
push @output, dbg("PRV3").$private_section_line."\n";
275293
}
276294
elsif ( $ACCESS == PRIVATE && $SIP_RUN == 0 ) {
277295
$comment = '';
@@ -298,7 +316,7 @@ sub processDoxygenLine
298316
}
299317
}
300318
$comment =~ s/\n+$//;
301-
#push @output, $comment;
319+
#push @output, dbg("XXX").$comment;
302320
next;
303321
}
304322

@@ -341,7 +359,7 @@ sub processDoxygenLine
341359
}
342360
$line .= "\n%TypeHeaderCode\n#include \"" . basename($headerfile) . "\"";
343361

344-
push @output, "$line\n";
362+
push @output, dbg("CLS")."$line\n";
345363

346364
# Skip opening curly bracket, we already added that above
347365
my $skip = $lines[$line_idx];
@@ -356,7 +374,7 @@ sub processDoxygenLine
356374

357375
# Enum declaration
358376
if ( $line =~ m/^\s*enum\s+\w+.*?$/ ){
359-
push @output, "$line\n";
377+
push @output, dbg("ENU1")."$line\n";
360378
if ($line =~ m/\{((\s*\w+)(\s*=\s*[\w\s\d<|]+.*?)?(,?))+\s*\}/){
361379
# one line declaration
362380
$line !~ m/=/ or die 'spify.pl does not handle enum one liners with value assignment. Use multiple lines instead.';
@@ -367,17 +385,17 @@ sub processDoxygenLine
367385
$line = $lines[$line_idx];
368386
$line_idx++;
369387
$line =~ m/^\s*\{\s*$/ || die "Unexpected content: enum should be followed by {\nline: $line";
370-
push @output, "$line\n";
388+
push @output, dbg("ENU2")."$line\n";
371389
while ($line_idx < $line_count){
372390
$line = $lines[$line_idx];
373391
$line_idx++;
374392
if ($line =~ m/\};/){
375393
last;
376394
}
377395
$line =~ s/(\s*\w+)(\s*=\s*[\w\s\d<|]+.*?)?(,?).*$/$1$3/;
378-
push @output, "$line\n";
396+
push @output, dbg("ENU3")."$line\n";
379397
}
380-
push @output, "$line\n";
398+
push @output, dbg("ENU4")."$line\n";
381399
# enums don't have Docstring apparently
382400
$comment = '';
383401
next;
@@ -386,11 +404,13 @@ sub processDoxygenLine
386404

387405
# skip non-method member declaration in non-public sections
388406
if ( $SIP_RUN != 1 && $ACCESS != PUBLIC && $line =~ m/^\s*(?:mutable\s)?\w+[\w<> *&:,]* \*?\w+( = \w+(\([^()]+\))?)?;/){
407+
dbg_info("skip non-method member declaration in non-public sections");
389408
next;
390409
}
391410

392411
# remove struct member assignment
393412
if ( $SIP_RUN != 1 && $ACCESS == PUBLIC && $line =~ m/^(\s*\w+[\w<> *&:,]* \*?\w+) = \w+(\([^()]+\))?;/ ){
413+
dbg_info("remove struct member assignment");
394414
$line = "$1;";
395415
}
396416

@@ -417,6 +437,7 @@ sub processDoxygenLine
417437
if ( $MULTILINE_DEFINITION == 1 ){
418438
my $virtual_line = $line;
419439
my $virtual_line_idx = $line_idx;
440+
dbg_info("handle multiline definition to add virtual keyword on opening line");
420441
while ( $virtual_line !~ m/^[^()]*\(([^()]*\([^()]*\)[^()]*)*[^()]*$/){
421442
$virtual_line_idx--;
422443
$virtual_line = $lines[$virtual_line_idx];
@@ -441,11 +462,14 @@ sub processDoxygenLine
441462

442463
# remove constructor definition, function bodies, member initializing list
443464
if ( $SIP_RUN != 1 && $line =~ m/^(\s*)?(explicit )?(virtual )?(static |const )*(([\w:]+(<.*?>)?\s+(\*|&)?)?(\w+|operator.{1,2})\([\w=()\/ ,&*<>:-]*\)( (?:const|SIP_[A-Z_]*?))*)\s*(\{.*\})?(?!;)(\s*\/\/.*)?$/ ){
465+
dbg_info("remove constructor definition, function bodies, member initializing list");
444466
my $newline = "$1$2$3$4$5;";
445-
if ($line !~ m/\{.*?\}$/){
467+
if ($line !~ m/\{.*?\}\s*(\/\/.*)?$/){
468+
dbg_info(" go for multiline");
446469
$line = $lines[$line_idx];
447470
$line_idx++;
448471
while ( $line =~ m/^\s*[:,] [\w<>]+\(.*?\)/){
472+
dbg_info(" member initializing list");
449473
$line = $lines[$line_idx];
450474
$line_idx++;
451475
}
@@ -454,7 +478,6 @@ sub processDoxygenLine
454478
while ($line_idx < $line_count){
455479
$line = $lines[$line_idx];
456480
$line_idx++;
457-
458481
$nesting_index += $line =~ tr/\{//;
459482
$nesting_index -= $line =~ tr/\}//;
460483
if ($nesting_index == 0){
@@ -542,14 +565,16 @@ sub processDoxygenLine
542565
$line =~ s/\s*% (MappedType|TypeCode|TypeHeaderCode|ConvertFromTypeCode|ConvertToTypeCode|MethodCode|End)/%$1/;
543566
$line =~ s/\/\s+GetWrapper\s+\//\/GetWrapper\//;
544567

545-
push @output, "$line\n";
568+
push @output, dbg("NOR")."$line\n";
546569

547570
# multiline definition (parenthesis left open)
548571
if ( $MULTILINE_DEFINITION == 1 ){
549-
if ( $line =~ m/^[^()]*([^()]*\([^()]*\)[^()]*)*\)[^()]*$/){
572+
# see https://regex101.com/r/DN01iM/2
573+
if ( $line =~ m/^([^()]+(\((?:[^()]++|(?1))*\)))*[^()]*\)[^()]*$/){
550574
$MULTILINE_DEFINITION = 0;
551575
# remove potential following body
552-
if ( $lines[$line_idx] =~ m/^\s*\{$/ ){
576+
if ( $SIP_RUN == 0 && $lines[$line_idx] =~ m/^\s*\{$/ ){
577+
dbg_info("remove following body of multiline def");
553578
my $last_line = $line;
554579
my $nesting_index = 0;
555580
while ($line_idx < $line_count){
@@ -563,8 +588,8 @@ sub processDoxygenLine
563588
}
564589
}
565590
# add missing semi column
566-
pop(@output);
567-
push @output, "$last_line;\n";
591+
my $dummy = pop(@output);
592+
push @output, dbg("MLT")."$last_line;\n";
568593
}
569594
}
570595
else
@@ -573,6 +598,7 @@ sub processDoxygenLine
573598
}
574599
}
575600
elsif ( $line =~ m/^[^()]+\([^()]*([^()]*\([^()]*\)[^()]*)*[^)]*$/ ){
601+
dbg_info("Mulitline detected");
576602
$MULTILINE_DEFINITION = 1;
577603
next;
578604
}
@@ -592,14 +618,14 @@ sub processDoxygenLine
592618
# parent class Docstring
593619
}
594620
else {
595-
push @output, "%Docstring\n";
621+
push @output, dbg("CM1")."%Docstring\n";
596622
if ( $comment !~ m/^\s*$/ ){
597-
push @output, "$comment\n";
623+
push @output, dbg("CM2")."$comment\n";
598624
}
599625
if ($return_type ne '' ){
600-
push @output, " :rtype: $return_type\n";
626+
push @output, dbg("CM3")." :rtype: $return_type\n";
601627
}
602-
push @output, "%End\n";
628+
push @output, dbg("CM4")."%End\n";
603629
}
604630
$comment = '';
605631
$return_type = '';

tests/scripts/sipifyheader.expected.sip

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ complex default value and type (i.e. containing commas) should be given as a str
196196
:rtype: bool
197197
%End
198198

199+
199200
void multilineBodyAndDefinition( const QList<int,
200201
QString> &list,
201202
QgsVectorLayer *vl,
@@ -221,6 +222,7 @@ Mulitline body
221222

222223

223224
virtual int overriddenProperty();
225+
224226
virtual int overrideWithoutVirtual();
225227

226228

@@ -296,6 +298,18 @@ remove argument
296298

297299
void ZshouldBeShown();
298300

301+
void methodCodeWithMultiLineDef();
302+
%MethodCode
303+
if ( QgsWkbTypes::flatType( a0 ) != QgsWkbTypes::Point )
304+
{
305+
multiLineDef( PyExc_ValueError,
306+
QString( "%1 is not nice" ).arg( QgsWkbTypes::displayString( a0 ) ).toUtf8().constData() );
307+
}
308+
else
309+
{
310+
sipCpp = new sipQgsPointV2( a0, a1, a2, a3, a4 );
311+
}
312+
%End
299313

300314
protected:
301315
bool thisShouldBeListed();

tests/scripts/sipifyheader.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ class CORE_EXPORT QgsSipifyHeader : public QtClass<QVariant>, private Ui::QgsBas
160160
QgsVectorLayer *vl,
161161
QgsSnappingResult::SnappingType snap_to ) const;
162162

163-
// Adding SIP_SKIP at the end of a line will discard this MethodCode
163+
// Adding SIP_SKIP at the end of a line will discard this line
164164
bool thisShouldBeSkipped() const SIP_SKIP;
165165

166166
void nonAnnotatedMethodFollowingSkip();
@@ -326,6 +326,20 @@ class CORE_EXPORT QgsSipifyHeader : public QtClass<QVariant>, private Ui::QgsBas
326326
void ZshouldBeShown();
327327
#endif
328328

329+
void methodCodeWithMultiLineDef();
330+
#ifdef SIP_RUN
331+
% MethodCode
332+
if ( QgsWkbTypes::flatType( a0 ) != QgsWkbTypes::Point )
333+
{
334+
multiLineDef( PyExc_ValueError,
335+
QString( "%1 is not nice" ).arg( QgsWkbTypes::displayString( a0 ) ).toUtf8().constData() );
336+
}
337+
else
338+
{
339+
sipCpp = new sipQgsPointV2( a0, a1, a2, a3, a4 );
340+
}
341+
% End
342+
#endif
329343

330344
protected:
331345
bool thisShouldBeListed();

0 commit comments

Comments
 (0)