Skip to content

Commit

Permalink
[sipify] properly handle python signatures
Browse files Browse the repository at this point in the history
  • Loading branch information
3nids committed Jun 12, 2017
1 parent faa7c75 commit 2eb3e64
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 31 deletions.
2 changes: 1 addition & 1 deletion python/core/qgsattributeeditorelement.sip
Expand Up @@ -38,7 +38,7 @@ class QgsAttributeEditorElement /Abstract/
sipType = sipType_QgsAttributeEditorRelation;
break;
default:
sipType = 0;
sipType = nullptr;
break;
}
%End
Expand Down
2 changes: 1 addition & 1 deletion python/core/qgsfield.sip
Expand Up @@ -291,7 +291,7 @@ Formats string for display
// Raise an exception if the arguments couldn't be parsed.
sipNoMethod( sipParseErr, sipName_QgsField, sipName_convertCompatible, doc_QgsField_convertCompatible );

return 0;
return nullptr;
%End

operator QVariant() const;
Expand Down
2 changes: 1 addition & 1 deletion python/core/qgsmaplayer.sip
Expand Up @@ -42,7 +42,7 @@ class QgsMapLayer : QObject
sipType = sipType_QgsPluginLayer;
break;
default:
sipType = 0;
sipType = nullptr;
break;
}
}
Expand Down
4 changes: 2 additions & 2 deletions python/core/qgssnappingconfig.sip
Expand Up @@ -207,7 +207,7 @@ return individual snapping settings for all layers
// Create the dictionary.
PyObject *d = PyDict_New();
if ( !d )
return 0;
return nullptr;
// Set the dictionary elements.
QHash<QgsVectorLayer *, QgsSnappingConfig::IndividualLayerSettings> container = sipCpp->individualLayerSettings();
QHash<QgsVectorLayer *, QgsSnappingConfig::IndividualLayerSettings>::const_iterator i = container.constBegin();
Expand All @@ -216,7 +216,7 @@ return individual snapping settings for all layers
QgsVectorLayer *vl = i.key();
QgsSnappingConfig::IndividualLayerSettings *ils = new QgsSnappingConfig::IndividualLayerSettings( i.value() );

PyObject *vlobj = sipConvertFromType( vl, sipType_QgsVectorLayer, 0 );
PyObject *vlobj = sipConvertFromType( vl, sipType_QgsVectorLayer, nullptr );
PyObject *ilsobj = sipConvertFromType( ils, sipType_QgsSnappingConfig_IndividualLayerSettings, Py_None );

if ( !vlobj || !ilsobj || PyDict_SetItem( d, vlobj, ilsobj ) < 0 )
Expand Down
104 changes: 78 additions & 26 deletions scripts/sipify.pl
Expand Up @@ -14,6 +14,10 @@
use constant STRICT => 10;
use constant UNSTRICT => 11;

use constant MULTILINE_NO => 20;
use constant MULTILINE_METHOD => 21;
use constant MULTILINE_CONDITIONAL_STATEMENT => 22;

# read arguments
my $debug = 0;
die("usage: $0 [-debug] headerfile\n") unless GetOptions ("debug" => \$debug) && @ARGV == 1;
Expand All @@ -35,8 +39,9 @@
my @ACCESS = (PUBLIC);
my @CLASSNAME = ();
my @EXPORTED = (0);
my $MULTILINE_DEFINITION = 0;
my $MULTILINE_DEFINITION = MULTILINE_NO;
my $ACTUAL_CLASS = '';
my $PYTHON_SIGNATURE = '';

my $COMMENT = '';
my $GLOB_IFDEF_NESTING_IDX = 0;
Expand Down Expand Up @@ -135,39 +140,64 @@ sub processDoxygenLine {

sub detect_and_remove_following_body_or_initializerlist {
# https://regex101.com/r/ZaP3tC/8
my $python_signature = '';
do {no warnings 'uninitialized';
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*\/\/.*)?$/
|| $LINE =~ m/SIP_SKIP\s*(?!;)\s*(\/\/.*)?$/
|| $LINE =~ m/^\s*class.*SIP_SKIP/ ){
dbg_info("remove constructor definition, function bodies, member initializing list");
my $newline = "$1$2$3;";
remove_following_body_or_initializerlist() unless $LINE =~ m/{.*}(\s*SIP_\w+)*\s*(\/\/.*)?$/;
$python_signature = remove_following_body_or_initializerlist() unless $LINE =~ m/{.*}(\s*SIP_\w+)*\s*(\/\/.*)?$/;
$LINE = $newline;
}
};
return $python_signature;
}

