summarylogtreecommitdiffstats
path: root/resolve-incomplete-header-includes.patch
blob: fc0d8d3c36f79d7211da69a9a6ec9dc3926dd70e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
diff --git a/clang-tools-extra/clangd/TUScheduler.cpp b/clang-tools-extra/clangd/TUScheduler.cpp
index 324ba1fc8cb8..21bd4308975d 100644
--- a/clang-tools-extra/clangd/TUScheduler.cpp
+++ b/clang-tools-extra/clangd/TUScheduler.cpp
@@ -52,6 +52,7 @@
 #include "Config.h"
 #include "Diagnostics.h"
 #include "GlobalCompilationDatabase.h"
+#include "HeaderSourceSwitch.h"
 #include "ParsedAST.h"
 #include "Preamble.h"
 #include "clang-include-cleaner/Record.h"
@@ -64,6 +65,7 @@
 #include "support/Threading.h"
 #include "support/Trace.h"
 #include "clang/Basic/Stack.h"
+#include "clang/Driver/Driver.h"
 #include "clang/Frontend/CompilerInvocation.h"
 #include "clang/Tooling/CompilationDatabase.h"
 #include "llvm/ADT/FunctionExtras.h"
@@ -622,7 +624,8 @@ public:
          const TUScheduler::Options &Opts, ParsingCallbacks &Callbacks);
   ~ASTWorker();
 
-  void update(ParseInputs Inputs, WantDiagnostics, bool ContentChanged);
+  void update(ParseInputs Inputs, WantDiagnostics, bool ContentChanged,
+              std::optional<std::vector<std::string>> SourceInclides);
   void
   runWithAST(llvm::StringRef Name,
              llvm::unique_function<void(llvm::Expected<InputsAndAST>)> Action,
@@ -857,7 +860,8 @@ ASTWorker::~ASTWorker() {
 }
 
 void ASTWorker::update(ParseInputs Inputs, WantDiagnostics WantDiags,
-                       bool ContentChanged) {
+                       bool ContentChanged,
+                       std::optional<std::vector<std::string>> SourceInclides) {
   llvm::StringLiteral TaskName = "Update";
   auto Task = [=]() mutable {
     // Get the actual command as `Inputs` does not have a command.
@@ -881,10 +885,24 @@ void ASTWorker::update(ParseInputs Inputs, WantDiagnostics WantDiags,
         }
       }
     }
-    if (Cmd)
+    if (!Cmd)
+      Cmd = CDB.getFallbackCommand(FileName);
+    if (Cmd) {
+      if (SourceInclides && !SourceInclides->empty()) {
+        Cmd->CommandLine.reserve(Cmd->CommandLine.size() +
+                                 SourceInclides->size());
+        auto PosArg =
+            std::find(Cmd->CommandLine.begin(), Cmd->CommandLine.end(), "--");
+        auto UsePushBack = PosArg == Cmd->CommandLine.end();
+        for (auto &&Arg : *SourceInclides) {
+          if (UsePushBack)
+            Cmd->CommandLine.push_back(std::move(Arg));
+          else
+            PosArg = std::next(Cmd->CommandLine.insert(PosArg, std::move(Arg)));
+        }
+      }
       Inputs.CompileCommand = std::move(*Cmd);
-    else
-      Inputs.CompileCommand = CDB.getFallbackCommand(FileName);
+    }
 
     bool InputsAreTheSame =
         std::tie(FileInputs.CompileCommand, FileInputs.Contents) ==
@@ -1684,7 +1702,39 @@ bool TUScheduler::update(PathRef File, ParseInputs Inputs,
     ContentChanged = true;
     FD->Contents = Inputs.Contents;
   }
-  FD->Worker->update(std::move(Inputs), WantDiags, ContentChanged);
+  std::optional<std::vector<std::string>> SourceInclides;
+  if (isHeaderFile(File)) {
+    std::string SourceFile;
+    auto VFS = Inputs.TFS->view(Inputs.CompileCommand.Directory);
+    if (auto CorrespondingFile =
+            clang::clangd::getCorrespondingHeaderOrSource(File, std::move(VFS)))
+      SourceFile = *CorrespondingFile;
+    if (SourceFile.empty()) // fallback to find pair source
+      SourceFile = HeaderIncluders->get(File);
+    if (!SourceFile.empty() && Files.contains(SourceFile)) {
+      std::unique_ptr<FileData> &FD = Files[SourceFile];
+      if (FD && FD->Worker->isASTCached()) {
+        if (auto AST = IdleASTs->take(FD->Worker.lock().get())) {
+          auto &Headers = AST.value()->getIncludeStructure().MainFileIncludes;
+          std::vector<std::string> Includes;
+          Includes.reserve(Headers.size());
+          for (const auto &H : Headers) {
+            if (H.Resolved == File) {
+              if (isSystem(H.FileKind))
+                Includes.clear();
+              else
+                SourceInclides = std::move(Includes);
+              break;
+            }
+            auto Include = "-include" + H.Resolved;
+            Includes.push_back(std::move(Include));
+          }
+          IdleASTs->put(FD->Worker.lock().get(), std::move(AST.value()));
+        }
+      }
+    }
+  }
+  FD->Worker->update(std::move(Inputs), WantDiags, ContentChanged, SourceInclides);
   // There might be synthetic update requests, don't change the LastActiveFile
   // in such cases.
   if (ContentChanged)