How to find the relative file path of a class file to csproj in SourceGenerator - roslyn

I am using SourceGenerator and analysing a class to create a string that needs to have the relative path of the class file to the csproj file.
I am able to find the absolute path of the class file using code below, but not the relative path
public class XamlControlAndPageFinder : ISyntaxContextReceiver
{
public void OnVisitSyntaxNode(GeneratorSyntaxContext context)
{
if (context.Node is ClassDeclarationSyntax userControl)
{
// This gives us the complete path and not relative path
var filePath = userControl.SyntaxTree.FilePath;
}
}
}

You can walk the file system upwards until you find a .csproj file. Then calculate the relative path from it to your class file.
This will NOT work if you are using linked files outside of the main path, but it may be good enough for your scenario.

Related

QDir currentPath and cd() not working?

I am currently attempting to create a new directory and create a new file inside of this directory. However, QDir recognizes that this file exists, however when I try to cd to my new directory, the currentPath returns the same value before and after the QDir().cd(dirName)
QDir().cdUp();
if(!QDir(dirName).exists())
QDir().mkdir(dirName);
qDebug() << QDir().currentPath(); // returns a path up from exe dir
if(QDir().cd(dirName))
qDebug() << QDir().currentPath(); //returns the same path as above
Really not sure why this isn't working, I am pretty new to programming and was wondering why this was.
QDir().cd(dirName)
Every time you perform QDir() you're creating a new instance of the object, then you perform an operation on it (i.e., .cd(dirName)), and finally that object goes out of scope and is destroyed; thereby losing all your changes.
Instead you should be creating a single instance and performing all operations on it.
QDir dir;
dir.cd(dirName);
dir.path();
The constructor QDir() creates a QDir object pointing to the program's working directory. QDir()::cd() changes that QDir object directory, however it does not change program directory. If you really want to change current application working directory, see QDir()::setCurrent(const QString & path)
That current application directory is used as relative path for files. So, to create a file in a new directory, you can specify the full file path or to use relative path as:
QDir::setCurrent(new_base_path);
QFile("some_relative_file_name");
...

Coapp / autopkg : multiple include folders in /build/native/include/

I am trying to build a nuget package via CoApp tool for c++.
The package needs to embed 3 folders when compiling a cpp using it.
So, I want an internal include structure as following :
/build/native/include/lib1,
/build/native/include/lib2,
/build/native/include/lib3
My question: how to add several include folders in /build/native/include/
I tryied :
Multiple blocs of (varying lib1, lib2, lib3):
nestedInclude +=
{
#destination = ${d_include}lib1;
".\lib1\**\*.hpp", ".\lib1\**\*.h"
};
Multiple blocs of (varying lib1, lib2, lib3):
nestedInclude
{
#destination = ${d_include}lib1;
".\lib1\**\*.hpp", ".\lib1\**\*.h"
};
but it seems coapp accumulates the .h/.hpp files among the blocs (depending of operator += or not) and at the end, add all of them to the last #destination tag value. So I get an unique entry : /build/native/include/lib3
The destination is overwritten in your example and therefore you get everything flat in the last given address. To handle this you can instead create multiple nested include,
nested1Include: {
#destination = ${d_include}lib1;
".\lib1\**\*.hpp", ".\lib1\**\*.h"
}
nested2Include: {
#destination = ${d_include}lib2;
".\lib2\**\*.hpp", ".\lib2\**\*.h"
}
I've just hit the same issue, and Gorgar's answer set me on the right track, thank you. But I do have one additional piece of information. I only had one underlying directory, and in that case CoApp still flattened everything. The trick is to make it think it has two, even if it doesn't, like this:
include1: {
#destination = ${d_include}NativeLogger;
"include\NativeLogger\*.h"
};
// The use of a second include spec here which doesn't actually address any files
// is to force CoApp to create the substructure of the first include. There is some
// discussion on the net about bugginess related to includes structures, but this
// seems to fix it.
include2: { include\* };

How to tell if a folder is a subfolder of a special Windows folder?

