Addin for enumerating source files - visual-studio

I've been asked to develop an addin that goes through a C# solution and extracts all the documentation from the source files and export them to an HTML file. We can't use normal document generators since the export needs to be in a specific format.
I know how to create a basic addin but have no clue as to how to go about enumerating through the source files.
Any ideas/resources on how to go about starting this project?
Thanks.

Here is some code I'm using to search for a file that ends with a given string.
The structure is like the Solution Explorer in Visual Studio:
Solution -> ProjectItems -> (Nested ProjectItems) -> FileNames
Wherever your code is executing, you can pull up the Projects in the Solution, and then the ProjectItems in those Projects.
var typeFileName = #"\MyClassName.cs";
// Search each Project in the Solution, exclude Unit Test Projects
foreach (Project item in _applicationObject.Solution.Projects.OfType<Project>().Where(p => !p.Name.EndsWith(".Tests")))
{
// Search each ProjectItem recursively
foreach (ProjectItem projectItem in item.ProjectItems)
{
RecursiveProjectItemSearch(projectItem, typeFileName);
}
}
asdasd
private void RecursiveProjectItemSearch(ProjectItem projectItem, string typeFileName)
{
for (short i = 0; i < projectItem.FileCount; i++)
{
var fileName = projectItem.FileNames[i];
if (fileName.EndsWith(typeFileName))
{
// In my case, I want to open the file that I'm searching for
_applicationObject.ItemOperations.OpenFile(fileName);
}
foreach(ProjectItem childProjectItem in projectItem.ProjectItems)
{
RecursiveProjectItemSearch(childProjectItem, typeFileName);
}
}
}
I don't know if this is the most optimal way to do this, but it should work. Given the code above you can change it to do a File.Open() and read the contents or something similar.

Related

Updating display of directory/folder path in MFC File-Open dialog [duplicate]

I'm trying to make a 'Save As' dialog with an event that would change the default path based on the type of file we choose from the filters combo box. The problem is, all the examples I've seen execute the code on result IDOK or IDCANCEL while I'd need the code to be executed while the dialog is still opened.
Also, is there any way to differentiate between what filter has been chosen if the filters have the same type? The GetFileExt() method just returns the extension but I have no way of telling if it was the first .my filter or the template .my filter.
I've seen something like LPOFNHOOKPROC but there was no example of how would I even use it and I'm not sure whether it would even solve my problem or not.
void CMyClass::OnFileOpen()
{
CString pathNam;
CString fileName;
TCHAR szFilters[]= _T("MyType Files (*.my)|*.my|Template MyType (*.my)|*.my||");
CFileDialog fileDlg(TRUE, _T("my"), _T("*.my"),
OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, szFilters);
if(fileDlg.DoModal() == IDOK)
{
pathName = fileDlg.GetPathName();
fileName = fileDlg.GetFileTitle();
}
}
EDIT:
I am now able to get the specific filter that's been chosen by getting the OFN and checking the nFilterIndex value. So the remaining problem is whether I can update the path based on the chosen file format?
EDIT2:
I've found the OnChangeType method and overloaded it in the subclass and it indeed executes the method and the code within, but when I try to update the file path I get an access violation:
void TFileDialogExt::OnTypeChange()
{
LPWSTR buff = L"C:\\TEST\\template.my";
if(m_pOFN->nFilterIndex == 2)
m_ofn.lpstrFile = buff;
}
Basically you have to subclass CFileDialog and handle its CFileDialog::OnTypeChange method.
But, as suggested by Microsoft: you'd better use a new Common Item Dialog instead.
I did some research about this and found some useful questions:
Programmatically pre-select using IFileDialog in C++
How to use SHCreateItemFromParsingName with names from the shell namespace?
Also, have a look at: SHCreateItemFromParsingName.
Here is a sample OnTypeChange handler:
void CMyFileDialog::OnTypeChange()
{
{
IFileOpenDialog* pfod = NULL;
HRESULT hr = (static_cast<IFileDialog*>(m_pIFileDialog))->QueryInterface(IID_PPV_ARGS(&pfod));
if (SUCCEEDED(hr))
{
IShellItem* psiInitialDir;
CString strFolder = L"d:\\";
hr = SHCreateItemFromParsingName(strFolder.GetString(), NULL, IID_PPV_ARGS(&psiInitialDir));
if(SUCCEEDED(hr))
{
pfod->SetFolder(psiInitialDir);
}
}
}
CFileDialog::OnTypeChange();
}
My code uses a hard coded path for testing purposes, but you should now be able to complete your code:
Determine which path you want to use based on the currently selected filter index.
Use similar logic as here to navigate to that folder.

TDirectory::GetFiles listing ignoring case on iOS (FMX, C++)

