[clang-tools-extra] 3b4936b - [clangd] Add --check-lines to restrict --check to specific lines

Adam Czachorowski via cfe-commits cfe-commits at lists.llvm.org
Fri Apr 9 04:53:37 PDT 2021


Author: Adam Czachorowski
Date: 2021-04-09T13:47:20+02:00
New Revision: 3b4936ba290594cda4e53169958fe11c83119657

URL: https://github.com/llvm/llvm-project/commit/3b4936ba290594cda4e53169958fe11c83119657
DIFF: https://github.com/llvm/llvm-project/commit/3b4936ba290594cda4e53169958fe11c83119657.diff

LOG: [clangd] Add --check-lines to restrict --check to specific lines

This will allow us to add code completion, which is too expensive at
every token, to --check too.

Differential Revision: https://reviews.llvm.org/D98970

Added: 
    clang-tools-extra/clangd/test/check-lines.test

Modified: 
    clang-tools-extra/clangd/tool/Check.cpp
    clang-tools-extra/clangd/tool/ClangdMain.cpp

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clangd/test/check-lines.test b/clang-tools-extra/clangd/test/check-lines.test
new file mode 100644
index 000000000000..bfd30dd6104f
--- /dev/null
+++ b/clang-tools-extra/clangd/test/check-lines.test
@@ -0,0 +1,15 @@
+// RUN: cp %s %t.cpp
+// RUN: not clangd -check=%t.cpp -check-lines=6-14 2>&1 | FileCheck -strict-whitespace %s
+// RUN: not clangd -check=%t.cpp -check-lines=14 2>&1 | FileCheck -strict-whitespace %s
+
+// CHECK: Testing on source file {{.*}}check-lines.test
+// CHECK: internal (cc1) args are: -cc1
+// CHECK: Building preamble...
+// CHECK: Building AST...
+// CHECK: Testing features at each token
+// CHECK: tweak: ExpandAutoType ==> FAIL
+// CHECK: All checks completed, 1 errors
+
+void fun();
+auto x = fun; // This line is tested
+auto y = fun; // This line is not tested

diff  --git a/clang-tools-extra/clangd/tool/Check.cpp b/clang-tools-extra/clangd/tool/Check.cpp
index 20b86daff8af..0138ae3eb13b 100644
--- a/clang-tools-extra/clangd/tool/Check.cpp
+++ b/clang-tools-extra/clangd/tool/Check.cpp
@@ -192,14 +192,19 @@ class Checker {
   }
 
   // Run AST-based features at each token in the file.
-  void testLocationFeatures() {
+  void testLocationFeatures(
+      llvm::function_ref<bool(const Position &)> ShouldCheckLine) {
     log("Testing features at each token (may be slow in large files)");
-    auto SpelledTokens =
-        AST->getTokens().spelledTokens(AST->getSourceManager().getMainFileID());
+    auto &SM = AST->getSourceManager();
+    auto SpelledTokens = AST->getTokens().spelledTokens(SM.getMainFileID());
     for (const auto &Tok : SpelledTokens) {
       unsigned Start = AST->getSourceManager().getFileOffset(Tok.location());
       unsigned End = Start + Tok.length();
       Position Pos = offsetToPosition(Inputs.Contents, Start);
+
+      if (!ShouldCheckLine(Pos))
+        continue;
+
       // FIXME: dumping the tokens may leak sensitive code into bug reports.
       // Add an option to turn this off, once we decide how options work.
       vlog("  {0} {1}", Pos, Tok.text(AST->getSourceManager()));
@@ -229,8 +234,9 @@ class Checker {
 
 } // namespace
 
-bool check(llvm::StringRef File, const ThreadsafeFS &TFS,
-           const ClangdLSPServer::Options &Opts) {
+bool check(llvm::StringRef File,
+           llvm::function_ref<bool(const Position &)> ShouldCheckLine,
+           const ThreadsafeFS &TFS, const ClangdLSPServer::Options &Opts) {
   llvm::SmallString<0> FakeFile;
   llvm::Optional<std::string> Contents;
   if (File.empty()) {
@@ -254,7 +260,7 @@ bool check(llvm::StringRef File, const ThreadsafeFS &TFS,
   if (!C.buildCommand(TFS) || !C.buildInvocation(TFS, Contents) ||
       !C.buildAST())
     return false;
-  C.testLocationFeatures();
+  C.testLocationFeatures(ShouldCheckLine);
 
   log("All checks completed, {0} errors", C.ErrCount);
   return C.ErrCount == 0;

diff  --git a/clang-tools-extra/clangd/tool/ClangdMain.cpp b/clang-tools-extra/clangd/tool/ClangdMain.cpp
index c48821cba2c7..6dd13a503887 100644
--- a/clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ b/clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -60,8 +60,9 @@ namespace clang {
 namespace clangd {
 
 // Implemented in Check.cpp.
-bool check(const llvm::StringRef File, const ThreadsafeFS &TFS,
-           const ClangdLSPServer::Options &Opts);
+bool check(const llvm::StringRef File,
+           llvm::function_ref<bool(const Position &)> ShouldCheckLine,
+           const ThreadsafeFS &TFS, const ClangdLSPServer::Options &Opts);
 
 namespace {
 
@@ -347,6 +348,17 @@ opt<Path> CheckFile{
     ValueOptional,
 };
 
+opt<std::string> CheckFileLines{
+    "check-lines",
+    cat(Misc),
+    desc("If specified, limits the range of tokens in -check file on which "
+         "various features are tested. Example --check-lines=3-7 restricts "
+         "testing to lines 3 to 7 (inclusive) or --check-lines=5 to restrict "
+         "to one line. Default is testing entire file."),
+    init(""),
+    ValueOptional,
+};
+
 enum PCHStorageFlag { Disk, Memory };
 opt<PCHStorageFlag> PCHStorage{
     "pch-storage",
@@ -883,10 +895,33 @@ clangd accepts flags on the commandline, and in the CLANGD_FLAGS environment var
     llvm::SmallString<256> Path;
     llvm::sys::fs::real_path(CheckFile, Path, /*expand_tilde=*/true);
     log("Entering check mode (no LSP server)");
-    return check(Path, TFS, Opts)
+    uint32_t Begin = 0, End = std::numeric_limits<uint32_t>::max();
+    if (!CheckFileLines.empty()) {
+      StringRef RangeStr(CheckFileLines);
+      bool ParseError = RangeStr.consumeInteger(0, Begin);
+      if (RangeStr.empty()) {
+        End = Begin;
+      } else {
+        ParseError |= !RangeStr.consume_front("-");
+        ParseError |= RangeStr.consumeInteger(0, End);
+      }
+      if (ParseError || !RangeStr.empty()) {
+        elog("Invalid --check-line specified. Use Begin-End format, e.g. 3-17");
+        return 1;
+      }
+    }
+    auto ShouldCheckLine = [&](const Position &Pos) {
+      uint32_t Line = Pos.line + 1; // Position::line is 0-based.
+      return Line >= Begin && Line <= End;
+    };
+    return check(Path, ShouldCheckLine, TFS, Opts)
                ? 0
                : static_cast<int>(ErrorResultCode::CheckFailed);
   }
+  if (!CheckFileLines.empty()) {
+    elog("--check-lines requires --check");
+    return 1;
+  }
 
   // Initialize and run ClangdLSPServer.
   // Change stdin to binary to not lose \r\n on windows.


        


More information about the cfe-commits mailing list