Configuring uncrustify to add braces - c++

I'm using version of 0.66.1 of uncrustify, and am puzzled by the behavior of 'mod_full_brace_if' which I've set to 'force'. Its comment says:
Add or remove braces on single-line 'if' statement. Will not remove the braces if they contain an 'else'.
Given the line:
if (flag) val = 10;
I hoped/expected it to be transformed to
if (flag) { val = 10; }
Instead it remains unchanged.
Is this just my misunderstanding of the behavior of 'mod_full_brace_if'?
Later:
I had some time to do a little experimentation at home. I started off by creating a new format file, and modified some of the settings having to do with forcing braces to be on the same line as various keywords, as well as some settings forcing braces to surround a one-line body. I made a test file with the following contents:
void foo() {
bool flag;
int var;
if (flag) var = 10;
if (!flag)
var = 20;
}
Running uncrustify with my new config file yielded the same lack of transformation that I saw at work.
I then created another config file and only changed 'mod_full_brace_if' (to 'force'). Using it on my test file resulted in braces surrounding the bodies of the if statements. Clearly there's some weird interaction of multiple settings. I see some change-a-setting-and-test drudgery in my future.

It turns out that the problem was setting "mod_full_brace_if_chain" to "true".
The documentation says:
Make all if/elseif/else statements in a chain be braced or not. Overrides mod_full_brace_if.
If any must be braced, they are all braced. If all can be unbraced, then the braces are removed.
I didn't read the last sentence closely enough when setting the value.

Related

any means of returning bool for yaml variables in yaml-cpp?

I have a config file for disabling specific code paths. I just added a bool option to the yaml file, and am having a hard time figuring out how yaml-cpp handles those. The documentation is a bit lighter than preferred, and I don't see anything for a Node that fits my use case. I could manually parse for the strings returned as true and false, but that seems like something the framework should support, as there are multiple styles of writing trueand false in the spec. Is there any means of getting a bool value out of yaml-cpp?
IsScalarwas the closest I could find.
void LoadConfig(string file)
{
Node config = LoadFile(file);
string targetDirectory;
bool compile;
if (config["TargetDirectory"])
targetDirectory = config["TargetDirectory"].Scalar();
if (config["Compile"])
compile = Config["Compile"].IsScalar();
}
You want the template as() method:
config["Compile"].as<bool>()
Or a neater way to do it all in one line instead of three using a default value (which also addresses your potential uninitialized variable bug):
bool compile = config["Compile"].as<bool>(false);

Determining macro expansion for VarDecl in clang

I'm a beginner to C++, attempting to lint Objective-C code with clang. I understand that macros are first expanded before nodes and properties are visited with AST.
I have a macro named NIL_CHECK, which is used in numerous files. While performing the lint, I would like to skip the variable declaration of the line where this macro is expanded/used.
For instance, the first line in this example should be linted, while the second line needs to be skipped such that false positives are not thrown when there's a macro expansion:
// Must be checked
NSDictionary *playerParams = #{ #"videoId" : videoId, #"playerVars" : playerVars };
// Must be skipped since there's a macro
PlayerProfile *const playerProfile = [[PlayerProfile alloc] initWithData:NIL_CHECK(playerParams)];
Here is the VisitVarDecl visitor method, which traverses through each variable declaration to perform appropriate lint checks:
bool VisitVarDecl(VarDecl *node) {
if (isCollectionType(node -> getType()) && !hasTypeArguments(node -> getType())) {
addViolation(node, this, description(node -> getNameAsString()));
}
return true;
}
How can I determine macros and skip such variable declarations?
Here is a nice answer by Valeriy, I think it covers what you want to achieve.
To summarise:
You want to find the string NIL_CHECK inside a VarDecl, which has already been expanded when you visit the AST. The original text in your source code can be obtained with the help of Lexer. You can use the location of the full varDecl expr or only the macro-contained part. Then the macro name can be detected from the string returned by getSourceText of the Lexer .

How to get clang-format to align chained method calls