The code below lists files that have extension .cfg and it works fine on Win32. But, on iOS if i have a file that a user named with caps for the extension (e.g. test.CFG) then i miss it. I found this post using Delphi that might work using TDirectory::TFilterPredicate but i don't know how to implement in C++Builder.
TStringDynArray list;
TSearchOption searchOption;
UnicodeString DocsPath;
int lenDocsFolder;
DocsPath = System::Ioutils::TPath::GetDocumentsPath();
lenDocsFolder = DocsPath.Length();
searchOption = TSearchOption::soTopDirectoryOnly;
try
{
list = TDirectory::GetFiles(DocsPath, "*.cfg", searchOption);
}
catch (...)
{
ShowMessage("Incorrect path or search mask");
return;
}
I suppose i can just run a *.cfg block of code followed by a *.CFG but i'm hoping there is a cleaner approach.
Sorry, but I'm not used to C++. But this applies to both C++ and Delphi.
You are calling:
TDirectory.GetFiles(
const Path, SearchPattern: string;
const SearchOption: TSearchOption): TStringDynArray;
If you instead call this overloaded version:
TDirectory.GetFiles(
const Path, SearchPattern: string;
const SearchOption: TSearchOption;
const Predicate: TFilterPredicate): TStringDynArray;
you should be able to get what you need.
The TFilterPredicate type is defined as:
TFilterPredicate = reference to function(
const Path: string;
const SearchRec: TSearchRec): Boolean;
and should be the correct way to override the way files are matched.
I tried the Using a Lambda Expression from the link Remy posted in comment. I got an E2188 Expression syntaxerror until i disabled the classic Borland compiler. The code works great for simple predicate (on both Win32 and iOS).
String ext(".cfg");
files = TDirectory::GetFiles(CalcPath,
[ext](const String Path, const System::Sysutils::TSearchRec &SearchRec) -> bool
{
return ExtractFileExt(SearchRec.Name) == ext;
});
Now, how do i modify the extension string to return results for both .cfg and .CFG at same time?
String ext(".cfg"); // works fine
String ext(".cfg;.CFG"); // finds nothing

Reference one RoslynPad script from another

What I'd like to do is reference one script from another.
One way to make this happen might be using assemblies. RoslynPad allows compiling a script into an assembly. Here is what I have tried so far.
Script A, which is compiled to SOME_PATH\thing.dll
class Thing
{
public string Name { get; set; }
}
Script B
#r "SOME_PATH\thing.dll"
using static Program;
var t = new Thing();
t.Name = "TEST";
t.Name.Dump();
This gives the error "The type or namespace 'Thing' could not be found..." so I tried the following.
#r "SOME_PATH\thing.dll"
var t = new Program.Thing();
t.Name = "TEST";
t.Name.Dump();
This gave the following error "The type name 'Thing' does not exist in the type 'Program'".
Is there a way to "Compile and Save assembly" and then reference it from another script? Or, is there a more direct way to cross reference between scripts?
What you're looking for is the #load directive:
#load "Path\To\ScriptA.csx"
var t = new Thing();
You can read more about the C# script variant in the Roslyn wiki. Note that not everything there is relevant to RoslynPad, which unlike the C# Interactive window, is not a REPL.

Is there a way to get the integer value of an enum in visual studio while the program is not running?

I have several large enums that are used like
switch(someEnumValue)
{
case SomeEnum.Value1:
DoSomething();
break;
case SomeEnum.Value2:
DoSomethingElse();
break;
...
case someEnum.ValueBigNumber:
break;
}
Is there a way in Visual Studio 2010 for me to see what the integer value of someEnum.SomeValue is without actually running the program and without manually counting the values in the enum definition?
Today I was finding a solution for this problem.
I couldn't find a cool solution like visual studio extension.
Instead, I found a useful trick for this problem using template code!
template<bool, int> class Value_of_someEnumValue_is;
template<> class Value_of_someEnumValue_is<false, someEnumValue> {};
Value_of_someEnumValue_is<true, someEnumValue> i;
If you compile this code, you will see the integer value of 'someEnumValue' in the error message. :)
There is nothing built in for this, though you can define the enumerations with the actual integer values directly, so one look at the enum declaration will tell you the members value:
public enum SomeEnum
{
Value1 = 0,
Value2 = 1,
...
ValueN = 78897
}
Its not clear why you want to do this, but thinking out the box; copy the enum definition into excel and see row number or copy into a new text file in visual studio and check the line number of the cursor (think its bottom right of the ide). Selecting the values from the first may even give you a selected lines count.

recording call stack in Visual Studio

I'm trying to debug a really large c++/c program in Visual Studio. Changing value of one parameter changes the result dramatically. I want to record a call stacks for both runs and diff them.
Does anybody know how to dump a call stack to a file in VS without setting breakpoints and using Select ALL/Copy in the window?
Thanks.
You can use System.Diagnostics.StackTrace to get a string representation of the current call stack and write that to a file. For example:
private static writeStack(string file)
{
StackTrace trace = new StackTrace(true); // the "true" param here allows you to get the file name, etc.
using (StreamWriter writer = new StreamWriter(file))
{
for (int i = 0; i < trace.FrameCount; i++)
{
StackFrame frame = trace.GetFrame(i);
writer.WriteLine("{0}\t{1}\t{2}", frame.GetFileName(), frame.GetFileLineNumber(), frame.GetMethod());
}
}
}
Then, whenever you want to write the current stack, just call writeStack(somePath).
Take a look at this codeproject example which uses the StackWalk64 API.

Resources