hokein created this revision.
Herald added subscribers: cfe-commits, usaxena95, kadircet, arphaman, jkorous.
Herald added a project: clang.
hokein requested review of this revision.
Herald added subscribers: MaskRay, ilya-biryukov.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D85635

Files:
  clang-tools-extra/clangd/SemanticHighlighting.cpp
  clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp

Index: clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
+++ clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
@@ -79,7 +79,8 @@
 ///     $Primitive[[int]] $Field[[a]] = 0;
 ///   };
 std::string annotate(llvm::StringRef Input,
-                     llvm::ArrayRef<HighlightingToken> Tokens) {
+                     llvm::ArrayRef<HighlightingToken> Tokens,
+                     size_t NextChar = 0) {
   assert(std::is_sorted(
       Tokens.begin(), Tokens.end(),
       [](const HighlightingToken &L, const HighlightingToken &R) {
@@ -87,18 +88,36 @@
       }));
 
   std::string Result;
-  unsigned NextChar = 0;
-  for (auto &T : Tokens) {
-    unsigned StartOffset = llvm::cantFail(positionToOffset(Input, T.R.start));
-    unsigned EndOffset = llvm::cantFail(positionToOffset(Input, T.R.end));
+  for (size_t I = 0; I < Tokens.size(); ++I) {
+    const auto &Current = Tokens[I];
+    unsigned StartOffset =
+        llvm::cantFail(positionToOffset(Input, Current.R.start));
+    assert(NextChar <= StartOffset && "Highlighting tokens must not overlap!");
+    unsigned EndOffset = llvm::cantFail(positionToOffset(Input, Current.R.end));
     assert(StartOffset <= EndOffset);
-    assert(NextChar <= StartOffset);
-
+    const auto *End =
+        llvm::find_if(llvm::makeArrayRef(Tokens.begin() + I + 1, Tokens.end()),
+                      [&](const HighlightingToken &Next) {
+                        return Current.R.end <= Next.R.start;
+                      });
+    // Tokens whose ranges are contained by the Current range, we recursively
+    // annotate them.
+    auto ContainedTokens = llvm::makeArrayRef(Tokens.begin() + I + 1, End);
     Result += Input.substr(NextChar, StartOffset - NextChar);
-    Result += std::string(
-        llvm::formatv("${0}[[{1}]]", T.Kind,
-                      Input.substr(StartOffset, EndOffset - StartOffset)));
+    if (ContainedTokens.empty()) {
+      // No extra tokens contained by Current.
+      Result +=
+          llvm::formatv("${0}[[{1}]]", Current.Kind,
+                        Input.substr(StartOffset, EndOffset - StartOffset));
+      NextChar = EndOffset;
+      continue;
+    }
+
+    auto Annotated =
+        annotate(Input.substr(0, EndOffset), ContainedTokens, StartOffset);
+    Result += llvm::formatv("${0}[[{1}]]", Current.Kind, Annotated);
     NextChar = EndOffset;
+    I += ContainedTokens.size();
   }
   Result += Input.substr(NextChar);
   return Result;
@@ -503,11 +522,11 @@
 
       #define $Macro[[test]]
       #undef $Macro[[test]]
-$InactiveCode[[]]      #ifdef $Macro[[test]]
-$InactiveCode[[]]      #endif
+$InactiveCode[[#ifdef $Macro[[test]]]]
+$InactiveCode[[#endif]]
 
-$InactiveCode[[]]      #if defined($Macro[[test]])
-$InactiveCode[[]]      #endif
+$InactiveCode[[#if defined($Macro[[test]])]]
+$InactiveCode[[#endif]]
     )cpp",
       R"cpp(
       struct $Class[[S]] {
@@ -614,8 +633,8 @@
       R"cpp(
       // Code in the preamble.
       // Inactive lines get an empty InactiveCode token at the beginning.
-$InactiveCode[[]]      #ifdef $Macro[[test]]
-$InactiveCode[[]]      #endif
+$InactiveCode[[#ifdef $Macro[[test]]]]
+$InactiveCode[[#endif]]
 
       // A declaration to cause the preamble to end.
       int $Variable[[EndPreamble]];
@@ -623,17 +642,17 @@
       // Code after the preamble.
       // Code inside inactive blocks does not get regular highlightings
       // because it's not part of the AST.
-$InactiveCode[[]]      #ifdef $Macro[[test]]
-$InactiveCode[[]]      int Inactive2;
-$InactiveCode[[]]      #endif
+$InactiveCode[[#ifdef $Macro[[test]]]]
+$InactiveCode[[int Inactive2;]]
+$InactiveCode[[#endif]]
 
       #ifndef $Macro[[test]]
       int $Variable[[Active1]];
       #endif
 
-$InactiveCode[[]]      #ifdef $Macro[[test]]
-$InactiveCode[[]]      int Inactive3;
-$InactiveCode[[]]      #else
+$InactiveCode[[#ifdef $Macro[[test]]]]
+$InactiveCode[[int Inactive3;]]
+$InactiveCode[[#else]]
       int $Variable[[Active2]];
       #endif
     )cpp",
Index: clang-tools-extra/clangd/SemanticHighlighting.cpp
===================================================================
--- clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -221,18 +221,27 @@
       // the end of the Tokens).
       TokRef = TokRef.drop_front(Conflicting.size());
     }
+    const auto &SM = AST.getSourceManager();
+    StringRef MainCode = SM.getBuffer(SM.getMainFileID())->getBuffer();
     // Add tokens indicating lines skipped by the preprocessor.
     for (const Range &R : AST.getMacros().SkippedRanges) {
       // Create one token for each line in the skipped range, so it works
       // with line-based diffing.
       assert(R.start.line <= R.end.line);
       for (int Line = R.start.line; Line <= R.end.line; ++Line) {
-        // Don't bother computing the offset for the end of the line, just use
-        // zero. The client will treat this highlighting kind specially, and
-        // highlight the entire line visually (i.e. not just to where the text
-        // on the line ends, but to the end of the screen).
-        NonConflicting.push_back({HighlightingKind::InactiveCode,
-                                  {Position{Line, 0}, Position{Line, 0}}});
+        auto StartOfLine = positionToOffset(MainCode, Position{Line, 0});
+        if (!StartOfLine) {
+          elog("Failed to convert position to offset: {0}",
+               StartOfLine.takeError());
+          continue;
+        }
+        size_t LineLength = MainCode.substr(*StartOfLine).find('\n');
+        size_t EndOfLine = LineLength == llvm::StringRef::npos
+                               ? MainCode.size() - 1 // EOF
+                               : *StartOfLine + LineLength;
+        NonConflicting.push_back(
+            {HighlightingKind::InactiveCode,
+             {Position{Line, 0}, offsetToPosition(MainCode, EndOfLine)}});
       }
     }
     // Re-sort the tokens because that's what the diffing expects.
@@ -493,9 +502,6 @@
   std::vector<SemanticToken> Result;
   const HighlightingToken *Last = nullptr;
   for (const HighlightingToken &Tok : Tokens) {
-    // FIXME: support inactive code - we need to provide the actual bounds.
-    if (Tok.Kind == HighlightingKind::InactiveCode)
-      continue;
     Result.emplace_back();
     SemanticToken &Out = Result.back();
     // deltaStart/deltaLine are relative if possible.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D85635: [clangd] Comp... Haojian Wu via Phabricator via cfe-commits

Reply via email to