vladimir.plyashkun created this revision.
vladimir.plyashkun added reviewers: alexfh, benlangmuir.
vladimir.plyashkun added a project: clang-tools-extra.
Herald added a subscriber: cfe-commits.

These changes introduce support for -vfsoverlay option in Clang-Tidy
The main reason for it:
In IDE integration we have two different pieces of source: editor and physical 
file.
File is placed in some project directory (let's call it "A")
We want to run clang-tidy exactly in this project directory "A",  in order to 
get all .clang-tidy files in parent directories along with correct resolution 
for all relative include paths.
But in IDE, saving mechanism perfoms periodically.
So, to perform analysis of actual text on the fly, we need to save document on 
every modification  (which is inefficient) or generate file in the temporary 
directory with actual text (it also leads to skipping .clang-tidy files and 
complicates include search paths resolution)
-vfsoverlay approach allows us to analyze source file in the project directory 
"A" but with actual data placed in another directory.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D41535

Files:
  clang-tidy/ClangTidy.cpp
  clang-tidy/ClangTidyOptions.cpp
  clang-tidy/ClangTidyOptions.h
  clang-tidy/tool/ClangTidyMain.cpp

Index: clang-tidy/tool/ClangTidyMain.cpp
===================================================================
--- clang-tidy/tool/ClangTidyMain.cpp
+++ clang-tidy/tool/ClangTidyMain.cpp
@@ -209,6 +209,12 @@
                            cl::init(false),
                            cl::cat(ClangTidyCategory));
 
