Community
Participate
Working Groups
Version: 8.2.0.201302052218 having trouble narrowing this down, but this is a reduction of an issue I was having in trying to use various refactorings on the cgreen open source project. my reduction: void myprint(const char *); #define MACRO(result) if (result) myprint("[" #result "]") int main(void) { MACRO(1); // can't extract 1 return 0; } placing the caret at the 1 and pressing alt+shift+L gives the error that an expression must be selected. highlighting the 1 and trying again gives the same message. steps: in the real code, -check out svn://matt_hargett@svn.code.sf.net/p/cgreen/code/trunk/cgreen -create a new project by importing existing code as makefile project -after indexing is complete, open mocks_tests.c -in can_stub_an_integer_return, try to extract a local variable for integer_out() from the line assert_that(integer_out(), is_equal_to(3)); result: an expression must be selected to activate this refactoring expected result: should add a new line "int integerOut = integer_out();" and modify the existing assert_that line to be "assert_that(integerOut, is_equal_to(3));" PS: trying a simple "assert_true(false);" in an existing cgreen test and attempt to extract the "false" into a local variable also fails.
(In reply to comment #0) > MACRO(1); // can't extract 1 The parameter to the macro is not an expression because it gets converted to a string by the macro. Extracting a variable for an arbitrary sequence of tokens cannot be done reliably.
okay, that explains my attempt at a reduced example. in the actual cgreen code, the types should be inferrable despite the stringification. any comments there?
(In reply to comment #2) > okay, that explains my attempt at a reduced example. in the actual cgreen > code, the types should be inferrable despite the stringification. any > comments there? Stringification means that the macro parameter doesn't map to an AST expression, doesn't it?
okay, I've simplified the macro to remove string-ification and it still won't extract: #define my_assert_true(result) \ (*get_test_reporter()->assert_true)(get_test_reporter(), "", 0, result, "[", NULL) Ensure(no_errors_thrown_and_default_return_value_when_no_presets_for_loose_mock) { my_assert_true(0); // can't extract local var for 'false' } some of the other relevant declarations: typedef struct TestReporter_ TestReporter; struct TestReporter_ { void (*destroy)(TestReporter *reporter); void (*start_suite)(TestReporter *reporter, const char *name, const int count); void (*start_test)(TestReporter *reporter, const char *name); void (*show_pass)(TestReporter *reporter, const char *file, int line, const char *message, va_list arguments); void (*show_fail)(TestReporter *reporter, const char *file, int line, const char *message, va_list arguments); void (*show_incomplete)(TestReporter *reporter, const char *file, int line, const char *message, va_list arguments); void (*assert_true)(TestReporter *reporter, const char *file, int line, int result, const char * message, ...); void (*finish_test)(TestReporter *reporter, const char *file, int line); void (*finish_suite)(TestReporter *reporter, const char *file, int line); int passes; int failures; int exceptions; void *breadcrumb; int ipc; void *memo; }; TestReporter *get_test_reporter(); the AST knows that get_test_reporter() returns a TestReporter*, and it also knows the parameter list (and types) for the assert_true function pointer on the TestReporter. It should be able to determine that the macro parameter is being substituted for fourth parameter, and the type is int, and therefore extract a local variable "int result = 0;" Again, this small project's source code is open so this can be more easily tested in-context. See initial comments for the svn URL. Thanks!