kadircet created this revision.
kadircet added reviewers: hokein, sammccall.
Herald added a subscriber: arphaman.
Herald added a project: All.
kadircet requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.
Herald added a project: clang-tools-extra.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D142890

Files:
  clang-tools-extra/clangd/Config.h
  clang-tools-extra/clangd/ConfigCompile.cpp
  clang-tools-extra/clangd/ConfigFragment.h
  clang-tools-extra/clangd/ConfigYAML.cpp
  clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp
  clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp
  clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp

Index: clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
+++ clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
@@ -538,7 +538,7 @@
     void foo() {}
   )cpp");
   Config Cfg;
-  Cfg.Diagnostics.UnusedIncludes = Config::Experiment;
+  Cfg.Diagnostics.UnusedIncludes = Config::UnusedIncludesPolicy::Experiment;
   WithContextValue Ctx(Config::Key, std::move(Cfg));
   ParsedAST AST = TU.build();
 
@@ -627,7 +627,7 @@
   TU.ExtraArgs.emplace_back("-xobjective-c");
 
   Config Cfg;
-  Cfg.Diagnostics.UnusedIncludes = Config::Strict;
+  Cfg.Diagnostics.UnusedIncludes = Config::UnusedIncludesPolicy::Strict;
   WithContextValue Ctx(Config::Key, std::move(Cfg));
   ParsedAST AST = TU.build();
   EXPECT_THAT(AST.getDiagnostics(), llvm::ValueIs(IsEmpty()));
Index: clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp
+++ clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp
@@ -273,6 +273,31 @@
   EXPECT_THAT(Results[0].Style.FullyQualifiedNamespaces,
               ElementsAre(val("foo"), val("bar")));
 }
+
+TEST(ParseYAML, DiagnosticsMode) {
+  CapturedDiags Diags;
+  {
+    Annotations YAML(R"yaml(
+Diagnostics:
+  Mode: Fast)yaml");
+    auto Results =
+        Fragment::parseYAML(YAML.code(), "config.yaml", Diags.callback());
+    ASSERT_THAT(Diags.Diagnostics, IsEmpty());
+    ASSERT_EQ(Results.size(), 1u);
+    EXPECT_THAT(Results[0].Diagnostics.Mode, llvm::ValueIs(val("Fast")));
+  }
+
+  {
+    Annotations YAML(R"yaml(
+Diagnostics:
+  Mode: Strict)yaml");
+    auto Results =
+        Fragment::parseYAML(YAML.code(), "config.yaml", Diags.callback());
+    ASSERT_THAT(Diags.Diagnostics, IsEmpty());
+    ASSERT_EQ(Results.size(), 1u);
+    EXPECT_THAT(Results[0].Diagnostics.Mode, llvm::ValueIs(val("Strict")));
+  }
+}
 } // namespace
 } // namespace config
 } // namespace clangd
Index: clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp
+++ clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp
@@ -543,6 +543,23 @@
   EXPECT_TRUE(compileAndApply());
   EXPECT_THAT(Conf.Style.FullyQualifiedNamespaces, ElementsAre("foo", "bar"));
 }
+
+TEST_F(ConfigCompileTests, DiagnosticsMode) {
+  Frag = {};
+  EXPECT_TRUE(compileAndApply());
+  // Defaults to Strict.
+  EXPECT_EQ(Conf.Diagnostics.Mode, Config::DiagnosticsMode::Strict);
+
+  Frag.Diagnostics.Mode.emplace("Fast");
+  EXPECT_TRUE(compileAndApply());
+  // Defaults to Strict.
+  EXPECT_EQ(Conf.Diagnostics.Mode, Config::DiagnosticsMode::Fast);
+
+  Frag.Diagnostics.Mode.emplace("Strict");
+  EXPECT_TRUE(compileAndApply());
+  // Defaults to Strict.
+  EXPECT_EQ(Conf.Diagnostics.Mode, Config::DiagnosticsMode::Strict);
+}
 } // namespace
 } // namespace config
 } // namespace clangd
