Skip to content

Commit 2eb3e64

Browse files
committed
[sipify] properly handle python signatures
1 parent faa7c75 commit 2eb3e64

5 files changed

Lines changed: 83 additions & 31 deletions

File tree

python/core/qgsattributeeditorelement.sip

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class QgsAttributeEditorElement /Abstract/
3838
sipType = sipType_QgsAttributeEditorRelation;
3939
break;
4040
default:
41-
sipType = 0;
41+
sipType = nullptr;
4242
break;
4343
}
4444
%End

python/core/qgsfield.sip

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ Formats string for display
291291
// Raise an exception if the arguments couldn't be parsed.
292292
sipNoMethod( sipParseErr, sipName_QgsField, sipName_convertCompatible, doc_QgsField_convertCompatible );
293293

294-
return 0;
294+
return nullptr;
295295
%End
296296

297297
operator QVariant() const;

python/core/qgsmaplayer.sip

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ class QgsMapLayer : QObject
4242
sipType = sipType_QgsPluginLayer;
4343
break;
4444
default:
45-
sipType = 0;
45+
sipType = nullptr;
4646
break;
4747
}
4848
}

python/core/qgssnappingconfig.sip

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ return individual snapping settings for all layers
207207
// Create the dictionary.
208208
PyObject *d = PyDict_New();
209209
if ( !d )
210-
return 0;
210+
return nullptr;
211211
// Set the dictionary elements.
212212
QHash<QgsVectorLayer *, QgsSnappingConfig::IndividualLayerSettings> container = sipCpp->individualLayerSettings();
213213
QHash<QgsVectorLayer *, QgsSnappingConfig::IndividualLayerSettings>::const_iterator i = container.constBegin();
@@ -216,7 +216,7 @@ return individual snapping settings for all layers
216216
QgsVectorLayer *vl = i.key();
217217
QgsSnappingConfig::IndividualLayerSettings *ils = new QgsSnappingConfig::IndividualLayerSettings( i.value() );
218218

219-
PyObject *vlobj = sipConvertFromType( vl, sipType_QgsVectorLayer, 0 );
219+
PyObject *vlobj = sipConvertFromType( vl, sipType_QgsVectorLayer, nullptr );
220220
PyObject *ilsobj = sipConvertFromType( ils, sipType_QgsSnappingConfig_IndividualLayerSettings, Py_None );
221221

222222
if ( !vlobj || !ilsobj || PyDict_SetItem( d, vlobj, ilsobj ) < 0 )

scripts/sipify.pl

Lines changed: 78 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414
use constant STRICT => 10;
1515
use constant UNSTRICT => 11;
1616

17+
use constant MULTILINE_NO => 20;
18+
use constant MULTILINE_METHOD => 21;
19+
use constant MULTILINE_CONDITIONAL_STATEMENT => 22;
20+
1721
# read arguments
1822
my $debug = 0;
1923
die("usage: $0 [-debug] headerfile\n") unless GetOptions ("debug" => \$debug) && @ARGV == 1;
@@ -35,8 +39,9 @@
3539
my @ACCESS = (PUBLIC);
3640
my @CLASSNAME = ();
3741
my @EXPORTED = (0);
38-
my $MULTILINE_DEFINITION = 0;
42+
my $MULTILINE_DEFINITION = MULTILINE_NO;
3943
my $ACTUAL_CLASS = '';
44+
my $PYTHON_SIGNATURE = '';
4045

