[PATCH] D36150: [clangd] LSP extension to switch between source/header file

Ilya Biryukov via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Mon Aug 21 01:29:33 PDT 2017


ilya-biryukov added a comment.

The function in `ClangdServer` seems to be getting more complicated and more complicated, mostly because of mixing up `std::string`, `StringRef`, `SmallString`.
Here's a slightly revamped implementation of your function, hope you'll find it (or parts of it) useful to simplify your implementation and address remaining comments.

  // Note that the returned value is now llvm::Optional to clearly indicate no matching file was found.
  llvm::Optional<Path> ClangdServer::switchSourceHeader(PathRef Path) {
    const StringRef SourceExtensions[] = {/*...*/; // only lower-case extensions
    const StringRef HeaderExtensions[] = {/*...*/}; // ...
  
    StringRef PathExt = llvm::sys::path::extension(Path);
    
    // Lookup in a list of known extensions.
    auto SourceIter = std::find(SourceExtensions, /*end iterator*/, PathExt, [](StringRef LHS, StringRef RHS) { return LHS.equals_lower(RHS); });
    bool IsSource = SourceIter != /*end iterator*/;
    
    // ...
    bool IsHeader = ...;
  
    // We can only switch between extensions known extensions.
    if (!IsSource && !IsHeader)
      return llvm::None;
  
    // Array to lookup extensions for the switch. An opposite of where original extension was found.
    ArrayRef<StringRef> NewExts = IsSource ? HeaderExtensions : SourceExtensions;
  
    // Storage for the new path.
    SmallString<128> NewPath;
    Path.toVector(NewPath);
  
    // Instance of vfs::FileSystem, used for file existence checks.
    auto FS = FSProvider.getTaggedFileSystem(Path).Value;
  
    // Loop through switched extension candidates.
    for (StringRef NewExt : NewExts) { 
      llvm::sys::path::replace_extension(NewPath, NewExt)
      if (FS->exists(NewPath))
        return NewPath.str().str(); // First str() to convert from SmallString to StringRef, second to convert from StringRef to std::string
  
      // Also check NewExt in upper-case, just in case.
      llvm::sys::path::replace_extension(NewPath, NewExt.upper())
      if (FS->exists(NewPath))
        return NewPath.str().str();
    }
  
    return llvm::None;
  }



================
Comment at: clangd/ClangdServer.cpp:404
+        std::string returnValue = "file://" + std::string(test.str());
+        returnValue = URI::unparse(URI::fromUri(returnValue));
+        return Path(returnValue);
----------------
No need to create a `URI` here, this should be handled outside `ClangdServer`, just return a path with replaced extension.


https://reviews.llvm.org/D36150





More information about the cfe-commits mailing list