Skip to content

Commit d9b8a4f

Browse files
authored
count special module methods once per name for completion (#1530)
* count special module methods once per name for completion
1 parent 586a198 commit d9b8a4f

4 files changed

Lines changed: 54 additions & 1 deletion

File tree

‎ChangeLog‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,13 @@
6666
* inst/tinytest/cpp/Module.cpp (Module_scope_is_cleared): New
6767
* inst/tinytest/test_module.R: Test loading the failing module
6868

69+
* inst/include/Rcpp/module/class.h (class_::AddMethod): Count special
70+
'[' methods once per name rather than once per overload, as complete()
71+
expects; overloading '[[' dropped methods from completion or ran past
72+
the end of the method map (#1529)
73+
* inst/tinytest/cpp/Module.cpp: Add classes overloading '[['
74+
* inst/tinytest/test_module.R: Test their completions
75+
6976
* vignettes/rmd/Rcpp-modules.Rmd: Document that objects of exposed
7077
classes returned by value or reference are copied, while a returned
7178
pointer is owned and eventually deleted by R, so that returning this or

‎inst/include/Rcpp/module/class.h‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,9 +254,10 @@
254254
typename map_vec_signed_method::iterator it = ptr->vec_methods.find( name_ ) ;
255255
if( it == ptr->vec_methods.end() ){
256256
it = ptr->vec_methods.insert( vec_signed_method_pair( name_, new vec_signed_method() ) ).first ;
257+
// complete() relies on this counting names, not overloads
258+
if( *name_ == '[' ) ptr->specials++ ;
257259
}
258260
(it->second)->push_back( new signed_method_class(m, valid, docstring ) ) ;
259-
if( *name_ == '[' ) ptr->specials++ ;
260261
return *this ;
261262
}
262263

‎inst/tinytest/cpp/Module.cpp‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,27 @@ double ModuleBase_value(const ModuleBase& x) {
173173
return x.value;
174174
}
175175

176+
class ModuleBrackets {
177+
public:
178+
ModuleBrackets() : value(1.0) {}
179+
180+
double at(int i) { return value * i; }
181+
double at2(int i, int j) { return value * i * j; }
182+
double total() { return value; }
183+
184+
double value;
185+
};
186+
187+
class ModuleBracketsOnly {
188+
public:
189+
ModuleBracketsOnly() : value(1.0) {}
190+
191+
double at(int i) { return value * i; }
192+
double at2(int i, int j) { return value * i * j; }
193+
194+
double value;
195+
};
196+
176197
// counts its destructions, to check who owns objects returned from C++
177198
class ModuleOwned {
178199
public:
@@ -303,6 +324,22 @@ RCPP_MODULE(demoModule) {
303324

304325
function("ModuleBase_value", &ModuleBase_value);
305326

327+
// overloaded [[, with and without an ordinary method
328+
class_<ModuleBrackets>("ModuleBrackets")
329+
.constructor()
330+
.method("[[", &ModuleBrackets::at)
331+
.method("[[", &ModuleBrackets::at2)
332+
.method("total", &ModuleBrackets::total)
333+
.field("value", &ModuleBrackets::value)
334+
;
335+
336+
class_<ModuleBracketsOnly>("ModuleBracketsOnly")
337+
.constructor()
338+
.method("[[", &ModuleBracketsOnly::at)
339+
.method("[[", &ModuleBracketsOnly::at2)
340+
.field("value", &ModuleBracketsOnly::value)
341+
;
342+
306343
class_<ModuleOwned>("ModuleOwned")
307344
.field_readonly("id", &ModuleOwned::id)
308345
;

‎inst/tinytest/test_module.R‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,14 @@ expect_error( r$get(10L), "not initialized" )
167167
expect_error( Rcpp::sourceCpp("cpp/ModuleInitError.cpp"), "no such class" )
168168
expect_true( Module_scope_is_cleared() )
169169

170+
## completion lists the ordinary methods and the fields; an overloaded [[
171+
## used to be counted once per overload, which dropped the last ordinary
172+
## method, or ran past the end of the method map when there was none (#1529)
173+
brackets <- new( ModuleBrackets )
174+
expect_equal( Rcpp:::complete( brackets ), c("total( ", "value") )
175+
expect_equal( brackets[[2L]], 2.0 )
176+
expect_equal( Rcpp:::complete( new( ModuleBracketsOnly ) ), "value" )
177+
170178
## a pointer returned from C++ is owned by the R object wrapping it, and
171179
## deleted when that object is garbage collected (#1533)
172180
destroyed <- ModuleOwned_destroyed()

0 commit comments

Comments
 (0)