4146
my $COMMENT = '';
4247
my $GLOB_IFDEF_NESTING_IDX = 0;
@@ -135,39 +140,64 @@ sub processDoxygenLine {
135140

136141
sub detect_and_remove_following_body_or_initializerlist {
137142
# https://regex101.com/r/ZaP3tC/8
143+
my $python_signature = '';
138144
do {no warnings 'uninitialized';
139145
if ( $LINE =~ m/^(\s*)?((?:(?:explicit|static|const|unsigned|virtual)\s+)*)(([\w:]+(<.*?>)?\s+[*&]?)?(~?\w+|(\w+::)?operator.{1,2})\s*\(([\w=()\/ ,&*<>."-]|::)*\)( +(?:const|SIP_[\w_]+?))*)\s*((\s*[:,]\s+\w+\(.*\))*\s*\{.*\}\s*(?:SIP_[\w_]+)?;?|(?!;))(\s*\/\/.*)?$/
140146
|| $LINE =~ m/SIP_SKIP\s*(?!;)\s*(\/\/.*)?$/
141147
|| $LINE =~ m/^\s*class.*SIP_SKIP/ ){
142148
dbg_info("remove constructor definition, function bodies, member initializing list");
143149
my $newline = "$1$2$3;";
144-
remove_following_body_or_initializerlist() unless $LINE =~ m/{.*}(\s*SIP_\w+)*\s*(\/\/.*)?$/;
150+
$python_signature = remove_following_body_or_initializerlist() unless $LINE =~ m/{.*}(\s*SIP_\w+)*\s*(\/\/.*)?$/;
145151
$LINE = $newline;
146152
}
147153
};
154+
return $python_signature;
148155
}
149156

150157
sub remove_following_body_or_initializerlist {
158+
my $python_signature = '';
151159
do {no warnings 'uninitialized';
152160
dbg_info("remove constructor definition, function bodies, member initializing list");
153-
$LINE = read_line();
154-
while ( $LINE =~ m/^\s*[:,]\s+([\w<>]|::)+\(.*?\)/){
155-
dbg_info(" member initializing list");
156-
$LINE = read_line();
161+
my $line = read_line();
162+
# python signature
163+
if ($line =~ m/^\s*\[\s*(\w+\s*)?\(/){
164+
dbg_info("python signature detected");
165+
my $nesting_index = 0;
166+
while ($LINE_IDX < $LINE_COUNT){
167+
$nesting_index += $line =~ tr/\[//;
168+
$nesting_index -= $line =~ tr/\]//;
169+
if ($nesting_index == 0){
170+
if ($line =~ m/^(.*);\s*(\/\/.*)?$/){
171+
$line = $1; # remove semicolon (added later)
172+
$python_signature .= "\n$line";
173+
return $python_signature;
174+
}
175+
last;
176+
}
177+
$python_signature .= "\n$line";
178+
$line = read_line();
179+
}
157180
}
158-
if ( $LINE =~ m/^\s*\{/ ){
181+
# member initializing list
182+
while ( $line =~ m/^\s*[:,]\s+([\w<>]|::)+\(.*?\)/){
183+
dbg_info("member initializing list");
184+
$line = read_line();
185+
}
186+
# body
187+
if ( $line =~ m/^\s*\{/ ){
159188
my $nesting_index = 0;
160189
while ($LINE_IDX < $LINE_COUNT){
161190
dbg_info(" remove body");
162-
$nesting_index += $LINE =~ tr/\{//;
163-
$nesting_index -= $LINE =~ tr/\}//;
191+
$nesting_index += $line =~ tr/\{//;
192+
$nesting_index -= $line =~ tr/\}//;
164193
if ($nesting_index == 0){
165194
last;
166195
}
167-
$LINE = read_line();
196+
$line = read_line();
168197
}
169198
}
170199
};
200+
return $python_signature;
171201
}
172202

173203
sub fix_annotations {
@@ -206,14 +236,14 @@ sub fix_annotations {
206236
# remove argument
207237
if ($line =~ m/SIP_PYARGREMOVE/){
208238
dbg_info("remove arg");
209-
if ( $MULTILINE_DEFINITION == 1 ){
239+
if ( $MULTILINE_DEFINITION != MULTILINE_NO ){
210240
my $prev_line = pop(@OUTPUT) =~ s/\n$//r;
211241
# update multi line status
212242
my $parenthesis_balance = 0;
213243
$parenthesis_balance += $prev_line =~ tr/\(//;
214244
$parenthesis_balance -= $prev_line =~ tr/\)//;
215245
if ($parenthesis_balance == 1){
216-
$MULTILINE_DEFINITION = 0;
246+
$MULTILINE_DEFINITION = MULTILINE_NO;
217247
}
218248
# concat with above line to bring previous commas
219249
$line =~ s/^\s+//;
@@ -257,10 +287,10 @@ sub detect_comment_block{
257287
# main loop
258288
while ($LINE_IDX < $LINE_COUNT){
259289

290+
$PYTHON_SIGNATURE = '';
260291
$ACTUAL_CLASS = $CLASSNAME[$#CLASSNAME] unless $#CLASSNAME < 0;
261292
$LINE = read_line();
262293

263-
264294
if ($LINE =~ m/^\s*SIP_FEATURE\( (\w+) \)(.*)$/){
265295
write_output("SF1", "%Feature $1$2\n");
266296
next;
@@ -270,8 +300,8 @@ sub detect_comment_block{
270300
next;
271301
}
272302
if ($LINE =~ m/^\s*SIP_CONVERT_TO_SUBCLASS_CODE(.*)$/){
273-
write_output("SCS", "%ConvertToSubClassCode$1\n");
274-
next;
303+
$LINE = "%ConvertToSubClassCode$1";
304+
# do not go next, let run the "do not process SIP code"
275305
}
276306

277307
if ($LINE =~ m/^\s*SIP_END(.*)$/){
@@ -284,9 +314,24 @@ sub detect_comment_block{
284314
$IF_FEATURE_CONDITION = $1;
285315
}
286316

317+
# do not process SIP code %XXXCode
318+
if ( $SIP_RUN == 1 && $LINE =~ m/^ *% *(MappedType|Type(?:Header)?Code|Module(?:Header)?Code|Convert(?:From|To)(?:Type|SubClass)Code|MethodCode)(.*)?$/ ){
319+
$LINE = "%$1$2";
320+
$COMMENT = '';
321+
dbg_info("do not process SIP code");
322+
while ( $LINE !~ m/^ *% *End/ ){
323+
write_output("COD", $LINE."\n");
324+
$LINE = read_line();
325+
$LINE =~ s/^ *% *(MappedType|Type(?:Header)?Code|Module(?:Header)?Code|Convert(?:From|To)(?:Type|SubClass)Code|MethodCode)(.*)?$/%$1$2/;
326+
$LINE =~ s/^\s*SIP_END(.*)$/%End$1/;
327+
}
328+
$LINE =~ s/^\s*% End/%End/;
329+
write_output("COD", $LINE."\n");
330+
next;
331+
}
332+
287333
# Skip preprocessor stuff
288334
if ($LINE =~ m/^\s*#/){
289-
290335
# skip #if 0 blocks
291336
if ( $LINE =~ m/^\s*#if (0|defined\(Q_OS_WIN\))/){
292337
dbg_info("skipping #if $1 block");
@@ -412,15 +457,15 @@ sub detect_comment_block{
412457
dbg_info('SIP SKIP!');
413458
$COMMENT = '';
414459
# if multiline definition, remove previous lines
415-
if ( $MULTILINE_DEFINITION == 1){
460+
if ( $MULTILINE_DEFINITION != MULTILINE_NO){
416461
dbg_info('SIP_SKIP with MultiLine');
417462
my $opening_line = '';
418463
while ( $opening_line !~ m/^[^()]*\(([^()]*\([^()]*\)[^()]*)*[^()]*$/){
419464
$opening_line = pop(@OUTPUT);
420465
$#OUTPUT >= 0 or exit_with_error('could not reach opening definition');
421466
}
422467
dbg_info("removed multiline definition of SIP_SKIP method");
423-
$MULTILINE_DEFINITION = 0;
468+
$MULTILINE_DEFINITION = MULTILINE_NO;
424469
}
425470
# also skip method body if there is one
426471
detect_and_remove_following_body_or_initializerlist();
@@ -704,7 +749,7 @@ sub detect_comment_block{
704749
# remove keywords
705750
if ( $IS_OVERRIDE == 1 ){
706751
# handle multiline definition to add virtual keyword on opening line
707-
if ( $MULTILINE_DEFINITION == 1 ){
752+
if ( $MULTILINE_DEFINITION != MULTILINE_NO ){
708753
my $virtual_line = $LINE;
709754
my $virtual_line_idx = $LINE_IDX;
710755
dbg_info("handle multiline definition to add virtual keyword on opening line");
@@ -728,7 +773,7 @@ sub detect_comment_block{
728773
}
729774

730775
# remove constructor definition, function bodies, member initializing list
731-
$SIP_RUN == 1 or detect_and_remove_following_body_or_initializerlist();
776+
$PYTHON_SIGNATURE = detect_and_remove_following_body_or_initializerlist();
732777

733778
# remove inline declarations
734779
if ( $LINE =~ m/^(\s*)?(static |const )*(([\w:]+(<.*?>)?\s+(\*|&)?)?(\w+)( (?:const*?))*)\s*(\{.*\});(\s*\/\/.*)?$/ ){
@@ -768,27 +813,29 @@ sub detect_comment_block{
768813
$LINE = fix_annotations($LINE);
769814

770815
# fix astyle placing space after % character
771-
$LINE =~ s/\s*% (MappedType|Type(Header)?Code|Module(Header)?Code|Convert(From|To)TypeCode|MethodCode|End)/%$1/;
772816
$LINE =~ s/\/\s+GetWrapper\s+\//\/GetWrapper\//;
773817

774818
write_output("NOR", "$LINE\n");
819+
if ($PYTHON_SIGNATURE ne ''){
820+
write_output("PSI", "$PYTHON_SIGNATURE\n");
821+
}
775822

776823
# multiline definition (parenthesis left open)
777-
if ( $MULTILINE_DEFINITION == 1 ){
824+
if ( $MULTILINE_DEFINITION != MULTILINE_NO ){
778825
dbg_info("on multiline");
779826
# https://regex101.com/r/DN01iM/2
780827
if ( $LINE =~ m/^([^()]+(\((?:[^()]++|(?1))*\)))*[^()]*\)[^()]*$/){
781-
$MULTILINE_DEFINITION = 0;
782828
dbg_info("ending multiline");
783829
# remove potential following body
784-
if ( $SIP_RUN == 0 && $LINE !~ m/(\{.*\}|;)\s*(\/\/.*)?$/ ){
830+
if ( $MULTILINE_DEFINITION != MULTILINE_CONDITIONAL_STATEMENT && $LINE !~ m/(\{.*\}|;)\s*(\/\/.*)?$/ ){
785831
dbg_info("remove following body of multiline def");
786832
my $last_line = $LINE;
787-
remove_following_body_or_initializerlist();
833+
$last_line .= remove_following_body_or_initializerlist();
788834
# add missing semi column
789835
my $dummy = pop(@OUTPUT);
790836
write_output("MLT", "$last_line;\n");
791837
}
838+
$MULTILINE_DEFINITION = MULTILINE_NO;
792839
}
793840
else
794841
{
@@ -797,7 +844,12 @@ sub detect_comment_block{
797844
}
798845
elsif ( $LINE =~ m/^[^()]+\([^()]*([^()]*\([^()]*\)[^()]*)*[^)]*$/ ){
799846
dbg_info("Mulitline detected");
800-
$MULTILINE_DEFINITION = 1;
847+
if ( $LINE =~ m/^\s*((else )?if|while|for) *\(/ ){
848+
$MULTILINE_DEFINITION = MULTILINE_CONDITIONAL_STATEMENT;
849+
}
850+
else {
851+
$MULTILINE_DEFINITION = MULTILINE_METHOD;
852+
}
801853
next;
802854
}
803855

0 commit comments

Comments
 (0)