I've joined an existing project and I'm the first team member to use clang-format. The existing style mostly matches except for a couple of annoying differences. Here's one (the other one being here):
folly::dynamic makeRequest(const string &response) {
return folly::dynamic::object()
("log_type", "FOO")
("src_id", "42")
("dst_id", "666")
("success", true);
}
clang-format insists on formatting it like this:
folly::dynamic makeRequest(const string &token_response) {
// using longer variable names to highlight using up the whole line lenght
return folly::dynamic::object()("log_type", "FOO")(
"src_id", somethingId)("dst_id", whateverId)("success",
sucess);
}
In the former style I don't feel strongly for how continuation lines are indented, as long as we get one method invocation per line. Is that possible?
Not the best possible solution, but you can force line breaks by putting "//" after each line:
return folly::dynamic::object() //
("log_type", "FOO") //
("src_id", "42") //
("dst_id", "666") //
("success", true);
Another approach that I have used myself is to turn off clang-format for the specific block of code.
// clang-format off
return folly::dynamic::object()
("log_type", "FOO")
("src_id", "42")
("dst_id", "666")
("success", true)
;
// clang-format on
This might not be optimal if you have more complicated logic inside the chained method params (since you will want that logic to be formatted), but if you just have a tuple like this it can be cleaner than adding empty comments.
Both ways you are bypassing clang-format, but this way is cleaner (imo) and signifies your intentions more clearly to future developers.

Visual Studio Breakpoint Macro to modify a value?

I'm debugging an application (C++), and I've found a point in the code where I want to change a value (via the debugger). So right now, I've got a breakpoint set, whereupon I do:
Debugger reaches breakpoint
I modify the variable I want to change
I hit F5 to continue running
lather, rinse, repeat
It's hitting this breakpoint a lot, so I would like to automate this. I would like to set the Breakpoint to run a macro, and continue execution.
However, I have no experience writing VisualStudio macros, so I don't know the commands for modifying a variable of the executing program. I've looked around, but haven't found anything helpful online so far.
I found how to do this with a macro. Initially, I tried using Ctrl-Shift-R to record a macro of keystrokes, but it stopped recording when I did Ctrl-Alt-Q. But I was able to edit the macro to get it to work. So here's what I did, in case anyone else wants to do something similar.
Tools -> Macros -> Macro Explorer
Right Click -> New macro
Public Module RecordingModule
Sub setvalue()
DTE.Debugger.ExecuteStatement("variable_name=0")
End Sub
End Module
This macro will execute the assignment statement, setting my variable (in this case, making it a NULL pointer).
Right Click on a BreakPoint -> When Hit...
Check "Run a macro"
Select Macros.MyMacros.RecordingModule.setvalue
Check "Continue execution"
Click OK
Then, I was able to run my program, automatically adjusting a pointer to NULL as it went. This was very useful for testing, and did not require recompiling.
Looking for similar today and found that you can also use the 'Print a message:' option instead of a macro. Values from code can be printed by placing them inside {}. The key is that VS will also evaluate the content as an expression - so {variable_name=0} should achieve the same as the macro example.
If you are think of a macro in the same way as Microsoft excel, then you're out of luck. It doesn't quite work that way.
In C++, a macro refers to a small inline function created with #define. It is a preprocessor, so a macro is like using a replace on all its references with its body.
For example:
#define add(a,b) ((a)+(b))
int main() {
int a=3, b=4, c=5, d=6, e, f;
d = add(a,b);
e = add(c,d);
}
Would like to the c++ compiler as:
int main() {
int a=3, b=4, c=5, ...;
d = ((a)+(b));
e = ((c)+(d));
}
Now, back to your question. If the variable is within scope at this breakpoint, just set it from within your code:
myVar = myValue;
If it is not, but it is guaranteed to exist, you may need a little hack. Say that this variable is an int, make a global int pointer. If this variable is static, make sure to set it to its address, and back to NULL inside it's scope. If it is dynamic, you may need some extra work. Here is an example:
int* globalIntPointer;
void func() {
*globalIntPointer = 3;
//...
}
int main() {
int a = 5;
globalIntPointer = &a;
func();
//...
globalIntPointer = NULL; // for safety sake
return 0;
}
You can execute a VS macro when a breakpoint is hit (open the breakpoints window, right click on the breakpoint in question, and select "When Hit..." off the popup menu). I'm less certain about writing a macro that modifies a variable of the program under debug though -- I've never done that, and a quick try with attempting to record a macro to do it doesn't seem to work (all it records is activating the right window, not changing the value).
Select "Condition..." and write an assignment for the variable in question in the "Condition:" textbox. This will naturally resolve to "true" with it not being an actual conditional test. Therefore, the breakpoint is never hit, and your variable has been set accordingly.

