nridge updated this revision to Diff 229707.
nridge added a comment.
Support preamble as well
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D67536/new/
https://reviews.llvm.org/D67536
Files:
clang-tools-extra/clangd/CollectMacros.h
clang-tools-extra/clangd/ParsedAST.h
clang-tools-extra/clangd/Protocol.cpp
clang-tools-extra/clangd/Protocol.h
clang-tools-extra/clangd/SemanticHighlighting.cpp
clang-tools-extra/clangd/SemanticHighlighting.h
clang-tools-extra/clangd/test/semantic-highlighting.test
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
@@ -140,7 +140,7 @@
}
for (auto &LineTokens : ExpectedLines)
ExpectedLinePairHighlighting.push_back(
- {LineTokens.first, LineTokens.second});
+ {LineTokens.first, LineTokens.second, /*IsInactive = */ false});
std::vector<LineHighlightings> ActualDiffed =
diffHighlightings(NewTokens, OldTokens);
@@ -493,11 +493,11 @@
#define $Macro[[test]]
#undef $Macro[[test]]
- #ifdef $Macro[[test]]
- #endif
+$InactiveCode[[]] #ifdef $Macro[[test]]
+$InactiveCode[[]] #endif
- #if defined($Macro[[test]])
- #endif
+$InactiveCode[[]] #if defined($Macro[[test]])
+$InactiveCode[[]] #endif
)cpp",
R"cpp(
struct $Class[[S]] {
@@ -589,6 +589,33 @@
R"cpp(
void $Function[[foo]]();
using ::$Function[[foo]];
+ )cpp",
+ // Inactive code highlighting
+ R"cpp(
+ // Code in the preamble.
+ // Inactive lines get an empty InactiveCode token at the beginning.
+$InactiveCode[[]] #ifdef $Macro[[test]]
+$InactiveCode[[]] #endif
+
+ // A declaration to cause the preamble to end.
+ int $Variable[[EndPreamble]];
+
+ // 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
+
+ #ifndef $Macro[[test]]
+ int $Variable[[Active1]];
+ #endif
+
+$InactiveCode[[]] #ifdef $Macro[[test]]
+$InactiveCode[[]] int Inactive3;
+$InactiveCode[[]] #else
+ int $Variable[[Active2]];
+ #endif
)cpp"};
for (const auto &TestCase : TestCases) {
checkHighlightings(TestCase);
@@ -656,10 +683,12 @@
{{HighlightingKind::Variable,
Range{CreatePosition(3, 8), CreatePosition(3, 12)}},
{HighlightingKind::Function,
- Range{CreatePosition(3, 4), CreatePosition(3, 7)}}}},
+ Range{CreatePosition(3, 4), CreatePosition(3, 7)}}},
+ /* IsInactive = */ false},
{1,
{{HighlightingKind::Variable,
- Range{CreatePosition(1, 1), CreatePosition(1, 5)}}}}};
+ Range{CreatePosition(1, 1), CreatePosition(1, 5)}}},
+ /* IsInactive = */ true}};
std::vector<SemanticHighlightingInformation> ActualResults =
toSemanticHighlightingInformation(Tokens);
std::vector<SemanticHighlightingInformation> ExpectedResults = {
Index: clang-tools-extra/clangd/test/semantic-highlighting.test
===================================================================
--- clang-tools-extra/clangd/test/semantic-highlighting.test
+++ clang-tools-extra/clangd/test/semantic-highlighting.test
@@ -57,6 +57,9 @@
# CHECK-NEXT: ],
# CHECK-NEXT: [
# CHECK-NEXT: "entity.name.function.preprocessor.cpp"
+# CHECK-NEXT: ],
+# CHECK-NEXT: [
+# CHECK-NEXT: "meta.disabled"
# CHECK-NEXT: ]
# CHECK-NEXT: ]
# CHECK-NEXT: },
@@ -66,6 +69,7 @@
# CHECK-NEXT: "params": {
# CHECK-NEXT: "lines": [
# CHECK-NEXT: {
+# CHECK-NEXT: "isInactive": false,
# CHECK-NEXT: "line": 0,
# CHECK-NEXT: "tokens": "AAAABAABAAA="
# CHECK-NEXT: }
@@ -81,10 +85,12 @@
# CHECK-NEXT: "params": {
# CHECK-NEXT: "lines": [
# CHECK-NEXT: {
+# CHECK-NEXT: "isInactive": false,
# CHECK-NEXT: "line": 0,
# CHECK-NEXT: "tokens": "AAAABAABAAA="
# CHECK-NEXT: }
# CHECK-NEXT: {
+# CHECK-NEXT: "isInactive": false,
# CHECK-NEXT: "line": 1,
# CHECK-NEXT: "tokens": "AAAABAABAAA="
# CHECK-NEXT: }
@@ -100,6 +106,7 @@
# CHECK-NEXT: "params": {
# CHECK-NEXT: "lines": [
# CHECK-NEXT: {
+# CHECK-NEXT: "isInactive": false,
# CHECK-NEXT: "line": 1,
# CHECK-NEXT: "tokens": "AAAABAABAAA="
# CHECK-NEXT: }
@@ -115,6 +122,7 @@
# CHECK-NEXT: "params": {
# CHECK-NEXT: "lines": [
# CHECK-NEXT: {
+# CHECK-NEXT: "isInactive": false,
# CHECK-NEXT: "line": 1,
# CHECK-NEXT: "tokens": ""
# CHECK-NEXT: }
Index: clang-tools-extra/clangd/SemanticHighlighting.h
===================================================================
--- clang-tools-extra/clangd/SemanticHighlighting.h
+++ clang-tools-extra/clangd/SemanticHighlighting.h
@@ -44,7 +44,11 @@
Primitive,
Macro,
- LastKind = Macro
+ // This one is different from the other kinds as it's a line style
+ // rather than a token style.
+ InactiveCode,
+
+ LastKind = InactiveCode
};
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, HighlightingKind K);
@@ -61,6 +65,7 @@
struct LineHighlightings {
int Line;
std::vector<HighlightingToken> Tokens;
+ bool IsInactive;
};
bool operator==(const LineHighlightings &L, const LineHighlightings &R);
Index: clang-tools-extra/clangd/SemanticHighlighting.cpp
===================================================================
--- clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -158,6 +158,22 @@
// the end of the Tokens).
TokRef = TokRef.drop_front(Conflicting.size());
}
+ // 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}}});
+ }
+ }
+ // Re-sort the tokens because that's what the diffing expects.
+ llvm::sort(NonConflicting);
return NonConflicting;
}
@@ -405,6 +421,8 @@
return OS << "Primitive";
case HighlightingKind::Macro:
return OS << "Macro";
+ case HighlightingKind::InactiveCode:
+ return OS << "InactiveCode";
}
llvm_unreachable("invalid HighlightingKind");
}
@@ -449,8 +467,24 @@
LineNumber = NextLineNumber()) {
NewLine = takeLine(New, NewLine.end(), LineNumber);
OldLine = takeLine(Old, OldLine.end(), LineNumber);
- if (NewLine != OldLine)
- DiffedLines.push_back({LineNumber, NewLine});
+ if (NewLine != OldLine) {
+ DiffedLines.push_back({LineNumber, NewLine, /*IsInactive=*/false});
+
+ // Turn a HighlightingKind::InactiveCode token into the IsInactive flag.
+ // We do this by iterating over the tokens in the line, and if we find
+ // one with kind InactiveCode, removing that token and setting the
+ // IsInactive flag on the line instead.
+ auto &AddedLine = DiffedLines.back();
+ for (auto Iter = AddedLine.Tokens.begin();
+ Iter != AddedLine.Tokens.end();) {
+ if (Iter->Kind == HighlightingKind::InactiveCode) {
+ Iter = AddedLine.Tokens.erase(Iter);
+ AddedLine.IsInactive = true;
+ } else {
+ ++Iter;
+ }
+ }
+ }
}
return DiffedLines;
@@ -493,7 +527,7 @@
write16be(static_cast<int>(Token.Kind), OS);
}
- Lines.push_back({Line.Line, encodeBase64(LineByteTokens)});
+ Lines.push_back({Line.Line, encodeBase64(LineByteTokens), Line.IsInactive});
}
return Lines;
@@ -538,6 +572,8 @@
return "storage.type.primitive.cpp";
case HighlightingKind::Macro:
return "entity.name.function.preprocessor.cpp";
+ case HighlightingKind::InactiveCode:
+ return "meta.disabled";
}
llvm_unreachable("unhandled HighlightingKind");
}
Index: clang-tools-extra/clangd/Protocol.h
===================================================================
--- clang-tools-extra/clangd/Protocol.h
+++ clang-tools-extra/clangd/Protocol.h
@@ -1209,6 +1209,9 @@
int Line = 0;
/// The base64 encoded string of highlighting tokens.
std::string Tokens;
+ /// Is the line in an inactive preprocessor branch?
+ /// This is a clangd extension.
+ bool IsInactive = false;
};
bool operator==(const SemanticHighlightingInformation &Lhs,
const SemanticHighlightingInformation &Rhs);
Index: clang-tools-extra/clangd/Protocol.cpp
===================================================================
--- clang-tools-extra/clangd/Protocol.cpp
+++ clang-tools-extra/clangd/Protocol.cpp
@@ -1063,7 +1063,8 @@
llvm::json::Value toJSON(const SemanticHighlightingInformation &Highlighting) {
return llvm::json::Object{{"line", Highlighting.Line},
- {"tokens", Highlighting.Tokens}};
+ {"tokens", Highlighting.Tokens},
+ {"isInactive", Highlighting.IsInactive}};
}
llvm::json::Value toJSON(const SemanticHighlightingParams &Highlighting) {
Index: clang-tools-extra/clangd/ParsedAST.h
===================================================================
--- clang-tools-extra/clangd/ParsedAST.h
+++ clang-tools-extra/clangd/ParsedAST.h
@@ -130,6 +130,8 @@
std::vector<Decl *> LocalTopLevelDecls;
IncludeStructure Includes;
CanonicalIncludes CanonIncludes;
+ // Ranges skipped during preprocessing.
+ std::vector<SourceRange> SkippedRanges;
};
/// Build an AST from provided user inputs. This function does not check if
Index: clang-tools-extra/clangd/CollectMacros.h
===================================================================
--- clang-tools-extra/clangd/CollectMacros.h
+++ clang-tools-extra/clangd/CollectMacros.h
@@ -23,6 +23,8 @@
// Instead of storing SourceLocation, we have to store the token range because
// SourceManager from preamble is not available when we build the AST.
std::vector<Range> Ranges;
+ // Ranges skipped by the preprocessor due to being inactive.
+ std::vector<Range> SkippedRanges;
};
/// Collects macro references (e.g. definitions, expansions) in the main file.
@@ -71,6 +73,14 @@
add(MacroName, MD.getMacroInfo());
}
+ void SourceRangeSkipped(SourceRange R, SourceLocation EndifLoc) override {
+ if (!InMainFile)
+ return;
+ Position Begin = sourceLocToPosition(SM, R.getBegin());
+ Position End = sourceLocToPosition(SM, R.getEnd());
+ Out.SkippedRanges.push_back(Range{Begin, End});
+ }
+
private:
void add(const Token &MacroNameTok, const MacroInfo *MI) {
if (!InMainFile)
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits