Can I programmatically collapse/expand all preprocessor blocks of a certain name in Visual Studio 2012? - c++

My current project has a lot of debug preprocessor blocks scattered throughout the code. These are intentionally named differently to the system _DEBUG and NDEBUG macros, so I have a lot of this:
// Some code here
#ifdef PROJNAME_DEBUG
//unit tests, assumption testing, etc.
#endif
// code continues
These blocks sometimes get rather large, and their presence can sometimes inhibit code readability. In Visual Studio 2012 I can easily collapse these, but it would be nice to automatically have all of them collapsed, allowing me to expand them if I want to see what's in there. However, as I also have a bunch of header guards I don't want to collapse all preprocessor blocks, only the #ifdef PROJNAME_DEBUG ones.
Can I do this?

This is the most easiest scenario you can achive it, I think.
You should create an Add-In first in C#. (in VS 2013 they become deprecated :( )
In the OnConnection method you should add your command:
public void OnConnection( object application, ext_ConnectMode connectMode, object addInInst, ref Array custom )
{
_applicationObject = (DTE2)application;
if (connectMode == ext_ConnectMode.ext_cm_AfterStartup || connectMode == ext_ConnectMode.ext_cm_Startup)
{
Commands2 commands = (Commands2)_applicationObject.Commands;
try
{
//Add a command to the Commands collection:
Command command = commands.AddNamedCommand2(_addInInstance, "MyAddinMenuBar", "MyAddinMenuBar", "Executes the command for MyAddinMenuBar", true, 59, ref contextGUIDS, (int)vsCommandStatus.vsCommandStatusSupported + (int)vsCommandStatus.vsCommandStatusEnabled, (int)vsCommandStyle.vsCommandStylePictAndText, vsCommandControlType.vsCommandControlTypeButton);
}
catch (System.ArgumentException)
{
//If we are here, bla, bla... (Auto generated)
}
}
}
Note: you can find how parameters are act at the reference of AddNamedCommand2
The template created version would be also fine, but naturaly it worth to name your command properly.
After that you need to add your logic to Exec method:
public void Exec( string commandName, vsCommandExecOption executeOption, ref object varIn, ref object varOut, ref bool handled )
{
handled = false;
if (executeOption == vsCommandExecOption.vsCommandExecOptionDoDefault)
{
if (commandName == "MyAddinMenuBar.Connect.MyAddinMenuBar")
{
List<string> args = (varIn as string).Split(' ').ToList();
TextSelection ts;
ts = (TextSelection)_applicationObject.ActiveDocument.Selection;
EditPoint ep = (ts.ActivePoint).CreateEditPoint();
ep.StartOfDocument();
do
{
string actualLine = ep.GetLines(ep.Line, ep.Line + 1);
if (args.TrueForAll(filter => actualLine.Contains(filter)))
{
_applicationObject.ExecuteCommand("Edit.GoTo", ep.Line.ToString());
_applicationObject.ExecuteCommand("Edit.ToggleOutliningExpansion");
}
ep.LineDown();
} while (!ep.AtEndOfDocument);
handled = true;
return;
}
}
}
Note: Name you given to the command is checked in exec.
Than you can build.
Deployment of Add-In can happen through an [ProjectName].AddIn file in ..\Documents\Visaul Studio 20[XY]\AddIns\. (Created by the template, you should copy if you move the Add-In elsewhere)
You should place your Add-In assembly where the Assembly element of the mentioned file you set to point. To change version you should modify the text in Version element.
After you deployed and started Studio, you should activate the Add-In in the manager in Toolsmenu.
You need to expand all collapsable section in your code file (CTRL+M+L with C# IDE settigs).
This is required because I found only a way to invert the state of collapsion. If you find better command, you can change it.
Next you should activate Command Window to use the the created command.
Now only you need to type your commands name, like this:
MyAddinMenuBar.Connect.MyAddinMenuBar #ifdef PROJNAME_DEBUG
Hopefully magic will happen.
This solution is independent of language of code you edit so pretty multifunctional.

Related

VS 2017 Designer: Method not found

I have a windows form that contains a user control (each defined in separate assemblies). Both the form and the user control call an extension method on BindingList<>. The extension method is defined in a 3rd assembly. Everything compiles & runs fine.
However, if I try to open the form in Visual Studio 2017 designer, I get an error:
To prevent possible data loss before loading the designer, the following errors must be resolved:
Method not found: 'System.ComponentModel.BindingList1 KamaTrenda.Utilities.Lists.ListUtilities.AddReset(System.ComponentModel.BindingList1,
System.Collections.Generic.IEnumerable`1)'.
Call stack:
at System.ComponentModel.ReflectPropertyDescriptor.SetValue(Object
component, Object value) at
Microsoft.VisualStudio.Shell.Design.VsTargetFrameworkPropertyDescriptor.SetValue(Object
component, Object value) at
System.ComponentModel.Design.Serialization.CodeDomSerializerBase.DeserializePropertyAssignStatement(IDesignerSerializationManager
manager, CodeAssignStatement statement,
CodePropertyReferenceExpression propertyReferenceEx, Boolean
reportError) at
System.ComponentModel.Design.Serialization.CodeDomSerializerBase.DeserializeAssignStatement(IDesignerSerializationManager
manager, CodeAssignStatement statement) at
System.ComponentModel.Design.Serialization.CodeDomSerializerBase.DeserializeStatement(IDesignerSerializationManager
manager, CodeStatement statement)
Commenting out the content of the setter of this property allows for opening the form in the designer:
public IList<IPosition> PositionsToDisplay
{
get { return myPositionsToDisplay.Select(x => x.Position).ToList(); }
set { myPositionsToDisplay.AddReset(value.Select(x => new PositionAdapter(x))); }
}
myPositionsToDisplay:
private readonly BindingList<PositionAdapter> myPositionsToDisplay = new SortableBindingList<PositionAdapter>();
And AddReset:
public static class ListUtilities
{
public static BindingList<T> AddReset<T>(this BindingList<T> list, IEnumerable<T> toAdd)
{
list.RaiseListChangedEvents = false;
foreach (T item in toAdd)
list.Add(item);
list.RaiseListChangedEvents = true;
list.ResetBindings();
return list; // for chaining
}
}
I have tried adding
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
to the definition of PositionsToDisplay, and it made no difference.
I tried rebuilding, manually deleting the contents obj & bin directories for all 3 projects, as well as the contents of AppData\Local\Microsoft\VisualStudio\15.0_6d397e1a\ProjectAssemblies, closing all open documents in VS 2017, closing the solution, and restarting Visual Studio, and it made no difference.
The .resx file of neither the form, nor the control, refer to the property.
The Designer.cs for the form had some code that seemed to be causing the issue:
this.control.PositionsToDisplay = ((System.Collections.Generic.IList<IPosition>)(resources.GetObject("control.PositionsToDisplay")));
Deleting this (presumably after adding DesignerSerializationVisibility.Hidden, so that it does not get re-generated) seemed to solve the issue.

Problems porting lexer string accumulator to new version of Quex

While porting my lexer file from Quex 0.64.8 to 0.67.4 I ran
into some problems with the string accumulator. The issues
I get look like this:
Severity Code Description Project File Line Suppression State
Error C3861 'ecmascript_lexer_Accumulator__clear': identifier not found (compiling source file C:\Users\Patrikj\Work\git\ecmascript_build_vc14_x64\generated\ecmascript_lexer.cpp) ktes C:\Users\Patrikj\Work\git\ecmascript\ecmascript.qx 107
I suppose it's the double underline Accumulator__clear that is the cause of the issue. Maybe I need to supply a new switch to Quex or maybe the API
has changed in the newer version. Either way I am at a loss on how to
fix the issue.
And example from my lexer (.qx) that generates the issue:
mode StringHelper : EOF
<inheritable: only>
{
on_exit {
/// All 3 rows using the accumulator generates an error similiar to the one mentioned above
if(self.accumulator.text.begin != self.accumulator.text.end)
self_send(TOK_STRLITPART);
self_accumulator_flush(TOK_QUOTE);
self_accumulator_clear();
}
}
Any help fixing this issue would be much appreciated.
Best regards,
Patrik J
Version 0.67.3 and later excluded the string accumulator from
the main generator. The reason was that for some situations
there is no general solution in the construct, include-push,
and reset scenarios. Users must specify them as they go along.
For using the accumulator, no command line option is required.
However, in the .qx files the following sections need to be defined
(this is an example):
header {
#include <quex/code_base/extra/accumulator/Accumulator>
}
footer {
#include <quex/code_base/extra/accumulator/Accumulator.i>
}
body {
QUEX_NAME(Accumulator) accumulator;
}
constructor {
if( ! QUEX_NAME(Accumulator_construct)(&me->accumulator, me) ) {
return false;
}
}
destructor {
QUEX_NAME(Accumulator_destruct)(&me->accumulator);
}
print {
QUEX_NAME(Accumulator_print_this)(&me->accumulator);
}
The case with the PostCategorizer is the same. You find the setup
shown below in 'common.qx' files in the demo subdirectories.
Also, after 'flush()' you do not need to 'clear()'.

AutoHotKey if statement not working

What is wrong with this?
if A_OSVersion = WIN_7 or A_OSVersion = WIN_XP
{
MsgBox, Win7 or XP
} else {
if WinActive("ahk_exe Explorer") {
!f::!h
}
}
The goal is to replace Alt+F with Alt+H in Explorer when I'm running Windows 8, 8.1, or 10, and I am testing on a Windows 7 machine, so the code shouldn't run at all, but the hotkey does and the MsgBox doesn't. Do I need to reorder things for it to work? The syntax looks right to me, but I've been having a hard time with syntax for AHKscript.
Kind comments are appreciated!
This
!f::!h
isn't a command, it's a key remap and thus, implicitly contains a return. You cannot use it within executable context. For details, see http://ahkscript.org/docs/misc/Remap.htm#Remarks somewhere below.
You wouldn't wanna have a return somewhere in between the lines which should be executed, would you.
(this was mostly a copy of my answer here)
For context-sensitive hotkeys, use the preprocessor directives:
#if (A_OSVersion = "WIN_7" or A_OSVersion = "WIN_XP") and not winActive("ahk_exe Explorer")
!f::!h
#if
#if winActive("ahk_exe Explorer") and !(A_OSVersion = "WIN_7" or A_OSVersion = "WIN_XP")
!f::!h
#if
To do it within normal script flow you will need to used the Hotkey Command but then it will not be a remap but a hotkey that sends another set of keys...

How do I write a very simple Visual Studio debugger visualizer?

I'm trying to write an 'autoexp.dat'-based visualizer for a string type. I've scaled-back my ambitions to attempting to write a visualizer for a really simple test type that contains a null-terminated string field:
namespace thizz { namespace izz {
class MyType {
const char* _ptr;
public:
MyType(const char* ptr) : _ptr(ptr) {}
};
}
}
This is my stab at a visualiser, but it has no effect on how Visual Studio (2010) displays an instance of this type:
thizz::izz::MyType
{
preview ([$e._ptr,s])
}
(That's going at the top of the [Visualizers] section in C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\Packages\Debugger\autoexp.dat).
Watching an instance of this type:
thizz::izz::MyType t("testing testing");
Just displays
t | {_ptr=0x0f56a6fc "testing testing" } | thizz::izz::MyType
in the Watch window.
To get an even more versatile viewer try changing to use this:
thizz::izz::MyType {
preview ( #( [$e._ptr,s] ) )
stringview ( #( [$e._ptr,sb] ) )
}
this will also give the magnifying glass icon which will open a larger text view window in the case that you have a longer string. It'll also give you the option of rendering as HTML or XML.
Note that as well as the format of the file being sensitive to whitespace, I've also found that you can't use a colon in the string otherwise it generates parse errors.
The debugger visualisers are incredibly powerful, though the syntax can be quite bewildering. As general advice I would suggest creating some entries first in the [AutoExpand] section to summarise the data types that you are most interested in, and then if you have custom containers then copy and adapt the examples for vector, list, etc, which will give you the largest return for the investment in your time.
I can't give a categorical reason why my original 'code' in autoexp.dat was not working, but I found that the same code worked when all the whitespace was removed.
I then tried re-adding whitespace and found that keeping the initial open brace on the first line was necessary to keep the definition working.

C++\IronPython integration example code?

I'm looking for a simple example code for C++\IronPython integration, i.e. embedding python code inside a C++, or better yet, Visual C++ program.
The example code should include: how to share objects between the languages, how to call functions\methods back and forth etc...
Also, an explicit setup procedure would help too. (How to include the Python runtime dll in Visual Studio etc...)
I've found a nice example for C#\IronPython here, but couldn't find C++\IronPython example code.
UPDATE - I've written a more generic example (plus a link to a zip file containing the entire VS2008 project) as entry on my blog here.
Sorry, I am so late to the game, but here is how I have integrated IronPython into a C++/cli app in Visual Studio 2008 - .net 3.5. (actually mixed mode app with C/C++)
I write add-ons for a map making applicaiton written in Assembly. The API is exposed so that C/C++ add-ons can be written. I mix C/C++ with C++/cli. Some of the elements from this example are from the API (such as XPCALL and CmdEnd() - please just ignore them)
///////////////////////////////////////////////////////////////////////
void XPCALL PythonCmd2(int Result, int Result1, int Result2)
{
if(Result==X_OK)
{
try
{
String^ filename = gcnew String(txtFileName);
String^ path = Assembly::GetExecutingAssembly()->Location;
ScriptEngine^ engine = Python::CreateEngine();
ScriptScope^ scope = engine->CreateScope();
ScriptSource^ source = engine->CreateScriptSourceFromFile(String::Concat(Path::GetDirectoryName(path), "\\scripts\\", filename + ".py"));
scope->SetVariable("DrawingList", DynamicHelpers::GetPythonTypeFromType(AddIn::DrawingList::typeid));
scope->SetVariable("DrawingElement", DynamicHelpers::GetPythonTypeFromType(AddIn::DrawingElement::typeid));
scope->SetVariable("DrawingPath", DynamicHelpers::GetPythonTypeFromType(AddIn::DrawingPath::typeid));
scope->SetVariable("Node", DynamicHelpers::GetPythonTypeFromType(AddIn::Node::typeid));
source->Execute(scope);
}
catch(Exception ^e)
{
Console::WriteLine(e->ToString());
CmdEnd();
}
}
else
{
CmdEnd();
}
}
///////////////////////////////////////////////////////////////////////////////
As you can see, I expose to IronPython some objects (DrawingList, DrawingElement, DrawingPath & Node). These objects are C++/cli objects that I created to expose "things" to IronPython.
When the C++/cli source->Execute(scope) line is called, the only python line
to run is the DrawingList.RequestData.
RequestData takes a delegate and a data type.
When the C++/cli code is done, it calls the delegate pointing to the
function "diamond"
In the function diamond it retrieves the requested data with the call to
DrawingList.RequestedValue() The call to DrawingList.AddElement(dp) adds the
new element to the Applications visual Database.
And lastly the call to DrawingList.EndCommand() tells the FastCAD engine to
clean up and end the running of the plugin.
import clr
def diamond(Result1, Result2, Result3):
if(Result1 == 0):
dp = DrawingPath()
dp.drawingStuff.EntityColor = 2
dp.drawingStuff.SecondEntityColor = 2
n = DrawingList.RequestedValue()
dp.Nodes.Add(Node(n.X-50,n.Y+25))
dp.Nodes.Add(Node(n.X-25,n.Y+50))
dp.Nodes.Add(Node(n.X+25,n.Y+50))
dp.Nodes.Add(Node(n.X+50,n.Y+25))
dp.Nodes.Add(Node(n.X,n.Y-40))
DrawingList.AddElement(dp)
DrawingList.EndCommand()
DrawingList.RequestData(diamond, DrawingList.RequestType.PointType)
I hope this is what you were looking for.
If you don't need .NET functionality, you could rely on embedding Python instead of IronPython. See Python's documentation on Embedding Python in Another Application for more info and an example. If you don't mind being dependent on BOOST, you could try out its Python integration library.