mirror of
				https://github.com/MaskRay/ccls.git
				synced 2025-10-31 12:42:34 +00:00 
			
		
		
		
	Support workspaces as symlinks and symlinks within a workspace
Fix #639
This commit is contained in:
		
							parent
							
								
									5108cfafcb
								
							
						
					
					
						commit
						ca95f48a53
					
				| @ -20,12 +20,22 @@ using namespace clang; | |||||||
| 
 | 
 | ||||||
| namespace ccls { | namespace ccls { | ||||||
| std::string pathFromFileEntry(const FileEntry &file) { | std::string pathFromFileEntry(const FileEntry &file) { | ||||||
|   StringRef name = file.tryGetRealPathName(); |   std::string ret; | ||||||
|   if (name.empty()) |   if (file.getName().startswith("/../")) { | ||||||
|     name = file.getName(); |     // Resolve symlinks outside of working folders. This handles leading path
 | ||||||
|   std::string ret = normalizePath(name); |     // components, e.g. (/lib -> /usr/lib) in
 | ||||||
|   // Resolve symlinks outside of workspace folders, e.g. /usr/include/c++/7.3.0
 |     // /../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/utility
 | ||||||
|   return normalizeFolder(ret) ? ret : realPath(ret); |     ret = file.tryGetRealPathName(); | ||||||
|  |   } else { | ||||||
|  |     // If getName() refers to a file within a workspace folder, we prefer it
 | ||||||
|  |     // (which may be a symlink).
 | ||||||
|  |     ret = normalizePath(file.getName()); | ||||||
|  |   } | ||||||
|  |   if (normalizeFolder(ret)) | ||||||
|  |     return ret; | ||||||
|  |   ret = realPath(ret); | ||||||
|  |   normalizeFolder(ret); | ||||||
|  |   return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool isInsideMainFile(const SourceManager &sm, SourceLocation sl) { | bool isInsideMainFile(const SourceManager &sm, SourceLocation sl) { | ||||||
|  | |||||||
| @ -348,17 +348,16 @@ void do_initialize(MessageHandler *m, InitializeParam ¶m, | |||||||
|     std::string path = wf.uri.getPath(); |     std::string path = wf.uri.getPath(); | ||||||
|     ensureEndsInSlash(path); |     ensureEndsInSlash(path); | ||||||
|     std::string real = realPath(path) + '/'; |     std::string real = realPath(path) + '/'; | ||||||
|     workspaceFolders.emplace_back(path, path == real ? "" : real); |     workspaceFolders.emplace_back(path, real); | ||||||
|   } |   } | ||||||
|   if (workspaceFolders.empty()) { |   if (workspaceFolders.empty()) { | ||||||
|     std::string real = realPath(project_path) + '/'; |     std::string real = realPath(project_path) + '/'; | ||||||
|     workspaceFolders.emplace_back(project_path, |     workspaceFolders.emplace_back(project_path, real); | ||||||
|                                   project_path == real ? "" : real); |  | ||||||
|   } |   } | ||||||
|   std::sort(workspaceFolders.begin(), workspaceFolders.end(), |   std::sort(workspaceFolders.begin(), workspaceFolders.end(), | ||||||
|             [](auto &l, auto &r) { return l.first.size() > r.first.size(); }); |             [](auto &l, auto &r) { return l.first.size() > r.first.size(); }); | ||||||
|   for (auto &[folder, real] : workspaceFolders) |   for (auto &[folder, real] : workspaceFolders) | ||||||
|     if (real.empty()) |     if (real == folder) | ||||||
|       LOG_S(INFO) << "workspace folder: " << folder; |       LOG_S(INFO) << "workspace folder: " << folder; | ||||||
|     else |     else | ||||||
|       LOG_S(INFO) << "workspace folder: " << folder << " -> " << real; |       LOG_S(INFO) << "workspace folder: " << folder << " -> " << real; | ||||||
|  | |||||||
| @ -433,7 +433,9 @@ void Project::loadDirectory(const std::string &root, Project::Folder &folder) { | |||||||
|       // If workspace folder is real/ but entries use symlink/, convert to
 |       // If workspace folder is real/ but entries use symlink/, convert to
 | ||||||
|       // real/.
 |       // real/.
 | ||||||
|       entry.directory = realPath(cmd.Directory); |       entry.directory = realPath(cmd.Directory); | ||||||
|  |       entry.directory.push_back('/'); | ||||||
|       normalizeFolder(entry.directory); |       normalizeFolder(entry.directory); | ||||||
|  |       entry.directory.pop_back(); | ||||||
|       doPathMapping(entry.directory); |       doPathMapping(entry.directory); | ||||||
|       entry.filename = |       entry.filename = | ||||||
|           realPath(resolveIfRelative(entry.directory, cmd.Filename)); |           realPath(resolveIfRelative(entry.directory, cmd.Filename)); | ||||||
|  | |||||||
| @ -138,11 +138,15 @@ std::string realPath(const std::string &path) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool normalizeFolder(std::string &path) { | bool normalizeFolder(std::string &path) { | ||||||
|   for (auto &[root, real] : g_config->workspaceFolders) |   for (auto &[root, real] : g_config->workspaceFolders) { | ||||||
|     if (real.size() && llvm::StringRef(path).startswith(real)) { |     StringRef p(path); | ||||||
|  |     if (p.startswith(root)) | ||||||
|  |       return true; | ||||||
|  |     if (p.startswith(real)) { | ||||||
|       path = root + path.substr(real.size()); |       path = root + path.substr(real.size()); | ||||||
|       return true; |       return true; | ||||||
|     } |     } | ||||||
|  |   } | ||||||
|   return false; |   return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user