+static cl::opt<std::string> VfsOverlay("vfsoverlay", cl::desc(R"(
+Overlay the virtual filesystem described by file over the real file system.
+)"),
+                           cl::value_desc("filename"),
+                           cl::cat(ClangTidyCategory));
+
 namespace clang {
 namespace tidy {
 
@@ -295,6 +301,7 @@
   DefaultOptions.AnalyzeTemporaryDtors = AnalyzeTemporaryDtors;
   DefaultOptions.FormatStyle = FormatStyle;
   DefaultOptions.User = llvm::sys::Process::GetEnv("USER");
+  DefaultOptions.VfsOverlay = VfsOverlay;
   // USERNAME is used on Windows.
   if (!DefaultOptions.User)
     DefaultOptions.User = llvm::sys::Process::GetEnv("USERNAME");
@@ -312,6 +319,8 @@
     OverrideOptions.AnalyzeTemporaryDtors = AnalyzeTemporaryDtors;
   if (FormatStyle.getNumOccurrences() > 0)
     OverrideOptions.FormatStyle = FormatStyle;
+  if (VfsOverlay.getNumOccurrences() > 0)
+    OverrideOptions.VfsOverlay = VfsOverlay;
 
   if (!Config.empty()) {
     if (llvm::ErrorOr<ClangTidyOptions> ParsedConfig =
@@ -331,7 +340,16 @@
 }
 
 static int clangTidyMain(int argc, const char **argv) {
-  CommonOptionsParser OptionsParser(argc, argv, ClangTidyCategory,
+  llvm::SpecificBumpPtrAllocator<char> ArgAllocator;
+  SmallVector<const char *, 256> Argv;
+  std::error_code EC = llvm::sys::Process::GetArgumentVector(
+      Argv, llvm::makeArrayRef(argv, argc), ArgAllocator);
+  if (EC) {
+    llvm::errs() << "error: couldn't get arguments: " << EC.message() << '\n';
+    return 1;
+  }
+
+  CommonOptionsParser OptionsParser(argc, &Argv[0], ClangTidyCategory,
                                     cl::ZeroOrMore);
 
   auto OwningOptionsProvider = createOptionsProvider();
Index: clang-tidy/ClangTidyOptions.h
===================================================================
--- clang-tidy/ClangTidyOptions.h
+++ clang-tidy/ClangTidyOptions.h
@@ -108,6 +108,8 @@
 
   /// \brief Add extra compilation arguments to the start of the list.
   llvm::Optional<ArgList> ExtraArgsBefore;
+
+  llvm::Optional<std::string> VfsOverlay;
 };
 
 /// \brief Abstract interface for retrieving various ClangTidy options.
Index: clang-tidy/ClangTidyOptions.cpp
===================================================================
--- clang-tidy/ClangTidyOptions.cpp
+++ clang-tidy/ClangTidyOptions.cpp
@@ -92,6 +92,7 @@
     IO.mapOptional("CheckOptions", NOpts->Options);
     IO.mapOptional("ExtraArgs", Options.ExtraArgs);
     IO.mapOptional("ExtraArgsBefore", Options.ExtraArgsBefore);
+    IO.mapOptional("VfsOverlay", Options.VfsOverlay);
   }
 };
 
@@ -152,6 +153,7 @@
   overrideValue(Result.User, Other.User);
   mergeVectors(Result.ExtraArgs, Other.ExtraArgs);
   mergeVectors(Result.ExtraArgsBefore, Other.ExtraArgsBefore);
+  overrideValue(Result.VfsOverlay, Other.VfsOverlay);
 
   for (const auto &KeyValue : Other.CheckOptions)
     Result.CheckOptions[KeyValue.first] = KeyValue.second;
Index: clang-tidy/ClangTidy.cpp
===================================================================
--- clang-tidy/ClangTidy.cpp
+++ clang-tidy/ClangTidy.cpp
@@ -87,17 +87,41 @@
   ClangTidyContext &Context;
 };
 
+void pushVfsOverlayFromFile(StringRef OverlayFile,
+                            vfs::OverlayFileSystem &OverlayFS) {
+  if (OverlayFile.empty())
+    return;
+
+  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buffer =
+      OverlayFS.getBufferForFile(OverlayFile);
+  if (!Buffer) {
+    return;
+  }
+
+  IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getVFSFromYAML(
+      std::move(Buffer.get()), /*DiagHandler*/ nullptr, OverlayFile);
+  if (!FS.get()) {
+    return;
+  }
+  OverlayFS.pushOverlay(FS);
+}
+
 class ErrorReporter {
 public:
   ErrorReporter(ClangTidyContext &Context, bool ApplyFixes)
-      : Files(FileSystemOptions()), DiagOpts(new DiagnosticOptions()),
+      : OverlayFS(new vfs::OverlayFileSystem(vfs::getRealFileSystem())),
+        Files(FileSystemOptions(), OverlayFS), DiagOpts(new DiagnosticOptions()),
         DiagPrinter(new TextDiagnosticPrinter(llvm::outs(), &*DiagOpts)),
         Diags(IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs), &*DiagOpts,
               DiagPrinter),
         SourceMgr(Diags, Files), Context(Context), ApplyFixes(ApplyFixes),
         TotalFixes(0), AppliedFixes(0), WarningsAsErrors(0) {
     DiagOpts->ShowColors = llvm::sys::Process::StandardOutHasColors();
     DiagPrinter->BeginSourceFile(LangOpts);
+
+    if (Context.getOptions().VfsOverlay) {
+      pushVfsOverlayFromFile(*Context.getOptions().VfsOverlay, *OverlayFS);
+    }
   }
 
   SourceManager &getSourceManager() { return SourceMgr; }
@@ -249,6 +273,7 @@
         << Message.Message;
   }
 
+  IntrusiveRefCntPtr<vfs::OverlayFileSystem> OverlayFS;
   FileManager Files;
   LangOptions LangOpts; // FIXME: use langopts from each original file
   IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
@@ -520,6 +545,10 @@
 
   Tool.setDiagnosticConsumer(&DiagConsumer);
 
+  if (Context.getOptions().VfsOverlay) {
+    pushVfsOverlayFromFile(*Context.getOptions().VfsOverlay, Tool.getOverlayFileSystem());
+  }
+
   class ActionFactory : public FrontendActionFactory {
   public:
     ActionFactory(ClangTidyContext &Context) : ConsumerFactory(Context) {}
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to