sub remove_following_body_or_initializerlist {
my $python_signature = '';
do {no warnings 'uninitialized';
dbg_info("remove constructor definition, function bodies, member initializing list");
$LINE = read_line();
while ( $LINE =~ m/^\s*[:,]\s+([\w<>]|::)+\(.*?\)/){
dbg_info(" member initializing list");
$LINE = read_line();
my $line = read_line();
# python signature
if ($line =~ m/^\s*\[\s*(\w+\s*)?\(/){
dbg_info("python signature detected");
my $nesting_index = 0;
while ($LINE_IDX < $LINE_COUNT){
$nesting_index += $line =~ tr/\[//;
$nesting_index -= $line =~ tr/\]//;
if ($nesting_index == 0){
if ($line =~ m/^(.*);\s*(\/\/.*)?$/){
$line = $1; # remove semicolon (added later)
$python_signature .= "\n$line";
return $python_signature;
}
last;
}
$python_signature .= "\n$line";
$line = read_line();
}
}
if ( $LINE =~ m/^\s*\{/ ){
# member initializing list
while ( $line =~ m/^\s*[:,]\s+([\w<>]|::)+\(.*?\)/){
dbg_info("member initializing list");
$line = read_line();
}
# body
if ( $line =~ m/^\s*\{/ ){
my $nesting_index = 0;
while ($LINE_IDX < $LINE_COUNT){
dbg_info(" remove body");
$nesting_index += $LINE =~ tr/\{//;
$nesting_index -= $LINE =~ tr/\}//;
$nesting_index += $line =~ tr/\{//;
$nesting_index -= $line =~ tr/\}//;
if ($nesting_index == 0){
last;
}
$LINE = read_line();
$line = read_line();
}
}
};
return $python_signature;
}

sub fix_annotations {
Expand Down Expand Up @@ -206,14 +236,14 @@ sub fix_annotations {
# remove argument
if ($line =~ m/SIP_PYARGREMOVE/){
dbg_info("remove arg");
if ( $MULTILINE_DEFINITION == 1 ){
if ( $MULTILINE_DEFINITION != MULTILINE_NO ){
my $prev_line = pop(@OUTPUT) =~ s/\n$//r;
# update multi line status
my $parenthesis_balance = 0;
$parenthesis_balance += $prev_line =~ tr/\(//;
$parenthesis_balance -= $prev_line =~ tr/\)//;
if ($parenthesis_balance == 1){
$MULTILINE_DEFINITION = 0;
$MULTILINE_DEFINITION = MULTILINE_NO;
}
# concat with above line to bring previous commas
$line =~ s/^\s+//;
Expand Down Expand Up @@ -257,10 +287,10 @@ sub detect_comment_block{
# main loop
while ($LINE_IDX < $LINE_COUNT){

$PYTHON_SIGNATURE = '';
$ACTUAL_CLASS = $CLASSNAME[$#CLASSNAME] unless $#CLASSNAME < 0;
$LINE = read_line();


if ($LINE =~ m/^\s*SIP_FEATURE\( (\w+) \)(.*)$/){
write_output("SF1", "%Feature $1$2\n");
next;
Expand All @@ -270,8 +300,8 @@ sub detect_comment_block{
next;
}
if ($LINE =~ m/^\s*SIP_CONVERT_TO_SUBCLASS_CODE(.*)$/){
write_output("SCS", "%ConvertToSubClassCode$1\n");
next;
$LINE = "%ConvertToSubClassCode$1";
# do not go next, let run the "do not process SIP code"
}

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

# do not process SIP code %XXXCode
if ( $SIP_RUN == 1 && $LINE =~ m/^ *% *(MappedType|Type(?:Header)?Code|Module(?:Header)?Code|Convert(?:From|To)(?:Type|SubClass)Code|MethodCode)(.*)?$/ ){
$LINE = "%$1$2";
$COMMENT = '';
dbg_info("do not process SIP code");
while ( $LINE !~ m/^ *% *End/ ){
write_output("COD", $LINE."\n");
$LINE = read_line();
$LINE =~ s/^ *% *(MappedType|Type(?:Header)?Code|Module(?:Header)?Code|Convert(?:From|To)(?:Type|SubClass)Code|MethodCode)(.*)?$/%$1$2/;
$LINE =~ s/^\s*SIP_END(.*)$/%End$1/;
}
$LINE =~ s/^\s*% End/%End/;
write_output("COD", $LINE."\n");
next;
}

# Skip preprocessor stuff
if ($LINE =~ m/^\s*#/){

# skip #if 0 blocks
if ( $LINE =~ m/^\s*#if (0|defined\(Q_OS_WIN\))/){
dbg_info("skipping #if $1 block");
Expand Down Expand Up @@ -412,15 +457,15 @@ sub detect_comment_block{
dbg_info('SIP SKIP!');
$COMMENT = '';
# if multiline definition, remove previous lines
if ( $MULTILINE_DEFINITION == 1){
if ( $MULTILINE_DEFINITION != MULTILINE_NO){
dbg_info('SIP_SKIP with MultiLine');
my $opening_line = '';
while ( $opening_line !~ m/^[^()]*\(([^()]*\([^()]*\)[^()]*)*[^()]*$/){
$opening_line = pop(@OUTPUT);
$#OUTPUT >= 0 or exit_with_error('could not reach opening definition');
}
dbg_info("removed multiline definition of SIP_SKIP method");
$MULTILINE_DEFINITION = 0;
$MULTILINE_DEFINITION = MULTILINE_NO;
}
# also skip method body if there is one
detect_and_remove_following_body_or_initializerlist();
Expand Down Expand Up @@ -704,7 +749,7 @@ sub detect_comment_block{
# remove keywords
if ( $IS_OVERRIDE == 1 ){
# handle multiline definition to add virtual keyword on opening line
if ( $MULTILINE_DEFINITION == 1 ){
if ( $MULTILINE_DEFINITION != MULTILINE_NO ){
my $virtual_line = $LINE;
my $virtual_line_idx = $LINE_IDX;
dbg_info("handle multiline definition to add virtual keyword on opening line");
Expand All @@ -728,7 +773,7 @@ sub detect_comment_block{
}

# remove constructor definition, function bodies, member initializing list
$SIP_RUN == 1 or detect_and_remove_following_body_or_initializerlist();
$PYTHON_SIGNATURE = detect_and_remove_following_body_or_initializerlist();

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

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

write_output("NOR", "$LINE\n");
if ($PYTHON_SIGNATURE ne ''){
write_output("PSI", "$PYTHON_SIGNATURE\n");
}

# multiline definition (parenthesis left open)
if ( $MULTILINE_DEFINITION == 1 ){
if ( $MULTILINE_DEFINITION != MULTILINE_NO ){
dbg_info("on multiline");
# https://regex101.com/r/DN01iM/2
if ( $LINE =~ m/^([^()]+(\((?:[^()]++|(?1))*\)))*[^()]*\)[^()]*$/){
$MULTILINE_DEFINITION = 0;
dbg_info("ending multiline");
# remove potential following body
if ( $SIP_RUN == 0 && $LINE !~ m/(\{.*\}|;)\s*(\/\/.*)?$/ ){
if ( $MULTILINE_DEFINITION != MULTILINE_CONDITIONAL_STATEMENT && $LINE !~ m/(\{.*\}|;)\s*(\/\/.*)?$/ ){
dbg_info("remove following body of multiline def");
my $last_line = $LINE;
remove_following_body_or_initializerlist();
$last_line .= remove_following_body_or_initializerlist();
# add missing semi column
my $dummy = pop(@OUTPUT);
write_output("MLT", "$last_line;\n");
}
$MULTILINE_DEFINITION = MULTILINE_NO;
}
else
{
Expand All @@ -797,7 +844,12 @@ sub detect_comment_block{
}
elsif ( $LINE =~ m/^[^()]+\([^()]*([^()]*\([^()]*\)[^()]*)*[^)]*$/ ){
dbg_info("Mulitline detected");
$MULTILINE_DEFINITION = 1;
if ( $LINE =~ m/^\s*((else )?if|while|for) *\(/ ){
$MULTILINE_DEFINITION = MULTILINE_CONDITIONAL_STATEMENT;
}
else {
$MULTILINE_DEFINITION = MULTILINE_METHOD;
}
next;
}

Expand Down

0 comments on commit 2eb3e64

Please sign in to comment.