Is there any way to make Visual Studio stop indenting namespaces?

Visual Studio keeps trying to indent the code inside namespaces.
For example:
namespace Foo
{
void Bar();
void Bar()
{
}
}
Now, if I un-indent it manually then it stays that way. But unfortunately if I add something right before void Bar(); - such as a comment - VS will keep trying to indent it.
This is so annoying that basically because of this only reason I almost never use namespaces in C++. I can't understand why it tries to indent them (what's the point in indenting 1 or even 5 tabs the whole file?), or how to make it stop.
Is there a way to stop this behavior? A config option, an add-in, a registry setting, hell even a hack that modifies devenv.exe directly.
As KindDragon points out, Visual Studio 2013 Update 2 has an option to stop indenting.
You can uncheck TOOLS -> Options -> Text Editor -> C/C++ -> Formatting -> Indentation -> Indent namespace contents.
Just don't insert anything before the first line of code. You could try the following approach to insert a null line of code (it seems to work in VS2005):
namespace foo
{; // !<---
void Test();
}
This seems to suppress the indentation, but compilers may issue warnings and code reviewers/maintainers may be surprised! (And quite rightly, in the usual case!)
Probably not what you wanted to hear, but a lot of people work around this by using macros:
#define BEGIN_NAMESPACE(x) namespace x {
#define END_NAMESPACE }
Sounds dumb, but you'd be surprised how many system headers use this. (glibc's stl implentation, for instance, has _GLIBCXX_BEGIN_NAMESPACE() for this.)
I actually prefer this way, because I always tend to cringe when I see un-indented lines following a {. That's just me though.
Here is a macro that could help you. It will remove indentation if it detects that you are currently creating a namespace. It is not perfect but seems to work so far.
Public Sub aftekeypress(ByVal key As String, ByVal sel As TextSelection, ByVal completion As Boolean) _
Handles TextDocumentKeyPressEvents.AfterKeyPress
If (Not completion And key = vbCr) Then
'Only perform this if we are using smart indent
If DTE.Properties("TextEditor", "C/C++").Item("IndentStyle").Value = 2 Then
Dim textDocument As TextDocument = DTE.ActiveDocument.Object("TextDocument")
Dim startPoint As EditPoint = sel.ActivePoint.CreateEditPoint()
Dim matchPoint As EditPoint = sel.ActivePoint.CreateEditPoint()
Dim findOptions As Integer = vsFindOptions.vsFindOptionsMatchCase + vsFindOptions.vsFindOptionsMatchWholeWord + vsFindOptions.vsFindOptionsBackwards
If startPoint.FindPattern("namespace", findOptions, matchPoint) Then
Dim lines = matchPoint.GetLines(matchPoint.Line, sel.ActivePoint.Line)
' Make sure we are still in the namespace {} but nothing has been typed
If System.Text.RegularExpressions.Regex.IsMatch(lines, "^[\s]*(namespace[\s\w]+)?[\s\{]+$") Then
sel.Unindent()
End If
End If
End If
End If
End Sub
Since it is running all the time, you need to make sure you are installing the macro inside in your EnvironmentEvents project item inside MyMacros. You can only access this module in the Macro Explorer (Tools->Macros->Macro Explorer).
One note, it does not currently support "packed" namespaces such as
namespace A { namespace B {
...
}
}
EDIT
To support "packed" namespaces such as the example above and/or support comments after the namespace, such as namespace A { /* Example */, you can try to use the following line instead:
If System.Text.RegularExpressions.Regex.IsMatch(lines, "^[\s]*(namespace.+)?[\s\{]+$") Then
I haven't had the chance to test it a lot yet, but it seems to be working.
You could also forward declare your types (or whatever) inside the namespace then implement outside like this:
namespace test {
class MyClass;
}
class test::MyClass {
//...
};
Visual Studio 2017+
You can get to this "Indent namespace contents" setting under Tools->Options then Text Editor->C/C++->Formatting->Indention. It's deep in the menus but extremely helpful once found.
I understand the problem when there are nested namespaces. I used to pack all the namespaces in a single line to avoid the multiple indentation. It will leave one level, but that's not as bad as many levels. It's been so long since I have used VS that I hardly remember those days.
namespace outer { namespace middle { namespace inner {
void Test();
.....
}}}