Index: clang-tools-extra/clangd/ConfigYAML.cpp
===================================================================
--- clang-tools-extra/clangd/ConfigYAML.cpp
+++ clang-tools-extra/clangd/ConfigYAML.cpp
@@ -130,6 +130,7 @@
     });
     Dict.handle("Includes", [&](Node &N) { parse(F.Includes, N); });
     Dict.handle("ClangTidy", [&](Node &N) { parse(F.ClangTidy, N); });
+    Dict.handle("Mode", [&](Node &N) { F.Mode = scalarValue(N, "Mode"); });
     Dict.parse(N);
   }
 
@@ -268,7 +269,7 @@
     // If Key is seen twice, Parse runs only once and an error is reported.
     void handle(llvm::StringLiteral Key, std::function<void(Node &)> Parse) {
       for (const auto &Entry : Keys) {
-        (void) Entry;
+        (void)Entry;
         assert(Entry.first != Key && "duplicate key handler");
       }
       Keys.emplace_back(Key, std::move(Parse));
Index: clang-tools-extra/clangd/ConfigFragment.h
===================================================================
--- clang-tools-extra/clangd/ConfigFragment.h
+++ clang-tools-extra/clangd/ConfigFragment.h
@@ -232,9 +232,16 @@
     ///
     /// Valid values are:
     /// - Strict
+    /// - Experiment
     /// - None
     std::optional<Located<std::string>> UnusedIncludes;
 
+    /// Controls whether clangd should emit fast but loose diagnostics.
+    /// Valid values are:
+    /// - Fast
+    /// - Strict
+    std::optional<Located<std::string>> Mode;
+
     /// Controls IncludeCleaner diagnostics.
     struct IncludesBlock {
       /// Regexes that will be used to avoid diagnosing certain includes as
Index: clang-tools-extra/clangd/ConfigCompile.cpp
===================================================================
--- clang-tools-extra/clangd/ConfigCompile.cpp
+++ clang-tools-extra/clangd/ConfigCompile.cpp
@@ -441,8 +441,16 @@
         Out.Apply.push_back([Val](const Params &, Config &C) {
           C.Diagnostics.UnusedIncludes = *Val;
         });
-    compile(std::move(F.Includes));
+    if (F.Mode) {
+      if (auto Val = compileEnum<Config::DiagnosticsMode>("Mode", **F.Mode)
+                         .map("Strict", Config::DiagnosticsMode::Strict)
+                         .map("Fast", Config::DiagnosticsMode::Fast)
+                         .value())
+        Out.Apply.push_back(
+            [Val](const Params &, Config &C) { C.Diagnostics.Mode = *Val; });
+    }
 
+    compile(std::move(F.Includes));
     compile(std::move(F.ClangTidy));
   }
 
Index: clang-tools-extra/clangd/Config.h
===================================================================
--- clang-tools-extra/clangd/Config.h
+++ clang-tools-extra/clangd/Config.h
@@ -88,13 +88,21 @@
     bool StandardLibrary = true;
   } Index;
 
-  enum UnusedIncludesPolicy {
+  enum class UnusedIncludesPolicy {
     /// Diagnose unused includes.
     Strict,
     None,
     /// The same as Strict, but using the include-cleaner library.
     Experiment,
   };
+  /// Configures whether clangd can emit fast but possibly inaccurate
+  /// diagnostics.
+  enum class DiagnosticsMode {
+    /// Only emit diagnostics with up-to-date analysis.
+    Strict,
+    /// Can emit diagnostics with stale analysis.
+    Fast,
+  };
   /// Controls warnings and errors when parsing code.
   struct {
     bool SuppressAll = false;
@@ -107,7 +115,9 @@
       llvm::StringMap<std::string> CheckOptions;
     } ClangTidy;
 
-    UnusedIncludesPolicy UnusedIncludes = None;
+    UnusedIncludesPolicy UnusedIncludes = UnusedIncludesPolicy::None;
+
+    DiagnosticsMode Mode = DiagnosticsMode::Strict;
 
     /// IncludeCleaner will not diagnose usages of these headers matched by
     /// these regexes.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to