If I have a CSIDL (or its newer alternative KNOWNFOLDERID) for a special folder (for the sake of this example, let's assume My Documents folder) and a DOS folder path, is there any way to tell that the path refers to a subfolder within the special folder?
EDIT 1: I implemented the following method after #RemyLebeau's suggestion, but it always sets my nIsParent to 0, or not a parent. What am I missing there?
int nCSIDL = CSIDL_PERSONAL;
LPCTSTR pDosPath = L"C:\\Users\\UserName\\Documents\\Subfolder1\\File.txt";
int nIsParent = -1; //-1=error, 0=no, 1=yes
LPITEMIDLIST pidlDocuments = NULL;
if(SUCCEEDED(SHGetFolderLocation(NULL, nCSIDL, NULL, 0, &pidlDocuments)))
{
LPITEMIDLIST pidl = ILCreateFromPath(pDosPath);
if(pidl)
{
nIsParent = ILIsParent(pidlDocuments, pidl, FALSE) ? 1 : 0;
ILFree(pidl);
}
ILFree(pidlDocuments);
}
EDIT 2: As for his 2nd suggestion to use SHGetPathFromIDList and then PathRelativePathTo on both DOS paths, it won't work for the following: My Documents on my computer is redirected to "\\SRVR-A\Home\UserName\Documents", which is also the "R:\Documents" folder with drive R: mapped to that Home share. PathRelativePathTo fails on those paths.
EDIT 3: If I had a folder Test folder in My Documents I could do this using my mapped drive R::
subst S: "R:\Documents\Test folder"
Which will technically make folder "S:\Test folder" a parent of My Documents as well, which is "\\SRVR-A\Home\UserName\Documents\Test folder".
That is why I was looking for a Shell-only, or a single API solution.
Everything in the Shell is represented by the ITEMIDLIST structure, even file system paths. Retrieve the ITEMIDLIST of the special folder using SHGetFolderLocation() or SHGetKnownFolderIDList(), then retrieve the ITEMIDLIST of the DOS path using SHParseDisplayName() or ILCreateFromPath(), then use ILIsParent() to check if the special folder's ITEMIDLIST is a parent of the DOS path's ITEMIDLIST.
Alternatively, retrieve the special folder's path using SHGetFolderPath() or SHGetKnownFolderPath(), then use PathRelativePathTo to check if the DOS path can be represented as a relative subfolder of the special folder's path without using any ".." components.
Create a function that gets a full path, name of the special folder, and just call
strstr on the full path with the name of the special folder and if it does not return NULL then it is a subfolder.
As for an API for it, I'm not aware of something like that but it could be possible.

Cocos2dx-3.0 use setSearchPaths adapted to screen size doesn't work

Problem is after i use setSearchPaths() to set different image path for different screen size, look like the project get image from image path random.
For example:if screen's height is 1136, the search path is "iphoneBig" and the project should use image of path "iphoneBig", but sometimes the project use the image of path "iphoneMid".
I put my code snippets at here:
typedef struct tagResource
{
cocos2d::Size size;
char directory[100];
}Resource;
static Resource smallResource = { cocos2d::Size::Size(480, 320), "iphoneSmall" };
static Resource iPhone4Resource = { cocos2d::Size::Size(960, 640), "iphoneMid" };
static Resource iPhone5Resource = { cocos2d::Size::Size(1136, 640), "iphoneBig" };
cocos2d::Size frameSize = pEGLView->getVisibleSize();
pEGLView->setDesignResolutionSize(frameSize.width, frameSize.height, ResolutionPolicy::NO_BORDER);
if (frameSize.height > 960)
{
std::string str(iPhone5Resource.directory);
std::vector<std::string> vtStr;
vtStr.push_back(str);
cocos2d::FileUtils::getInstance()->setSearchPaths(vtStr);
}
else if (frameSize.height > smallResource.size.height)
{
std::string str(iPhone4Resource.directory);
std::vector<std::string> vtStr;
vtStr.push_back(str);
cocos2d::FileUtils::getInstance()->setSearchPaths(vtStr);
}
Who can tell me the reason? A lot of thanks.
The behavior described arises from the fact that the various folders of resources have been added as groups and when Xcode creates the executable it copies all the resource files into a single path, and then identical names will be overwritten. The order in which the files are copied can make sure that the file really present in the app is different from run to run.
When you add resources to your project you have to create a folder reference (not a group) especially if more than one of the resource folders share a common filename:

Reading a file from Java Servlet

I wrote some code to read a file in my Java Servlet class. (I'm using Netbeans on Windows along with Tomcat server). However, my servlet cannot find the file!
After much digging, I found that I had to place the file I wanted to read in Tomcat/bin folder. That's very surprising. How can I get the path to my Webapps/ folder? Let's assume my website project is called "Web1".
Essentially what I'm doing is I'm trying to read my .xsl file for converting my DOM Document to be an HTML. At first I tried placing this .xsl file everywhere (at the same level as my index.jsp, in the same directory as my servlet class file, etc...but didnt work at all)
Also, when I finished transform(), my HTML file also goes into the Tomcat/bin folder~!
Can you use javax.servlet.ServletContext.getRealPath(String path)?
Returns a String containing the real path for a given virtual path. For example, the path "/index.html" returns the absolute file path on the server's filesystem would be served by a request for "http://host/contextPath/index.html", where contextPath is the context path of this ServletContext..
The real path returned will be in a form appropriate to the computer and operating system on which the servlet container is running, including the proper path separators. This method returns null if the servlet container cannot translate the virtual path to a real path for any reason (such as when the content is being made available from a .war archive).
Where are you consuming that XSL? If from your Java code place the file into src/java/resources so it will end up in the top of your classpath when the WAR is assembled /WEB-INF/classes/foo.xsl. Then you can use Class#getResource("foo.xsl") or even better if you are using DOM4J or equivalent there are ways of loading the file.
Now if it is you JavaScript that performs the transformation on the client that's a different story
Something like this might be more convenient for you:
java.net.URL url = ClassLoader.getSystemResource(file_name);
try {
InputStream is = url.openStream());
//Read the file and do stuff
} catch(IOException e) {
System.err.println("Error: could not load the file");
}
This will allow you to get an InputStream for a file within the classpath (in your case, something in the webapps folder). As for writing results, I'm not sure.