[PATCH] D66995: [clangd] Add highlighting for macro expansions.

2019-08-30 Thread Johan Vikström via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL370482: [clangd] Add highlighting for macro expansions. 
(authored by jvikstrom, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D66995?vs=218089=218112#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66995/new/

https://reviews.llvm.org/D66995

Files:
  clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
  clang-tools-extra/trunk/clangd/SemanticHighlighting.h
  clang-tools-extra/trunk/clangd/test/semantic-highlighting.test
  clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp

Index: clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
@@ -24,16 +24,20 @@
 class HighlightingTokenCollector
 : public RecursiveASTVisitor {
   std::vector Tokens;
-  ASTContext 
-  const SourceManager 
+  ParsedAST 
 
 public:
-  HighlightingTokenCollector(ParsedAST )
-  : Ctx(AST.getASTContext()), SM(AST.getSourceManager()) {}
+  HighlightingTokenCollector(ParsedAST ) : AST(AST) {}
 
   std::vector collectTokens() {
 Tokens.clear();
-TraverseAST(Ctx);
+TraverseAST(AST.getASTContext());
+// Add highlightings for macro expansions as they are not traversed by the
+// visitor.
+// FIXME: Should add highlighting to the macro definitions as well. But this
+// information is not collected in ParsedAST right now.
+for (const SourceLocation  : AST.getMainFileExpansions())
+  addToken(L, HighlightingKind::Macro);
 // Initializer lists can give duplicates of tokens, therefore all tokens
 // must be deduplicated.
 llvm::sort(Tokens);
@@ -264,6 +268,7 @@
   }
 
   void addToken(SourceLocation Loc, HighlightingKind Kind) {
+const auto  = AST.getSourceManager();
 if (Loc.isMacroID()) {
   // Only intereseted in highlighting arguments in macros (DEF_X(arg)).
   if (!SM.isMacroArgExpansion(Loc))
@@ -279,7 +284,7 @@
 if (!isInsideMainFile(Loc, SM))
   return;
 
-auto R = getTokenRange(SM, Ctx.getLangOpts(), Loc);
+auto R = getTokenRange(SM, AST.getASTContext().getLangOpts(), Loc);
 if (!R) {
   // R should always have a value, if it doesn't something is very wrong.
   elog("Tried to add semantic token with an invalid range");
@@ -466,6 +471,8 @@
 return "entity.name.type.template.cpp";
   case HighlightingKind::Primitive:
 return "storage.type.primitive.cpp";
+  case HighlightingKind::Macro:
+return "entity.name.function.preprocessor.cpp";
   case HighlightingKind::NumKinds:
 llvm_unreachable("must not pass NumKinds to the function");
   }
Index: clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
===
--- clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
+++ clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
@@ -47,7 +47,8 @@
   {HighlightingKind::Method, "Method"},
   {HighlightingKind::StaticMethod, "StaticMethod"},
   {HighlightingKind::TemplateParameter, "TemplateParameter"},
-  {HighlightingKind::Primitive, "Primitive"}};
+  {HighlightingKind::Primitive, "Primitive"},
+  {HighlightingKind::Macro, "Macro"}};
   std::vector ExpectedTokens;
   for (const auto  : KindToString) {
 std::vector Toks = makeHighlightingTokens(
@@ -391,9 +392,9 @@
   R"cpp(
   #define DEF_MULTIPLE(X) namespace X { class X { int X; }; }
   #define DEF_CLASS(T) class T {};
-  DEF_MULTIPLE(XYZ);
-  DEF_MULTIPLE(XYZW);
-  DEF_CLASS($Class[[A]])
+  $Macro[[DEF_MULTIPLE]](XYZ);
+  $Macro[[DEF_MULTIPLE]](XYZW);
+  $Macro[[DEF_CLASS]]($Class[[A]])
   #define MACRO_CONCAT(X, V, T) T foo##X = V
   #define DEF_VAR(X, V) int X = V
   #define DEF_VAR_T(T, X, V) T X = V
@@ -404,26 +405,27 @@
   #define SOME_NAME_SET variable2 = 123
   #define INC_VAR(X) X += 2
   $Primitive[[void]] $Function[[foo]]() {
-DEF_VAR($LocalVariable[[X]],  123);
-DEF_VAR_REV(908, $LocalVariable[[XY]]);
-$Primitive[[int]] CPY( $LocalVariable[[XX]] );
-DEF_VAR_TYPE($Class[[A]], $LocalVariable[[AA]]);
-$Primitive[[double]] SOME_NAME;
-$Primitive[[int]] SOME_NAME_SET;
+$Macro[[DEF_VAR]]($LocalVariable[[X]],  123);
+$Macro[[DEF_VAR_REV]](908, $LocalVariable[[XY]]);
+$Primitive[[int]] $Macro[[CPY]]( $LocalVariable[[XX]] );
+$Macro[[DEF_VAR_TYPE]]($Class[[A]], $LocalVariable[[AA]]);
+$Primitive[[double]] $Macro[[SOME_NAME]];
+$Primitive[[int]] $Macro[[SOME_NAME_SET]];
 $LocalVariable[[variable]] = 20.1;
-MACRO_CONCAT(var, 2, $Primitive[[float]]);
- 

[PATCH] D66738: [clangd] Added highlighting for structured bindings.

2019-08-30 Thread Johan Vikström via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL370473: [clangd] Added highlighting for structured bindings. 
(authored by jvikstrom, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D66738?vs=217652=218090#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66738/new/

https://reviews.llvm.org/D66738

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


Index: clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
@@ -233,6 +233,10 @@
: HighlightingKind::Variable);
   return;
 }
+if (isa(D)) {
+  addToken(Loc, HighlightingKind::Variable);
+  return;
+}
 if (isa(D)) {
   addToken(Loc, HighlightingKind::Function);
   return;
Index: clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
===
--- clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
+++ clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
@@ -436,6 +436,21 @@
 assert($Variable[[x]] != $Variable[[y]]);
 assert($Variable[[x]] != $Function[[f]]());
   }
+)cpp",
+R"cpp(
+  struct $Class[[S]] {
+$Primitive[[float]] $Field[[Value]];
+$Class[[S]] *$Field[[Next]];
+  };
+  $Class[[S]] $Variable[[Global]][2] = {$Class[[S]](), $Class[[S]]()};
+  $Primitive[[void]] $Function[[f]]($Class[[S]] $Parameter[[P]]) {
+$Primitive[[int]] $LocalVariable[[A]][2] = {1,2};
+auto [$Variable[[B1]], $Variable[[B2]]] = $LocalVariable[[A]];
+auto [$Variable[[G1]], $Variable[[G2]]] = $Variable[[Global]];
+$Class[[auto]] [$Variable[[P1]], $Variable[[P2]]] = $Parameter[[P]];
+// Highlights references to BindingDecls.
+$Variable[[B1]]++;
+  }
 )cpp"};
   for (const auto  : TestCases) {
 checkHighlightings(TestCase);


Index: clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
@@ -233,6 +233,10 @@
: HighlightingKind::Variable);
   return;
 }
+if (isa(D)) {
+  addToken(Loc, HighlightingKind::Variable);
+  return;
+}
 if (isa(D)) {
   addToken(Loc, HighlightingKind::Function);
   return;
Index: clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
===
--- clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
+++ clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
@@ -436,6 +436,21 @@
 assert($Variable[[x]] != $Variable[[y]]);
 assert($Variable[[x]] != $Function[[f]]());
   }
+)cpp",
+R"cpp(
+  struct $Class[[S]] {
+$Primitive[[float]] $Field[[Value]];
+$Class[[S]] *$Field[[Next]];
+  };
+  $Class[[S]] $Variable[[Global]][2] = {$Class[[S]](), $Class[[S]]()};
+  $Primitive[[void]] $Function[[f]]($Class[[S]] $Parameter[[P]]) {
+$Primitive[[int]] $LocalVariable[[A]][2] = {1,2};
+auto [$Variable[[B1]], $Variable[[B2]]] = $LocalVariable[[A]];
+auto [$Variable[[G1]], $Variable[[G2]]] = $Variable[[Global]];
+$Class[[auto]] [$Variable[[P1]], $Variable[[P2]]] = $Parameter[[P]];
+// Highlights references to BindingDecls.
+$Variable[[B1]]++;
+  }
 )cpp"};
   for (const auto  : TestCases) {
 checkHighlightings(TestCase);
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D66995: [clangd] Add highlighting for macro expansions.

2019-08-30 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom updated this revision to Diff 218089.
jvikstrom added a comment.

Renamed MacroExpansion to Macro.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66995/new/

https://reviews.llvm.org/D66995

Files:
  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
@@ -47,7 +47,8 @@
   {HighlightingKind::Method, "Method"},
   {HighlightingKind::StaticMethod, "StaticMethod"},
   {HighlightingKind::TemplateParameter, "TemplateParameter"},
-  {HighlightingKind::Primitive, "Primitive"}};
+  {HighlightingKind::Primitive, "Primitive"},
+  {HighlightingKind::Macro, "Macro"}};
   std::vector ExpectedTokens;
   for (const auto  : KindToString) {
 std::vector Toks = makeHighlightingTokens(
@@ -391,9 +392,9 @@
   R"cpp(
   #define DEF_MULTIPLE(X) namespace X { class X { int X; }; }
   #define DEF_CLASS(T) class T {};
-  DEF_MULTIPLE(XYZ);
-  DEF_MULTIPLE(XYZW);
-  DEF_CLASS($Class[[A]])
+  $Macro[[DEF_MULTIPLE]](XYZ);
+  $Macro[[DEF_MULTIPLE]](XYZW);
+  $Macro[[DEF_CLASS]]($Class[[A]])
   #define MACRO_CONCAT(X, V, T) T foo##X = V
   #define DEF_VAR(X, V) int X = V
   #define DEF_VAR_T(T, X, V) T X = V
@@ -404,26 +405,27 @@
   #define SOME_NAME_SET variable2 = 123
   #define INC_VAR(X) X += 2
   $Primitive[[void]] $Function[[foo]]() {
-DEF_VAR($LocalVariable[[X]],  123);
-DEF_VAR_REV(908, $LocalVariable[[XY]]);
-$Primitive[[int]] CPY( $LocalVariable[[XX]] );
-DEF_VAR_TYPE($Class[[A]], $LocalVariable[[AA]]);
-$Primitive[[double]] SOME_NAME;
-$Primitive[[int]] SOME_NAME_SET;
+$Macro[[DEF_VAR]]($LocalVariable[[X]],  123);
+$Macro[[DEF_VAR_REV]](908, $LocalVariable[[XY]]);
+$Primitive[[int]] $Macro[[CPY]]( $LocalVariable[[XX]] );
+$Macro[[DEF_VAR_TYPE]]($Class[[A]], $LocalVariable[[AA]]);
+$Primitive[[double]] $Macro[[SOME_NAME]];
+$Primitive[[int]] $Macro[[SOME_NAME_SET]];
 $LocalVariable[[variable]] = 20.1;
-MACRO_CONCAT(var, 2, $Primitive[[float]]);
-DEF_VAR_T($Class[[A]], CPY(CPY($LocalVariable[[Nested]])),
-  CPY($Class[[A]]()));
-INC_VAR($LocalVariable[[variable]]);
+$Macro[[MACRO_CONCAT]](var, 2, $Primitive[[float]]);
+$Macro[[DEF_VAR_T]]($Class[[A]], $Macro[[CPY]](
+  $Macro[[CPY]]($LocalVariable[[Nested]])),
+$Macro[[CPY]]($Class[[A]]()));
+$Macro[[INC_VAR]]($LocalVariable[[variable]]);
   }
-  $Primitive[[void]] SOME_NAME();
-  DEF_VAR($Variable[[XYZ]], 567);
-  DEF_VAR_REV(756, $Variable[[AB]]);
+  $Primitive[[void]] $Macro[[SOME_NAME]]();
+  $Macro[[DEF_VAR]]($Variable[[XYZ]], 567);
+  $Macro[[DEF_VAR_REV]](756, $Variable[[AB]]);
 
   #define CALL_FN(F) F();
   #define DEF_FN(F) void F ()
-  DEF_FN($Function[[g]]) {
-CALL_FN($Function[[foo]]);
+  $Macro[[DEF_FN]]($Function[[g]]) {
+$Macro[[CALL_FN]]($Function[[foo]]);
   }
 )cpp",
   R"cpp(
@@ -433,8 +435,8 @@
   $Primitive[[int]] $Variable[[y]];
   $Primitive[[int]] $Function[[f]]();
   $Primitive[[void]] $Function[[foo]]() {
-assert($Variable[[x]] != $Variable[[y]]);
-assert($Variable[[x]] != $Function[[f]]());
+$Macro[[assert]]($Variable[[x]] != $Variable[[y]]);
+$Macro[[assert]]($Variable[[x]] != $Function[[f]]());
   }
 )cpp"};
   for (const auto  : TestCases) {
@@ -455,8 +457,8 @@
   // A separate test for macros in headers.
   checkHighlightings(R"cpp(
 #include "imp.h"
-DEFINE_Y
-DXYZ_Y(A);
+$Macro[[DEFINE_Y]]
+$Macro[[DXYZ_Y]](A);
   )cpp",
  {{"imp.h", R"cpp(
 #define DXYZ(X) class X {};
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
@@ -45,6 +45,9 @@
 # CHECK-NEXT:  ],
 # CHECK-NEXT:  [
 # CHECK-NEXT:"storage.type.primitive.cpp"
+# CHECK-NEXT:  ],
+# CHECK-NEXT:  [
+# CHECK-NEXT:"entity.name.function.preprocessor.expansion.cpp"
 # CHECK-NEXT:  ]
 # CHECK-NEXT:]
 # CHECK-NEXT:  },
Index: clang-tools-extra/clangd/SemanticHighlighting.h
===
--- 

[PATCH] D66995: [clangd] Add highlighting for macro expansions.

2019-08-30 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom added inline comments.



Comment at: clang-tools-extra/clangd/SemanticHighlighting.cpp:469
+  case HighlightingKind::MacroExpansion:
+return "entity.name.function.preprocessor.expansion.cpp";
   case HighlightingKind::NumKinds:

ilya-biryukov wrote:
> Is there a place on the internet with conventional textmate scope names?
> Or do we come up with these on our own?
This is from the vscode c++ extension. (we mostly use the same scopes as in 
that extension, but in a few cases we have our own scopes as there aren't any 
in vscode)



Comment at: clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp:394
   #define DEF_MULTIPLE(X) namespace X { class X { int X; }; }
   #define DEF_CLASS(T) class T {};
+  $MacroExpansion[[DEF_MULTIPLE]](XYZ);

hokein wrote:
> ilya-biryukov wrote:
> > Similar to how we highlight everything else, we should also highlight macro 
> > declarations and usages (i.e. expansions in the same way).
> > Could we add the corresponding highlightings?
> > ```
> > #define $Macro[[DEF_CLASS]](T) class T T{}
> > $Macro[[DEF_CLASS]](A);
> > ```
> +1, I think we could name the HighlightingKind as `Macro` instead of 
> `MacroExpansion`  (even through we don't highlighting the macro def yet).
We don't seem to collect information about where macro declarations are in the 
code in ParsedAST.
Added a fixme to add it.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66995/new/

https://reviews.llvm.org/D66995



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D66995: [clangd] Add highlighting for macro expansions.

2019-08-30 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom updated this revision to Diff 218087.
jvikstrom marked 3 inline comments as done.
jvikstrom added a comment.

Address comments.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66995/new/

https://reviews.llvm.org/D66995

Files:
  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
@@ -47,7 +47,8 @@
   {HighlightingKind::Method, "Method"},
   {HighlightingKind::StaticMethod, "StaticMethod"},
   {HighlightingKind::TemplateParameter, "TemplateParameter"},
-  {HighlightingKind::Primitive, "Primitive"}};
+  {HighlightingKind::Primitive, "Primitive"},
+  {HighlightingKind::MacroExpansion, "MacroExpansion"}};
   std::vector ExpectedTokens;
   for (const auto  : KindToString) {
 std::vector Toks = makeHighlightingTokens(
@@ -391,9 +392,9 @@
   R"cpp(
   #define DEF_MULTIPLE(X) namespace X { class X { int X; }; }
   #define DEF_CLASS(T) class T {};
-  DEF_MULTIPLE(XYZ);
-  DEF_MULTIPLE(XYZW);
-  DEF_CLASS($Class[[A]])
+  $MacroExpansion[[DEF_MULTIPLE]](XYZ);
+  $MacroExpansion[[DEF_MULTIPLE]](XYZW);
+  $MacroExpansion[[DEF_CLASS]]($Class[[A]])
   #define MACRO_CONCAT(X, V, T) T foo##X = V
   #define DEF_VAR(X, V) int X = V
   #define DEF_VAR_T(T, X, V) T X = V
@@ -404,26 +405,27 @@
   #define SOME_NAME_SET variable2 = 123
   #define INC_VAR(X) X += 2
   $Primitive[[void]] $Function[[foo]]() {
-DEF_VAR($LocalVariable[[X]],  123);
-DEF_VAR_REV(908, $LocalVariable[[XY]]);
-$Primitive[[int]] CPY( $LocalVariable[[XX]] );
-DEF_VAR_TYPE($Class[[A]], $LocalVariable[[AA]]);
-$Primitive[[double]] SOME_NAME;
-$Primitive[[int]] SOME_NAME_SET;
+$MacroExpansion[[DEF_VAR]]($LocalVariable[[X]],  123);
+$MacroExpansion[[DEF_VAR_REV]](908, $LocalVariable[[XY]]);
+$Primitive[[int]] $MacroExpansion[[CPY]]( $LocalVariable[[XX]] );
+$MacroExpansion[[DEF_VAR_TYPE]]($Class[[A]], $LocalVariable[[AA]]);
+$Primitive[[double]] $MacroExpansion[[SOME_NAME]];
+$Primitive[[int]] $MacroExpansion[[SOME_NAME_SET]];
 $LocalVariable[[variable]] = 20.1;
-MACRO_CONCAT(var, 2, $Primitive[[float]]);
-DEF_VAR_T($Class[[A]], CPY(CPY($LocalVariable[[Nested]])),
-  CPY($Class[[A]]()));
-INC_VAR($LocalVariable[[variable]]);
+$MacroExpansion[[MACRO_CONCAT]](var, 2, $Primitive[[float]]);
+$MacroExpansion[[DEF_VAR_T]]($Class[[A]], $MacroExpansion[[CPY]](
+  $MacroExpansion[[CPY]]($LocalVariable[[Nested]])),
+$MacroExpansion[[CPY]]($Class[[A]]()));
+$MacroExpansion[[INC_VAR]]($LocalVariable[[variable]]);
   }
-  $Primitive[[void]] SOME_NAME();
-  DEF_VAR($Variable[[XYZ]], 567);
-  DEF_VAR_REV(756, $Variable[[AB]]);
+  $Primitive[[void]] $MacroExpansion[[SOME_NAME]]();
+  $MacroExpansion[[DEF_VAR]]($Variable[[XYZ]], 567);
+  $MacroExpansion[[DEF_VAR_REV]](756, $Variable[[AB]]);
 
   #define CALL_FN(F) F();
   #define DEF_FN(F) void F ()
-  DEF_FN($Function[[g]]) {
-CALL_FN($Function[[foo]]);
+  $MacroExpansion[[DEF_FN]]($Function[[g]]) {
+$MacroExpansion[[CALL_FN]]($Function[[foo]]);
   }
 )cpp",
   R"cpp(
@@ -433,8 +435,8 @@
   $Primitive[[int]] $Variable[[y]];
   $Primitive[[int]] $Function[[f]]();
   $Primitive[[void]] $Function[[foo]]() {
-assert($Variable[[x]] != $Variable[[y]]);
-assert($Variable[[x]] != $Function[[f]]());
+$MacroExpansion[[assert]]($Variable[[x]] != $Variable[[y]]);
+$MacroExpansion[[assert]]($Variable[[x]] != $Function[[f]]());
   }
 )cpp"};
   for (const auto  : TestCases) {
@@ -455,8 +457,8 @@
   // A separate test for macros in headers.
   checkHighlightings(R"cpp(
 #include "imp.h"
-DEFINE_Y
-DXYZ_Y(A);
+$MacroExpansion[[DEFINE_Y]]
+$MacroExpansion[[DXYZ_Y]](A);
   )cpp",
  {{"imp.h", R"cpp(
 #define DXYZ(X) class X {};
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
@@ -45,6 +45,9 @@
 # CHECK-NEXT:  ],
 # CHECK-NEXT:  [
 # CHECK-NEXT:"storage.type.primitive.cpp"
+# CHECK-NEXT:  ],
+# CHECK-NEXT:  [
+# CHECK-NEXT:

[PATCH] D66995: [clangd] Add highlighting for macro expansions.

2019-08-30 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom updated this revision to Diff 218061.
jvikstrom added a comment.

Removed SourceManager field from HighlightingTokenCollector.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66995/new/

https://reviews.llvm.org/D66995

Files:
  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
@@ -47,7 +47,8 @@
   {HighlightingKind::Method, "Method"},
   {HighlightingKind::StaticMethod, "StaticMethod"},
   {HighlightingKind::TemplateParameter, "TemplateParameter"},
-  {HighlightingKind::Primitive, "Primitive"}};
+  {HighlightingKind::Primitive, "Primitive"},
+  {HighlightingKind::MacroExpansion, "MacroExpansion"}};
   std::vector ExpectedTokens;
   for (const auto  : KindToString) {
 std::vector Toks = makeHighlightingTokens(
@@ -391,9 +392,9 @@
   R"cpp(
   #define DEF_MULTIPLE(X) namespace X { class X { int X; }; }
   #define DEF_CLASS(T) class T {};
-  DEF_MULTIPLE(XYZ);
-  DEF_MULTIPLE(XYZW);
-  DEF_CLASS($Class[[A]])
+  $MacroExpansion[[DEF_MULTIPLE]](XYZ);
+  $MacroExpansion[[DEF_MULTIPLE]](XYZW);
+  $MacroExpansion[[DEF_CLASS]]($Class[[A]])
   #define MACRO_CONCAT(X, V, T) T foo##X = V
   #define DEF_VAR(X, V) int X = V
   #define DEF_VAR_T(T, X, V) T X = V
@@ -404,26 +405,27 @@
   #define SOME_NAME_SET variable2 = 123
   #define INC_VAR(X) X += 2
   $Primitive[[void]] $Function[[foo]]() {
-DEF_VAR($LocalVariable[[X]],  123);
-DEF_VAR_REV(908, $LocalVariable[[XY]]);
-$Primitive[[int]] CPY( $LocalVariable[[XX]] );
-DEF_VAR_TYPE($Class[[A]], $LocalVariable[[AA]]);
-$Primitive[[double]] SOME_NAME;
-$Primitive[[int]] SOME_NAME_SET;
+$MacroExpansion[[DEF_VAR]]($LocalVariable[[X]],  123);
+$MacroExpansion[[DEF_VAR_REV]](908, $LocalVariable[[XY]]);
+$Primitive[[int]] $MacroExpansion[[CPY]]( $LocalVariable[[XX]] );
+$MacroExpansion[[DEF_VAR_TYPE]]($Class[[A]], $LocalVariable[[AA]]);
+$Primitive[[double]] $MacroExpansion[[SOME_NAME]];
+$Primitive[[int]] $MacroExpansion[[SOME_NAME_SET]];
 $LocalVariable[[variable]] = 20.1;
-MACRO_CONCAT(var, 2, $Primitive[[float]]);
-DEF_VAR_T($Class[[A]], CPY(CPY($LocalVariable[[Nested]])),
-  CPY($Class[[A]]()));
-INC_VAR($LocalVariable[[variable]]);
+$MacroExpansion[[MACRO_CONCAT]](var, 2, $Primitive[[float]]);
+$MacroExpansion[[DEF_VAR_T]]($Class[[A]], $MacroExpansion[[CPY]](
+  $MacroExpansion[[CPY]]($LocalVariable[[Nested]])),
+$MacroExpansion[[CPY]]($Class[[A]]()));
+$MacroExpansion[[INC_VAR]]($LocalVariable[[variable]]);
   }
-  $Primitive[[void]] SOME_NAME();
-  DEF_VAR($Variable[[XYZ]], 567);
-  DEF_VAR_REV(756, $Variable[[AB]]);
+  $Primitive[[void]] $MacroExpansion[[SOME_NAME]]();
+  $MacroExpansion[[DEF_VAR]]($Variable[[XYZ]], 567);
+  $MacroExpansion[[DEF_VAR_REV]](756, $Variable[[AB]]);
 
   #define CALL_FN(F) F();
   #define DEF_FN(F) void F ()
-  DEF_FN($Function[[g]]) {
-CALL_FN($Function[[foo]]);
+  $MacroExpansion[[DEF_FN]]($Function[[g]]) {
+$MacroExpansion[[CALL_FN]]($Function[[foo]]);
   }
 )cpp",
   R"cpp(
@@ -433,8 +435,8 @@
   $Primitive[[int]] $Variable[[y]];
   $Primitive[[int]] $Function[[f]]();
   $Primitive[[void]] $Function[[foo]]() {
-assert($Variable[[x]] != $Variable[[y]]);
-assert($Variable[[x]] != $Function[[f]]());
+$MacroExpansion[[assert]]($Variable[[x]] != $Variable[[y]]);
+$MacroExpansion[[assert]]($Variable[[x]] != $Function[[f]]());
   }
 )cpp"};
   for (const auto  : TestCases) {
@@ -455,8 +457,8 @@
   // A separate test for macros in headers.
   checkHighlightings(R"cpp(
 #include "imp.h"
-DEFINE_Y
-DXYZ_Y(A);
+$MacroExpansion[[DEFINE_Y]]
+$MacroExpansion[[DXYZ_Y]](A);
   )cpp",
  {{"imp.h", R"cpp(
 #define DXYZ(X) class X {};
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
@@ -45,6 +45,9 @@
 # CHECK-NEXT:  ],
 # CHECK-NEXT:  [
 # CHECK-NEXT:"storage.type.primitive.cpp"
+# CHECK-NEXT:  ],
+# CHECK-NEXT:  [
+# CHECK-NEXT:

[PATCH] D66738: [clangd] Added highlighting for structured bindings.

2019-08-30 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom marked an inline comment as done.
jvikstrom added inline comments.



Comment at: clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp:443
+$Primitive[[int]] $Variable[[A]][2] = {1,2};
+auto [$Variable[[B1]], $Variable[[B2]]] = $Variable[[A]];
+auto [$Variable[[G1]], $Variable[[G2]]] = $Variable[[Global]];

hokein wrote:
> this is not related to the patch,  but the highlighting behavior for auto 
> here is weird, some of them are highlighted while some of them are not. 
The reason for that is broken down here: 
https://reviews.llvm.org/D66516#inline-599982

Basically we don't traverse the type hierarchy when trying to add highlightings 
for auto so if we have a pointer/array type it will not find the actual type 
and just silently not add any highlightings.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66738/new/

https://reviews.llvm.org/D66738



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D66995: [clangd] Add highlighting for macro expansions.

2019-08-30 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom created this revision.
jvikstrom added reviewers: hokein, ilya-biryukov.
Herald added subscribers: cfe-commits, kadircet, arphaman, jkorous, MaskRay.
Herald added a project: clang.

https://github.com/clangd/clangd/issues/134


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D66995

Files:
  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
@@ -47,7 +47,8 @@
   {HighlightingKind::Method, "Method"},
   {HighlightingKind::StaticMethod, "StaticMethod"},
   {HighlightingKind::TemplateParameter, "TemplateParameter"},
-  {HighlightingKind::Primitive, "Primitive"}};
+  {HighlightingKind::Primitive, "Primitive"},
+  {HighlightingKind::MacroExpansion, "MacroExpansion"}};
   std::vector ExpectedTokens;
   for (const auto  : KindToString) {
 std::vector Toks = makeHighlightingTokens(
@@ -391,9 +392,9 @@
   R"cpp(
   #define DEF_MULTIPLE(X) namespace X { class X { int X; }; }
   #define DEF_CLASS(T) class T {};
-  DEF_MULTIPLE(XYZ);
-  DEF_MULTIPLE(XYZW);
-  DEF_CLASS($Class[[A]])
+  $MacroExpansion[[DEF_MULTIPLE]](XYZ);
+  $MacroExpansion[[DEF_MULTIPLE]](XYZW);
+  $MacroExpansion[[DEF_CLASS]]($Class[[A]])
   #define MACRO_CONCAT(X, V, T) T foo##X = V
   #define DEF_VAR(X, V) int X = V
   #define DEF_VAR_T(T, X, V) T X = V
@@ -404,26 +405,27 @@
   #define SOME_NAME_SET variable2 = 123
   #define INC_VAR(X) X += 2
   $Primitive[[void]] $Function[[foo]]() {
-DEF_VAR($LocalVariable[[X]],  123);
-DEF_VAR_REV(908, $LocalVariable[[XY]]);
-$Primitive[[int]] CPY( $LocalVariable[[XX]] );
-DEF_VAR_TYPE($Class[[A]], $LocalVariable[[AA]]);
-$Primitive[[double]] SOME_NAME;
-$Primitive[[int]] SOME_NAME_SET;
+$MacroExpansion[[DEF_VAR]]($LocalVariable[[X]],  123);
+$MacroExpansion[[DEF_VAR_REV]](908, $LocalVariable[[XY]]);
+$Primitive[[int]] $MacroExpansion[[CPY]]( $LocalVariable[[XX]] );
+$MacroExpansion[[DEF_VAR_TYPE]]($Class[[A]], $LocalVariable[[AA]]);
+$Primitive[[double]] $MacroExpansion[[SOME_NAME]];
+$Primitive[[int]] $MacroExpansion[[SOME_NAME_SET]];
 $LocalVariable[[variable]] = 20.1;
-MACRO_CONCAT(var, 2, $Primitive[[float]]);
-DEF_VAR_T($Class[[A]], CPY(CPY($LocalVariable[[Nested]])),
-  CPY($Class[[A]]()));
-INC_VAR($LocalVariable[[variable]]);
+$MacroExpansion[[MACRO_CONCAT]](var, 2, $Primitive[[float]]);
+$MacroExpansion[[DEF_VAR_T]]($Class[[A]], $MacroExpansion[[CPY]](
+  $MacroExpansion[[CPY]]($LocalVariable[[Nested]])),
+$MacroExpansion[[CPY]]($Class[[A]]()));
+$MacroExpansion[[INC_VAR]]($LocalVariable[[variable]]);
   }
-  $Primitive[[void]] SOME_NAME();
-  DEF_VAR($Variable[[XYZ]], 567);
-  DEF_VAR_REV(756, $Variable[[AB]]);
+  $Primitive[[void]] $MacroExpansion[[SOME_NAME]]();
+  $MacroExpansion[[DEF_VAR]]($Variable[[XYZ]], 567);
+  $MacroExpansion[[DEF_VAR_REV]](756, $Variable[[AB]]);
 
   #define CALL_FN(F) F();
   #define DEF_FN(F) void F ()
-  DEF_FN($Function[[g]]) {
-CALL_FN($Function[[foo]]);
+  $MacroExpansion[[DEF_FN]]($Function[[g]]) {
+$MacroExpansion[[CALL_FN]]($Function[[foo]]);
   }
 )cpp",
   R"cpp(
@@ -433,8 +435,8 @@
   $Primitive[[int]] $Variable[[y]];
   $Primitive[[int]] $Function[[f]]();
   $Primitive[[void]] $Function[[foo]]() {
-assert($Variable[[x]] != $Variable[[y]]);
-assert($Variable[[x]] != $Function[[f]]());
+$MacroExpansion[[assert]]($Variable[[x]] != $Variable[[y]]);
+$MacroExpansion[[assert]]($Variable[[x]] != $Function[[f]]());
   }
 )cpp"};
   for (const auto  : TestCases) {
@@ -455,8 +457,8 @@
   // A separate test for macros in headers.
   checkHighlightings(R"cpp(
 #include "imp.h"
-DEFINE_Y
-DXYZ_Y(A);
+$MacroExpansion[[DEFINE_Y]]
+$MacroExpansion[[DXYZ_Y]](A);
   )cpp",
  {{"imp.h", R"cpp(
 #define DXYZ(X) class X {};
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
@@ -45,6 +45,9 @@
 # CHECK-NEXT:  ],
 # CHECK-NEXT:  [
 # CHECK-NEXT:"storage.type.primitive.cpp"
+# CHECK-NEXT:  ],
+# CHECK-NEXT:  [
+# CHECK-NEXT:   

[PATCH] D66928: [clangd] Collecting main file macro expansion locations in ParsedAST.

2019-08-30 Thread Johan Vikström via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL370452: [clangd] Collecting main file macro expansion 
locations in ParsedAST. (authored by jvikstrom, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D66928?vs=217920=218049#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66928/new/

https://reviews.llvm.org/D66928

Files:
  clang-tools-extra/trunk/clangd/ClangdUnit.cpp
  clang-tools-extra/trunk/clangd/ClangdUnit.h
  clang-tools-extra/trunk/clangd/unittests/ClangdUnitTests.cpp

Index: clang-tools-extra/trunk/clangd/ClangdUnit.cpp
===
--- clang-tools-extra/trunk/clangd/ClangdUnit.cpp
+++ clang-tools-extra/trunk/clangd/ClangdUnit.cpp
@@ -22,6 +22,7 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Decl.h"
 #include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TokenKinds.h"
 #include "clang/Frontend/CompilerInstance.h"
@@ -32,6 +33,7 @@
 #include "clang/Index/IndexingAction.h"
 #include "clang/Lex/Lexer.h"
 #include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/PPCallbacks.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Lex/PreprocessorOptions.h"
 #include "clang/Sema/Sema.h"
@@ -103,6 +105,28 @@
   std::vector TopLevelDecls;
 };
 
+// CollectMainFileMacroExpansions and CollectMainFileMacros are two different
+// classes as CollectMainFileMacroExpansions is only used when building the AST
+// for the main file. CollectMainFileMacros is only used when building the
+// preamble.
+class CollectMainFileMacroExpansions : public PPCallbacks {
+  const SourceManager 
+  std::vector 
+
+public:
+  CollectMainFileMacroExpansions(const SourceManager ,
+ std::vector )
+  : SM(SM), MainFileMacroLocs(MainFileMacroLocs) {}
+
+  virtual void MacroExpands(const Token ,
+const MacroDefinition , SourceRange Range,
+const MacroArgs *Args) {
+SourceLocation L = MacroNameTok.getLocation();
+if (!L.isMacroID() && isInsideMainFile(L, SM))
+  MainFileMacroLocs.push_back(L);
+  }
+};
+
 class CollectMainFileMacros : public PPCallbacks {
 public:
   explicit CollectMainFileMacros(const SourceManager ,
@@ -417,6 +441,11 @@
   // (We can't *just* use the replayed includes, they don't have Resolved path).
   Clang->getPreprocessor().addPPCallbacks(
   collectIncludeStructureCallback(Clang->getSourceManager(), ));
+  // Collect the macro expansions in the main file.
+  std::vector MainFileMacroExpLocs;
+  Clang->getPreprocessor().addPPCallbacks(
+  std::make_unique(
+  Clang->getSourceManager(), MainFileMacroExpLocs));
 
   // Copy over the includes from the preamble, then combine with the
   // non-preamble includes below.
@@ -470,7 +499,8 @@
 Diags.insert(Diags.end(), D.begin(), D.end());
   }
   return ParsedAST(std::move(Preamble), std::move(Clang), std::move(Action),
-   std::move(Tokens), std::move(ParsedDecls), std::move(Diags),
+   std::move(Tokens), std::move(MainFileMacroExpLocs),
+   std::move(ParsedDecls), std::move(Diags),
std::move(Includes), std::move(CanonIncludes));
 }
 
@@ -509,6 +539,10 @@
   return LocalTopLevelDecls;
 }
 
+llvm::ArrayRef ParsedAST::getMainFileExpansions() const {
+  return MainFileMacroExpLocs;
+}
+
 const std::vector ::getDiagnostics() const { return Diags; }
 
 std::size_t ParsedAST::getUsedBytes() const {
@@ -565,11 +599,13 @@
  std::unique_ptr Clang,
  std::unique_ptr Action,
  syntax::TokenBuffer Tokens,
+ std::vector MainFileMacroExpLocs,
  std::vector LocalTopLevelDecls,
  std::vector Diags, IncludeStructure Includes,
  CanonicalIncludes CanonIncludes)
 : Preamble(std::move(Preamble)), Clang(std::move(Clang)),
   Action(std::move(Action)), Tokens(std::move(Tokens)),
+  MainFileMacroExpLocs(std::move(MainFileMacroExpLocs)),
   Diags(std::move(Diags)),
   LocalTopLevelDecls(std::move(LocalTopLevelDecls)),
   Includes(std::move(Includes)), CanonIncludes(std::move(CanonIncludes)) {
Index: clang-tools-extra/trunk/clangd/ClangdUnit.h
===
--- clang-tools-extra/trunk/clangd/ClangdUnit.h
+++ clang-tools-extra/trunk/clangd/ClangdUnit.h
@@ -118,6 +118,9 @@
   const IncludeStructure () const;
   const CanonicalIncludes () const;
 
+  /// The start locations of all macro expansions spelled inside the main file.
+  /// Does not include expansions from inside other macro expansions.
+  llvm::ArrayRef getMainFileExpansions() const;
   /// Tokens recorded while 

[PATCH] D66516: [clangd] Added highlighting to types dependant on templates.

2019-08-30 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom added a comment.

Pinging about this @ilya-biryukov


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66516/new/

https://reviews.llvm.org/D66516



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D66990: [clangd] Add distinct highlightings for declarations of functions and methods

2019-08-30 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom added a comment.

Should we have different highlightings for declarations vs usages? (Although I 
guess in the end it will be up to the editor if they highlight them differently 
as the scope is just more specific for declarations)
I guess I personally don't really see the reason as it should be clear from the 
context if it's a declaration or a function call.
But this might actually be nice if you have macros that declare functions


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66990/new/

https://reviews.llvm.org/D66990



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D66928: [clangd] Collecting main file macro expansion locations in ParsedAST.

2019-08-29 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom marked an inline comment as done.
jvikstrom added inline comments.



Comment at: clang-tools-extra/clangd/unittests/ClangdUnitTests.cpp:260
+// Macros from token concatenations included.
+#define CONCAT(X) X##1()
+#define MACRO1() 123

ilya-biryukov wrote:
> Could we also test?
> ```
> #define PREPEND(X) Foo##X
> ```
> 
> It'll probably be the same, but still interesting to see whether it's any 
> differnet.
So it turns out that the tests weren't actually passing before, must have 
accidentally forgot to save the file or something before compiling. Anyways 
tokens from concatenations are not included right now (which for highlighting 
is probably what we want, we don't highlight types/names that are from macro 
concatenations either)

But the reason they are not are because:
* They do not pass the `isInsideMainFile` check. Their file id is set to 
something that prints `` when dumped
* Even if they did pass the check the SourceLocation does not seem to be 
correct. They return the same SourceLocation as the parent `CONCAT` or `PREPEND`

Don't know how to fix any of this, and don't know if we actually want to 
collect these expansions either.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66928/new/

https://reviews.llvm.org/D66928



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D66928: [clangd] Collecting main file macro expansion locations in ParsedAST.

2019-08-29 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom updated this revision to Diff 217920.
jvikstrom marked 4 inline comments as done.
jvikstrom added a comment.

Added test for prepending concatenations. Also added made tests pass.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66928/new/

https://reviews.llvm.org/D66928

Files:
  clang-tools-extra/clangd/ClangdUnit.cpp
  clang-tools-extra/clangd/ClangdUnit.h
  clang-tools-extra/clangd/unittests/ClangdUnitTests.cpp

Index: clang-tools-extra/clangd/unittests/ClangdUnitTests.cpp
===
--- clang-tools-extra/clangd/unittests/ClangdUnitTests.cpp
+++ clang-tools-extra/clangd/unittests/ClangdUnitTests.cpp
@@ -244,6 +244,49 @@
   EXPECT_EQ(T.expandedTokens().drop_back().back().text(SM), "}");
 }
 
+TEST(ClangdUnitTest, CollectsMainFileMacroExpansions) {
+  Annotations TestCase(R"cpp(
+#define MACRO_ARGS(X, Y) X Y
+^ID(int A);
+// Macro arguments included.
+^MACRO_ARGS(^MACRO_ARGS(^MACRO_EXP(int), A), ^ID(= 2));
+
+// Macro names inside other macros not included.
+#define FOO BAR
+#define BAR 1
+int A = ^FOO;
+
+// Macros from token concatenations not included.
+#define CONCAT(X) X##A()
+#define PREPEND(X) MACRO##X()
+#define MACROA() 123
+int B = ^CONCAT(MACRO);
+int D = ^PREPEND(A)
+
+// Macros included not from preamble not included.
+#include "foo.inc"
+  )cpp");
+  auto TU = TestTU::withCode(TestCase.code());
+  TU.HeaderCode = R"cpp(
+#define ID(X) X
+#define MACRO_EXP(X) ID(X)
+MACRO_EXP(int B);
+  )cpp";
+  TU.AdditionalFiles["foo.inc"] = R"cpp(
+int C = ID(1);
+#define DEF 1
+int D = DEF;
+  )cpp";
+  ParsedAST AST = TU.build();
+  const std::vector  =
+  AST.getMainFileExpansions();
+  std::vector MacroExpansionPositions;
+  for (const auto  : MacroExpansionLocations)
+MacroExpansionPositions.push_back(
+sourceLocToPosition(AST.getSourceManager(), L));
+  EXPECT_EQ(MacroExpansionPositions, TestCase.points());
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/ClangdUnit.h
===
--- clang-tools-extra/clangd/ClangdUnit.h
+++ clang-tools-extra/clangd/ClangdUnit.h
@@ -116,6 +116,9 @@
   const IncludeStructure () const;
   const CanonicalIncludes () const;
 
+  /// The start locations of all macro expansions spelled inside the main file.
+  /// Does not include expansions from inside other macro expansions.
+  llvm::ArrayRef getMainFileExpansions() const;
   /// Tokens recorded while parsing the main file.
   /// (!) does not have tokens from the preamble.
   const syntax::TokenBuffer () const { return Tokens; }
@@ -124,6 +127,7 @@
   ParsedAST(std::shared_ptr Preamble,
 std::unique_ptr Clang,
 std::unique_ptr Action, syntax::TokenBuffer Tokens,
+std::vector MainFileMacroExpLocs,
 std::vector LocalTopLevelDecls, std::vector Diags,
 IncludeStructure Includes, CanonicalIncludes CanonIncludes);
 
@@ -143,6 +147,9 @@
   ///   - Does not have spelled or expanded tokens for files from preamble.
   syntax::TokenBuffer Tokens;
 
+  /// The start locations of all macro expansions spelled inside the main file.
+  /// Does not include expansions from inside other macro expansions.
+  std::vector MainFileMacroExpLocs;
   // Data, stored after parsing.
   std::vector Diags;
   // Top-level decls inside the current file. Not that this does not include
Index: clang-tools-extra/clangd/ClangdUnit.cpp
===
--- clang-tools-extra/clangd/ClangdUnit.cpp
+++ clang-tools-extra/clangd/ClangdUnit.cpp
@@ -22,6 +22,7 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Decl.h"
 #include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TokenKinds.h"
 #include "clang/Frontend/CompilerInstance.h"
@@ -32,6 +33,7 @@
 #include "clang/Index/IndexingAction.h"
 #include "clang/Lex/Lexer.h"
 #include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/PPCallbacks.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Lex/PreprocessorOptions.h"
 #include "clang/Sema/Sema.h"
@@ -103,6 +105,28 @@
   std::vector TopLevelDecls;
 };
 
+// CollectMainFileMacroExpansions and CollectMainFileMacros are two different
+// classes as CollectMainFileMacroExpansions is only used when building the AST
+// for the main file. CollectMainFileMacros is only used when building the
+// preamble.
+class CollectMainFileMacroExpansions : public PPCallbacks {
+  const SourceManager 
+  std::vector 
+
+public:
+  CollectMainFileMacroExpansions(const SourceManager ,
+ std::vector )
+  : SM(SM), MainFileMacroLocs(MainFileMacroLocs) {}
+
+  virtual void MacroExpands(const Token ,
+

[PATCH] D66928: [clangd] Collecting main file macro expansion locations in ParsedAST.

2019-08-29 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom marked an inline comment as done.
jvikstrom added inline comments.



Comment at: clang-tools-extra/clangd/ClangdUnit.cpp:107
 
+class CollectMainFileMacroExpansions : public PPCallbacks {
+  const SourceManager 

ilya-biryukov wrote:
> Maybe make this part of `CollectMainFileMacros`? It looks like a natural fit 
> there and we won't need another instance of `PPCallbacks`.
But `CollectMainFileMacros` is only used for `buildPreamble`. 
I think this one needs to run in `ParsedAST::build`?

Is it safe to add a `CollectMainFileMacros in `ParsedAST::build`?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66928/new/

https://reviews.llvm.org/D66928



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D66928: [clangd] Collecting main file macro expansion locations in ParsedAST.

2019-08-29 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom added inline comments.



Comment at: clang-tools-extra/clangd/unittests/ClangdUnitTests.cpp:248
+TEST(ClangdUnitTest, CollectsMainFileMacroExpansions) {
+  Annotations TestCase(R"cpp(
+#define MACRO_ARGS(X, Y) X Y

ilya-biryukov wrote:
> Could you add a few more interesting cases?
> 
> 1. Macros outside the main file **and** the preamble:
> ```
> // foo.inc
> int a = ID(1);
> 
> // foo.cpp
> #define ID(X) X
> 
> int b;
> #include "foo.inc"
> ```
> 
> 2. macro expansions from token concatenations
> ```
> #define FOO(X) X##1()
> #define MACRO1() 123
> 
> int a = FOO(MACRO);
> ```
> 3. Macro names inside other macros:
> ```
> #define FOO BAR
> #define BAR 1
> 
> 
> int a = FOO; // should BAR at line 1 be highlighted?
> 
> ```
> 
> 4. #include not part of the preamble:
> ```
> #define FOO 1
> 
> // Preamble ends here.
> int a = 10;
> #include "some_file_with_macros.h" // <-- should not get any macros from here
> ```
Does clangd handle `.inc` files differently from `.h`? Because if it doesn't 
shouldn't ` case 1 cover case 4 as well ?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66928/new/

https://reviews.llvm.org/D66928



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D66928: [clangd] Collecting main file macro expansion locations in ParsedAST.

2019-08-29 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom updated this revision to Diff 217811.
jvikstrom marked 5 inline comments as done.
jvikstrom added a comment.

Clarified comments. Added tests. Not getting expansions inside other macro 
expansions.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66928/new/

https://reviews.llvm.org/D66928

Files:
  clang-tools-extra/clangd/ClangdUnit.cpp
  clang-tools-extra/clangd/ClangdUnit.h
  clang-tools-extra/clangd/unittests/ClangdUnitTests.cpp

Index: clang-tools-extra/clangd/unittests/ClangdUnitTests.cpp
===
--- clang-tools-extra/clangd/unittests/ClangdUnitTests.cpp
+++ clang-tools-extra/clangd/unittests/ClangdUnitTests.cpp
@@ -244,6 +244,47 @@
   EXPECT_EQ(T.expandedTokens().drop_back().back().text(SM), "}");
 }
 
+TEST(ClangdUnitTest, CollectsMainFileMacroExpansions) {
+  Annotations TestCase(R"cpp(
+#define MACRO_ARGS(X, Y) X Y
+^ID(int A);
+// Macro arguments included.
+^MACRO_ARGS(^MACRO_ARGS(^MACRO_EXP(int), A), ^ID(= 2));
+
+// Macro names inside other macros not included.
+#define FOO BAR
+#define BAR 1
+int A = ^FOO;
+
+// Macros from token concatenations included.
+#define CONCAT(X) X##1()
+#define MACRO1() 123
+int B = ^CONCAT(^MACRO);
+
+// Macros included not from preamble not included.
+#include "foo.inc"
+  )cpp");
+  auto TU = TestTU::withCode(TestCase.code());
+  TU.HeaderCode = R"cpp(
+#define ID(X) X
+#define MACRO_EXP(X) ID(X)
+MACRO_EXP(int B);
+  )cpp";
+  TU.AdditionalFiles["foo.inc"] = R"cpp(
+int C = ID(1);
+#define DEF 1
+int D = DEF;
+  )cpp";
+  ParsedAST AST = TU.build();
+  const std::vector  =
+  AST.getMainFileMacroExpansionLocations();
+  std::vector MacroExpansionPositions;
+  for (const auto  : MacroExpansionLocations)
+MacroExpansionPositions.push_back(
+sourceLocToPosition(AST.getSourceManager(), L));
+  EXPECT_EQ(MacroExpansionPositions, TestCase.points());
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/ClangdUnit.h
===
--- clang-tools-extra/clangd/ClangdUnit.h
+++ clang-tools-extra/clangd/ClangdUnit.h
@@ -116,6 +116,7 @@
   const IncludeStructure () const;
   const CanonicalIncludes () const;
 
+  const std::vector () const;
   /// Tokens recorded while parsing the main file.
   /// (!) does not have tokens from the preamble.
   const syntax::TokenBuffer () const { return Tokens; }
@@ -124,6 +125,7 @@
   ParsedAST(std::shared_ptr Preamble,
 std::unique_ptr Clang,
 std::unique_ptr Action, syntax::TokenBuffer Tokens,
+std::vector MainFileMacroExpLocs,
 std::vector LocalTopLevelDecls, std::vector Diags,
 IncludeStructure Includes, CanonicalIncludes CanonIncludes);
 
@@ -143,6 +145,9 @@
   ///   - Does not have spelled or expanded tokens for files from preamble.
   syntax::TokenBuffer Tokens;
 
+  /// The start locations of all macro expansions spelled inside the main file.
+  /// Does not include expansions from inside other macro expansions.
+  std::vector MainFileMacroExpLocs;
   // Data, stored after parsing.
   std::vector Diags;
   // Top-level decls inside the current file. Not that this does not include
Index: clang-tools-extra/clangd/ClangdUnit.cpp
===
--- clang-tools-extra/clangd/ClangdUnit.cpp
+++ clang-tools-extra/clangd/ClangdUnit.cpp
@@ -32,6 +32,7 @@
 #include "clang/Index/IndexingAction.h"
 #include "clang/Lex/Lexer.h"
 #include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/PPCallbacks.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Lex/PreprocessorOptions.h"
 #include "clang/Sema/Sema.h"
@@ -103,6 +104,24 @@
   std::vector TopLevelDecls;
 };
 
+class CollectMainFileMacroExpansions : public PPCallbacks {
+  const SourceManager 
+  std::vector 
+
+public:
+  CollectMainFileMacroExpansions(const SourceManager ,
+ std::vector )
+  : SM(SM), MainFileMacroLocs(MainFileMacroLocs) {}
+
+  virtual void MacroExpands(const Token ,
+const MacroDefinition , SourceRange Range,
+const MacroArgs *Args) {
+SourceLocation L = MacroNameTok.getLocation();
+if (isInsideMainFile(SM.getSpellingLoc(L), SM) && !L.isMacroID())
+  MainFileMacroLocs.push_back(L);
+  }
+};
+
 class CollectMainFileMacros : public PPCallbacks {
 public:
   explicit CollectMainFileMacros(const SourceManager ,
@@ -414,6 +433,11 @@
   // (We can't *just* use the replayed includes, they don't have Resolved path).
   Clang->getPreprocessor().addPPCallbacks(
   collectIncludeStructureCallback(Clang->getSourceManager(), ));
+  // Collect the macro expansions in the main file.
+  std::vector MainFileMacroExpLocs;
+  Clang->getPreprocessor().addPPCallbacks(
+ 

[PATCH] D66406: [clangd] Update theme when color theme changes in vscode extension.

2019-08-29 Thread Johan Vikström via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL370305: [clangd] Update themeRuleMatcher when color theme 
changes in vscode extension. (authored by jvikstrom, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D66406?vs=217785=217794#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66406/new/

https://reviews.llvm.org/D66406

Files:
  
clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/semantic-highlighting.ts


Index: 
clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
===
--- 
clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
+++ 
clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
@@ -91,6 +91,13 @@
 // highlighter being created.
 this.highlighter = new Highlighter(this.scopeLookupTable);
 this.subscriptions.push(vscode.Disposable.from(this.highlighter));
+// Adds a listener to reload the theme when it changes.
+this.subscriptions.push(
+vscode.workspace.onDidChangeConfiguration((conf) => {
+  if (!conf.affectsConfiguration('workbench.colorTheme'))
+return;
+  this.loadCurrentTheme();
+}));
 this.loadCurrentTheme();
 // Event handling for handling with TextDocuments/Editors lifetimes.
 this.subscriptions.push(vscode.window.onDidChangeVisibleTextEditors(


Index: clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
===
--- clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
+++ clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
@@ -91,6 +91,13 @@
 // highlighter being created.
 this.highlighter = new Highlighter(this.scopeLookupTable);
 this.subscriptions.push(vscode.Disposable.from(this.highlighter));
+// Adds a listener to reload the theme when it changes.
+this.subscriptions.push(
+vscode.workspace.onDidChangeConfiguration((conf) => {
+  if (!conf.affectsConfiguration('workbench.colorTheme'))
+return;
+  this.loadCurrentTheme();
+}));
 this.loadCurrentTheme();
 // Event handling for handling with TextDocuments/Editors lifetimes.
 this.subscriptions.push(vscode.window.onDidChangeVisibleTextEditors(
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D66928: [clangd] Collecting main file macro expansion locations in ParsedAST.

2019-08-29 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom created this revision.
jvikstrom added reviewers: hokein, ilya-biryukov.
Herald added subscribers: cfe-commits, kadircet, arphaman, jkorous, MaskRay.
Herald added a project: clang.

TokenBuffer does not collect macro expansions inside macro arguments which is 
needed for semantic higlighting. Therefore collects macro expansions in the 
main file in a PPCallback when building the ParsedAST instead.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D66928

Files:
  clang-tools-extra/clangd/ClangdUnit.cpp
  clang-tools-extra/clangd/ClangdUnit.h
  clang-tools-extra/clangd/unittests/ClangdUnitTests.cpp

Index: clang-tools-extra/clangd/unittests/ClangdUnitTests.cpp
===
--- clang-tools-extra/clangd/unittests/ClangdUnitTests.cpp
+++ clang-tools-extra/clangd/unittests/ClangdUnitTests.cpp
@@ -244,6 +244,28 @@
   EXPECT_EQ(T.expandedTokens().drop_back().back().text(SM), "}");
 }
 
+TEST(ClangdUnitTest, CollectsMainFileMacroExpansions) {
+  Annotations TestCase(R"cpp(
+#define MACRO_ARGS(X, Y) X Y
+^MACRO_EXP(int A);
+^MACRO_ARGS(^MACRO_ARGS(^MACRO_EXP(int), A), ^MACRO_EXP(= 2));
+  )cpp");
+  auto TU = TestTU::withCode(TestCase.code());
+  TU.HeaderCode = R"cpp(
+#define INNER_MACRO_EXP(X) X
+#define MACRO_EXP(X) INNER_MACRO_EXP(X)
+MACRO_EXP(int B);
+  )cpp";
+  ParsedAST AST = TU.build();
+  const std::vector  =
+  AST.getMainFileMacroExpansionLocations();
+  std::vector MacroExpansionPositions(MacroExpansionLocations.size());
+  for (int I = 0, End = MacroExpansionLocations.size(); I < End; ++I)
+MacroExpansionPositions[I] =
+sourceLocToPosition(AST.getSourceManager(), MacroExpansionLocations[I]);
+  EXPECT_EQ(MacroExpansionPositions, TestCase.points());
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clang-tools-extra/clangd/ClangdUnit.h
===
--- clang-tools-extra/clangd/ClangdUnit.h
+++ clang-tools-extra/clangd/ClangdUnit.h
@@ -116,6 +116,7 @@
   const IncludeStructure () const;
   const CanonicalIncludes () const;
 
+  const std::vector () const;
   /// Tokens recorded while parsing the main file.
   /// (!) does not have tokens from the preamble.
   const syntax::TokenBuffer () const { return Tokens; }
@@ -124,6 +125,7 @@
   ParsedAST(std::shared_ptr Preamble,
 std::unique_ptr Clang,
 std::unique_ptr Action, syntax::TokenBuffer Tokens,
+std::vector MainFileMacroExpLocs,
 std::vector LocalTopLevelDecls, std::vector Diags,
 IncludeStructure Includes, CanonicalIncludes CanonIncludes);
 
@@ -143,6 +145,8 @@
   ///   - Does not have spelled or expanded tokens for files from preamble.
   syntax::TokenBuffer Tokens;
 
+  /// All macro expansion locations in the main file.
+  std::vector MainFileMacroExpLocs;
   // Data, stored after parsing.
   std::vector Diags;
   // Top-level decls inside the current file. Not that this does not include
Index: clang-tools-extra/clangd/ClangdUnit.cpp
===
--- clang-tools-extra/clangd/ClangdUnit.cpp
+++ clang-tools-extra/clangd/ClangdUnit.cpp
@@ -32,6 +32,7 @@
 #include "clang/Index/IndexingAction.h"
 #include "clang/Lex/Lexer.h"
 #include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/PPCallbacks.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Lex/PreprocessorOptions.h"
 #include "clang/Sema/Sema.h"
@@ -103,6 +104,24 @@
   std::vector TopLevelDecls;
 };
 
+class CollectMainFileMacroExpansions : public PPCallbacks {
+  const SourceManager 
+  std::vector 
+
+public:
+  CollectMainFileMacroExpansions(const SourceManager ,
+ std::vector )
+  : SM(SM), MainFileMacroLocs(MainFileMacroLocs) {}
+
+  virtual void MacroExpands(const Token ,
+const MacroDefinition , SourceRange Range,
+const MacroArgs *Args) {
+SourceLocation L = MacroNameTok.getLocation();
+if (isInsideMainFile(SM.getSpellingLoc(L), SM))
+  MainFileMacroLocs.push_back(L);
+  }
+};
+
 class CollectMainFileMacros : public PPCallbacks {
 public:
   explicit CollectMainFileMacros(const SourceManager ,
@@ -414,6 +433,11 @@
   // (We can't *just* use the replayed includes, they don't have Resolved path).
   Clang->getPreprocessor().addPPCallbacks(
   collectIncludeStructureCallback(Clang->getSourceManager(), ));
+  // Collect the macro expansions in the main file.
+  std::vector MainFileMacroExpLocs;
+  Clang->getPreprocessor().addPPCallbacks(
+  std::make_unique(
+  Clang->getSourceManager(), MainFileMacroExpLocs));
 
   // Copy over the includes from the preamble, then combine with the
   // non-preamble includes below.
@@ -462,7 +486,8 @@
   if (Preamble)
 Diags.insert(Diags.begin(), Preamble->Diags.begin(), Preamble->Diags.end());
   return 

[PATCH] D66406: [clangd] Update themeRuleMatcher when color theme changes in vscode extension.

2019-08-29 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom updated this revision to Diff 217785.
jvikstrom marked an inline comment as done.
jvikstrom added a comment.

Use `conf.affectsConfiguration('workbench.colorTheme')` instead of keeping 
track of the old color theme manually.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66406/new/

https://reviews.llvm.org/D66406

Files:
  clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts


Index: 
clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
@@ -91,6 +91,13 @@
 // highlighter being created.
 this.highlighter = new Highlighter(this.scopeLookupTable);
 this.subscriptions.push(vscode.Disposable.from(this.highlighter));
+// Adds a listener to reload the theme when it changes.
+this.subscriptions.push(
+vscode.workspace.onDidChangeConfiguration((conf) => {
+  if (!conf.affectsConfiguration('workbench.colorTheme'))
+return;
+  this.loadCurrentTheme();
+}));
 this.loadCurrentTheme();
 // Event handling for handling with TextDocuments/Editors lifetimes.
 this.subscriptions.push(vscode.window.onDidChangeVisibleTextEditors(


Index: clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
@@ -91,6 +91,13 @@
 // highlighter being created.
 this.highlighter = new Highlighter(this.scopeLookupTable);
 this.subscriptions.push(vscode.Disposable.from(this.highlighter));
+// Adds a listener to reload the theme when it changes.
+this.subscriptions.push(
+vscode.workspace.onDidChangeConfiguration((conf) => {
+  if (!conf.affectsConfiguration('workbench.colorTheme'))
+return;
+  this.loadCurrentTheme();
+}));
 this.loadCurrentTheme();
 // Event handling for handling with TextDocuments/Editors lifetimes.
 this.subscriptions.push(vscode.window.onDidChangeVisibleTextEditors(
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D66738: [clangd] Added highlighting for structured bindings.

2019-08-28 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom updated this revision to Diff 217652.
jvikstrom marked 6 inline comments as done.
jvikstrom added a comment.

Abandoned trying to highlight the same as the bound decl.

Reasoning: If you have a reference to a parameter we are not trying to 
highlight the reference as a parameter, the reference is highlighted as a 
variable. Don't really think bindings should be different.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66738/new/

https://reviews.llvm.org/D66738

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
@@ -431,6 +431,21 @@
 assert($Variable[[x]] != $Variable[[y]]);
 assert($Variable[[x]] != $Function[[f]]());
   }
+)cpp",
+R"cpp(
+  struct $Class[[S]] {
+$Primitive[[float]] $Field[[Value]];
+$Class[[S]] *$Field[[Next]];
+  };
+  $Class[[S]] $Variable[[Global]][2] = {$Class[[S]](), $Class[[S]]()};
+  $Primitive[[void]] $Function[[f]]($Class[[S]] $Parameter[[P]]) {
+$Primitive[[int]] $Variable[[A]][2] = {1,2};
+auto [$Variable[[B1]], $Variable[[B2]]] = $Variable[[A]];
+auto [$Variable[[G1]], $Variable[[G2]]] = $Variable[[Global]];
+$Class[[auto]] [$Variable[[P1]], $Variable[[P2]]] = $Parameter[[P]];
+// Highlights references to BindingDecls.
+$Variable[[B1]]++;
+  }
 )cpp"};
   for (const auto  : TestCases) {
 checkHighlightings(TestCase);
Index: clang-tools-extra/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -229,6 +229,10 @@
   addToken(Loc, HighlightingKind::Variable);
   return;
 }
+if (isa(D)) {
+  addToken(Loc, HighlightingKind::Variable);
+  return;
+}
 if (isa(D)) {
   addToken(Loc, HighlightingKind::Function);
   return;


Index: clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
===
--- clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
+++ clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
@@ -431,6 +431,21 @@
 assert($Variable[[x]] != $Variable[[y]]);
 assert($Variable[[x]] != $Function[[f]]());
   }
+)cpp",
+R"cpp(
+  struct $Class[[S]] {
+$Primitive[[float]] $Field[[Value]];
+$Class[[S]] *$Field[[Next]];
+  };
+  $Class[[S]] $Variable[[Global]][2] = {$Class[[S]](), $Class[[S]]()};
+  $Primitive[[void]] $Function[[f]]($Class[[S]] $Parameter[[P]]) {
+$Primitive[[int]] $Variable[[A]][2] = {1,2};
+auto [$Variable[[B1]], $Variable[[B2]]] = $Variable[[A]];
+auto [$Variable[[G1]], $Variable[[G2]]] = $Variable[[Global]];
+$Class[[auto]] [$Variable[[P1]], $Variable[[P2]]] = $Parameter[[P]];
+// Highlights references to BindingDecls.
+$Variable[[B1]]++;
+  }
 )cpp"};
   for (const auto  : TestCases) {
 checkHighlightings(TestCase);
Index: clang-tools-extra/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -229,6 +229,10 @@
   addToken(Loc, HighlightingKind::Variable);
   return;
 }
+if (isa(D)) {
+  addToken(Loc, HighlightingKind::Variable);
+  return;
+}
 if (isa(D)) {
   addToken(Loc, HighlightingKind::Function);
   return;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D66881: [clangd][vscode] Don't leak the resources

2019-08-28 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom added a comment.

Oh, was not aware we needed to dispose the extension as well.

I think you should probably add the SemanticHighlightingFeature to the 
context.subscriptions as well, right? (because I didn't when I did the cleanup 
patch for it, sorry)


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66881/new/

https://reviews.llvm.org/D66881



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D66406: [clangd] Update themeRuleMatcher when color theme changes in vscode extension.

2019-08-28 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom updated this revision to Diff 217638.
jvikstrom added a comment.

Updated to new master.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66406/new/

https://reviews.llvm.org/D66406

Files:
  clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts


Index: 
clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
@@ -5,6 +5,11 @@
 import * as vscodelc from 'vscode-languageclient';
 import * as vscodelct from 'vscode-languageserver-types';
 
+function getCurrentThemeName() {
+  return vscode.workspace.getConfiguration('workbench')
+  .get('colorTheme');
+}
+
 // Parameters for the semantic highlighting (server-side) push notification.
 // Mirrors the structure in the semantic highlighting proposal for LSP.
 interface SemanticHighlightingParams {
@@ -56,6 +61,8 @@
   scopeLookupTable: string[][];
   // The object that applies the highlightings clangd sends.
   highlighter: Highlighter;
+  // The current color theme used for colorization.
+  private currentColorThemeName: string;
   // Any disposables that should be cleaned up when clangd crashes.
   private subscriptions: vscode.Disposable[] = [];
   fillClientCapabilities(capabilities: vscodelc.ClientCapabilities) {
@@ -70,9 +77,9 @@
   }
 
   async loadCurrentTheme() {
-const themeRuleMatcher = new ThemeRuleMatcher(
-await loadTheme(vscode.workspace.getConfiguration('workbench')
-.get('colorTheme')));
+this.currentColorThemeName = getCurrentThemeName();
+const themeRuleMatcher =
+new ThemeRuleMatcher(await loadTheme(this.currentColorThemeName));
 this.highlighter.initialize(themeRuleMatcher);
   }
 
@@ -91,6 +98,16 @@
 // highlighter being created.
 this.highlighter = new Highlighter(this.scopeLookupTable);
 this.subscriptions.push(vscode.Disposable.from(this.highlighter));
+// Adds a listener to reload the theme when it changes.
+this.subscriptions.push(
+vscode.workspace.onDidChangeConfiguration((conf) => {
+  if (!conf.affectsConfiguration('workbench'))
+// Configuration could not have affected the current colorTheme.
+return;
+  const newColorTheme = getCurrentThemeName();
+  if (newColorTheme !== this.currentColorThemeName)
+this.loadCurrentTheme();
+}));
 this.loadCurrentTheme();
 // Event handling for handling with TextDocuments/Editors lifetimes.
 this.subscriptions.push(vscode.window.onDidChangeVisibleTextEditors(


Index: clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
@@ -5,6 +5,11 @@
 import * as vscodelc from 'vscode-languageclient';
 import * as vscodelct from 'vscode-languageserver-types';
 
+function getCurrentThemeName() {
+  return vscode.workspace.getConfiguration('workbench')
+  .get('colorTheme');
+}
+
 // Parameters for the semantic highlighting (server-side) push notification.
 // Mirrors the structure in the semantic highlighting proposal for LSP.
 interface SemanticHighlightingParams {
@@ -56,6 +61,8 @@
   scopeLookupTable: string[][];
   // The object that applies the highlightings clangd sends.
   highlighter: Highlighter;
+  // The current color theme used for colorization.
+  private currentColorThemeName: string;
   // Any disposables that should be cleaned up when clangd crashes.
   private subscriptions: vscode.Disposable[] = [];
   fillClientCapabilities(capabilities: vscodelc.ClientCapabilities) {
@@ -70,9 +77,9 @@
   }
 
   async loadCurrentTheme() {
-const themeRuleMatcher = new ThemeRuleMatcher(
-await loadTheme(vscode.workspace.getConfiguration('workbench')
-.get('colorTheme')));
+this.currentColorThemeName = getCurrentThemeName();
+const themeRuleMatcher =
+new ThemeRuleMatcher(await loadTheme(this.currentColorThemeName));
 this.highlighter.initialize(themeRuleMatcher);
   }
 
@@ -91,6 +98,16 @@
 // highlighter being created.
 this.highlighter = new Highlighter(this.scopeLookupTable);
 this.subscriptions.push(vscode.Disposable.from(this.highlighter));
+// Adds a listener to reload the theme when it changes.
+this.subscriptions.push(
+vscode.workspace.onDidChangeConfiguration((conf) => {
+  if (!conf.affectsConfiguration('workbench'))
+// Configuration could not have affected the current colorTheme.
+return;
+  const newColorTheme = 

[PATCH] D66743: [clangd] Cleans up the semantic highlighting resources if clangd crashes.

2019-08-28 Thread Johan Vikström via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL370202: [clangd] Cleans up the semantic highlighting 
resources if clangd stops. (authored by jvikstrom, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D66743?vs=217396=217630#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66743/new/

https://reviews.llvm.org/D66743

Files:
  clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/extension.ts
  
clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
  
clang-tools-extra/trunk/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts

Index: clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
===
--- clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
+++ clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
@@ -56,6 +56,8 @@
   scopeLookupTable: string[][];
   // The object that applies the highlightings clangd sends.
   highlighter: Highlighter;
+  // Any disposables that should be cleaned up when clangd crashes.
+  private subscriptions: vscode.Disposable[] = [];
   fillClientCapabilities(capabilities: vscodelc.ClientCapabilities) {
 // Extend the ClientCapabilities type and add semantic highlighting
 // capability to the object.
@@ -88,14 +90,15 @@
 // otherwise it could try to update the themeRuleMatcher without the
 // highlighter being created.
 this.highlighter = new Highlighter(this.scopeLookupTable);
+this.subscriptions.push(vscode.Disposable.from(this.highlighter));
 this.loadCurrentTheme();
 // Event handling for handling with TextDocuments/Editors lifetimes.
-vscode.window.onDidChangeVisibleTextEditors(
+this.subscriptions.push(vscode.window.onDidChangeVisibleTextEditors(
 (editors: vscode.TextEditor[]) =>
 editors.forEach((e) => this.highlighter.applyHighlights(
-e.document.uri.toString(;
-vscode.workspace.onDidCloseTextDocument(
-(doc) => this.highlighter.removeFileHighlightings(doc.uri.toString()));
+e.document.uri.toString();
+this.subscriptions.push(vscode.workspace.onDidCloseTextDocument(
+(doc) => this.highlighter.removeFileHighlightings(doc.uri.toString(;
   }
 
   handleNotification(params: SemanticHighlightingParams) {
@@ -103,6 +106,11 @@
 (line) => ({line : line.line, tokens : decodeTokens(line.tokens)}));
 this.highlighter.highlight(params.textDocument.uri, lines);
   }
+  // Disposes of all disposable resources used by this object.
+  public dispose() {
+this.subscriptions.forEach((d) => d.dispose());
+this.subscriptions = [];
+  }
 }
 
 // Converts a string of base64 encoded tokens into the corresponding array of
@@ -138,6 +146,13 @@
   constructor(scopeLookupTable: string[][]) {
 this.scopeLookupTable = scopeLookupTable;
   }
+  public dispose() {
+this.files.clear();
+this.decorationTypes.forEach((t) => t.dispose());
+// Dispose must not be not called multiple times if initialize is
+// called again.
+this.decorationTypes = [];
+  }
   // This function must be called at least once or no highlightings will be
   // done. Sets the theme that is used when highlighting. Also triggers a
   // recolorization for all current highlighters. Should be called whenever the
@@ -174,6 +189,27 @@
 this.applyHighlights(fileUri);
   }
 
+  // Applies all the highlightings currently stored for a file with fileUri.
+  public applyHighlights(fileUri: string) {
+if (!this.files.has(fileUri))
+  // There are no highlightings for this file, must return early or will get
+  // out of bounds when applying the decorations below.
+  return;
+if (!this.decorationTypes.length)
+  // Can't apply any decorations when there is no theme loaded.
+  return;
+// This must always do a full re-highlighting due to the fact that
+// TextEditorDecorationType are very expensive to create (which makes
+// incremental updates infeasible). For this reason one
+// TextEditorDecorationType is used per scope.
+const ranges = this.getDecorationRanges(fileUri);
+vscode.window.visibleTextEditors.forEach((e) => {
+  if (e.document.uri.toString() !== fileUri)
+return;
+  this.decorationTypes.forEach((d, i) => e.setDecorations(d, ranges[i]));
+});
+  }
+
   // Called when a text document is closed. Removes any highlighting entries for
   // the text document that was closed.
   public removeFileHighlightings(fileUri: string) {
@@ -207,27 +243,6 @@
 });
 return decorations;
   }
-
-  // Applies all the highlightings currently stored for a file with fileUri.
-  public applyHighlights(fileUri: 

[PATCH] D66516: [clangd] Added highlighting to types dependant on templates.

2019-08-28 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom marked an inline comment as done.
jvikstrom added inline comments.



Comment at: clang-tools-extra/clangd/SemanticHighlighting.cpp:177
   return;
+if (TP->isPointerType() || TP->isLValueReferenceType())
+  // When highlighting dependant template types the type can be a pointer 
or

ilya-biryukov wrote:
> ilya-biryukov wrote:
> > jvikstrom wrote:
> > > ilya-biryukov wrote:
> > > > jvikstrom wrote:
> > > > > ilya-biryukov wrote:
> > > > > > jvikstrom wrote:
> > > > > > > ilya-biryukov wrote:
> > > > > > > > `RecursiveASTVisitor` also traverses the pointer and reference 
> > > > > > > > types, why does it not reach the inner `TemplateTypeParmType` 
> > > > > > > > in the cases you describe?
> > > > > > > The D in `using D = ...` `typedef ... D` does not have a TypeLoc 
> > > > > > > (at least not one that is visited). Therefore we use the 
> > > > > > > VisitTypedefNameDecl (line 121) to get the location of `D` to be 
> > > > > > > able to highlight it. And we just send the typeLocs typeptr to 
> > > > > > > addType (which is a Pointer for `using D = T*;`)...
> > > > > > > 
> > > > > > > But maybe we should get the underlying type before we call 
> > > > > > > addType with TypePtr? Just a while loop on line 123 basically 
> > > > > > > (can we have multiple PointerTypes nested in each other actually?)
> > > > > > > 
> > > > > > > Even if we keep it in addType the comment is actually wrong, 
> > > > > > > because it obviously works when for the actual "type occurrences" 
> > > > > > > for `D` (so will fix that no matter what). This recursion will 
> > > > > > > just make us add more duplicate tokens...
> > > > > > Could we investigate why `RecursiveASTVisitor` does not visit the 
> > > > > > `TypeLoc` of a corresponding decl?
> > > > > > Here's the code from `RecursiveASTVisitor.h` that should do the 
> > > > > > trick:
> > > > > > ```
> > > > > > DEF_TRAVERSE_DECL(TypeAliasDecl, {
> > > > > >   TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
> > > > > >   // We shouldn't traverse D->getTypeForDecl(); it's a result of
> > > > > >   // declaring the type alias, not something that was written in the
> > > > > >   // source.
> > > > > > })
> > > > > > ```
> > > > > > 
> > > > > > If it doesn't, we are probably holding it wrong.
> > > > > There just doesn't seem to be a TypeLoc for the typedef'ed Decl.  We 
> > > > > can get the `T*` TypeLoc (with 
> > > > > `D->getTypeSourceInfo()->getTypeLoc()`). But there isn't one for `D`. 
> > > > > Even the `D->getTypeForDecl` returns null.
> > > > > 
> > > > > And I have no idea where I'd even start debugging that. Or if it's 
> > > > > even a bug
> > > > > 
> > > > I may have misinterpreted the patch. Are we trying to add highlightings 
> > > > for the names of using aliases here? E.g. for the following range:
> > > > ```
> > > > template 
> > > > struct Foo {
> > > >   using [[D]] = T**;
> > > > };
> > > > ```
> > > > 
> > > > Why isn't this handled in `VisitNamedDecl`?
> > > > We don't seem to call this function for `TypedefNameDecl` at all and it 
> > > > actually weird. Is this because we attempt to highlight typedefs as 
> > > > their underlying types?
> > > So currently using aliases and typedefs are highlighted the same as the 
> > > underlying type (in most cases). One case where they aren't is when the 
> > > underlying type is a template parameter (which is what this patch is 
> > > trying to solve).
> > > 
> > > 
> > > > Why isn't this handled in VisitNamedDecl?
> > > 
> > > The Decl is actually visited in `VisitNamedDecl`, however as it is a 
> > > `TypeAliasDecl` which we do not have a check for in the addToken function 
> > > it will not get highlighted in that visit.
> > > 
> > > Actually, could add a check for `TypeAliasDecl` in `addToken` (should 
> > > probably be a check for `TypedefNameDecl` to cover both `using ...` and 
> > > `typedef ...`) and move the code from the `VisitTypedefNameDecl` to the 
> > > `addToken` function inside that check instead.
> > > 
> > > 
> > > 
> > > > We don't seem to call this function for TypedefNameDecl at all and it 
> > > > actually weird. Is this because we attempt to highlight typedefs as 
> > > > their underlying types?
> > > 
> > > 
> > > Don't understand what you mean. What function? 
> > > So currently using aliases and typedefs are highlighted the same as the 
> > > underlying type (in most cases). 
> > Thanks for clarifying this. This is where my confusion is coming from.
> > A few question to try understanding the approach taken (sorry if that's too 
> > detailed, I am probably missing the context here)
> > - What do we fallback to? From my reading of the code, we do not highlight 
> > them at all if the underlying type is not one of the predefined cases.
> > - Why are pointers and **l-value** references special? What about arrays, 
> > r-value references, function types, pack expansions, etc.?
> > 
> > > Don't understand what you mean. What 

[PATCH] D66516: [clangd] Added highlighting to types dependant on templates.

2019-08-28 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom updated this revision to Diff 217618.
jvikstrom added a comment.

Added a RecursiveASTVisitor for finding 'underlying' types.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66516/new/

https://reviews.llvm.org/D66516

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
@@ -16,6 +16,10 @@
 
 namespace clang {
 namespace clangd {
+void PrintTo(const HighlightingToken , ::std::ostream *OS) {
+  *OS << "(" << T.R.start.line << ", " << T.R.start.character << ") -> (" << T.R.end.line << ", " << T.R.end.character << "): " << (int)T.Kind;
+}
+
 namespace {
 
 MATCHER_P(LineNumber, L, "") { return arg.Line == L; }
@@ -225,7 +229,9 @@
 )cpp",
 R"cpp(
   namespace $Namespace[[a]] {
-struct $Class[[A]] {};
+struct $Class[[A]] {
+  $Primitive[[void]] $Method[[foo]]($Class[[A]]*);
+};
 typedef $Primitive[[char]] $Primitive[[C]];
   }
   typedef $Namespace[[a]]::$Class[[A]] $Class[[B]];
@@ -238,6 +244,12 @@
   $Enum[[CD]] $Function[[f]]($Class[[BB]]);
   typedef $Namespace[[a]]::$Primitive[[C]] $Primitive[[PC]];
   typedef $Primitive[[float]] $Primitive[[F]];
+  using $Primitive[[Member]] =
+$Primitive[[void]] (B::*)($Namespace[[a]]::$Class[[A]]*);
+  $Primitive[[void]] $Function[[foo]]($Primitive[[int]], $Class[[B]]);
+  typedef decltype($Function[[foo]]) $Primitive[[fooo]];
+  typedef $Class[[B]] (*$Class[[func]])();
+  typedef $Primitive[[int]] (*$Primitive[[func]])();
 )cpp",
 R"cpp(
   template
@@ -431,6 +443,20 @@
 assert($Variable[[x]] != $Variable[[y]]);
 assert($Variable[[x]] != $Function[[f]]());
   }
+)cpp",
+R"cpp(
+  template
+  class $Class[[A]] {
+using $TemplateParameter[[D]] = $TemplateParameter[[T]];
+using $TemplateParameter[[DD]] = $TemplateParameter[[T]] *;
+using $TemplateParameter[[DDD]] = $TemplateParameter[[T]] &;
+using $TemplateParameter[[B]] = $TemplateParameter[[T]]*[3];
+using $TemplateParameter[[BB]] = $TemplateParameter[[T]]&&;
+using $TemplateParameter[[Member]] =
+  BB (T::*)($Primitive[[int]]);
+using $TemplateParameter[[MemberT]] =
+  $TemplateParameter[[T]]*& (T::*)($Class[[A]]);
+  };
 )cpp"};
   for (const auto  : TestCases) {
 checkHighlightings(TestCase);
Index: clang-tools-extra/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -14,12 +14,83 @@
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/TypeLoc.h"
 #include 
 
 namespace clang {
 namespace clangd {
 namespace {
 
+/// Gets an underlying type in a type hierarchy. Should be used to find the type
+/// in a hieracrchy when the HighlightingTokenCollector's RecursiveASTVisitor
+/// can not recurse to it by default and the addType function is used outside a
+/// Visit*TypeLoc.
+class UnderlyingTypeVisitor
+: public RecursiveASTVisitor {
+  const Type *Underlying;
+
+public:
+  /// Gets an underlying type in the \p T type hierarchy.
+  /// Gets the first type ptr with a Tag decl if one exists.
+  /// Else gets the first Leaf type ptr.
+  /// If neither are found returns the type ptr.
+  const Type *getUnderlyingType(QualType T) {
+Underlying = &(*T);
+TraverseType(T);
+return Underlying;
+  }
+
+  // Check if T has a tag decl and if so stop traversing the type hierachy as we
+  // want to return this.
+  bool VisitType(Type *T) {
+if (T->getAsTagDecl()) {
+  Underlying = T;
+  return false;
+}
+return true;
+  }
+
+  // The default behaviour for RecursiveASTVisitor is to traverse the class type
+  // as well. This makes member pointers become highlighted as classes which is
+  // incorrect.
+  bool TraverseMemberPointerType(MemberPointerType *T) {
+return RecursiveASTVisitor::TraverseType(
+T->getPointeeType());
+  }
+
+  // RecursiveASTVisitor does not traverse the underlying type of a decltype.
+  bool TraverseDecltypeType(DecltypeType *T) {
+return RecursiveASTVisitor::TraverseType(
+T->getUnderlyingType());
+  }
+
+  // RecursiveASTVisitor also traverses parameter and exception types. Only want
+  // return type for this.
+  bool TraverseFunctionProtoType(FunctionProtoType *T) {
+return RecursiveASTVisitor::TraverseType(
+T->getReturnType());
+  }
+
+  // 

[PATCH] D66743: [clangd] Cleans up the semantic highlighting resources if clangd crashes.

2019-08-27 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom updated this revision to Diff 217396.
jvikstrom added a comment.

Dispose of all resources when disposing.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66743/new/

https://reviews.llvm.org/D66743

Files:
  clang-tools-extra/clangd/clients/clangd-vscode/src/extension.ts
  clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
  
clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts

Index: clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
@@ -107,7 +107,8 @@
 highlighter.highlight('file1', []);
 assert.deepEqual(highlighter.applicationUriHistory, [ 'file1' ]);
 highlighter.initialize(tm);
-assert.deepEqual(highlighter.applicationUriHistory, [ 'file1', 'file1', 'file2' ]);
+assert.deepEqual(highlighter.applicationUriHistory,
+ [ 'file1', 'file1', 'file2' ]);
 // Groups decorations into the scopes used.
 let highlightingsInLine: semanticHighlighting.SemanticHighlightingLine[] = [
   {
Index: clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
@@ -56,6 +56,8 @@
   scopeLookupTable: string[][];
   // The object that applies the highlightings clangd sends.
   highlighter: Highlighter;
+  // Any disposables that should be cleaned up when clangd crashes.
+  private subscriptions: vscode.Disposable[] = [];
   fillClientCapabilities(capabilities: vscodelc.ClientCapabilities) {
 // Extend the ClientCapabilities type and add semantic highlighting
 // capability to the object.
@@ -88,14 +90,15 @@
 // otherwise it could try to update the themeRuleMatcher without the
 // highlighter being created.
 this.highlighter = new Highlighter(this.scopeLookupTable);
+this.subscriptions.push(vscode.Disposable.from(this.highlighter));
 this.loadCurrentTheme();
 // Event handling for handling with TextDocuments/Editors lifetimes.
-vscode.window.onDidChangeVisibleTextEditors(
+this.subscriptions.push(vscode.window.onDidChangeVisibleTextEditors(
 (editors: vscode.TextEditor[]) =>
 editors.forEach((e) => this.highlighter.applyHighlights(
-e.document.uri.toString(;
-vscode.workspace.onDidCloseTextDocument(
-(doc) => this.highlighter.removeFileHighlightings(doc.uri.toString()));
+e.document.uri.toString();
+this.subscriptions.push(vscode.workspace.onDidCloseTextDocument(
+(doc) => this.highlighter.removeFileHighlightings(doc.uri.toString(;
   }
 
   handleNotification(params: SemanticHighlightingParams) {
@@ -103,6 +106,11 @@
 (line) => ({line : line.line, tokens : decodeTokens(line.tokens)}));
 this.highlighter.highlight(params.textDocument.uri, lines);
   }
+  // Disposes of all disposable resources used by this object.
+  public dispose() {
+this.subscriptions.forEach((d) => d.dispose());
+this.subscriptions = [];
+  }
 }
 
 // Converts a string of base64 encoded tokens into the corresponding array of
@@ -138,6 +146,13 @@
   constructor(scopeLookupTable: string[][]) {
 this.scopeLookupTable = scopeLookupTable;
   }
+  public dispose() {
+this.files.clear();
+this.decorationTypes.forEach((t) => t.dispose());
+// Dispose must not be not called multiple times if initialize is
+// called again.
+this.decorationTypes = [];
+  }
   // This function must be called at least once or no highlightings will be
   // done. Sets the theme that is used when highlighting. Also triggers a
   // recolorization for all current highlighters. Should be called whenever the
@@ -174,6 +189,27 @@
 this.applyHighlights(fileUri);
   }
 
+  // Applies all the highlightings currently stored for a file with fileUri.
+  public applyHighlights(fileUri: string) {
+if (!this.files.has(fileUri))
+  // There are no highlightings for this file, must return early or will get
+  // out of bounds when applying the decorations below.
+  return;
+if (!this.decorationTypes.length)
+  // Can't apply any decorations when there is no theme loaded.
+  return;
+// This must always do a full re-highlighting due to the fact that
+// TextEditorDecorationType are very expensive to create (which makes
+// incremental updates infeasible). For this reason one
+// TextEditorDecorationType is used per scope.
+const ranges = this.getDecorationRanges(fileUri);
+

[PATCH] D66743: [clangd] Cleans up the semantic highlighting resources if clangd crashes.

2019-08-27 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom marked 2 inline comments as done.
jvikstrom added inline comments.



Comment at: 
clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts:114
+  // restarts.
+  public crashDispose() {
+this.disposables.forEach((d) => d.dispose());

hokein wrote:
> we just dispose some class members (leading the class to an intermediate 
> state), I'd suggest that we dispose the whole class.
> 
> nit: please remove the "clangd crashes" bit in the API.
The only thing remaining to dispose is the highlighter. Should we remove all 
highlightings if clangd restarts?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66743/new/

https://reviews.llvm.org/D66743



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D66743: [clangd] Cleans up the semantic highlighting resources if clangd crashes.

2019-08-27 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom updated this revision to Diff 217367.
jvikstrom added a comment.

Renamed disposables to subscriptions and removed clangd crashes in api.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66743/new/

https://reviews.llvm.org/D66743

Files:
  clang-tools-extra/clangd/clients/clangd-vscode/src/extension.ts
  clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
  
clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts

Index: clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
@@ -107,7 +107,8 @@
 highlighter.highlight('file1', []);
 assert.deepEqual(highlighter.applicationUriHistory, [ 'file1' ]);
 highlighter.initialize(tm);
-assert.deepEqual(highlighter.applicationUriHistory, [ 'file1', 'file1', 'file2' ]);
+assert.deepEqual(highlighter.applicationUriHistory,
+ [ 'file1', 'file1', 'file2' ]);
 // Groups decorations into the scopes used.
 let highlightingsInLine: semanticHighlighting.SemanticHighlightingLine[] = [
   {
Index: clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
@@ -56,6 +56,8 @@
   scopeLookupTable: string[][];
   // The object that applies the highlightings clangd sends.
   highlighter: Highlighter;
+  // Any disposables that should be cleaned up when clangd crashes.
+  private subscriptions: vscode.Disposable[] = [];
   fillClientCapabilities(capabilities: vscodelc.ClientCapabilities) {
 // Extend the ClientCapabilities type and add semantic highlighting
 // capability to the object.
@@ -87,15 +89,19 @@
 // Important that highlighter is created before the theme is loading as
 // otherwise it could try to update the themeRuleMatcher without the
 // highlighter being created.
-this.highlighter = new Highlighter(this.scopeLookupTable);
+if (!this.highlighter)
+  // If there already is a highlighter existing there is no need to create a
+  // new one, just reset and keep using it.
+  this.highlighter = new Highlighter(this.scopeLookupTable);
+this.highlighter.clear();
 this.loadCurrentTheme();
 // Event handling for handling with TextDocuments/Editors lifetimes.
-vscode.window.onDidChangeVisibleTextEditors(
+this.subscriptions.push(vscode.window.onDidChangeVisibleTextEditors(
 (editors: vscode.TextEditor[]) =>
 editors.forEach((e) => this.highlighter.applyHighlights(
-e.document.uri.toString(;
-vscode.workspace.onDidCloseTextDocument(
-(doc) => this.highlighter.removeFileHighlightings(doc.uri.toString()));
+e.document.uri.toString();
+this.subscriptions.push(vscode.workspace.onDidCloseTextDocument(
+(doc) => this.highlighter.removeFileHighlightings(doc.uri.toString(;
   }
 
   handleNotification(params: SemanticHighlightingParams) {
@@ -103,6 +109,12 @@
 (line) => ({line : line.line, tokens : decodeTokens(line.tokens)}));
 this.highlighter.highlight(params.textDocument.uri, lines);
   }
+  // Disposes of any resources that are not reused when if initialize is called
+  // again.
+  public restartDispose() {
+this.subscriptions.forEach((d) => d.dispose());
+this.subscriptions = [];
+  }
 }
 
 // Converts a string of base64 encoded tokens into the corresponding array of
@@ -138,6 +150,7 @@
   constructor(scopeLookupTable: string[][]) {
 this.scopeLookupTable = scopeLookupTable;
   }
+  public clear() { this.files.clear(); }
   // This function must be called at least once or no highlightings will be
   // done. Sets the theme that is used when highlighting. Also triggers a
   // recolorization for all current highlighters. Should be called whenever the
@@ -174,6 +187,27 @@
 this.applyHighlights(fileUri);
   }
 
+  // Applies all the highlightings currently stored for a file with fileUri.
+  public applyHighlights(fileUri: string) {
+if (!this.files.has(fileUri))
+  // There are no highlightings for this file, must return early or will get
+  // out of bounds when applying the decorations below.
+  return;
+if (!this.decorationTypes.length)
+  // Can't apply any decorations when there is no theme loaded.
+  return;
+// This must always do a full re-highlighting due to the fact that
+// TextEditorDecorationType are very expensive to create (which makes
+// incremental updates 

[PATCH] D66743: [clangd] Cleans up the semantic highlighting resources if clangd crashes.

2019-08-26 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom created this revision.
jvikstrom added reviewers: hokein, ilya-biryukov.
Herald added subscribers: cfe-commits, kadircet, arphaman, jkorous, MaskRay.
Herald added a project: clang.

Disposes of the vscode listeners when clangd crashes and reuses the old 
highlighter when it restarts. The reason for reusing the highlighter is because 
this way the highlightings will not disappear as we won't have to dispose of 
them.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D66743

Files:
  clang-tools-extra/clangd/clients/clangd-vscode/src/extension.ts
  clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
  
clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts

Index: clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
@@ -107,7 +107,8 @@
 highlighter.highlight('file1', []);
 assert.deepEqual(highlighter.applicationUriHistory, [ 'file1' ]);
 highlighter.initialize(tm);
-assert.deepEqual(highlighter.applicationUriHistory, [ 'file1', 'file1', 'file2' ]);
+assert.deepEqual(highlighter.applicationUriHistory,
+ [ 'file1', 'file1', 'file2' ]);
 // Groups decorations into the scopes used.
 let highlightingsInLine: semanticHighlighting.SemanticHighlightingLine[] = [
   {
Index: clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
@@ -56,6 +56,8 @@
   scopeLookupTable: string[][];
   // The object that applies the highlightings clangd sends.
   highlighter: Highlighter;
+  // Any disposables that should be cleaned up when clangd crashes.
+  private disposables: vscode.Disposable[] = [];
   fillClientCapabilities(capabilities: vscodelc.ClientCapabilities) {
 // Extend the ClientCapabilities type and add semantic highlighting
 // capability to the object.
@@ -87,15 +89,19 @@
 // Important that highlighter is created before the theme is loading as
 // otherwise it could try to update the themeRuleMatcher without the
 // highlighter being created.
-this.highlighter = new Highlighter(this.scopeLookupTable);
+if (!this.highlighter)
+  // If there already is a highlighter existing there is no need to create a
+  // new one, just reset and keep using it.
+  this.highlighter = new Highlighter(this.scopeLookupTable);
+this.highlighter.clear();
 this.loadCurrentTheme();
 // Event handling for handling with TextDocuments/Editors lifetimes.
-vscode.window.onDidChangeVisibleTextEditors(
+this.disposables.push(vscode.window.onDidChangeVisibleTextEditors(
 (editors: vscode.TextEditor[]) =>
 editors.forEach((e) => this.highlighter.applyHighlights(
-e.document.uri.toString(;
-vscode.workspace.onDidCloseTextDocument(
-(doc) => this.highlighter.removeFileHighlightings(doc.uri.toString()));
+e.document.uri.toString();
+this.disposables.push(vscode.workspace.onDidCloseTextDocument(
+(doc) => this.highlighter.removeFileHighlightings(doc.uri.toString(;
   }
 
   handleNotification(params: SemanticHighlightingParams) {
@@ -103,6 +109,12 @@
 (line) => ({line : line.line, tokens : decodeTokens(line.tokens)}));
 this.highlighter.highlight(params.textDocument.uri, lines);
   }
+  // Disposes of any resources that are not reused if clangd crashes and
+  // restarts.
+  public crashDispose() {
+this.disposables.forEach((d) => d.dispose());
+this.disposables = [];
+  }
 }
 
 // Converts a string of base64 encoded tokens into the corresponding array of
@@ -138,6 +150,7 @@
   constructor(scopeLookupTable: string[][]) {
 this.scopeLookupTable = scopeLookupTable;
   }
+  public clear() { this.files.clear(); }
   // This function must be called at least once or no highlightings will be
   // done. Sets the theme that is used when highlighting. Also triggers a
   // recolorization for all current highlighters. Should be called whenever the
@@ -174,6 +187,27 @@
 this.applyHighlights(fileUri);
   }
 
+  // Applies all the highlightings currently stored for a file with fileUri.
+  public applyHighlights(fileUri: string) {
+if (!this.files.has(fileUri))
+  // There are no highlightings for this file, must return early or will get
+  // out of bounds when applying the decorations below.
+  return;
+if (!this.decorationTypes.length)
+  // Can't apply any decorations when there is no theme loaded.
+ 

[PATCH] D66735: [clangd] Handling text editor/document lifetimes in vscode extension.

2019-08-26 Thread Johan Vikström via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
jvikstrom marked 4 inline comments as done.
Closed by commit rG1c9aa70b042b: [clangd] Handling text editor/document 
lifetimes in vscode extension. (authored by jvikstrom).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66735/new/

https://reviews.llvm.org/D66735

Files:
  clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
  
clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts

Index: clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
@@ -107,7 +107,7 @@
 highlighter.highlight('file1', []);
 assert.deepEqual(highlighter.applicationUriHistory, [ 'file1' ]);
 highlighter.initialize(tm);
-assert.deepEqual(highlighter.applicationUriHistory, [ 'file1', 'file1' ]);
+assert.deepEqual(highlighter.applicationUriHistory, [ 'file1', 'file1', 'file2' ]);
 // Groups decorations into the scopes used.
 let highlightingsInLine: semanticHighlighting.SemanticHighlightingLine[] = [
   {
@@ -129,7 +129,7 @@
 
 highlighter.highlight('file1', highlightingsInLine);
 assert.deepEqual(highlighter.applicationUriHistory,
- [ 'file1', 'file1', 'file1' ]);
+ [ 'file1', 'file1', 'file2', 'file1' ]);
 assert.deepEqual(highlighter.getDecorationRanges('file1'),
  createHighlightingScopeRanges(highlightingsInLine));
 // Keeps state separate between files.
@@ -142,18 +142,24 @@
 };
 highlighter.highlight('file2', [ highlightingsInLine1 ]);
 assert.deepEqual(highlighter.applicationUriHistory,
- [ 'file1', 'file1', 'file1', 'file2' ]);
+ [ 'file1', 'file1', 'file2', 'file1', 'file2' ]);
 assert.deepEqual(highlighter.getDecorationRanges('file2'),
  createHighlightingScopeRanges([ highlightingsInLine1 ]));
 // Does full colorizations.
 highlighter.highlight('file1', [ highlightingsInLine1 ]);
 assert.deepEqual(highlighter.applicationUriHistory,
- [ 'file1', 'file1', 'file1', 'file2', 'file1' ]);
+ [ 'file1', 'file1', 'file2', 'file1', 'file2', 'file1' ]);
 // After the incremental update to line 1, the old highlightings at line 1
 // will no longer exist in the array.
 assert.deepEqual(
 highlighter.getDecorationRanges('file1'),
 createHighlightingScopeRanges(
 [ highlightingsInLine1, ...highlightingsInLine.slice(1) ]));
+// Closing a text document removes all highlightings for the file and no
+// other files.
+highlighter.removeFileHighlightings('file1');
+assert.deepEqual(highlighter.getDecorationRanges('file1'), []);
+assert.deepEqual(highlighter.getDecorationRanges('file2'),
+ createHighlightingScopeRanges([ highlightingsInLine1 ]));
   });
 });
Index: clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
@@ -89,6 +89,13 @@
 // highlighter being created.
 this.highlighter = new Highlighter(this.scopeLookupTable);
 this.loadCurrentTheme();
+// Event handling for handling with TextDocuments/Editors lifetimes.
+vscode.window.onDidChangeVisibleTextEditors(
+(editors: vscode.TextEditor[]) =>
+editors.forEach((e) => this.highlighter.applyHighlights(
+e.document.uri.toString(;
+vscode.workspace.onDidCloseTextDocument(
+(doc) => this.highlighter.removeFileHighlightings(doc.uri.toString()));
   }
 
   handleNotification(params: SemanticHighlightingParams) {
@@ -150,12 +157,8 @@
   };
   return vscode.window.createTextEditorDecorationType(options);
 });
-this.getVisibleTextEditorUris().forEach((fileUri) => {
-  // A TextEditor might not be a cpp file. So we must check we have
-  // highlightings for the file before applying them.
-  if (this.files.has(fileUri))
-this.applyHighlights(fileUri);
-})
+this.getVisibleTextEditorUris().forEach((fileUri) =>
+this.applyHighlights(fileUri));
   }
 
   // Adds incremental highlightings to the current highlightings for the file
@@ -171,6 +174,13 @@
 this.applyHighlights(fileUri);
   }
 
+  // Called when a text document is closed. Removes any highlighting entries for
+  // the text document that was closed.
+  public 

[PATCH] D66735: [clangd] Handling text editor/document lifetimes in vscode extension.

2019-08-26 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom updated this revision to Diff 217134.
jvikstrom added a comment.

Fixed changes that weren't supposed to be made.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66735/new/

https://reviews.llvm.org/D66735

Files:
  clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
  
clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts

Index: clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
@@ -107,7 +107,7 @@
 highlighter.highlight('file1', []);
 assert.deepEqual(highlighter.applicationUriHistory, [ 'file1' ]);
 highlighter.initialize(tm);
-assert.deepEqual(highlighter.applicationUriHistory, [ 'file1', 'file1' ]);
+assert.deepEqual(highlighter.applicationUriHistory, [ 'file1', 'file1', 'file2' ]);
 // Groups decorations into the scopes used.
 let highlightingsInLine: semanticHighlighting.SemanticHighlightingLine[] = [
   {
@@ -129,7 +129,7 @@
 
 highlighter.highlight('file1', highlightingsInLine);
 assert.deepEqual(highlighter.applicationUriHistory,
- [ 'file1', 'file1', 'file1' ]);
+ [ 'file1', 'file1', 'file2', 'file1' ]);
 assert.deepEqual(highlighter.getDecorationRanges('file1'),
  createHighlightingScopeRanges(highlightingsInLine));
 // Keeps state separate between files.
@@ -142,18 +142,24 @@
 };
 highlighter.highlight('file2', [ highlightingsInLine1 ]);
 assert.deepEqual(highlighter.applicationUriHistory,
- [ 'file1', 'file1', 'file1', 'file2' ]);
+ [ 'file1', 'file1', 'file2', 'file1', 'file2' ]);
 assert.deepEqual(highlighter.getDecorationRanges('file2'),
  createHighlightingScopeRanges([ highlightingsInLine1 ]));
 // Does full colorizations.
 highlighter.highlight('file1', [ highlightingsInLine1 ]);
 assert.deepEqual(highlighter.applicationUriHistory,
- [ 'file1', 'file1', 'file1', 'file2', 'file1' ]);
+ [ 'file1', 'file1', 'file2', 'file1', 'file2', 'file1' ]);
 // After the incremental update to line 1, the old highlightings at line 1
 // will no longer exist in the array.
 assert.deepEqual(
 highlighter.getDecorationRanges('file1'),
 createHighlightingScopeRanges(
 [ highlightingsInLine1, ...highlightingsInLine.slice(1) ]));
+// Closing a text document removes all highlightings for the file and no
+// other files.
+highlighter.removeFileHighlightings('file1');
+assert.deepEqual(highlighter.getDecorationRanges('file1'), []);
+assert.deepEqual(highlighter.getDecorationRanges('file2'),
+ createHighlightingScopeRanges([ highlightingsInLine1 ]));
   });
 });
Index: clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
@@ -89,6 +89,13 @@
 // highlighter being created.
 this.highlighter = new Highlighter(this.scopeLookupTable);
 this.loadCurrentTheme();
+// Event handling for handling with TextDocuments/Editors lifetimes.
+vscode.window.onDidChangeVisibleTextEditors(
+(editors: vscode.TextEditor[]) =>
+editors.forEach((e) => this.highlighter.applyHighlights(
+e.document.uri.toString(;
+vscode.workspace.onDidCloseTextDocument(
+(doc) => this.highlighter.removeFileHighlightings(doc.uri.toString()));
   }
 
   handleNotification(params: SemanticHighlightingParams) {
@@ -150,12 +157,8 @@
   };
   return vscode.window.createTextEditorDecorationType(options);
 });
-this.getVisibleTextEditorUris().forEach((fileUri) => {
-  // A TextEditor might not be a cpp file. So we must check we have
-  // highlightings for the file before applying them.
-  if (this.files.has(fileUri))
-this.applyHighlights(fileUri);
-})
+this.getVisibleTextEditorUris().forEach((fileUri) =>
+this.applyHighlights(fileUri));
   }
 
   // Adds incremental highlightings to the current highlightings for the file
@@ -171,6 +174,13 @@
 this.applyHighlights(fileUri);
   }
 
+  // Called when a text document is closed. Removes any highlighting entries for
+  // the text document that was closed.
+  public removeFileHighlightings(fileUri: string) {
+// If there exists no entry the call to delete just returns false.
+

[PATCH] D66735: [clangd] Handling text editor/document lifetimes in vscode extension.

2019-08-26 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom updated this revision to Diff 217131.
jvikstrom added a comment.

Address comments.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66735/new/

https://reviews.llvm.org/D66735

Files:
  clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
  
clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts


Index: 
clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
===
--- 
clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
+++ 
clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
@@ -155,5 +155,11 @@
 highlighter.getDecorationRanges('file1'),
 createHighlightingScopeRanges(
 [ highlightingsInLine1, ...highlightingsInLine.slice(1) ]));
+// Closing a text document removes all highlightings for the file and no
+// other files.
+highlighter.removeHighlightings('file1');
+assert.deepEqual(highlighter.getDecorationRanges('file1'), []);
+assert.deepEqual(highlighter.getDecorationRanges('file2'),
+ createHighlightingScopeRanges([ highlightingsInLine1 ]));
   });
 });
Index: 
clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
@@ -89,6 +89,13 @@
 // highlighter being created.
 this.highlighter = new Highlighter(this.scopeLookupTable);
 this.loadCurrentTheme();
+// Event handling for handling with TextDocuments/Editors lifetimes.
+vscode.window.onDidChangeVisibleTextEditors(
+(editors: vscode.TextEditor[]) =>
+editors.forEach((e) => this.highlighter.applyHighlights(
+e.document.uri.toString(;
+vscode.workspace.onDidCloseTextDocument(
+(doc) => this.highlighter.removeHighlightings(doc.uri.toString()));
   }
 
   handleNotification(params: SemanticHighlightingParams) {
@@ -150,12 +157,8 @@
   };
   return vscode.window.createTextEditorDecorationType(options);
 });
-this.getVisibleTextEditorUris().forEach((fileUri) => {
-  // A TextEditor might not be a cpp file. So we must check we have
-  // highlightings for the file before applying them.
-  if (this.files.has(fileUri))
-this.applyHighlights(fileUri);
-})
+this.getVisibleTextEditorUris().forEach((fileUri) =>
+this.applyHighlights(fileUri));
   }
 
   // Adds incremental highlightings to the current highlightings for the file
@@ -171,6 +174,13 @@
 this.applyHighlights(fileUri);
   }
 
+  // Called when a text document is closed. Removes any highlighting entries 
for
+  // the text document that was closed.
+  public removeHighlightings(fileUri: string) {
+// If there exists no entry the call to delete just returns false.
+this.files.delete(fileUri);
+  }
+
   // Gets the uris as strings for the currently visible text editors.
   protected getVisibleTextEditorUris(): string[] {
 return vscode.window.visibleTextEditors.map((e) =>
@@ -180,6 +190,11 @@
   // Returns the ranges that should be used when decorating. Index i in the
   // range array has the decoration type at index i of this.decorationTypes.
   protected getDecorationRanges(fileUri: string): vscode.Range[][] {
+if (!this.files.has(fileUri))
+  // this.files should always have an entry for fileUri if we are here. But
+  // if there isn't one we don't want to crash the extension. This is also
+  // useful for tests.
+  return [];
 const lines: SemanticHighlightingLine[] =
 Array.from(this.files.get(fileUri).values());
 const decorations: vscode.Range[][] = this.decorationTypes.map(() => []);
@@ -193,8 +208,12 @@
 return decorations;
   }
 
-  // Applies all the highlightings currently stored for a file with fileUri.
-  protected applyHighlights(fileUri: string) {
+  // Applies all the highlightings currently stored for a file with fileUri. If
+  public applyHighlights(fileUri: string) {
+if (!this.files.has(fileUri))
+  // There are no highlightings for this file, must return early or will 
get
+  // out of bounds when applying the decorations below.
+  return;
 if (!this.decorationTypes.length)
   // Can't apply any decorations when there is no theme loaded.
   return;


Index: clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
+++ 

[PATCH] D66738: [clangd] Added highlighting for structured bindings.

2019-08-26 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom created this revision.
jvikstrom added reviewers: hokein, ilya-biryukov.
Herald added subscribers: cfe-commits, kadircet, arphaman, jkorous, MaskRay.
Herald added a project: clang.

Structured bindings are in a BindingDecl. The decl the declRefExpr points to 
are the BindingDecls. So this adds an additional if statement in the addToken 
function to highlight them. First tries to find the "underlying" decl and 
highlight as that decl (for example, if it's a field it should be highligted as 
a field). If that does not work, it will be highlighted as a variable.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D66738

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
@@ -431,6 +431,23 @@
 assert($Variable[[x]] != $Variable[[y]]);
 assert($Variable[[x]] != $Function[[f]]());
   }
+)cpp",
+R"cpp(
+  struct $Class[[S]] {
+$Primitive[[float]] $Field[[Member]];
+  };
+  $Class[[S]] $Function[[foo]]();
+  $Primitive[[void]] $Function[[f]]() {
+$Primitive[[int]] $Variable[[A]][2] = {1,2};
+auto [$Variable[[B1]], $Variable[[B2]]] = $Variable[[A]];
+auto& [$Variable[[R1]], $Variable[[R2]]] = $Variable[[A]];
+$Class[[auto]] [$Field[[M1]]] = $Class[[S]]();
+$Class[[auto]] [$Field[[F1]]] = $Function[[foo]]();
+$Field[[M1]] += 12.2;
+$Variable[[B1]] += 2;
+$Class[[S]] $Variable[[SArr]][2] = {$Class[[S]](), $Class[[S]]()};
+auto [$Variable[[S1]], $Variable[[S2]]] = $Variable[[SArr]];
+  }
 )cpp"};
   for (const auto  : TestCases) {
 checkHighlightings(TestCase);
Index: clang-tools-extra/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -229,6 +229,21 @@
   addToken(Loc, HighlightingKind::Variable);
   return;
 }
+if (const auto *B = dyn_cast(D)) {
+  // If we can find the underlying decl and highlight that we should do it.
+  // So first try to find and highlight the underlying NamedDecl for the
+  // binding if one exist.
+  if (const auto *BB = B->getBinding())
+if (const auto *RD = BB->getReferencedDeclOfCallee())
+  if (const auto *D = dyn_cast(RD)) {
+addToken(Loc, D);
+return;
+  }
+  // Could not find a more specific decl for this BindingDecl. So just
+  // highlight as a normal variable.
+  addToken(Loc, HighlightingKind::Variable);
+  return;
+}
 if (isa(D)) {
   addToken(Loc, HighlightingKind::Function);
   return;


Index: clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
===
--- clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
+++ clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
@@ -431,6 +431,23 @@
 assert($Variable[[x]] != $Variable[[y]]);
 assert($Variable[[x]] != $Function[[f]]());
   }
+)cpp",
+R"cpp(
+  struct $Class[[S]] {
+$Primitive[[float]] $Field[[Member]];
+  };
+  $Class[[S]] $Function[[foo]]();
+  $Primitive[[void]] $Function[[f]]() {
+$Primitive[[int]] $Variable[[A]][2] = {1,2};
+auto [$Variable[[B1]], $Variable[[B2]]] = $Variable[[A]];
+auto& [$Variable[[R1]], $Variable[[R2]]] = $Variable[[A]];
+$Class[[auto]] [$Field[[M1]]] = $Class[[S]]();
+$Class[[auto]] [$Field[[F1]]] = $Function[[foo]]();
+$Field[[M1]] += 12.2;
+$Variable[[B1]] += 2;
+$Class[[S]] $Variable[[SArr]][2] = {$Class[[S]](), $Class[[S]]()};
+auto [$Variable[[S1]], $Variable[[S2]]] = $Variable[[SArr]];
+  }
 )cpp"};
   for (const auto  : TestCases) {
 checkHighlightings(TestCase);
Index: clang-tools-extra/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -229,6 +229,21 @@
   addToken(Loc, HighlightingKind::Variable);
   return;
 }
+if (const auto *B = dyn_cast(D)) {
+  // If we can find the underlying decl and highlight that we should do it.
+  // So first try to find and highlight the underlying NamedDecl for the
+  // binding if one exist.
+  if (const auto *BB = B->getBinding())
+if (const auto *RD = BB->getReferencedDeclOfCallee())
+  if (const auto *D = dyn_cast(RD)) {
+addToken(Loc, D);
+  

[PATCH] D66735: [clangd] Handling text editor/document lifetimes in vscode extension.

2019-08-26 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom marked an inline comment as done.
jvikstrom added inline comments.



Comment at: 
clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts:94
+vscode.window.onDidChangeVisibleTextEditors(
+() => this.highlighter.onDidChangeVisibleTextEditors());
+vscode.workspace.onDidCloseTextDocument(

hokein wrote:
> I think we can do it like 
> `vscode.window.onDidChangeVisibleTextEditors((TextEditor[] editors) => { // 
> call applyHighlight for each text editor })`.
There might be TextEditors that are not a c++ file/haven't gotten highlightings 
yet.

So we'd still need to do the this.files.has(fileUri) check which we also do in 
the initialize function. 

Maybe I should just expose the reapplyAllHighlightings function and call that 
one instead?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66735/new/

https://reviews.llvm.org/D66735



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D66735: [clangd] Handling text editor/document lifetimes in vscode extension.

2019-08-26 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom created this revision.
jvikstrom added reviewers: hokein, ilya-biryukov.
Herald added subscribers: cfe-commits, kadircet, arphaman, jkorous, MaskRay.
Herald added a project: clang.

Just reapplies highlightings for all files when visible text editors change. 
Could find the correct text editor that should be reapplied but going for a 
simple implementation instead.
Removes the associated highlighting entry from the Colorizer when a text 
document is closed.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D66735

Files:
  clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
  
clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts


Index: 
clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
===
--- 
clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
+++ 
clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
@@ -155,5 +155,19 @@
 highlighter.getDecorationRanges('file1'),
 createHighlightingScopeRanges(
 [ highlightingsInLine1, ...highlightingsInLine.slice(1) ]));
+// Opening a text editor reapplies all highlightings.
+highlighter.onDidChangeVisibleTextEditors();
+assert.deepEqual(
+highlighter.applicationUriHistory,
+[ 'file1', 'file1', 'file1', 'file2', 'file1', 'file1', 'file2' ]);
+assert.deepEqual(
+highlighter.getDecorationRanges('file1'),
+createHighlightingScopeRanges(
+[ highlightingsInLine1, ...highlightingsInLine.slice(1) ]));
+assert.deepEqual(highlighter.getDecorationRanges('file2'),
+ createHighlightingScopeRanges([ highlightingsInLine1 ]));
+// Closing a text document removes all highlightings for the file.
+highlighter.onDidCloseTextDocument('file1');
+assert.deepEqual(highlighter.getDecorationRanges('file1'), []);
   });
 });
Index: 
clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
@@ -89,6 +89,11 @@
 // highlighter being created.
 this.highlighter = new Highlighter(this.scopeLookupTable);
 this.loadCurrentTheme();
+// Event handling for handling with TextDocuments/Editors lifetimes.
+vscode.window.onDidChangeVisibleTextEditors(
+() => this.highlighter.onDidChangeVisibleTextEditors());
+vscode.workspace.onDidCloseTextDocument(
+(doc) => this.highlighter.onDidCloseTextDocument(doc.uri.toString()));
   }
 
   handleNotification(params: SemanticHighlightingParams) {
@@ -150,12 +155,7 @@
   };
   return vscode.window.createTextEditorDecorationType(options);
 });
-this.getVisibleTextEditorUris().forEach((fileUri) => {
-  // A TextEditor might not be a cpp file. So we must check we have
-  // highlightings for the file before applying them.
-  if (this.files.has(fileUri))
-this.applyHighlights(fileUri);
-})
+this.reapplyAllHighlightings();
   }
 
   // Adds incremental highlightings to the current highlightings for the file
@@ -171,6 +171,25 @@
 this.applyHighlights(fileUri);
   }
 
+  // Called when a text document is closed. Removes any highlighting entries 
for
+  // the text document that was closed.
+  public onDidCloseTextDocument(fileUri: string) {
+// If there exists no entry the call to delete just returns false.
+this.files.delete(fileUri);
+  }
+
+  // Called when the currently visible text editors have changed. Reapplies
+  // highlightings to all visible text editors that highlightings exist for.
+  public onDidChangeVisibleTextEditors() { this.reapplyAllHighlightings(); }
+
+  protected reapplyAllHighlightings() {
+this.getVisibleTextEditorUris().forEach((fileUri) => {
+  // A TextEditor might not be a cpp file. So we must check we have
+  // highlightings for the file before applying them.
+  if (this.files.has(fileUri))
+this.applyHighlights(fileUri);
+});
+  }
   // Gets the uris as strings for the currently visible text editors.
   protected getVisibleTextEditorUris(): string[] {
 return vscode.window.visibleTextEditors.map((e) =>
@@ -180,6 +199,11 @@
   // Returns the ranges that should be used when decorating. Index i in the
   // range array has the decoration type at index i of this.decorationTypes.
   protected getDecorationRanges(fileUri: string): vscode.Range[][] {
+if (!this.files.has(fileUri))
+  // this.files should always have an entry for fileUri if we are here. But
+  // if there isn't one we don't want to crash the extension. This is also
+  // useful for tests.
+  return [];
 const lines: SemanticHighlightingLine[] =

[PATCH] D66219: [clangd] Added a colorizer to the vscode extension.

2019-08-26 Thread Johan Vikström via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
jvikstrom marked 10 inline comments as done.
Closed by commit rL369893: [clangd] Added a colorizer to the vscode extension. 
(authored by jvikstrom, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D66219?vs=217099=217115#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66219/new/

https://reviews.llvm.org/D66219

Files:
  clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/extension.ts
  
clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
  
clang-tools-extra/trunk/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts

Index: clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/extension.ts
===
--- clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/extension.ts
+++ clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/extension.ts
@@ -1,5 +1,6 @@
 import * as vscode from 'vscode';
 import * as vscodelc from 'vscode-languageclient';
+import * as semanticHighlighting from './semantic-highlighting';
 
 /**
  * Method to get workspace configuration option
@@ -108,6 +109,17 @@
 
   const clangdClient = new ClangdLanguageClient('Clang Language Server',
 serverOptions, clientOptions);
+  const semanticHighlightingFeature =
+  new semanticHighlighting.SemanticHighlightingFeature();
+  clangdClient.registerFeature(semanticHighlightingFeature);
+  // The notification handler must be registered after the client is ready or
+  // the client will crash.
+  clangdClient.onReady().then(
+  () => clangdClient.onNotification(
+  semanticHighlighting.NotificationType,
+  semanticHighlightingFeature.handleNotification.bind(
+  semanticHighlightingFeature)));
+
   console.log('Clang Language Server is now active!');
   context.subscriptions.push(clangdClient.start());
   context.subscriptions.push(vscode.commands.registerCommand(
Index: clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
===
--- clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
+++ clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
@@ -34,6 +34,13 @@
   // The TextMate scope index to the clangd scope lookup table.
   scopeIndex: number;
 }
+// A line of decoded highlightings from the data clangd sent.
+export interface SemanticHighlightingLine {
+  // The zero-based line position in the text document.
+  line: number;
+  // All SemanticHighlightingTokens on the line.
+  tokens: SemanticHighlightingToken[];
+}
 
 // Language server push notification providing the semantic highlighting
 // information for a text document.
@@ -47,8 +54,8 @@
   // The TextMate scope lookup table. A token with scope index i has the scopes
   // on index i in the lookup table.
   scopeLookupTable: string[][];
-  // The rules for the current theme.
-  themeRuleMatcher: ThemeRuleMatcher;
+  // The object that applies the highlightings clangd sends.
+  highlighter: Highlighter;
   fillClientCapabilities(capabilities: vscodelc.ClientCapabilities) {
 // Extend the ClientCapabilities type and add semantic highlighting
 // capability to the object.
@@ -61,9 +68,10 @@
   }
 
   async loadCurrentTheme() {
-this.themeRuleMatcher = new ThemeRuleMatcher(
+const themeRuleMatcher = new ThemeRuleMatcher(
 await loadTheme(vscode.workspace.getConfiguration('workbench')
 .get('colorTheme')));
+this.highlighter.initialize(themeRuleMatcher);
   }
 
   initialize(capabilities: vscodelc.ServerCapabilities,
@@ -76,10 +84,18 @@
 if (!serverCapabilities.semanticHighlighting)
   return;
 this.scopeLookupTable = serverCapabilities.semanticHighlighting.scopes;
+// Important that highlighter is created before the theme is loading as
+// otherwise it could try to update the themeRuleMatcher without the
+// highlighter being created.
+this.highlighter = new Highlighter(this.scopeLookupTable);
 this.loadCurrentTheme();
   }
 
-  handleNotification(params: SemanticHighlightingParams) {}
+  handleNotification(params: SemanticHighlightingParams) {
+const lines: SemanticHighlightingLine[] = params.lines.map(
+(line) => ({line : line.line, tokens : decodeTokens(line.tokens)}));
+this.highlighter.highlight(params.textDocument.uri, lines);
+  }
 }
 
 // Converts a string of base64 encoded tokens into the corresponding array of
@@ -101,6 +117,100 @@
   return retTokens;
 }
 
+// The main class responsible for processing of highlightings that clangd
+// sends.
+export class Highlighter {
+  // Maps uris with currently open TextDocuments to the current highlightings.

[PATCH] D66516: [clangd] Added highlighting to types dependant on templates.

2019-08-26 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom marked an inline comment as done.
jvikstrom added inline comments.



Comment at: clang-tools-extra/clangd/SemanticHighlighting.cpp:177
   return;
+if (TP->isPointerType() || TP->isLValueReferenceType())
+  // When highlighting dependant template types the type can be a pointer 
or

ilya-biryukov wrote:
> jvikstrom wrote:
> > ilya-biryukov wrote:
> > > jvikstrom wrote:
> > > > ilya-biryukov wrote:
> > > > > `RecursiveASTVisitor` also traverses the pointer and reference types, 
> > > > > why does it not reach the inner `TemplateTypeParmType` in the cases 
> > > > > you describe?
> > > > The D in `using D = ...` `typedef ... D` does not have a TypeLoc (at 
> > > > least not one that is visited). Therefore we use the 
> > > > VisitTypedefNameDecl (line 121) to get the location of `D` to be able 
> > > > to highlight it. And we just send the typeLocs typeptr to addType 
> > > > (which is a Pointer for `using D = T*;`)...
> > > > 
> > > > But maybe we should get the underlying type before we call addType with 
> > > > TypePtr? Just a while loop on line 123 basically (can we have multiple 
> > > > PointerTypes nested in each other actually?)
> > > > 
> > > > Even if we keep it in addType the comment is actually wrong, because it 
> > > > obviously works when for the actual "type occurrences" for `D` (so will 
> > > > fix that no matter what). This recursion will just make us add more 
> > > > duplicate tokens...
> > > Could we investigate why `RecursiveASTVisitor` does not visit the 
> > > `TypeLoc` of a corresponding decl?
> > > Here's the code from `RecursiveASTVisitor.h` that should do the trick:
> > > ```
> > > DEF_TRAVERSE_DECL(TypeAliasDecl, {
> > >   TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
> > >   // We shouldn't traverse D->getTypeForDecl(); it's a result of
> > >   // declaring the type alias, not something that was written in the
> > >   // source.
> > > })
> > > ```
> > > 
> > > If it doesn't, we are probably holding it wrong.
> > There just doesn't seem to be a TypeLoc for the typedef'ed Decl.  We can 
> > get the `T*` TypeLoc (with `D->getTypeSourceInfo()->getTypeLoc()`). But 
> > there isn't one for `D`. Even the `D->getTypeForDecl` returns null.
> > 
> > And I have no idea where I'd even start debugging that. Or if it's even a 
> > bug
> > 
> I may have misinterpreted the patch. Are we trying to add highlightings for 
> the names of using aliases here? E.g. for the following range:
> ```
> template 
> struct Foo {
>   using [[D]] = T**;
> };
> ```
> 
> Why isn't this handled in `VisitNamedDecl`?
> We don't seem to call this function for `TypedefNameDecl` at all and it 
> actually weird. Is this because we attempt to highlight typedefs as their 
> underlying types?
So currently using aliases and typedefs are highlighted the same as the 
underlying type (in most cases). One case where they aren't is when the 
underlying type is a template parameter (which is what this patch is trying to 
solve).


> Why isn't this handled in VisitNamedDecl?

The Decl is actually visited in `VisitNamedDecl`, however as it is a 
`TypeAliasDecl` which we do not have a check for in the addToken function it 
will not get highlighted in that visit.

Actually, could add a check for `TypeAliasDecl` in `addToken` (should probably 
be a check for `TypedefNameDecl` to cover both `using ...` and `typedef ...`) 
and move the code from the `VisitTypedefNameDecl` to the `addToken` function 
inside that check instead.



> We don't seem to call this function for TypedefNameDecl at all and it 
> actually weird. Is this because we attempt to highlight typedefs as their 
> underlying types?


Don't understand what you mean. What function? 


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66516/new/

https://reviews.llvm.org/D66516



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D66219: [clangd] Added a colorizer to the vscode extension.

2019-08-26 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom added inline comments.



Comment at: 
clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts:135
+  // Update the themeRuleMatcher that is used when highlighting. Also triggers 
a
+  // recolorization for all current highlighters. Safe to call multiple times.
+  public initialize(themeRuleMatcher: ThemeRuleMatcher) {

hokein wrote:
> nit: the comment is stale now.  I believe this function is only called 
> whenever we reload a theme or at the first launch of the extension.
It's should only called when a theme is loaded (and we happen to load a theme 
when we initialize, but it's async).
Don't see why the comment is stale though, it seems to describe what it does to 
me.



Comment at: 
clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts:139
+  const options: vscode.DecorationRenderOptions = {
+color : themeRuleMatcher.getBestThemeRule(scopes[0]).foreground,
+// If the rangeBehavior is set to Open in any direction the

hokein wrote:
> just want to confirm: if we fail to find a matched theme rule, we return an 
> empty decoration. I think vscode just doesn't do anything on an empty color?
vscode indeed does not do anything on empty colors.



Comment at: 
clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts:94
+let line = [
+  {character : 1, length : 2, scopeIndex : 1},
+  {character : 5, length : 2, scopeIndex : 1},

hokein wrote:
> I believe the test code is correct, but the code here/below is complex and 
> hard to follow. I think we need make the code more readable/understandable.
> 
> some suggestions:
> 
> - the line number is implicitly indicated by the index of the array, I think 
> we can add one more field `line` to the structure (call HighlightingTokens).
> - and creates some helper functions (with proper names) that take the 
> `HighlightingTokens` as parameter and generate the data you need e.g. 
> `SemanticHighlightingLine[]`, `vscode.Range`.
> 
Started exporting the `SemanticHighlightingLine` interface and use that format 
in the tests to not create more interfaces (also means we don't need a helper 
for creating the SemanticHighlightingLine).


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66219/new/

https://reviews.llvm.org/D66219



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D66219: [clangd] Added a colorizer to the vscode extension.

2019-08-26 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom updated this revision to Diff 217099.
jvikstrom marked 12 inline comments as done.
jvikstrom added a comment.

Made tests more readable.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66219/new/

https://reviews.llvm.org/D66219

Files:
  clang-tools-extra/clangd/clients/clangd-vscode/src/extension.ts
  clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
  
clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts

Index: clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
@@ -1,13 +1,15 @@
 import * as assert from 'assert';
 import * as path from 'path';
+import * as vscode from 'vscode';
 
-import * as SM from '../src/semantic-highlighting';
+import * as semanticHighlighting from '../src/semantic-highlighting';
 
 suite('SemanticHighlighting Tests', () => {
   test('Parses arrays of textmate themes.', async () => {
 const themePath =
 path.join(__dirname, '../../test/assets/includeTheme.jsonc');
-const scopeColorRules = await SM.parseThemeFile(themePath);
+const scopeColorRules =
+await semanticHighlighting.parseThemeFile(themePath);
 const getScopeRule = (scope: string) =>
 scopeColorRules.find((v) => v.scope === scope);
 assert.equal(scopeColorRules.length, 3);
@@ -32,8 +34,9 @@
 {character : 10, scopeIndex : 0, length : 1}
   ]
 ];
-testCases.forEach((testCase, i) => assert.deepEqual(
-  SM.decodeTokens(testCase), expected[i]));
+testCases.forEach(
+(testCase, i) => assert.deepEqual(
+semanticHighlighting.decodeTokens(testCase), expected[i]));
   });
   test('ScopeRules overrides for more specific themes', () => {
 const rules = [
@@ -44,7 +47,7 @@
   {scope : 'storage', foreground : '5'},
   {scope : 'variable.other.parameter', foreground : '6'},
 ];
-const tm = new SM.ThemeRuleMatcher(rules);
+const tm = new semanticHighlighting.ThemeRuleMatcher(rules);
 assert.deepEqual(tm.getBestThemeRule('variable.other.cpp').scope,
  'variable.other');
 assert.deepEqual(tm.getBestThemeRule('storage.static').scope,
@@ -57,4 +60,103 @@
 assert.deepEqual(tm.getBestThemeRule('variable.other.parameter.cpp').scope,
  'variable.other.parameter');
   });
+  test('Colorizer groups decorations correctly', async () => {
+// Helper for creating a vscode Range.
+const createRange = (line: number, startCharacter: number,
+ length: number) =>
+new vscode.Range(new vscode.Position(line, startCharacter),
+ new vscode.Position(line, startCharacter + length));
+const scopeTable = [
+  [ 'variable' ], [ 'entity.type.function' ],
+  [ 'entity.type.function.method' ]
+];
+// Create the scope source ranges the highlightings should be highlighted
+// at. Assumes the scopes used are the ones in the "scopeTable" variable.
+const createHighlightingScopeRanges =
+(highlightingLines:
+ semanticHighlighting.SemanticHighlightingLine[]) => {
+  // Initialize the scope ranges list to the correct size. Otherwise
+  // scopes that don't have any highlightings are missed.
+  let scopeRanges: vscode.Range[][] = scopeTable.map(() => []);
+  highlightingLines.forEach((line) => {
+line.tokens.forEach((token) => {
+  scopeRanges[token.scopeIndex].push(
+  createRange(line.line, token.character, token.length));
+});
+  });
+  return scopeRanges;
+};
+
+const rules = [
+  {scope : 'variable', foreground : '1'},
+  {scope : 'entity.type', foreground : '2'},
+];
+class MockHighlighter extends semanticHighlighting.Highlighter {
+  applicationUriHistory: string[] = [];
+  // Override to make the highlighting calls accessible to the test. Also makes the test not depend on visible text editors.
+  applyHighlights(fileUri: string) {
+this.applicationUriHistory.push(fileUri);
+  }
+  // Override to make it accessible from the test.
+  getDecorationRanges(fileUri: string) {
+return super.getDecorationRanges(fileUri);
+  }
+  // Override to make tests not depend on visible text editors.
+  getVisibleTextEditorUris() { return [ 'a', 'b' ]; }
+}
+const highlighter = new MockHighlighter(scopeTable);
+const tm = new semanticHighlighting.ThemeRuleMatcher(rules);
+// Recolorizes when initialized.
+highlighter.highlight('a', []);
+assert.deepEqual(highlighter.applicationUriHistory, [ 'a' ]);
+

[PATCH] D66516: [clangd] Added highlighting to types dependant on templates.

2019-08-22 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom marked an inline comment as done.
jvikstrom added inline comments.



Comment at: clang-tools-extra/clangd/SemanticHighlighting.cpp:177
   return;
+if (TP->isPointerType() || TP->isLValueReferenceType())
+  // When highlighting dependant template types the type can be a pointer 
or

ilya-biryukov wrote:
> jvikstrom wrote:
> > ilya-biryukov wrote:
> > > `RecursiveASTVisitor` also traverses the pointer and reference types, why 
> > > does it not reach the inner `TemplateTypeParmType` in the cases you 
> > > describe?
> > The D in `using D = ...` `typedef ... D` does not have a TypeLoc (at least 
> > not one that is visited). Therefore we use the VisitTypedefNameDecl (line 
> > 121) to get the location of `D` to be able to highlight it. And we just 
> > send the typeLocs typeptr to addType (which is a Pointer for `using D = 
> > T*;`)...
> > 
> > But maybe we should get the underlying type before we call addType with 
> > TypePtr? Just a while loop on line 123 basically (can we have multiple 
> > PointerTypes nested in each other actually?)
> > 
> > Even if we keep it in addType the comment is actually wrong, because it 
> > obviously works when for the actual "type occurrences" for `D` (so will fix 
> > that no matter what). This recursion will just make us add more duplicate 
> > tokens...
> Could we investigate why `RecursiveASTVisitor` does not visit the `TypeLoc` 
> of a corresponding decl?
> Here's the code from `RecursiveASTVisitor.h` that should do the trick:
> ```
> DEF_TRAVERSE_DECL(TypeAliasDecl, {
>   TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
>   // We shouldn't traverse D->getTypeForDecl(); it's a result of
>   // declaring the type alias, not something that was written in the
>   // source.
> })
> ```
> 
> If it doesn't, we are probably holding it wrong.
There just doesn't seem to be a TypeLoc for the typedef'ed Decl.  We can get 
the `T*` TypeLoc (with `D->getTypeSourceInfo()->getTypeLoc()`). But there isn't 
one for `D`. Even the `D->getTypeForDecl` returns null.

And I have no idea where I'd even start debugging that. Or if it's even a bug



Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66516/new/

https://reviews.llvm.org/D66516



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D66219: [clangd] Added a colorizer to the vscode extension.

2019-08-22 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom updated this revision to Diff 216624.
jvikstrom added a comment.

Added missing protected and comment.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66219/new/

https://reviews.llvm.org/D66219

Files:
  clang-tools-extra/clangd/clients/clangd-vscode/src/extension.ts
  clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
  
clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts

Index: clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
@@ -1,5 +1,6 @@
 import * as assert from 'assert';
 import * as path from 'path';
+import * as vscode from 'vscode';
 
 import * as SM from '../src/semantic-highlighting';
 
@@ -57,4 +58,71 @@
 assert.deepEqual(tm.getBestThemeRule('variable.other.parameter.cpp').scope,
  'variable.other.parameter');
   });
+  test('Colorizer groups decorations correctly', async () => {
+// Helper for creating a vscode Range.
+const createRange = (line: number, startCharacter: number,
+ length: number) =>
+new vscode.Range(new vscode.Position(line, startCharacter),
+ new vscode.Position(line, startCharacter + length));
+const scopeTable = [
+  [ 'variable' ], [ 'entity.type.function' ],
+  [ 'entity.type.function.method' ]
+];
+const rules = [
+  {scope : 'variable', foreground : '1'},
+  {scope : 'entity.type', foreground : '2'},
+];
+class MockHighlighter extends SM.Highlighter {
+  applicationUriHistory: string[] = [];
+  applyHighlights(fileUri: string) {
+this.applicationUriHistory.push(fileUri);
+  }
+  getDecorationRanges(fileUri: string) {
+return super.getDecorationRanges(fileUri);
+  }
+  getVisibleTextEditorUris() { return [ 'a', 'b' ]; }
+}
+const highlighter = new MockHighlighter(scopeTable);
+const tm = new SM.ThemeRuleMatcher(rules);
+// Recolorizes when initialized.
+highlighter.highlight('a', []);
+assert.deepEqual(highlighter.applicationUriHistory, [ 'a' ]);
+highlighter.initialize(tm);
+assert.deepEqual(highlighter.applicationUriHistory, [ 'a', 'a' ]);
+// Groups decorations into the scopes used.
+let line = [
+  {character : 1, length : 2, scopeIndex : 1},
+  {character : 5, length : 2, scopeIndex : 1},
+  {character : 10, length : 2, scopeIndex : 2}
+];
+highlighter.highlight(
+'a', [ {line : 1, tokens : line}, {line : 2, tokens : line} ]);
+assert.deepEqual(highlighter.applicationUriHistory, [ 'a', 'a', 'a' ]);
+assert.deepEqual(highlighter.getDecorationRanges('a'), [
+  [],
+  [
+createRange(1, 1, 2), createRange(1, 5, 2), createRange(2, 1, 2),
+createRange(2, 5, 2)
+  ],
+  [ createRange(1, 10, 2), createRange(2, 10, 2) ],
+]);
+// Keeps state separate between files.
+highlighter.highlight('b', [
+  {line : 1, tokens : [ {character : 1, length : 1, scopeIndex : 0} ]}
+]);
+assert.deepEqual(highlighter.applicationUriHistory, [ 'a', 'a', 'a', 'b' ]);
+assert.deepEqual(highlighter.getDecorationRanges('b'),
+ [ [ createRange(1, 1, 1) ], [], [] ]);
+// Does full colorizations.
+highlighter.highlight('a', [
+  {line : 1, tokens : [ {character : 2, length : 1, scopeIndex : 0} ]}
+]);
+assert.deepEqual(highlighter.applicationUriHistory,
+ [ 'a', 'a', 'a', 'b', 'a' ]);
+assert.deepEqual(highlighter.getDecorationRanges('a'), [
+  [ createRange(1, 2, 1) ],
+  [ createRange(2, 1, 2), createRange(2, 5, 2) ],
+  [ createRange(2, 10, 2) ],
+]);
+  });
 });
Index: clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
@@ -34,6 +34,13 @@
   // The TextMate scope index to the clangd scope lookup table.
   scopeIndex: number;
 }
+// A line of decoded highlightings from the data clangd sent.
+interface SemanticHighlightingLine {
+  // The zero-based line position in the text document.
+  line: number;
+  // All SemanticHighlightingTokens on the line.
+  tokens: SemanticHighlightingToken[];
+}
 
 // Language server push notification providing the semantic highlighting
 // information for a text document.
@@ -49,6 +56,8 @@
   scopeLookupTable: string[][];
   // The rules for the current theme.
   themeRuleMatcher: ThemeRuleMatcher;
+  // The object that applies the highlightings clangd sends.
+  

[PATCH] D66219: [clangd] Added a colorizer to the vscode extension.

2019-08-22 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom added a comment.

I had completely forgotten we could just override the applyHighlightings method 
in the tests, everything is much simpler now.

Basically this entire CL was rewritten just now.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66219/new/

https://reviews.llvm.org/D66219



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D66219: [clangd] Added a colorizer to the vscode extension.

2019-08-22 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom updated this revision to Diff 216621.
jvikstrom marked 6 inline comments as done.
jvikstrom added a comment.

Rewrote the Highlighter class as we can override the highlighting method for 
the tests.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66219/new/

https://reviews.llvm.org/D66219

Files:
  clang-tools-extra/clangd/clients/clangd-vscode/src/extension.ts
  clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
  
clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts

Index: clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
@@ -1,5 +1,6 @@
 import * as assert from 'assert';
 import * as path from 'path';
+import * as vscode from 'vscode';
 
 import * as SM from '../src/semantic-highlighting';
 
@@ -57,4 +58,71 @@
 assert.deepEqual(tm.getBestThemeRule('variable.other.parameter.cpp').scope,
  'variable.other.parameter');
   });
+  test('Colorizer groups decorations correctly', async () => {
+// Helper for creating a vscode Range.
+const createRange = (line: number, startCharacter: number,
+ length: number) =>
+new vscode.Range(new vscode.Position(line, startCharacter),
+ new vscode.Position(line, startCharacter + length));
+const scopeTable = [
+  [ 'variable' ], [ 'entity.type.function' ],
+  [ 'entity.type.function.method' ]
+];
+const rules = [
+  {scope : 'variable', foreground : '1'},
+  {scope : 'entity.type', foreground : '2'},
+];
+class MockHighlighter extends SM.Highlighter {
+  applicationUriHistory: string[] = [];
+  applyHighlights(fileUri: string) {
+this.applicationUriHistory.push(fileUri);
+  }
+  getDecorationRanges(fileUri: string) {
+return super.getDecorationRanges(fileUri);
+  }
+  getVisibleTextEditorUris() { return [ 'a', 'b' ]; }
+}
+const highlighter = new MockHighlighter(scopeTable);
+const tm = new SM.ThemeRuleMatcher(rules);
+// Recolorizes when initialized.
+highlighter.highlight('a', []);
+assert.deepEqual(highlighter.applicationUriHistory, [ 'a' ]);
+highlighter.initialize(tm);
+assert.deepEqual(highlighter.applicationUriHistory, [ 'a', 'a' ]);
+// Groups decorations into the scopes used.
+let line = [
+  {character : 1, length : 2, scopeIndex : 1},
+  {character : 5, length : 2, scopeIndex : 1},
+  {character : 10, length : 2, scopeIndex : 2}
+];
+highlighter.highlight(
+'a', [ {line : 1, tokens : line}, {line : 2, tokens : line} ]);
+assert.deepEqual(highlighter.applicationUriHistory, [ 'a', 'a', 'a' ]);
+assert.deepEqual(highlighter.getDecorationRanges('a'), [
+  [],
+  [
+createRange(1, 1, 2), createRange(1, 5, 2), createRange(2, 1, 2),
+createRange(2, 5, 2)
+  ],
+  [ createRange(1, 10, 2), createRange(2, 10, 2) ],
+]);
+// Keeps state separate between files.
+highlighter.highlight('b', [
+  {line : 1, tokens : [ {character : 1, length : 1, scopeIndex : 0} ]}
+]);
+assert.deepEqual(highlighter.applicationUriHistory, [ 'a', 'a', 'a', 'b' ]);
+assert.deepEqual(highlighter.getDecorationRanges('b'),
+ [ [ createRange(1, 1, 1) ], [], [] ]);
+// Does full colorizations.
+highlighter.highlight('a', [
+  {line : 1, tokens : [ {character : 2, length : 1, scopeIndex : 0} ]}
+]);
+assert.deepEqual(highlighter.applicationUriHistory,
+ [ 'a', 'a', 'a', 'b', 'a' ]);
+assert.deepEqual(highlighter.getDecorationRanges('a'), [
+  [ createRange(1, 2, 1) ],
+  [ createRange(2, 1, 2), createRange(2, 5, 2) ],
+  [ createRange(2, 10, 2) ],
+]);
+  });
 });
Index: clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
@@ -34,6 +34,13 @@
   // The TextMate scope index to the clangd scope lookup table.
   scopeIndex: number;
 }
+// A line of decoded highlightings from the data clangd sent.
+interface SemanticHighlightingLine {
+  // The zero-based line position in the text document.
+  line: number;
+  // All SemanticHighlightingTokens on the line.
+  tokens: SemanticHighlightingToken[];
+}
 
 // Language server push notification providing the semantic highlighting
 // information for a text document.
@@ -49,6 +56,8 @@
   scopeLookupTable: string[][];
   // The rules for the current theme.
   

[PATCH] D66541: [clangd] Send highlighting diff beyond the end of the file.

2019-08-22 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom accepted this revision.
jvikstrom added a comment.
This revision is now accepted and ready to land.

It feels a bit strange to be sending highlighting (even if they are empty)  
beyond eof. But I guess the proposal does not specify this and it would make 
life for the vscode extension (much) simpler.
Theia also does not crash from this and if we apply decorations to vscode 
outside the file nothing happens as well so I guess it should be fine. (even 
when vscode finally implements this feature into lsp)

Just had the comment about comparing HighlightigLine objects instead of using 
matchers but up to you.




Comment at: clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp:625
+  testing::UnorderedElementsAre(
+  testing::AllOf(LineNumber(3), EmptyHighlightings()),
+  testing::AllOf(LineNumber(4), EmptyHighlightings(;

Maybe create the HighlightingLine objects for Line 3 and 4 and add them 
directly in the `UnorderedElementsAre` because then we don't have to create the 
matchers.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66541/new/

https://reviews.llvm.org/D66541



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D66516: [clangd] Added highlighting to types dependant on templates.

2019-08-21 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom marked an inline comment as done.
jvikstrom added inline comments.



Comment at: clang-tools-extra/clangd/SemanticHighlighting.cpp:177
   return;
+if (TP->isPointerType() || TP->isLValueReferenceType())
+  // When highlighting dependant template types the type can be a pointer 
or

ilya-biryukov wrote:
> `RecursiveASTVisitor` also traverses the pointer and reference types, why 
> does it not reach the inner `TemplateTypeParmType` in the cases you describe?
The D in `using D = ...` `typedef ... D` does not have a TypeLoc (at least not 
one that is visited). Therefore we use the VisitTypedefNameDecl (line 121) to 
get the location of `D` to be able to highlight it. And we just send the 
typeLocs typeptr to addType (which is a Pointer for `using D = T*;`)...

But maybe we should get the underlying type before we call addType with 
TypePtr? Just a while loop on line 123 basically (can we have multiple 
PointerTypes nested in each other actually?)

Even if we keep it in addType the comment is actually wrong, because it 
obviously works when for the actual "type occurrences" for `D` (so will fix 
that no matter what). This recursion will just make us add more duplicate 
tokens...


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66516/new/

https://reviews.llvm.org/D66516



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D66516: [clangd] Added highlighting to types dependant on templates.

2019-08-21 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom created this revision.
jvikstrom added reviewers: hokein, ilya-biryukov.
Herald added subscribers: cfe-commits, kadircet, arphaman, jkorous, MaskRay, 
kristof.beyls, javed.absar.
Herald added a project: clang.

Types dependant on templates did not get highlighted properly. This is because 
the TemplateTypeParmType does not contain a TagDecl and was special cased in 
the Visit* function, not in the addType function. Moved the spec
ial casing to the addType function to solve this.
addType is now also checking if a type is a pointer type and recursing to the 
underlying type if it is. Otherwise for example, `using D = T*;` would not get 
highlighted.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D66516

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
@@ -427,6 +427,14 @@
 assert($Variable[[x]] != $Variable[[y]]);
 assert($Variable[[x]] != $Function[[f]]());
   }
+)cpp",
+R"cpp(
+  template
+  class $Class[[A]] {
+using $TemplateParameter[[D]] = $TemplateParameter[[T]];
+using $TemplateParameter[[DD]] = $TemplateParameter[[T]] *;
+using $TemplateParameter[[DDD]] = $TemplateParameter[[T]] &;
+  };
 )cpp"};
   for (const auto  : TestCases) {
 checkHighlightings(TestCase);
Index: clang-tools-extra/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -14,6 +14,7 @@
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/Type.h"
 #include 
 
 namespace clang {
@@ -123,12 +124,6 @@
 return true;
   }
 
-  bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc ) {
-// TemplateTypeParmTypeLoc does not have a TagDecl in its type ptr.
-addToken(TL.getBeginLoc(), TL.getDecl());
-return true;
-  }
-
   bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc ) {
 if (const TemplateDecl *TD =
 TL.getTypePtr()->getTemplateName().getAsTemplateDecl())
@@ -179,9 +174,17 @@
   void addType(SourceLocation Loc, const Type *TP) {
 if (!TP)
   return;
+if (TP->isPointerType() || TP->isLValueReferenceType())
+  // When highlighting dependant template types the type can be a pointer 
or
+  // reference of a template type. To highlight that type we need to get to
+  // the underlying type.
+  addType(Loc, TP->getPointeeType().getTypePtr());
 if (TP->isBuiltinType())
   // Builtins must be special cased as they do not have a TagDecl.
   addToken(Loc, HighlightingKind::Primitive);
+if (const TemplateTypeParmType *TD = dyn_cast(TP))
+  // TemplateTypeParmType does not have a TagDecl.
+  addToken(Loc, TD->getDecl());
 if (const TagDecl *TD = TP->getAsTagDecl())
   addToken(Loc, TD);
   }


Index: clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
===
--- clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
+++ clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
@@ -427,6 +427,14 @@
 assert($Variable[[x]] != $Variable[[y]]);
 assert($Variable[[x]] != $Function[[f]]());
   }
+)cpp",
+R"cpp(
+  template
+  class $Class[[A]] {
+using $TemplateParameter[[D]] = $TemplateParameter[[T]];
+using $TemplateParameter[[DD]] = $TemplateParameter[[T]] *;
+using $TemplateParameter[[DDD]] = $TemplateParameter[[T]] &;
+  };
 )cpp"};
   for (const auto  : TestCases) {
 checkHighlightings(TestCase);
Index: clang-tools-extra/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -14,6 +14,7 @@
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/Type.h"
 #include 
 
 namespace clang {
@@ -123,12 +124,6 @@
 return true;
   }
 
-  bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc ) {
-// TemplateTypeParmTypeLoc does not have a TagDecl in its type ptr.
-addToken(TL.getBeginLoc(), TL.getDecl());
-return true;
-  }
-
   bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc ) {
 if (const TemplateDecl *TD =
 TL.getTypePtr()->getTemplateName().getAsTemplateDecl())
@@ -179,9 +174,17 @@
   void addType(SourceLocation Loc, const Type 

[PATCH] D66470: [Syntax] Added function to get macro expansion tokens to TokenBuffer.

2019-08-20 Thread Johan Vikström via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
jvikstrom marked 2 inline comments as done.
Closed by commit rL369385: [Syntax] Added function to get macro expansion 
tokens to TokenBuffer. (authored by jvikstrom, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D66470?vs=216103=216135#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66470/new/

https://reviews.llvm.org/D66470

Files:
  cfe/trunk/include/clang/Tooling/Syntax/Tokens.h
  cfe/trunk/lib/Tooling/Syntax/Tokens.cpp
  cfe/trunk/unittests/Tooling/Syntax/TokensTest.cpp


Index: cfe/trunk/lib/Tooling/Syntax/Tokens.cpp
===
--- cfe/trunk/lib/Tooling/Syntax/Tokens.cpp
+++ cfe/trunk/lib/Tooling/Syntax/Tokens.cpp
@@ -232,6 +232,21 @@
   return E;
 }
 
+std::vector
+TokenBuffer::macroExpansions(FileID FID) const {
+  auto FileIt = Files.find(FID);
+  assert(FileIt != Files.end() && "file not tracked by token buffer");
+  auto  = FileIt->second;
+  std::vector Expansions;
+  auto  = File.SpelledTokens;
+  for (auto Mapping : File.Mappings) {
+const syntax::Token *Token = [Mapping.BeginSpelled];
+if (Token->kind() == tok::TokenKind::identifier)
+  Expansions.push_back(Token);
+  }
+  return Expansions;
+}
+
 std::vector syntax::tokenize(FileID FID, const SourceManager 
,
 const LangOptions ) {
   std::vector Tokens;
Index: cfe/trunk/unittests/Tooling/Syntax/TokensTest.cpp
===
--- cfe/trunk/unittests/Tooling/Syntax/TokensTest.cpp
+++ cfe/trunk/unittests/Tooling/Syntax/TokensTest.cpp
@@ -755,4 +755,27 @@
   // We don't test assertion failures because death tests are slow.
 }
 
+TEST_F(TokenBufferTest, macroExpansions) {
+  llvm::Annotations Code(R"cpp(
+#define FOO B
+#define FOO2 BA
+#define CALL(X) int X
+#define G CALL(FOO2)
+int B;
+$macro[[FOO]];
+$macro[[CALL]](A);
+$macro[[G]];
+  )cpp");
+  recordTokens(Code.code());
+  auto  = *SourceMgr;
+  auto Expansions = Buffer.macroExpansions(SM.getMainFileID());
+  std::vector ExpectedMacroRanges;
+  for (auto Range : Code.ranges("macro"))
+ExpectedMacroRanges.push_back(
+FileRange(SM.getMainFileID(), Range.Begin, Range.End));
+  std::vector ActualMacroRanges;
+  for (auto Expansion : Expansions)
+ActualMacroRanges.push_back(Expansion->range(SM));
+  EXPECT_EQ(ExpectedMacroRanges, ActualMacroRanges);
+}
 } // namespace
Index: cfe/trunk/include/clang/Tooling/Syntax/Tokens.h
===
--- cfe/trunk/include/clang/Tooling/Syntax/Tokens.h
+++ cfe/trunk/include/clang/Tooling/Syntax/Tokens.h
@@ -236,6 +236,16 @@
   ///#pragma, etc.
   llvm::ArrayRef spelledTokens(FileID FID) const;
 
+  /// Get all tokens that expand a macro in \p FID. For the following input
+  /// #define FOO B
+  /// #define FOO2(X) int X
+  /// FOO2(XY)
+  /// int B;
+  /// FOO;
+  /// macroExpansions() returns {"FOO2", "FOO"} (from line 3 and 5
+  /// respecitvely).
+  std::vector macroExpansions(FileID FID) const;
+
   const SourceManager () const { return *SourceMgr; }
 
   std::string dumpForTests() const;


Index: cfe/trunk/lib/Tooling/Syntax/Tokens.cpp
===
--- cfe/trunk/lib/Tooling/Syntax/Tokens.cpp
+++ cfe/trunk/lib/Tooling/Syntax/Tokens.cpp
@@ -232,6 +232,21 @@
   return E;
 }
 
+std::vector
+TokenBuffer::macroExpansions(FileID FID) const {
+  auto FileIt = Files.find(FID);
+  assert(FileIt != Files.end() && "file not tracked by token buffer");
+  auto  = FileIt->second;
+  std::vector Expansions;
+  auto  = File.SpelledTokens;
+  for (auto Mapping : File.Mappings) {
+const syntax::Token *Token = [Mapping.BeginSpelled];
+if (Token->kind() == tok::TokenKind::identifier)
+  Expansions.push_back(Token);
+  }
+  return Expansions;
+}
+
 std::vector syntax::tokenize(FileID FID, const SourceManager ,
 const LangOptions ) {
   std::vector Tokens;
Index: cfe/trunk/unittests/Tooling/Syntax/TokensTest.cpp
===
--- cfe/trunk/unittests/Tooling/Syntax/TokensTest.cpp
+++ cfe/trunk/unittests/Tooling/Syntax/TokensTest.cpp
@@ -755,4 +755,27 @@
   // We don't test assertion failures because death tests are slow.
 }
 
+TEST_F(TokenBufferTest, macroExpansions) {
+  llvm::Annotations Code(R"cpp(
+#define FOO B
+#define FOO2 BA
+#define CALL(X) int X
+#define G CALL(FOO2)
+int B;
+$macro[[FOO]];
+$macro[[CALL]](A);
+$macro[[G]];
+  )cpp");
+  recordTokens(Code.code());
+  auto  = *SourceMgr;
+  auto Expansions = Buffer.macroExpansions(SM.getMainFileID());
+  std::vector ExpectedMacroRanges;

[PATCH] D66470: [Syntax] Added function to get macro expansion tokens to TokenBuffer.

2019-08-20 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom updated this revision to Diff 216103.
jvikstrom added a comment.

Readded dissapeared newline.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66470/new/

https://reviews.llvm.org/D66470

Files:
  clang/include/clang/Tooling/Syntax/Tokens.h
  clang/lib/Tooling/Syntax/Tokens.cpp
  clang/unittests/Tooling/Syntax/TokensTest.cpp


Index: clang/unittests/Tooling/Syntax/TokensTest.cpp
===
--- clang/unittests/Tooling/Syntax/TokensTest.cpp
+++ clang/unittests/Tooling/Syntax/TokensTest.cpp
@@ -755,4 +755,27 @@
   // We don't test assertion failures because death tests are slow.
 }
 
+TEST_F(TokenBufferTest, macroExpansions) {
+  llvm::Annotations Code(R"cpp(
+#define FOO B
+#define FOO2 BA
+#define CALL(X) int X
+#define G CALL(FOO2)
+int B;
+$macro[[FOO]];
+$macro[[CALL]](A);
+$macro[[G]];
+  )cpp");
+  recordTokens(Code.code());
+  auto  = *SourceMgr;
+  auto Expansions = Buffer.macroExpansions(SM.getMainFileID());
+  std::vector ExpectedMacroRanges;
+  for (auto Range : Code.ranges("macro"))
+ExpectedMacroRanges.push_back(
+FileRange(SM.getMainFileID(), Range.Begin, Range.End));
+  std::vector ActualMacroRanges;
+  for (auto Expansion : Expansions)
+ActualMacroRanges.push_back(Expansion->range(SM));
+  EXPECT_EQ(ExpectedMacroRanges, ActualMacroRanges);
+}
 } // namespace
Index: clang/lib/Tooling/Syntax/Tokens.cpp
===
--- clang/lib/Tooling/Syntax/Tokens.cpp
+++ clang/lib/Tooling/Syntax/Tokens.cpp
@@ -232,6 +232,21 @@
   return E;
 }
 
+std::vector
+TokenBuffer::macroExpansions(FileID FID) const {
+  auto FileIt = Files.find(FID);
+  assert(FileIt != Files.end() && "file not tracked by token buffer");
+  auto  = FileIt->second;
+  std::vector Expansions;
+  auto  = File.SpelledTokens;
+  for (auto Mapping : File.Mappings) {
+const syntax::Token *Token = [Mapping.BeginSpelled];
+if (Token->kind() == tok::TokenKind::identifier)
+  Expansions.push_back(Token);
+  }
+  return Expansions;
+}
+
 std::vector syntax::tokenize(FileID FID, const SourceManager 
,
 const LangOptions ) {
   std::vector Tokens;
Index: clang/include/clang/Tooling/Syntax/Tokens.h
===
--- clang/include/clang/Tooling/Syntax/Tokens.h
+++ clang/include/clang/Tooling/Syntax/Tokens.h
@@ -236,6 +236,15 @@
   ///#pragma, etc.
   llvm::ArrayRef spelledTokens(FileID FID) const;
 
+  /// Get all tokens that expand a macro in FID. For the following input
+  /// #define FOO B
+  /// #define FOO2(X) int X
+  /// FOO2(XY)
+  /// int B;
+  /// FOO;
+  /// macroExpansions() returns {"FOO2", "FOO"}.
+  std::vector macroExpansions(FileID FID) const;
+
   const SourceManager () const { return *SourceMgr; }
 
   std::string dumpForTests() const;


Index: clang/unittests/Tooling/Syntax/TokensTest.cpp
===
--- clang/unittests/Tooling/Syntax/TokensTest.cpp
+++ clang/unittests/Tooling/Syntax/TokensTest.cpp
@@ -755,4 +755,27 @@
   // We don't test assertion failures because death tests are slow.
 }
 
+TEST_F(TokenBufferTest, macroExpansions) {
+  llvm::Annotations Code(R"cpp(
+#define FOO B
+#define FOO2 BA
+#define CALL(X) int X
+#define G CALL(FOO2)
+int B;
+$macro[[FOO]];
+$macro[[CALL]](A);
+$macro[[G]];
+  )cpp");
+  recordTokens(Code.code());
+  auto  = *SourceMgr;
+  auto Expansions = Buffer.macroExpansions(SM.getMainFileID());
+  std::vector ExpectedMacroRanges;
+  for (auto Range : Code.ranges("macro"))
+ExpectedMacroRanges.push_back(
+FileRange(SM.getMainFileID(), Range.Begin, Range.End));
+  std::vector ActualMacroRanges;
+  for (auto Expansion : Expansions)
+ActualMacroRanges.push_back(Expansion->range(SM));
+  EXPECT_EQ(ExpectedMacroRanges, ActualMacroRanges);
+}
 } // namespace
Index: clang/lib/Tooling/Syntax/Tokens.cpp
===
--- clang/lib/Tooling/Syntax/Tokens.cpp
+++ clang/lib/Tooling/Syntax/Tokens.cpp
@@ -232,6 +232,21 @@
   return E;
 }
 
+std::vector
+TokenBuffer::macroExpansions(FileID FID) const {
+  auto FileIt = Files.find(FID);
+  assert(FileIt != Files.end() && "file not tracked by token buffer");
+  auto  = FileIt->second;
+  std::vector Expansions;
+  auto  = File.SpelledTokens;
+  for (auto Mapping : File.Mappings) {
+const syntax::Token *Token = [Mapping.BeginSpelled];
+if (Token->kind() == tok::TokenKind::identifier)
+  Expansions.push_back(Token);
+  }
+  return Expansions;
+}
+
 std::vector syntax::tokenize(FileID FID, const SourceManager ,
 const LangOptions ) {
   std::vector Tokens;
Index: clang/include/clang/Tooling/Syntax/Tokens.h

[PATCH] D66470: [Syntax] Added function to get macro expansion tokens to TokenBuffer.

2019-08-20 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom created this revision.
jvikstrom added reviewers: hokein, ilya-biryukov.
Herald added subscribers: cfe-commits, kadircet.
Herald added a project: clang.

Returns the first token in every mapping where the token is an identifier.
This API is required to be able to highlight macro expansions in clangd.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D66470

Files:
  clang/include/clang/Tooling/Syntax/Tokens.h
  clang/lib/Tooling/Syntax/Tokens.cpp
  clang/unittests/Tooling/Syntax/TokensTest.cpp


Index: clang/unittests/Tooling/Syntax/TokensTest.cpp
===
--- clang/unittests/Tooling/Syntax/TokensTest.cpp
+++ clang/unittests/Tooling/Syntax/TokensTest.cpp
@@ -59,7 +59,6 @@
 using ::testing::Matcher;
 using ::testing::Not;
 using ::testing::StartsWith;
-
 namespace {
 // Checks the passed ArrayRef has the same begin() and end() iterators as 
the
 // argument.
@@ -755,4 +754,27 @@
   // We don't test assertion failures because death tests are slow.
 }
 
+TEST_F(TokenBufferTest, macroExpansions) {
+  llvm::Annotations Code(R"cpp(
+#define FOO B
+#define FOO2 BA
+#define CALL(X) int X
+#define G CALL(FOO2)
+int B;
+$macro[[FOO]];
+$macro[[CALL]](A);
+$macro[[G]];
+  )cpp");
+  recordTokens(Code.code());
+  auto  = *SourceMgr;
+  auto Expansions = Buffer.macroExpansions(SM.getMainFileID());
+  std::vector ExpectedMacroRanges;
+  for (auto Range : Code.ranges("macro"))
+ExpectedMacroRanges.push_back(
+FileRange(SM.getMainFileID(), Range.Begin, Range.End));
+  std::vector ActualMacroRanges;
+  for (auto Expansion : Expansions)
+ActualMacroRanges.push_back(Expansion->range(SM));
+  EXPECT_EQ(ExpectedMacroRanges, ActualMacroRanges);
+}
 } // namespace
Index: clang/lib/Tooling/Syntax/Tokens.cpp
===
--- clang/lib/Tooling/Syntax/Tokens.cpp
+++ clang/lib/Tooling/Syntax/Tokens.cpp
@@ -232,6 +232,21 @@
   return E;
 }
 
+std::vector
+TokenBuffer::macroExpansions(FileID FID) const {
+  auto FileIt = Files.find(FID);
+  assert(FileIt != Files.end() && "file not tracked by token buffer");
+  auto  = FileIt->second;
+  std::vector Expansions;
+  auto  = File.SpelledTokens;
+  for (auto Mapping : File.Mappings) {
+const syntax::Token *Token = [Mapping.BeginSpelled];
+if (Token->kind() == tok::TokenKind::identifier)
+  Expansions.push_back(Token);
+  }
+  return Expansions;
+}
+
 std::vector syntax::tokenize(FileID FID, const SourceManager 
,
 const LangOptions ) {
   std::vector Tokens;
Index: clang/include/clang/Tooling/Syntax/Tokens.h
===
--- clang/include/clang/Tooling/Syntax/Tokens.h
+++ clang/include/clang/Tooling/Syntax/Tokens.h
@@ -236,6 +236,15 @@
   ///#pragma, etc.
   llvm::ArrayRef spelledTokens(FileID FID) const;
 
+  /// Get all tokens that expand a macro in FID. For the following input
+  /// #define FOO B
+  /// #define FOO2(X) int X
+  /// FOO2(XY)
+  /// int B;
+  /// FOO;
+  /// macroExpansions() returns {"FOO2", "FOO"}.
+  std::vector macroExpansions(FileID FID) const;
+
   const SourceManager () const { return *SourceMgr; }
 
   std::string dumpForTests() const;


Index: clang/unittests/Tooling/Syntax/TokensTest.cpp
===
--- clang/unittests/Tooling/Syntax/TokensTest.cpp
+++ clang/unittests/Tooling/Syntax/TokensTest.cpp
@@ -59,7 +59,6 @@
 using ::testing::Matcher;
 using ::testing::Not;
 using ::testing::StartsWith;
-
 namespace {
 // Checks the passed ArrayRef has the same begin() and end() iterators as the
 // argument.
@@ -755,4 +754,27 @@
   // We don't test assertion failures because death tests are slow.
 }
 
+TEST_F(TokenBufferTest, macroExpansions) {
+  llvm::Annotations Code(R"cpp(
+#define FOO B
+#define FOO2 BA
+#define CALL(X) int X
+#define G CALL(FOO2)
+int B;
+$macro[[FOO]];
+$macro[[CALL]](A);
+$macro[[G]];
+  )cpp");
+  recordTokens(Code.code());
+  auto  = *SourceMgr;
+  auto Expansions = Buffer.macroExpansions(SM.getMainFileID());
+  std::vector ExpectedMacroRanges;
+  for (auto Range : Code.ranges("macro"))
+ExpectedMacroRanges.push_back(
+FileRange(SM.getMainFileID(), Range.Begin, Range.End));
+  std::vector ActualMacroRanges;
+  for (auto Expansion : Expansions)
+ActualMacroRanges.push_back(Expansion->range(SM));
+  EXPECT_EQ(ExpectedMacroRanges, ActualMacroRanges);
+}
 } // namespace
Index: clang/lib/Tooling/Syntax/Tokens.cpp
===
--- clang/lib/Tooling/Syntax/Tokens.cpp
+++ clang/lib/Tooling/Syntax/Tokens.cpp
@@ -232,6 +232,21 @@
   return E;
 }
 
+std::vector
+TokenBuffer::macroExpansions(FileID FID) const {
+  auto FileIt = Files.find(FID);
+  assert(FileIt != Files.end() 

[PATCH] D64741: [clangd] Added highlighting for tokens that are macro arguments.

2019-08-19 Thread Johan Vikström via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
jvikstrom marked 2 inline comments as done.
Closed by commit rL369275: [clangd] Added highlighting for tokens that are 
macro arguments. (authored by jvikstrom, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D64741?vs=215907=215929#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64741/new/

https://reviews.llvm.org/D64741

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

Index: clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
@@ -39,7 +39,27 @@
 llvm::sort(Tokens);
 auto Last = std::unique(Tokens.begin(), Tokens.end());
 Tokens.erase(Last, Tokens.end());
-return Tokens;
+// Macros can give tokens that have the same source range but conflicting
+// kinds. In this case all tokens sharing this source range should be
+// removed.
+std::vector NonConflicting;
+NonConflicting.reserve(Tokens.size());
+for (ArrayRef TokRef = Tokens; !TokRef.empty();) {
+  ArrayRef Conflicting =
+  TokRef.take_while([&](const HighlightingToken ) {
+// TokRef is guaranteed at least one element here because otherwise
+// this predicate would never fire.
+return T.R == TokRef.front().R;
+  });
+  // If there is exactly one token with this range it's non conflicting and
+  // should be in the highlightings.
+  if (Conflicting.size() == 1)
+NonConflicting.push_back(TokRef.front());
+  // TokRef[Conflicting.size()] is the next token with a different range (or
+  // the end of the Tokens).
+  TokRef = TokRef.drop_front(Conflicting.size());
+}
+return NonConflicting;
   }
 
   bool VisitNamespaceAliasDecl(NamespaceAliasDecl *NAD) {
@@ -236,13 +256,18 @@
   }
 
   void addToken(SourceLocation Loc, HighlightingKind Kind) {
-if (Loc.isMacroID())
-  // FIXME: skip tokens inside macros for now.
-  return;
+if(Loc.isMacroID()) {
+  // Only intereseted in highlighting arguments in macros (DEF_X(arg)).
+  if (!SM.isMacroArgExpansion(Loc))
+return;
+  Loc = SM.getSpellingLoc(Loc);
+}
 
 // Non top level decls that are included from a header are not filtered by
 // topLevelDecls. (example: method declarations being included from another
 // file for a class from another file)
+// There are also cases with macros where the spelling loc will not be in the
+// main file and the highlighting would be incorrect.
 if (!isInsideMainFile(Loc, SM))
   return;
 
Index: clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
===
--- clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
+++ clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
@@ -16,10 +16,6 @@
 
 namespace clang {
 namespace clangd {
-  void PrintTo(const HighlightingToken , ::std::ostream *OS) {
-  *OS << "(" << T.R.start.line << ", " << T.R.start.character << ") -> (" << T.R.end.line << ", " << T.R.end.character << "): " << (int)T.Kind;
-}
-
 namespace {
 
 std::vector
@@ -380,6 +376,56 @@
 $Class[[G]]<$Class[[F]], &$Class[[F]]::$Method[[f]]> $Variable[[GG]];
 $Variable[[GG]].$Method[[foo]](&$Variable[[FF]]);
 $Class[[A]]<$Function[[foo]]> $Variable[[AA]];
+)cpp",
+// Tokens that share a source range but have conflicting Kinds are not
+// highlighted.
+R"cpp(
+  #define DEF_MULTIPLE(X) namespace X { class X { int X; }; }
+  #define DEF_CLASS(T) class T {};
+  DEF_MULTIPLE(XYZ);
+  DEF_MULTIPLE(XYZW);
+  DEF_CLASS($Class[[A]])
+  #define MACRO_CONCAT(X, V, T) T foo##X = V
+  #define DEF_VAR(X, V) int X = V
+  #define DEF_VAR_T(T, X, V) T X = V
+  #define DEF_VAR_REV(V, X) DEF_VAR(X, V)
+  #define CPY(X) X
+  #define DEF_VAR_TYPE(X, Y) X Y
+  #define SOME_NAME variable
+  #define SOME_NAME_SET variable2 = 123
+  #define INC_VAR(X) X += 2
+  $Primitive[[void]] $Function[[foo]]() {
+DEF_VAR($Variable[[X]],  123);
+DEF_VAR_REV(908, $Variable[[XY]]);
+$Primitive[[int]] CPY( $Variable[[XX]] );
+DEF_VAR_TYPE($Class[[A]], $Variable[[AA]]);
+$Primitive[[double]] SOME_NAME;
+$Primitive[[int]] SOME_NAME_SET;
+$Variable[[variable]] = 20.1;
+MACRO_CONCAT(var, 2, $Primitive[[float]]);
+DEF_VAR_T($Class[[A]], CPY(CPY($Variable[[Nested]])),
+  CPY($Class[[A]]()));
+INC_VAR($Variable[[variable]]);
+  }
+  $Primitive[[void]] 

[PATCH] D64741: [clangd] Added highlighting for tokens that are macro arguments.

2019-08-19 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom added inline comments.



Comment at: clang-tools-extra/clangd/SemanticHighlighting.cpp:54
+  if (Conflicting.size() > 1) {
+Tokens.erase(Tokens.begin() + I,
+ Tokens.begin() + I + Conflicting.size());

ilya-biryukov wrote:
> This is potentially `O(n^2)`. Could we instead create a new vector and fill 
> it with the new items?
> 
> The memory usage should not matter much - we have the AST stored in the 
> background anyway. I bet we would be looking at it first if we wanted to 
> minimize memory usage.
> 
> If we really wanted to **not** waste any memory, we could do it 
> `std::erase_if`-style, i.e. move the items we want to remove to the end of 
> the vector, call `vector::erase` once at the end.
Completely forgot that erase is linear. Will go for the "allocate another 
vector" approach. 

Rewrote the entire conflicting checking code to hopefully be simpler as well 
(it changed substantially, so you might want to take another look at it).



Comment at: clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp:332
+  #define DEF_CLASS(T) class T {};
+  DEF_MULTIPLE(XYZ);
+  DEF_MULTIPLE(XYZW);

ilya-biryukov wrote:
> Unrelated to the change: do we plan to highlight macro names?
> That seems very useful.
Yes


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64741/new/

https://reviews.llvm.org/D64741



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D64741: [clangd] Added highlighting for tokens that are macro arguments.

2019-08-19 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom updated this revision to Diff 215907.
jvikstrom marked 2 inline comments as done.
jvikstrom added a comment.

Rewrote conflicting token removal code.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64741/new/

https://reviews.llvm.org/D64741

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
@@ -323,6 +323,57 @@
   $Primitive[[auto]] $Variable[[Form]] = 10.2 + 2 * 4;
   $Primitive[[decltype]]($Variable[[Form]]) $Variable[[F]] = 10;
   auto $Variable[[Fun]] = []()->$Primitive[[void]]{};
+)cpp",
+// Tokens that share a source range but have conflicting Kinds are not
+// highlighted.
+R"cpp(
+  #define DEF_MULTIPLE(X) namespace X { class X { int X; }; }
+  #define DEF_CLASS(T) class T {};
+  DEF_MULTIPLE(XYZ);
+  DEF_MULTIPLE(XYZW);
+  DEF_CLASS($Class[[A]])
+  #define MACRO_CONCAT(X, V, T) T foo##X = V
+  #define DEF_VAR(X, V) int X = V
+  #define DEF_VAR_T(T, X, V) T X = V
+  #define DEF_VAR_REV(V, X) DEF_VAR(X, V)
+  #define CPY(X) X
+  #define DEF_VAR_TYPE(X, Y) X Y
+  #define SOME_NAME variable
+  #define SOME_NAME_SET variable2 = 123
+  #define INC_VAR(X) X += 2
+  $Primitive[[void]] $Function[[foo]]() {
+DEF_VAR($Variable[[X]],  123);
+DEF_VAR_REV(908, $Variable[[XY]]);
+$Primitive[[int]] CPY( $Variable[[XX]] );
+DEF_VAR_TYPE($Class[[A]], $Variable[[AA]]);
+$Primitive[[double]] SOME_NAME;
+$Primitive[[int]] SOME_NAME_SET;
+$Variable[[variable]] = 20.1;
+MACRO_CONCAT(var, 2, $Primitive[[float]]);
+DEF_VAR_T($Class[[A]], CPY(CPY($Variable[[Nested]])),
+  CPY($Class[[A]]()));
+INC_VAR($Variable[[variable]]);
+  }
+  $Primitive[[void]] SOME_NAME();
+  DEF_VAR($Variable[[XYZ]], 567);
+  DEF_VAR_REV(756, $Variable[[AB]]);
+
+  #define CALL_FN(F) F();
+  #define DEF_FN(F) void F ()
+  DEF_FN($Function[[g]]) {
+CALL_FN($Function[[foo]]);
+  }
+)cpp",
+R"cpp(
+  #define fail(expr) expr
+  #define assert(COND) if (!(COND)) { fail("assertion failed" #COND); }
+  $Primitive[[int]] $Variable[[x]];
+  $Primitive[[int]] $Variable[[y]];
+  $Primitive[[int]] $Function[[f]]();
+  $Primitive[[void]] $Function[[foo]]() {
+assert($Variable[[x]] != $Variable[[y]]);
+assert($Variable[[x]] != $Function[[f]]());
+  }
 )cpp"};
   for (const auto  : TestCases) {
 checkHighlightings(TestCase);
@@ -338,6 +389,19 @@
 int someMethod();
 void otherMethod();
   )cpp"}});
+
+  // A separate test for macros in headers.
+  checkHighlightings(R"cpp(
+#include "imp.h"
+DEFINE_Y
+DXYZ_Y(A);
+  )cpp",
+ {{"imp.h", R"cpp(
+#define DXYZ(X) class X {};
+#define DXYZ_Y(Y) DXYZ(x##Y)
+#define DEFINE(X) int X;
+#define DEFINE_Y DEFINE(Y)
+  )cpp"}});
 }
 
 TEST(SemanticHighlighting, GeneratesHighlightsWhenFileChange) {
Index: clang-tools-extra/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -38,7 +38,28 @@
 llvm::sort(Tokens);
 auto Last = std::unique(Tokens.begin(), Tokens.end());
 Tokens.erase(Last, Tokens.end());
-return Tokens;
+// Macros can give tokens that have the same source range but conflicting
+// kinds. In this case all tokens sharing this source range should be
+// removed.
+std::vector NonConflicting;
+NonConflicting.reserve(Tokens.size());
+ArrayRef TokRef(Tokens);
+while (!TokRef.empty()) {
+  ArrayRef Conflicting =
+  TokRef.take_while([&](const HighlightingToken ) {
+// TokRef is guaranteed at least one element here because otherwise
+// this predicate would never fire.
+return T.R == TokRef.front().R;
+  });
+  // If there is exactly one token with this range it's non conflicting and
+  // should be in the highlightings.
+  if (Conflicting.size() == 1)
+NonConflicting.push_back(TokRef.front());
+  // Conflicting.end() is the next token with a different range (or the end
+  // of the Tokens).
+  TokRef = ArrayRef(Conflicting.end(), TokRef.end());
+}
+return NonConflicting;
   }
 
   bool VisitNamespaceAliasDecl(NamespaceAliasDecl *NAD) {
@@ -227,13 +248,18 @@
   }
 
   void addToken(SourceLocation Loc, HighlightingKind Kind) {
-if (Loc.isMacroID())
-  // FIXME: skip tokens inside macros 

[PATCH] D66219: [clangd] Added a colorizer to the vscode extension.

2019-08-19 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom updated this revision to Diff 215886.
jvikstrom marked 4 inline comments as done.
jvikstrom added a comment.

Renamed colorizer to highlighter and added FIXME about highlightings below eof.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66219/new/

https://reviews.llvm.org/D66219

Files:
  clang-tools-extra/clangd/clients/clangd-vscode/src/extension.ts
  clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
  
clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts

Index: clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
@@ -1,5 +1,6 @@
 import * as assert from 'assert';
 import * as path from 'path';
+import * as vscode from 'vscode';
 
 import * as SM from '../src/semantic-highlighting';
 
@@ -57,4 +58,72 @@
 assert.deepEqual(tm.getBestThemeRule('variable.other.parameter.cpp').scope,
  'variable.other.parameter');
   });
+  test('Colorizer groups decorations correctly', () => {
+const colorizations: {uri: string, decorations: any[]}[] = [];
+// Mock of a colorizer that saves the parameters in the colorizations array.
+class MockFileColorizer extends SM.FileHighlighter {
+  public highlight(uri: string, decorationRangePairs: any[]) {
+colorizations.push({uri : uri, decorations : decorationRangePairs});
+  }
+  public dispose() {}
+}
+// Helper for creating a vscode Range.
+const createRange = (line: number, startCharacter: number,
+ length: number) =>
+new vscode.Range(new vscode.Position(line, startCharacter),
+ new vscode.Position(line, startCharacter + length));
+const scopeTable = [
+  [ 'variable' ], [ 'entity.type.function' ],
+  [ 'entity.type.function.method' ]
+];
+const rules = [
+  {scope : 'variable', foreground : '1'},
+  {scope : 'entity.type', foreground : '2'},
+];
+const tm = new SM.ThemeRuleMatcher(rules);
+const colorizer = new SM.Highlighter(MockFileColorizer, scopeTable);
+// No colorization if themeRuleMatcher has not been set.
+colorizer.setFileLines('a', []);
+assert.deepEqual(colorizations, []);
+colorizer.updateThemeRuleMatcher(tm);
+assert.deepEqual(colorizations, [ {decorations : [], uri : 'a'} ]);
+// Groups decorations into the scopes used.
+let line = [
+  {character : 1, length : 2, scopeIndex : 1},
+  {character : 5, length : 2, scopeIndex : 1},
+  {character : 10, length : 2, scopeIndex : 2}
+];
+colorizer.setFileLines(
+'a', [ {line : 1, tokens : line}, {line : 2, tokens : line} ]);
+assert.equal(colorizations[1].uri, 'a');
+assert.equal(colorizations[1].decorations.length, 2);
+// Can't test the actual decorations as vscode does not seem to have an api
+// for getting the actual decoration objects.
+assert.deepEqual(colorizations[1].decorations[0].ranges, [
+  createRange(1, 1, 2), createRange(1, 5, 2), createRange(2, 1, 2),
+  createRange(2, 5, 2)
+]);
+assert.deepEqual(colorizations[1].decorations[1].ranges,
+ [ createRange(1, 10, 2), createRange(2, 10, 2) ]);
+// Keeps state separate between files.
+colorizer.setFileLines('b', [
+  {line : 1, tokens : [ {character : 1, length : 1, scopeIndex : 0} ]}
+]);
+assert.equal(colorizations[2].uri, 'b');
+assert.equal(colorizations[2].decorations.length, 1);
+assert.deepEqual(colorizations[2].decorations[0].ranges,
+ [ createRange(1, 1, 1) ]);
+// Does full colorizations.
+colorizer.setFileLines('a', [
+  {line : 1, tokens : [ {character : 2, length : 1, scopeIndex : 0} ]}
+]);
+assert.equal(colorizations[3].uri, 'a');
+assert.equal(colorizations[3].decorations.length, 3);
+assert.deepEqual(colorizations[3].decorations[0].ranges,
+ [ createRange(1, 2, 1) ]);
+assert.deepEqual(colorizations[3].decorations[1].ranges,
+ [ createRange(2, 1, 2), createRange(2, 5, 2) ]);
+assert.deepEqual(colorizations[3].decorations[2].ranges,
+ [ createRange(2, 10, 2) ]);
+  });
 });
Index: clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
@@ -34,6 +34,13 @@
   // The TextMate scope index to the clangd scope lookup table.
   scopeIndex: number;
 }
+// A line of decoded highlightings from the data clangd sent.

[PATCH] D64741: [clangd] Added highlighting for tokens that are macro arguments.

2019-08-19 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom added a comment.

@ilya-biryukov @hokein ping


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64741/new/

https://reviews.llvm.org/D64741



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D66406: [clangd] Update themeRuleMatcher when color theme changes in vscode extension.

2019-08-19 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom created this revision.
jvikstrom added reviewers: hokein, ilya-biryukov.
Herald added subscribers: cfe-commits, kadircet, arphaman, jkorous, MaskRay.
Herald added a project: clang.

Add event listener that listens to configuration changes and reloads the 
ThemeRuleMatcher when the theme changes.

Right now it will not recolor the files, depends on the colorizer CL for that.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D66406

Files:
  clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts


Index: 
clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
@@ -5,6 +5,11 @@
 import * as vscodelc from 'vscode-languageclient';
 import * as vscodelct from 'vscode-languageserver-types';
 
+function getCurrentThemeName() {
+  return vscode.workspace.getConfiguration('workbench')
+  .get('colorTheme');
+}
+
 // Parameters for the semantic highlighting (server-side) push notification.
 // Mirrors the structure in the semantic highlighting proposal for LSP.
 interface SemanticHighlightingParams {
@@ -49,6 +54,10 @@
   scopeLookupTable: string[][];
   // The rules for the current theme.
   themeRuleMatcher: ThemeRuleMatcher;
+  // The current color theme used for colorization.
+  currentColorThemeName: string;
+  // Disposable that should be cleaned up.
+  disposable: vscode.Disposable;
   fillClientCapabilities(capabilities: vscodelc.ClientCapabilities) {
 // Extend the ClientCapabilities type and add semantic highlighting
 // capability to the object.
@@ -61,9 +70,9 @@
   }
 
   async loadCurrentTheme() {
-this.themeRuleMatcher = new ThemeRuleMatcher(
-await loadTheme(vscode.workspace.getConfiguration('workbench')
-.get('colorTheme')));
+this.currentColorThemeName = getCurrentThemeName();
+this.themeRuleMatcher =
+new ThemeRuleMatcher(await loadTheme(this.currentColorThemeName));
   }
 
   initialize(capabilities: vscodelc.ServerCapabilities,
@@ -76,6 +85,14 @@
 if (!serverCapabilities.semanticHighlighting)
   return;
 this.scopeLookupTable = serverCapabilities.semanticHighlighting.scopes;
+this.disposable = vscode.workspace.onDidChangeConfiguration((conf) => {
+  if (!conf.affectsConfiguration('workbench'))
+// Configuration could not have affected the current colorTheme.
+return;
+  const newColorTheme = getCurrentThemeName();
+  if (newColorTheme != this.currentColorThemeName)
+this.loadCurrentTheme();
+});
 this.loadCurrentTheme();
   }
 


Index: clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
@@ -5,6 +5,11 @@
 import * as vscodelc from 'vscode-languageclient';
 import * as vscodelct from 'vscode-languageserver-types';
 
+function getCurrentThemeName() {
+  return vscode.workspace.getConfiguration('workbench')
+  .get('colorTheme');
+}
+
 // Parameters for the semantic highlighting (server-side) push notification.
 // Mirrors the structure in the semantic highlighting proposal for LSP.
 interface SemanticHighlightingParams {
@@ -49,6 +54,10 @@
   scopeLookupTable: string[][];
   // The rules for the current theme.
   themeRuleMatcher: ThemeRuleMatcher;
+  // The current color theme used for colorization.
+  currentColorThemeName: string;
+  // Disposable that should be cleaned up.
+  disposable: vscode.Disposable;
   fillClientCapabilities(capabilities: vscodelc.ClientCapabilities) {
 // Extend the ClientCapabilities type and add semantic highlighting
 // capability to the object.
@@ -61,9 +70,9 @@
   }
 
   async loadCurrentTheme() {
-this.themeRuleMatcher = new ThemeRuleMatcher(
-await loadTheme(vscode.workspace.getConfiguration('workbench')
-.get('colorTheme')));
+this.currentColorThemeName = getCurrentThemeName();
+this.themeRuleMatcher =
+new ThemeRuleMatcher(await loadTheme(this.currentColorThemeName));
   }
 
   initialize(capabilities: vscodelc.ServerCapabilities,
@@ -76,6 +85,14 @@
 if (!serverCapabilities.semanticHighlighting)
   return;
 this.scopeLookupTable = serverCapabilities.semanticHighlighting.scopes;
+this.disposable = vscode.workspace.onDidChangeConfiguration((conf) => {
+  if (!conf.affectsConfiguration('workbench'))
+// Configuration could not have affected the current colorTheme.
+return;
+  const newColorTheme = getCurrentThemeName();
+  if (newColorTheme != this.currentColorThemeName)
+

[PATCH] D66335: [clangd] Added special HighlightingKind for function parameters.

2019-08-19 Thread Johan Vikström via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL369238: [clangd] Added special HighlightingKind for function 
parameters. (authored by jvikstrom, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D66335?vs=215548=215827#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66335/new/

https://reviews.llvm.org/D66335

Files:
  clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
  clang-tools-extra/trunk/clangd/SemanticHighlighting.h
  clang-tools-extra/trunk/clangd/test/semantic-highlighting.test
  clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp

Index: clang-tools-extra/trunk/clangd/test/semantic-highlighting.test
===
--- clang-tools-extra/trunk/clangd/test/semantic-highlighting.test
+++ clang-tools-extra/trunk/clangd/test/semantic-highlighting.test
@@ -8,6 +8,9 @@
 # CHECK-NEXT:"variable.other.cpp"
 # CHECK-NEXT:  ],
 # CHECK-NEXT:  [
+# CHECK-NEXT:"variable.parameter.cpp"
+# CHECK-NEXT:  ],
+# CHECK-NEXT:  [
 # CHECK-NEXT:"entity.name.function.cpp"
 # CHECK-NEXT:  ],
 # CHECK-NEXT:  [
@@ -43,7 +46,7 @@
 # CHECK-NEXT:"lines": [
 # CHECK-NEXT:  {
 # CHECK-NEXT:"line": 0,
-# CHECK-NEXT:"tokens": "AAADAAkEAAEAAA=="
+# CHECK-NEXT:"tokens": "AAADAAoEAAEAAA=="
 # CHECK-NEXT:  }
 # CHECK-NEXT:],
 # CHECK-NEXT:"textDocument": {
@@ -58,11 +61,11 @@
 # CHECK-NEXT:"lines": [
 # CHECK-NEXT:  {
 # CHECK-NEXT:"line": 0,
-# CHECK-NEXT:"tokens": "AAADAAkEAAEAAA=="
+# CHECK-NEXT:"tokens": "AAADAAoEAAEAAA=="
 # CHECK-NEXT:  }
 # CHECK-NEXT:  {
 # CHECK-NEXT:"line": 1,
-# CHECK-NEXT:"tokens": "AAADAAkEAAEAAA=="
+# CHECK-NEXT:"tokens": "AAADAAoEAAEAAA=="
 # CHECK-NEXT:  }
 # CHECK-NEXT:],
 # CHECK-NEXT:"textDocument": {
@@ -77,7 +80,7 @@
 # CHECK-NEXT:"lines": [
 # CHECK-NEXT:  {
 # CHECK-NEXT:"line": 1,
-# CHECK-NEXT:"tokens": "AAADAAkEAAEAAA=="
+# CHECK-NEXT:"tokens": "AAADAAoEAAEAAA=="
 # CHECK-NEXT:  }
 # CHECK-NEXT:   ],
 # CHECK-NEXT:"textDocument": {
Index: clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
@@ -11,6 +11,7 @@
 #include "Protocol.h"
 #include "SourceCode.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/RecursiveASTVisitor.h"
 #include 
@@ -200,6 +201,10 @@
   addToken(Loc, HighlightingKind::EnumConstant);
   return;
 }
+if (isa(D)) {
+  addToken(Loc, HighlightingKind::Parameter);
+  return;
+}
 if (isa(D)) {
   addToken(Loc, HighlightingKind::Variable);
   return;
@@ -406,6 +411,8 @@
 return "entity.name.function.method.cpp";
   case HighlightingKind::Variable:
 return "variable.other.cpp";
+  case HighlightingKind::Parameter:
+return "variable.parameter.cpp";
   case HighlightingKind::Field:
 return "variable.other.field.cpp";
   case HighlightingKind::Class:
Index: clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
===
--- clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
+++ clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
@@ -16,6 +16,10 @@
 
 namespace clang {
 namespace clangd {
+  void PrintTo(const HighlightingToken , ::std::ostream *OS) {
+  *OS << "(" << T.R.start.line << ", " << T.R.start.character << ") -> (" << T.R.end.line << ", " << T.R.end.character << "): " << (int)T.Kind;
+}
+
 namespace {
 
 std::vector
@@ -32,6 +36,7 @@
 std::vector getExpectedTokens(Annotations ) {
   static const std::map KindToString{
   {HighlightingKind::Variable, "Variable"},
+  {HighlightingKind::Parameter, "Parameter"},
   {HighlightingKind::Function, "Function"},
   {HighlightingKind::Class, "Class"},
   {HighlightingKind::Enum, "Enum"},
@@ -104,11 +109,11 @@
   };
   struct {
   } $Variable[[S]];
-  $Primitive[[void]] $Function[[foo]]($Primitive[[int]] $Variable[[A]], $Class[[AS]] $Variable[[As]]) {
+  $Primitive[[void]] $Function[[foo]]($Primitive[[int]] $Parameter[[A]], $Class[[AS]] $Parameter[[As]]) {
 $Primitive[[auto]] $Variable[[VeryLongVariableName]] = 12312;
 $Class[[AS]] $Variable[[AA]];
-$Primitive[[auto]] $Variable[[L]] = $Variable[[AA]].$Field[[SomeMember]] + $Variable[[A]];
-auto $Variable[[FN]] = [ 

[PATCH] D66221: [clangd] Added highlighting for non type templates.

2019-08-16 Thread Johan Vikström via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL369090: [clangd] Added highlighting for non type templates. 
(authored by jvikstrom, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D66221?vs=215544=215549#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66221/new/

https://reviews.llvm.org/D66221

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


Index: clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
@@ -224,6 +224,10 @@
   addToken(Loc, HighlightingKind::TemplateParameter);
   return;
 }
+if (isa(D)) {
+  addToken(Loc, HighlightingKind::TemplateParameter);
+  return;
+}
   }
 
   void addToken(SourceLocation Loc, HighlightingKind Kind) {
Index: clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
===
--- clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
+++ clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
@@ -323,6 +323,59 @@
   $Primitive[[auto]] $Variable[[Form]] = 10.2 + 2 * 4;
   $Primitive[[decltype]]($Variable[[Form]]) $Variable[[F]] = 10;
   auto $Variable[[Fun]] = []()->$Primitive[[void]]{};
+)cpp",
+R"cpp(
+  class $Class[[G]] {};
+  template<$Class[[G]] *$TemplateParameter[[U]]>
+  class $Class[[GP]] {};
+  template<$Class[[G]] &$TemplateParameter[[U]]>
+  class $Class[[GR]] {};
+  template<$Primitive[[int]] *$TemplateParameter[[U]]>
+  class $Class[[IP]] {
+$Primitive[[void]] $Method[[f]]() {
+  *$TemplateParameter[[U]] += 5;
+}
+  };
+  template<$Primitive[[unsigned]] $TemplateParameter[[U]] = 2>
+  class $Class[[Foo]] {
+$Primitive[[void]] $Method[[f]]() {
+  for($Primitive[[int]] $Variable[[I]] = 0;
+$Variable[[I]] < $TemplateParameter[[U]];) {}
+}
+  };
+
+  $Class[[G]] $Variable[[L]];
+  $Primitive[[void]] $Function[[f]]() {
+$Class[[Foo]]<123> $Variable[[F]];
+$Class[[GP]]<&$Variable[[L]]> $Variable[[LL]];
+$Class[[GR]]<$Variable[[L]]> $Variable[[LLL]];
+  }
+)cpp",
+R"cpp(
+  template
+  struct $Class[[G]] {
+$Primitive[[void]] $Method[[foo]](
+$TemplateParameter[[T]] *$Variable[[O]]) {
+  ($Variable[[O]]->*$TemplateParameter[[method]])(10);
+}
+  };
+  struct $Class[[F]] {
+$Primitive[[void]] $Method[[f]]($Primitive[[int]]);
+  };
+  template<$Primitive[[void]] (*$TemplateParameter[[Func]])()>
+  struct $Class[[A]] {
+$Primitive[[void]] $Method[[f]]() {
+  (*$TemplateParameter[[Func]])();
+}
+  };
+
+  $Primitive[[void]] $Function[[foo]]() {
+$Class[[F]] $Variable[[FF]];
+$Class[[G]]<$Class[[F]], &$Class[[F]]::$Method[[f]]> $Variable[[GG]];
+$Variable[[GG]].$Method[[foo]](&$Variable[[FF]]);
+$Class[[A]]<$Function[[foo]]> $Variable[[AA]];
+  }
 )cpp"};
   for (const auto  : TestCases) {
 checkHighlightings(TestCase);


Index: clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
@@ -224,6 +224,10 @@
   addToken(Loc, HighlightingKind::TemplateParameter);
   return;
 }
+if (isa(D)) {
+  addToken(Loc, HighlightingKind::TemplateParameter);
+  return;
+}
   }
 
   void addToken(SourceLocation Loc, HighlightingKind Kind) {
Index: clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
===
--- clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
+++ clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
@@ -323,6 +323,59 @@
   $Primitive[[auto]] $Variable[[Form]] = 10.2 + 2 * 4;
   $Primitive[[decltype]]($Variable[[Form]]) $Variable[[F]] = 10;
   auto $Variable[[Fun]] = []()->$Primitive[[void]]{};
+)cpp",
+R"cpp(
+  class $Class[[G]] {};
+  template<$Class[[G]] *$TemplateParameter[[U]]>
+  class $Class[[GP]] {};
+  template<$Class[[G]] &$TemplateParameter[[U]]>
+  class $Class[[GR]] {};
+  template<$Primitive[[int]] *$TemplateParameter[[U]]>
+  class $Class[[IP]] {
+$Primitive[[void]] $Method[[f]]() {
+  *$TemplateParameter[[U]] += 5;
+}
+  };
+  template<$Primitive[[unsigned]] 

[PATCH] D66335: [clangd] Added special HighlightingKind for function parameters.

2019-08-16 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom created this revision.
jvikstrom added reviewers: hokein, ilya-biryukov.
Herald added subscribers: cfe-commits, kadircet, arphaman, jkorous, MaskRay.
Herald added a project: clang.

This means that function parameters are no longer highlighted as 
variable.other.cpp but instead as variable.parameter.cpp which is the more 
"correct" TextMate scope for them.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D66335

Files:
  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
@@ -32,6 +32,7 @@
 std::vector getExpectedTokens(Annotations ) {
   static const std::map KindToString{
   {HighlightingKind::Variable, "Variable"},
+  {HighlightingKind::Parameter, "Parameter"},
   {HighlightingKind::Function, "Function"},
   {HighlightingKind::Class, "Class"},
   {HighlightingKind::Enum, "Enum"},
@@ -104,11 +105,11 @@
   };
   struct {
   } $Variable[[S]];
-  $Primitive[[void]] $Function[[foo]]($Primitive[[int]] $Variable[[A]], $Class[[AS]] $Variable[[As]]) {
+  $Primitive[[void]] $Function[[foo]]($Primitive[[int]] $Parameter[[A]], $Class[[AS]] $Parameter[[As]]) {
 $Primitive[[auto]] $Variable[[VeryLongVariableName]] = 12312;
 $Class[[AS]] $Variable[[AA]];
-$Primitive[[auto]] $Variable[[L]] = $Variable[[AA]].$Field[[SomeMember]] + $Variable[[A]];
-auto $Variable[[FN]] = [ $Variable[[AA]]]($Primitive[[int]] $Variable[[A]]) -> $Primitive[[void]] {};
+$Primitive[[auto]] $Variable[[L]] = $Variable[[AA]].$Field[[SomeMember]] + $Parameter[[A]];
+auto $Variable[[FN]] = [ $Variable[[AA]]]($Primitive[[int]] $Parameter[[A]]) -> $Primitive[[void]] {};
 $Variable[[FN]](12312);
   }
 )cpp",
@@ -287,10 +288,10 @@
   struct $Class[[B]] {};
   struct $Class[[A]] {
 $Class[[B]] $Field[[BB]];
-$Class[[A]] =($Class[[A]] &&$Variable[[O]]);
+$Class[[A]] =($Class[[A]] &&$Parameter[[O]]);
   };
 
-  $Class[[A]] &$Class[[A]]::operator=($Class[[A]] &&$Variable[[O]]) = default;
+  $Class[[A]] &$Class[[A]]::operator=($Class[[A]] &&$Parameter[[O]]) = default;
 )cpp",
 R"cpp(
   enum $Enum[[En]] {
@@ -301,9 +302,9 @@
 $Class[[Foo]] $Field[[Fo]];
 $Enum[[En]] $Field[[E]];
 $Primitive[[int]] $Field[[I]];
-$Class[[Bar]] ($Class[[Foo]] $Variable[[F]],
-$Enum[[En]] $Variable[[E]])
-: $Field[[Fo]] ($Variable[[F]]), $Field[[E]] ($Variable[[E]]),
+$Class[[Bar]] ($Class[[Foo]] $Parameter[[F]],
+$Enum[[En]] $Parameter[[E]])
+: $Field[[Fo]] ($Parameter[[F]]), $Field[[E]] ($Parameter[[E]]),
   $Field[[I]] (123) {}
   };
   class $Class[[Bar2]] : public $Class[[Bar]] {
@@ -385,7 +386,7 @@
   std::vector ActualResults =
   toSemanticHighlightingInformation(Tokens);
   std::vector ExpectedResults = {
-  {3, "CAAEAAAEAAMAAQ=="}, {1, "AQAEAAA="}};
+  {3, "CAAEAAAEAAMAAg=="}, {1, "AQAEAAA="}};
   EXPECT_EQ(ActualResults, 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
@@ -8,6 +8,9 @@
 # CHECK-NEXT:"variable.other.cpp"
 # CHECK-NEXT:  ],
 # CHECK-NEXT:  [
+# CHECK-NEXT:"variable.parameter.cpp"
+# CHECK-NEXT:  ],
+# CHECK-NEXT:  [
 # CHECK-NEXT:"entity.name.function.cpp"
 # CHECK-NEXT:  ],
 # CHECK-NEXT:  [
@@ -43,7 +46,7 @@
 # CHECK-NEXT:"lines": [
 # CHECK-NEXT:  {
 # CHECK-NEXT:"line": 0,
-# CHECK-NEXT:"tokens": "AAADAAkEAAEAAA=="
+# CHECK-NEXT:"tokens": "AAADAAoEAAEAAA=="
 # CHECK-NEXT:  }
 # CHECK-NEXT:],
 # CHECK-NEXT:"textDocument": {
@@ -58,11 +61,11 @@
 # CHECK-NEXT:"lines": [
 # CHECK-NEXT:  {
 # CHECK-NEXT:"line": 0,
-# CHECK-NEXT:"tokens": "AAADAAkEAAEAAA=="
+# CHECK-NEXT:"tokens": "AAADAAoEAAEAAA=="
 # CHECK-NEXT:  }
 # CHECK-NEXT:  {
 # CHECK-NEXT:"line": 1,
-# CHECK-NEXT:"tokens": "AAADAAkEAAEAAA=="
+# CHECK-NEXT:"tokens": "AAADAAoEAAEAAA=="
 # CHECK-NEXT:  }
 # CHECK-NEXT:],
 # CHECK-NEXT:"textDocument": {
@@ -77,7 +80,7 @@
 # CHECK-NEXT:"lines": [
 # CHECK-NEXT:  {
 # CHECK-NEXT:"line": 1,
-# 

[PATCH] D66221: [clangd] Added highlighting for non type templates.

2019-08-16 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom updated this revision to Diff 215544.
jvikstrom marked an inline comment as done.
jvikstrom added a comment.

Highlight as TemplateParameter.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66221/new/

https://reviews.llvm.org/D66221

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
@@ -323,6 +323,59 @@
   $Primitive[[auto]] $Variable[[Form]] = 10.2 + 2 * 4;
   $Primitive[[decltype]]($Variable[[Form]]) $Variable[[F]] = 10;
   auto $Variable[[Fun]] = []()->$Primitive[[void]]{};
+)cpp",
+R"cpp(
+  class $Class[[G]] {};
+  template<$Class[[G]] *$TemplateParameter[[U]]>
+  class $Class[[GP]] {};
+  template<$Class[[G]] &$TemplateParameter[[U]]>
+  class $Class[[GR]] {};
+  template<$Primitive[[int]] *$TemplateParameter[[U]]>
+  class $Class[[IP]] {
+$Primitive[[void]] $Method[[f]]() {
+  *$TemplateParameter[[U]] += 5;
+}
+  };
+  template<$Primitive[[unsigned]] $TemplateParameter[[U]] = 2>
+  class $Class[[Foo]] {
+$Primitive[[void]] $Method[[f]]() {
+  for($Primitive[[int]] $Variable[[I]] = 0;
+$Variable[[I]] < $TemplateParameter[[U]];) {}
+}
+  };
+
+  $Class[[G]] $Variable[[L]];
+  $Primitive[[void]] $Function[[f]]() {
+$Class[[Foo]]<123> $Variable[[F]];
+$Class[[GP]]<&$Variable[[L]]> $Variable[[LL]];
+$Class[[GR]]<$Variable[[L]]> $Variable[[LLL]];
+  }
+)cpp",
+R"cpp(
+  template
+  struct $Class[[G]] {
+$Primitive[[void]] $Method[[foo]](
+$TemplateParameter[[T]] *$Variable[[O]]) {
+  ($Variable[[O]]->*$TemplateParameter[[method]])(10);
+}
+  };
+  struct $Class[[F]] {
+$Primitive[[void]] $Method[[f]]($Primitive[[int]]);
+  };
+  template<$Primitive[[void]] (*$TemplateParameter[[Func]])()>
+  struct $Class[[A]] {
+$Primitive[[void]] $Method[[f]]() {
+  (*$TemplateParameter[[Func]])();
+}
+  };
+
+  $Primitive[[void]] $Function[[foo]]() {
+$Class[[F]] $Variable[[FF]];
+$Class[[G]]<$Class[[F]], &$Class[[F]]::$Method[[f]]> $Variable[[GG]];
+$Variable[[GG]].$Method[[foo]](&$Variable[[FF]]);
+$Class[[A]]<$Function[[foo]]> $Variable[[AA]];
+  }
 )cpp"};
   for (const auto  : TestCases) {
 checkHighlightings(TestCase);
Index: clang-tools-extra/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -224,6 +224,10 @@
   addToken(Loc, HighlightingKind::TemplateParameter);
   return;
 }
+if (isa(D)) {
+  addToken(Loc, HighlightingKind::TemplateParameter);
+  return;
+}
   }
 
   void addToken(SourceLocation Loc, HighlightingKind Kind) {


Index: clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
===
--- clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
+++ clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
@@ -323,6 +323,59 @@
   $Primitive[[auto]] $Variable[[Form]] = 10.2 + 2 * 4;
   $Primitive[[decltype]]($Variable[[Form]]) $Variable[[F]] = 10;
   auto $Variable[[Fun]] = []()->$Primitive[[void]]{};
+)cpp",
+R"cpp(
+  class $Class[[G]] {};
+  template<$Class[[G]] *$TemplateParameter[[U]]>
+  class $Class[[GP]] {};
+  template<$Class[[G]] &$TemplateParameter[[U]]>
+  class $Class[[GR]] {};
+  template<$Primitive[[int]] *$TemplateParameter[[U]]>
+  class $Class[[IP]] {
+$Primitive[[void]] $Method[[f]]() {
+  *$TemplateParameter[[U]] += 5;
+}
+  };
+  template<$Primitive[[unsigned]] $TemplateParameter[[U]] = 2>
+  class $Class[[Foo]] {
+$Primitive[[void]] $Method[[f]]() {
+  for($Primitive[[int]] $Variable[[I]] = 0;
+$Variable[[I]] < $TemplateParameter[[U]];) {}
+}
+  };
+
+  $Class[[G]] $Variable[[L]];
+  $Primitive[[void]] $Function[[f]]() {
+$Class[[Foo]]<123> $Variable[[F]];
+$Class[[GP]]<&$Variable[[L]]> $Variable[[LL]];
+$Class[[GR]]<$Variable[[L]]> $Variable[[LLL]];
+  }
+)cpp",
+R"cpp(
+  template
+  struct $Class[[G]] {
+$Primitive[[void]] $Method[[foo]](
+$TemplateParameter[[T]] *$Variable[[O]]) {
+  ($Variable[[O]]->*$TemplateParameter[[method]])(10);
+}
+  };
+  struct $Class[[F]] {
+  

[PATCH] D66221: [clangd] Added highlighting for non type templates.

2019-08-16 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom added inline comments.



Comment at: clang-tools-extra/clangd/SemanticHighlighting.cpp:231
+  if (TP->isFunctionPointerType()) {
+addToken(Loc, HighlightingKind::Function);
+return;

ilya-biryukov wrote:
> jvikstrom wrote:
> > ilya-biryukov wrote:
> > > Why do we special-case template parameters, but not other kinds of 
> > > variables?
> > > We definitely need a comment explaining why template parameters are 
> > > handled in a special way, but variables, parameters, fields are not.
> > Not quite sure what you mean about variables/parameters/fields not being 
> > handled in a special way.
> > 
> > The reason for special casing non type templates is because it probably 
> > gives more information/is more valuable to highlight a reference/pointer as 
> > a variable rather than a normal template parameter (same for 
> > methods/functions).
> > 
> > But maybe they all should just be highlighted as with the TemplateParameter 
> > kind instead?
> > Not quite sure what you mean about variables/parameters/fields not being 
> > handled in a special way.
> Non-type template parameters are very similar to global and local variables, 
> function parameters, class fields, etc.
> We could also match those on type and highlight differently based on the type.
> 
> > The reason for special casing non type templates is because it probably 
> > gives more information/is more valuable to highlight a reference/pointer as 
> > a variable rather than a normal template parameter (same for 
> > methods/functions).
> However, if a global variable has a function pointer type we do not highlight 
> it as a function. Why would this be different?
> 
> > But maybe they all should just be highlighted as with the TemplateParameter 
> > kind instead?
> I would personally vouch for this option. The highlighting functionality lets 
> me understand what the name resolves to; if it's a template parameter and it 
> would be highlighted as a variable instead, this would create confusion on my 
> end. If I need to know the type I'll look at completion results or hover.
> 
> It is my personal preference and I'm ok with this going in a different 
> direction if you feel the opposite is better. Just asking to put the 
> rationale of this decision (why do this only for template parameters and not 
> other things) in a comment somewhere in the source code.
> I would personally vouch for this option. The highlighting functionality lets 
> me understand what the name resolves to;

Very true actually, was a bit unsure what was the correct way to go but this is 
very true actually.

Changing to just highlight as TemplateParameter. 


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66221/new/

https://reviews.llvm.org/D66221



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D66221: [clangd] Added highlighting for non type templates.

2019-08-16 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom marked an inline comment as done.
jvikstrom added inline comments.



Comment at: clang-tools-extra/clangd/SemanticHighlighting.cpp:231
+  if (TP->isFunctionPointerType()) {
+addToken(Loc, HighlightingKind::Function);
+return;

ilya-biryukov wrote:
> Why do we special-case template parameters, but not other kinds of variables?
> We definitely need a comment explaining why template parameters are handled 
> in a special way, but variables, parameters, fields are not.
Not quite sure what you mean about variables/parameters/fields not being 
handled in a special way.

The reason for special casing non type templates is because it probably gives 
more information/is more valuable to highlight a reference/pointer as a 
variable rather than a normal template parameter (same for methods/functions).

But maybe they all should just be highlighted as with the TemplateParameter 
kind instead?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66221/new/

https://reviews.llvm.org/D66221



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D66221: [clangd] Added highlighting for non type templates.

2019-08-14 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom created this revision.
jvikstrom added reviewers: hokein, ilya-biryukov.
Herald added subscribers: cfe-commits, kadircet, arphaman, jkorous, MaskRay.
Herald added a project: clang.

Highlights pointers to variables as variables. Function pointers are 
highlighted as functions. Member function pointers are highlighted as members. 
Values are highlighted as TemplateParameter.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D66221

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
@@ -323,6 +323,59 @@
   $Primitive[[auto]] $Variable[[Form]] = 10.2 + 2 * 4;
   $Primitive[[decltype]]($Variable[[Form]]) $Variable[[F]] = 10;
   auto $Variable[[Fun]] = []()->$Primitive[[void]]{};
+)cpp",
+R"cpp(
+  class $Class[[G]] {};
+  template<$Class[[G]] *$Variable[[U]]>
+  class $Class[[GP]] {};
+  template<$Class[[G]] &$Variable[[U]]>
+  class $Class[[GR]] {};
+  template<$Primitive[[int]] *$Variable[[U]]>
+  class $Class[[IP]] {
+$Primitive[[void]] $Method[[f]]() {
+  *$Variable[[U]] += 5;
+}
+  };
+  template<$Primitive[[unsigned]] $TemplateParameter[[U]] = 2>
+  class $Class[[Foo]] {
+$Primitive[[void]] $Method[[f]]() {
+  for($Primitive[[int]] $Variable[[I]] = 0;
+$Variable[[I]] < $TemplateParameter[[U]];) {}
+}
+  };
+
+  $Class[[G]] $Variable[[L]];
+  $Primitive[[void]] $Function[[f]]() {
+$Class[[Foo]]<123> $Variable[[F]];
+$Class[[GP]]<&$Variable[[L]]> $Variable[[LL]];
+$Class[[GR]]<$Variable[[L]]> $Variable[[LLL]];
+  }
+)cpp",
+R"cpp(
+  template
+  struct $Class[[G]] {
+$Primitive[[void]] $Method[[foo]](
+$TemplateParameter[[T]] *$Variable[[O]]) {
+  ($Variable[[O]]->*$Method[[method]])(10);
+}
+  };
+  struct $Class[[F]] {
+$Primitive[[void]] $Method[[f]]($Primitive[[int]]);
+  };
+  template<$Primitive[[void]] (*$Function[[Func]])()>
+  struct $Class[[A]] {
+$Primitive[[void]] $Method[[f]]() {
+  (*$Function[[Func]])();
+}
+  };
+
+  $Primitive[[void]] $Function[[foo]]() {
+$Class[[F]] $Variable[[FF]];
+$Class[[G]]<$Class[[F]], &$Class[[F]]::$Method[[f]]> $Variable[[GG]];
+$Variable[[GG]].$Method[[foo]](&$Variable[[FF]]);
+$Class[[A]]<$Function[[foo]]> $Variable[[AA]];
+  }
 )cpp"};
   for (const auto  : TestCases) {
 checkHighlightings(TestCase);
Index: clang-tools-extra/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -224,6 +224,28 @@
   addToken(Loc, HighlightingKind::TemplateParameter);
   return;
 }
+if (const auto *NTP = dyn_cast(D)) {
+  if (const auto *T = NTP->getTypeSourceInfo())
+if (const auto *TP = T->getTypeLoc().getTypePtr()) {
+  if (TP->isFunctionPointerType()) {
+addToken(Loc, HighlightingKind::Function);
+return;
+  }
+  if (TP->isMemberFunctionPointerType()) {
+addToken(Loc, HighlightingKind::Method);
+return;
+  }
+  if (TP->isPointerType() || TP->isLValueReferenceType()) {
+addToken(Loc, HighlightingKind::Variable);
+return;
+  }
+}
+  // If it's not a function ptr, member ptr, ptr or reference that means it
+  // is probably a builtin value. Those should just be highlighted as 
normal
+  // TemplateParameters.
+  addToken(Loc, HighlightingKind::TemplateParameter);
+  return;
+}
   }
 
   void addToken(SourceLocation Loc, HighlightingKind Kind) {


Index: clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
===
--- clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
+++ clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
@@ -323,6 +323,59 @@
   $Primitive[[auto]] $Variable[[Form]] = 10.2 + 2 * 4;
   $Primitive[[decltype]]($Variable[[Form]]) $Variable[[F]] = 10;
   auto $Variable[[Fun]] = []()->$Primitive[[void]]{};
+)cpp",
+R"cpp(
+  class $Class[[G]] {};
+  template<$Class[[G]] *$Variable[[U]]>
+  class $Class[[GP]] {};
+  template<$Class[[G]] &$Variable[[U]]>
+  class $Class[[GR]] {};
+  template<$Primitive[[int]] *$Variable[[U]]>
+  class $Class[[IP]] {
+$Primitive[[void]] $Method[[f]]() {
+  

[PATCH] D66219: [clangd] Added a colorizer to the vscode extension.

2019-08-14 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom created this revision.
jvikstrom added reviewers: hokein, ilya-biryukov.
Herald added subscribers: cfe-commits, kadircet, arphaman, jkorous, MaskRay.
Herald added a project: clang.

Adds the main colorizer component. It colorizes every time clangd sends a 
publishSemanticHighlighting notification.
Every time it colorizes it does a full recolorization (removes all decorations 
from the editor and applies new ones). The reason for this is that all ranges 
for the same scope share a TextEditorDecorationType. This is due to 
TextEditorDecorationTypes being very expensive to create. The prototype used 
one DecorationType per range but that ran into very big performance problems 
(it took >100 ms to apply 600 lines of highlightings which froze the editor).

This version does not share the problem of being extremly slow, but there is 
probably potential to optimize it even more.

The Colorizer uses a FileColorizer interface to make it possible to mock out 
all the code that applies colorizations to a specific editor so that we can 
test it.

No document/texteditor lifecycle management code in this CL, that will come in 
the next one.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D66219

Files:
  clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
  
clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts

Index: clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
@@ -1,5 +1,6 @@
 import * as assert from 'assert';
 import * as path from 'path';
+import * as vscode from 'vscode';
 
 import * as SM from '../src/semantic-highlighting';
 
@@ -57,4 +58,73 @@
 assert.deepEqual(tm.getBestThemeRule('variable.other.parameter.cpp').scope,
  'variable.other.parameter');
   });
+  test('Colorizer groups decorations correctly', () => {
+const colorizations: {uri: string, decorations: any[]}[] = [];
+// Mock of a colorizer that saves the parameters in the colorizations array.
+class MockFileColorizer {
+  public colorize(uri: string, decorationRangePairs: any[]) {
+colorizations.push({uri : uri, decorations : decorationRangePairs});
+  }
+  public dispose() {}
+}
+// Helper for creating a vscode Range.
+const createRange = (line: number, startCharacter: number,
+ length: number) =>
+new vscode.Range(new vscode.Position(line, startCharacter),
+ new vscode.Position(line, startCharacter + length));
+const scopeTable = [
+  [ 'variable' ], [ 'entity.type.function' ],
+  [ 'entity.type.function.method' ]
+];
+const rules = [
+  {scope : 'variable', foreground : '1'},
+  {scope : 'entity.type', foreground : '2'},
+];
+const tm = new SM.ThemeRuleMatcher(rules);
+const colorizer =
+new SM.Colorizer(MockFileColorizer, scopeTable);
+// No colorization if themeRuleMatcher has not been set.
+colorizer.setFileLines('a', []);
+assert.deepEqual(colorizations, []);
+colorizer.updateThemeRuleMatcher(tm);
+assert.deepEqual(colorizations, [ {decorations : [], uri : 'a'} ]);
+// Groups decorations into the scopes used.
+let line = [
+  {character : 1, length : 2, scopeIndex : 1},
+  {character : 5, length : 2, scopeIndex : 1},
+  {character : 10, length : 2, scopeIndex : 2}
+];
+colorizer.setFileLines(
+'a', [ {line : 1, tokens : line}, {line : 2, tokens : line} ]);
+assert.equal(colorizations[1].uri, 'a');
+assert.equal(colorizations[1].decorations.length, 2);
+// Can't test the actual decorations as vscode does not seem to have an api
+// for getting the actual decoration objects.
+assert.deepEqual(colorizations[1].decorations[0].ranges, [
+  createRange(1, 1, 2), createRange(1, 5, 2), createRange(2, 1, 2),
+  createRange(2, 5, 2)
+]);
+assert.deepEqual(colorizations[1].decorations[1].ranges,
+ [ createRange(1, 10, 2), createRange(2, 10, 2) ]);
+// Keeps state separate between files.
+colorizer.setFileLines('b', [
+  {line : 1, tokens : [ {character : 1, length : 1, scopeIndex : 0} ]}
+]);
+assert.equal(colorizations[2].uri, 'b');
+assert.equal(colorizations[2].decorations.length, 1);
+assert.deepEqual(colorizations[2].decorations[0].ranges,
+ [ createRange(1, 1, 1) ]);
+// Does full colorizations.
+colorizer.setFileLines('a', [
+  {line : 1, tokens : [ {character : 2, length : 1, scopeIndex : 0} ]}
+]);
+assert.equal(colorizations[3].uri, 'a');
+assert.equal(colorizations[3].decorations.length, 3);
+

[PATCH] D65856: [clangd] Added class for mapping TokenColorRules to their associated clangd TextMate scope

2019-08-14 Thread Johan Vikström via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL368834: [clangd] Loading TokenColorRules as a class mapping 
the rules to their… (authored by jvikstrom, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D65856?vs=215065=215085#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65856/new/

https://reviews.llvm.org/D65856

Files:
  
clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
  
clang-tools-extra/trunk/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts

Index: clang-tools-extra/trunk/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
===
--- clang-tools-extra/trunk/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
+++ clang-tools-extra/trunk/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
@@ -1,13 +1,13 @@
 import * as assert from 'assert';
 import * as path from 'path';
 
-import * as TM from '../src/semantic-highlighting';
+import * as SM from '../src/semantic-highlighting';
 
 suite('SemanticHighlighting Tests', () => {
   test('Parses arrays of textmate themes.', async () => {
 const themePath =
 path.join(__dirname, '../../test/assets/includeTheme.jsonc');
-const scopeColorRules = await TM.parseThemeFile(themePath);
+const scopeColorRules = await SM.parseThemeFile(themePath);
 const getScopeRule = (scope: string) =>
 scopeColorRules.find((v) => v.scope === scope);
 assert.equal(scopeColorRules.length, 3);
@@ -33,6 +33,28 @@
   ]
 ];
 testCases.forEach((testCase, i) => assert.deepEqual(
-  TM.decodeTokens(testCase), expected[i]));
+  SM.decodeTokens(testCase), expected[i]));
+  });
+  test('ScopeRules overrides for more specific themes', () => {
+const rules = [
+  {scope : 'variable.other.css', foreground : '1'},
+  {scope : 'variable.other', foreground : '2'},
+  {scope : 'storage', foreground : '3'},
+  {scope : 'storage.static', foreground : '4'},
+  {scope : 'storage', foreground : '5'},
+  {scope : 'variable.other.parameter', foreground : '6'},
+];
+const tm = new SM.ThemeRuleMatcher(rules);
+assert.deepEqual(tm.getBestThemeRule('variable.other.cpp').scope,
+ 'variable.other');
+assert.deepEqual(tm.getBestThemeRule('storage.static').scope,
+ 'storage.static');
+assert.deepEqual(
+tm.getBestThemeRule('storage'),
+rules[2]); // Match the first element if there are duplicates.
+assert.deepEqual(tm.getBestThemeRule('variable.other.parameter').scope,
+ 'variable.other.parameter');
+assert.deepEqual(tm.getBestThemeRule('variable.other.parameter.cpp').scope,
+ 'variable.other.parameter');
   });
 });
Index: clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
===
--- clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
+++ clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
@@ -47,6 +47,8 @@
   // The TextMate scope lookup table. A token with scope index i has the scopes
   // on index i in the lookup table.
   scopeLookupTable: string[][];
+  // The rules for the current theme.
+  themeRuleMatcher: ThemeRuleMatcher;
   fillClientCapabilities(capabilities: vscodelc.ClientCapabilities) {
 // Extend the ClientCapabilities type and add semantic highlighting
 // capability to the object.
@@ -58,6 +60,12 @@
 };
   }
 
+  async loadCurrentTheme() {
+this.themeRuleMatcher = new ThemeRuleMatcher(
+await loadTheme(vscode.workspace.getConfiguration('workbench')
+.get('colorTheme')));
+  }
+
   initialize(capabilities: vscodelc.ServerCapabilities,
  documentSelector: vscodelc.DocumentSelector|undefined) {
 // The semantic highlighting capability information is in the capabilities
@@ -68,6 +76,7 @@
 if (!serverCapabilities.semanticHighlighting)
   return;
 this.scopeLookupTable = serverCapabilities.semanticHighlighting.scopes;
+this.loadCurrentTheme();
   }
 
   handleNotification(params: SemanticHighlightingParams) {}
@@ -101,6 +110,39 @@
   foreground: string;
 }
 
+export class ThemeRuleMatcher {
+  // The rules for the theme.
+  private themeRules: TokenColorRule[];
+  // A cache for the getBestThemeRule function.
+  private bestRuleCache: Map = new Map();
+  constructor(rules: TokenColorRule[]) { this.themeRules = rules; }
+  // Returns the best rule for a scope.
+  getBestThemeRule(scope: string): TokenColorRule {
+if (this.bestRuleCache.has(scope))
+  return this.bestRuleCache.get(scope);
+let bestRule: 

[PATCH] D65856: [clangd] Added class for mapping TokenColorRules to their associated clangd TextMate scope

2019-08-14 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom updated this revision to Diff 215065.
jvikstrom marked 4 inline comments as done.
jvikstrom added a comment.

Simplified matching code. Use real scopes for test.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65856/new/

https://reviews.llvm.org/D65856

Files:
  clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
  
clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts

Index: clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
@@ -1,13 +1,13 @@
 import * as assert from 'assert';
 import * as path from 'path';
 
-import * as TM from '../src/semantic-highlighting';
+import * as SM from '../src/semantic-highlighting';
 
 suite('SemanticHighlighting Tests', () => {
   test('Parses arrays of textmate themes.', async () => {
 const themePath =
 path.join(__dirname, '../../test/assets/includeTheme.jsonc');
-const scopeColorRules = await TM.parseThemeFile(themePath);
+const scopeColorRules = await SM.parseThemeFile(themePath);
 const getScopeRule = (scope: string) =>
 scopeColorRules.find((v) => v.scope === scope);
 assert.equal(scopeColorRules.length, 3);
@@ -33,6 +33,28 @@
   ]
 ];
 testCases.forEach((testCase, i) => assert.deepEqual(
-  TM.decodeTokens(testCase), expected[i]));
+  SM.decodeTokens(testCase), expected[i]));
+  });
+  test('ScopeRules overrides for more specific themes', () => {
+const rules = [
+  {scope : 'variable.other.css', foreground : '1'},
+  {scope : 'variable.other', foreground : '2'},
+  {scope : 'storage', foreground : '3'},
+  {scope : 'storage.static', foreground : '4'},
+  {scope : 'storage', foreground : '5'},
+  {scope : 'variable.other.parameter', foreground : '6'},
+];
+const tm = new SM.ThemeRuleMatcher(rules);
+assert.deepEqual(tm.getBestThemeRule('variable.other.cpp').scope,
+ 'variable.other');
+assert.deepEqual(tm.getBestThemeRule('storage.static').scope,
+ 'storage.static');
+assert.deepEqual(
+tm.getBestThemeRule('storage'),
+rules[2]); // Match the first element if there are duplicates.
+assert.deepEqual(tm.getBestThemeRule('variable.other.parameter').scope,
+ 'variable.other.parameter');
+assert.deepEqual(tm.getBestThemeRule('variable.other.parameter.cpp').scope,
+ 'variable.other.parameter');
   });
 });
Index: clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
@@ -47,6 +47,8 @@
   // The TextMate scope lookup table. A token with scope index i has the scopes
   // on index i in the lookup table.
   scopeLookupTable: string[][];
+  // The rules for the current theme.
+  themeRuleMatcher: ThemeRuleMatcher;
   fillClientCapabilities(capabilities: vscodelc.ClientCapabilities) {
 // Extend the ClientCapabilities type and add semantic highlighting
 // capability to the object.
@@ -58,6 +60,12 @@
 };
   }
 
+  async loadCurrentTheme() {
+this.themeRuleMatcher = new ThemeRuleMatcher(
+await loadTheme(vscode.workspace.getConfiguration('workbench')
+.get('colorTheme')));
+  }
+
   initialize(capabilities: vscodelc.ServerCapabilities,
  documentSelector: vscodelc.DocumentSelector|undefined) {
 // The semantic highlighting capability information is in the capabilities
@@ -68,6 +76,7 @@
 if (!serverCapabilities.semanticHighlighting)
   return;
 this.scopeLookupTable = serverCapabilities.semanticHighlighting.scopes;
+this.loadCurrentTheme();
   }
 
   handleNotification(params: SemanticHighlightingParams) {}
@@ -101,6 +110,39 @@
   foreground: string;
 }
 
+export class ThemeRuleMatcher {
+  // The rules for the theme.
+  private themeRules: TokenColorRule[];
+  // A cache for the getBestThemeRule function.
+  private bestRuleCache: Map = new Map();
+  constructor(rules: TokenColorRule[]) { this.themeRules = rules; }
+  // Returns the best rule for a scope.
+  getBestThemeRule(scope: string): TokenColorRule {
+if (this.bestRuleCache.has(scope))
+  return this.bestRuleCache.get(scope);
+let bestRule: TokenColorRule = {scope : '', foreground : ''};
+this.themeRules.forEach((rule) => {
+  // The best rule for a scope is the rule that is the longest prefix of the
+  // scope (unless a perfect match exists in which 

[PATCH] D65856: [clangd] Added class for mapping TokenColorRules to their associated clangd TextMate scope

2019-08-13 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom updated this revision to Diff 214845.
jvikstrom marked an inline comment as done.
jvikstrom added a comment.

Added fixme for ranking.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65856/new/

https://reviews.llvm.org/D65856

Files:
  clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
  
clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts

Index: clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
@@ -1,13 +1,13 @@
 import * as assert from 'assert';
 import * as path from 'path';
 
-import * as TM from '../src/semantic-highlighting';
+import * as SM from '../src/semantic-highlighting';
 
 suite('SemanticHighlighting Tests', () => {
   test('Parses arrays of textmate themes.', async () => {
 const themePath =
 path.join(__dirname, '../../test/assets/includeTheme.jsonc');
-const scopeColorRules = await TM.parseThemeFile(themePath);
+const scopeColorRules = await SM.parseThemeFile(themePath);
 const getScopeRule = (scope: string) =>
 scopeColorRules.find((v) => v.scope === scope);
 assert.equal(scopeColorRules.length, 3);
@@ -33,6 +33,21 @@
   ]
 ];
 testCases.forEach((testCase, i) => assert.deepEqual(
-  TM.decodeTokens(testCase), expected[i]));
+  SM.decodeTokens(testCase), expected[i]));
+  });
+  test('ScopeRules overrides for more specific themes', () => {
+const rules = [
+  {scope : 'c.b', foreground : '1'},
+  {scope : 'a', foreground : '2'},
+  {scope : 'a.b', foreground : '3'},
+  {scope : 'a', foreground : '4'},
+  {scope : 'c.b.a', foreground : '5'},
+];
+const tm = new SM.ThemeRuleMatcher(rules);
+assert.deepEqual(tm.getBestThemeRule('c.b'), rules[0]);
+assert.deepEqual(tm.getBestThemeRule('a.b'), rules[2]);
+assert.deepEqual(tm.getBestThemeRule('a'), rules[1]);
+assert.deepEqual(tm.getBestThemeRule('c.b.a'), rules[4]);
+assert.deepEqual(tm.getBestThemeRule('c.b.a.d.f'), rules[4]);
   });
 });
Index: clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
@@ -47,6 +47,8 @@
   // The TextMate scope lookup table. A token with scope index i has the scopes
   // on index i in the lookup table.
   scopeLookupTable: string[][];
+  // The rules for the current theme.
+  themeRuleMatcher: ThemeRuleMatcher;
   fillClientCapabilities(capabilities: vscodelc.ClientCapabilities) {
 // Extend the ClientCapabilities type and add semantic highlighting
 // capability to the object.
@@ -58,6 +60,12 @@
 };
   }
 
+  async loadCurrentTheme() {
+this.themeRuleMatcher = new ThemeRuleMatcher(
+await loadTheme(vscode.workspace.getConfiguration('workbench')
+.get('colorTheme')));
+  }
+
   initialize(capabilities: vscodelc.ServerCapabilities,
  documentSelector: vscodelc.DocumentSelector|undefined) {
 // The semantic highlighting capability information is in the capabilities
@@ -68,6 +76,7 @@
 if (!serverCapabilities.semanticHighlighting)
   return;
 this.scopeLookupTable = serverCapabilities.semanticHighlighting.scopes;
+this.loadCurrentTheme();
   }
 
   handleNotification(params: SemanticHighlightingParams) {}
@@ -101,6 +110,35 @@
   foreground: string;
 }
 
+export class ThemeRuleMatcher {
+  // The rules for the theme.
+  private rules: TokenColorRule[];
+  // A cache for the getBestThemeRule function.
+  private bestRuleCache: Map = new Map();
+  constructor(rules: TokenColorRule[]) { this.rules = rules; }
+  // Returns the best rule for a scope.
+  getBestThemeRule(scope: string): TokenColorRule {
+if (this.bestRuleCache.has(scope))
+  return this.bestRuleCache.get(scope);
+let bestRule: TokenColorRule = {scope : '', foreground : ''};
+this.rules.forEach((rule) => {
+  // The best rule for a scope is the rule that is the longest prefix of the
+  // scope (unless a perfect match exists in which case the perfect match is
+  // the best).
+  // FIXME: This is not defined in the TextMate standard (it is explicitly
+  // undefined, https://macromates.com/manual/en/scope_selectors). Might
+  // want to rank some other way.
+  if (rule.scope.length <= scope.length &&
+  scope.substr(0, rule.scope.length) === rule.scope &&
+  rule.scope.length > bestRule.scope.length)
+// This rule matches and is more 

[PATCH] D65856: [clangd] Added class for mapping TokenColorRules to their associated clangd TextMate scope

2019-08-13 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom added inline comments.



Comment at: 
clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts:128
+  // Find the rule wich is the longest prefix of scope.
+  if (rule.scope.length <= scope.length &&
+  scope.substr(0, rule.scope.length) === rule.scope &&

hokein wrote:
> The algorithm doesn't seems correct to me, if scope.length > 
> rule.scope.length, then we drop it.
> 
> I think we should 
> - calculate the common prefix between two scopes
> - update the bestRule if the length of common prefix is greater than the 
> current best length
If the scope's length is less than the rule's length the rule can not be a 
prefix.
(Not sure I fully follow with what you mean in the first sentence though)


If we check common prefixes we run into this weird case (this is taken from the 
Light+ theme):
```
variable.css
variable.scss
variable.other.less
variable
```
With that kind of matching we have now this means that `variable.other.less` 
will match `variable.other` and `variable.other.less` and the variables would 
be colored as less variables while they should be `variable.other`. Same goes 
for `variable.other.field`.

And even if `variable.other.less` did not exist `variable.other` would still 
match `variable.css` and now be highlighted as css variables.



Comment at: 
clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts:47
+const tm = new SM.ThemeRuleMatcher(rules);
+assert.deepEqual(tm.getBestThemeRule('c.b'), rules[0]);
+assert.deepEqual(tm.getBestThemeRule('a.b'), rules[2]);

hokein wrote:
> I'd use `assert.deepEqual(tm.getBestThemeRule('c.b').scope, 'c.b');` to make 
> the code more readable.
> 
For the `a` case we are interested in the foreground color as well. Should I 
change the others and keep `assert.deepEqual(tm.getBestThemeRule('a'), 
rules[1]);` as is or be consistent?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65856/new/

https://reviews.llvm.org/D65856



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D65856: [clangd] Added class for mapping TokenColorRules to their associated clangd TextMate scope

2019-08-13 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom updated this revision to Diff 214844.
jvikstrom marked 4 inline comments as done.
jvikstrom added a comment.

Changed variable name.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65856/new/

https://reviews.llvm.org/D65856

Files:
  clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
  
clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts

Index: clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
@@ -1,13 +1,13 @@
 import * as assert from 'assert';
 import * as path from 'path';
 
-import * as TM from '../src/semantic-highlighting';
+import * as SM from '../src/semantic-highlighting';
 
 suite('SemanticHighlighting Tests', () => {
   test('Parses arrays of textmate themes.', async () => {
 const themePath =
 path.join(__dirname, '../../test/assets/includeTheme.jsonc');
-const scopeColorRules = await TM.parseThemeFile(themePath);
+const scopeColorRules = await SM.parseThemeFile(themePath);
 const getScopeRule = (scope: string) =>
 scopeColorRules.find((v) => v.scope === scope);
 assert.equal(scopeColorRules.length, 3);
@@ -33,6 +33,21 @@
   ]
 ];
 testCases.forEach((testCase, i) => assert.deepEqual(
-  TM.decodeTokens(testCase), expected[i]));
+  SM.decodeTokens(testCase), expected[i]));
+  });
+  test('ScopeRules overrides for more specific themes', () => {
+const rules = [
+  {scope : 'c.b', foreground : '1'},
+  {scope : 'a', foreground : '2'},
+  {scope : 'a.b', foreground : '3'},
+  {scope : 'a', foreground : '4'},
+  {scope : 'c.b.a', foreground : '5'},
+];
+const tm = new SM.ThemeRuleMatcher(rules);
+assert.deepEqual(tm.getBestThemeRule('c.b'), rules[0]);
+assert.deepEqual(tm.getBestThemeRule('a.b'), rules[2]);
+assert.deepEqual(tm.getBestThemeRule('a'), rules[1]);
+assert.deepEqual(tm.getBestThemeRule('c.b.a'), rules[4]);
+assert.deepEqual(tm.getBestThemeRule('c.b.a.d.f'), rules[4]);
   });
 });
Index: clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
@@ -47,6 +47,8 @@
   // The TextMate scope lookup table. A token with scope index i has the scopes
   // on index i in the lookup table.
   scopeLookupTable: string[][];
+  // The rules for the current theme.
+  themeRuleMatcher: ThemeRuleMatcher;
   fillClientCapabilities(capabilities: vscodelc.ClientCapabilities) {
 // Extend the ClientCapabilities type and add semantic highlighting
 // capability to the object.
@@ -58,6 +60,12 @@
 };
   }
 
+  async loadCurrentTheme() {
+this.themeRuleMatcher = new ThemeRuleMatcher(
+await loadTheme(vscode.workspace.getConfiguration('workbench')
+.get('colorTheme')));
+  }
+
   initialize(capabilities: vscodelc.ServerCapabilities,
  documentSelector: vscodelc.DocumentSelector|undefined) {
 // The semantic highlighting capability information is in the capabilities
@@ -68,6 +76,7 @@
 if (!serverCapabilities.semanticHighlighting)
   return;
 this.scopeLookupTable = serverCapabilities.semanticHighlighting.scopes;
+this.loadCurrentTheme();
   }
 
   handleNotification(params: SemanticHighlightingParams) {}
@@ -101,6 +110,32 @@
   foreground: string;
 }
 
+export class ThemeRuleMatcher {
+  // The rules for the theme.
+  private rules: TokenColorRule[];
+  // A cache for the getBestThemeRule function.
+  private bestRuleCache: Map = new Map();
+  constructor(rules: TokenColorRule[]) { this.rules = rules; }
+  // Returns the best rule for a scope.
+  getBestThemeRule(scope: string): TokenColorRule {
+if (this.bestRuleCache.has(scope))
+  return this.bestRuleCache.get(scope);
+let bestRule: TokenColorRule = {scope : '', foreground : ''};
+this.rules.forEach((rule) => {
+  // The best rule for a scope is the rule that is the longest prefix of the
+  // scope (unless a perfect match exists in which case the perfect match is
+  // the best).
+  if (rule.scope.length <= scope.length &&
+  scope.substr(0, rule.scope.length) === rule.scope &&
+  rule.scope.length > bestRule.scope.length)
+// This rule matches and is more specific than the old rule.
+bestRule = rule;
+});
+this.bestRuleCache.set(scope, bestRule);
+return bestRule;
+  }
+}
+
 // Get all token color rules provided by the theme.
 function 

[PATCH] D65856: [clangd] Added class for mapping TokenColorRules to their associated clangd TextMate scope

2019-08-13 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom added inline comments.



Comment at: 
clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts:131
+this.rules.forEach((rule) => {
+  if (rule.scope.length <= scope.length &&
+  scope.substr(0, rule.scope.length) === rule.scope &&

hokein wrote:
> hmm, here comes the question, we need algorithm to find the best match rule. 
> not doing it in this patch is fine, please add a FIXME.
> 
> could you also document what's the strategy using here?
But isn't the best match for a scope just the rule that is the longest prefix 
of the scope (or a perfect match if one exists)? (as that should be the most 
specific rule)


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65856/new/

https://reviews.llvm.org/D65856



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D65856: [clangd] Added class for mapping TokenColorRules to their associated clangd TextMate scope

2019-08-13 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom updated this revision to Diff 214834.
jvikstrom added a comment.

Removed stray edits from loadTheme.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65856/new/

https://reviews.llvm.org/D65856

Files:
  clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
  
clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts

Index: clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
@@ -1,13 +1,13 @@
 import * as assert from 'assert';
 import * as path from 'path';
 
-import * as TM from '../src/semantic-highlighting';
+import * as SM from '../src/semantic-highlighting';
 
 suite('SemanticHighlighting Tests', () => {
   test('Parses arrays of textmate themes.', async () => {
 const themePath =
 path.join(__dirname, '../../test/assets/includeTheme.jsonc');
-const scopeColorRules = await TM.parseThemeFile(themePath);
+const scopeColorRules = await SM.parseThemeFile(themePath);
 const getScopeRule = (scope: string) =>
 scopeColorRules.find((v) => v.scope === scope);
 assert.equal(scopeColorRules.length, 3);
@@ -33,6 +33,21 @@
   ]
 ];
 testCases.forEach((testCase, i) => assert.deepEqual(
-  TM.decodeTokens(testCase), expected[i]));
+  SM.decodeTokens(testCase), expected[i]));
+  });
+  test('ScopeRules overrides for more specific themes', () => {
+const rules = [
+  {scope : 'c.b', foreground : '1'},
+  {scope : 'a', foreground : '2'},
+  {scope : 'a.b', foreground : '3'},
+  {scope : 'a', foreground : '4'},
+  {scope : 'c.b.a', foreground : '5'},
+];
+const tm = new SM.ThemeRuleMatcher(rules);
+assert.deepEqual(tm.getBestThemeRule('c.b'), rules[0]);
+assert.deepEqual(tm.getBestThemeRule('a.b'), rules[2]);
+assert.deepEqual(tm.getBestThemeRule('a'), rules[1]);
+assert.deepEqual(tm.getBestThemeRule('c.b.a'), rules[4]);
+assert.deepEqual(tm.getBestThemeRule('c.b.a.d.f'), rules[4]);
   });
 });
Index: clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
@@ -47,6 +47,8 @@
   // The TextMate scope lookup table. A token with scope index i has the scopes
   // on index i in the lookup table.
   scopeLookupTable: string[][];
+  // The rules for the current theme.
+  themeRules: ThemeRuleMatcher;
   fillClientCapabilities(capabilities: vscodelc.ClientCapabilities) {
 // Extend the ClientCapabilities type and add semantic highlighting
 // capability to the object.
@@ -58,6 +60,12 @@
 };
   }
 
+  async loadCurrentTheme() {
+this.themeRules = new ThemeRuleMatcher(
+await loadTheme(vscode.workspace.getConfiguration('workbench')
+.get('colorTheme')));
+  }
+
   initialize(capabilities: vscodelc.ServerCapabilities,
  documentSelector: vscodelc.DocumentSelector|undefined) {
 // The semantic highlighting capability information is in the capabilities
@@ -68,6 +76,7 @@
 if (!serverCapabilities.semanticHighlighting)
   return;
 this.scopeLookupTable = serverCapabilities.semanticHighlighting.scopes;
+this.loadCurrentTheme();
   }
 
   handleNotification(params: SemanticHighlightingParams) {}
@@ -101,6 +110,32 @@
   foreground: string;
 }
 
+export class ThemeRuleMatcher {
+  // The rules for the theme.
+  private rules: TokenColorRule[];
+  // A cache for the getBestThemeRule function.
+  private bestRuleCache: Map = new Map();
+  constructor(rules: TokenColorRule[]) { this.rules = rules; }
+  // Returns the best rule for a scope. The best rule for a scope is the rule
+  // that is the longest prefix of the scope (unless a perfect match exists in
+  // which case the perfect match is the best).
+  getBestThemeRule(scope: string): TokenColorRule {
+if (this.bestRuleCache.has(scope))
+  return this.bestRuleCache.get(scope);
+let bestRule: TokenColorRule = {scope : '', foreground : ''};
+this.rules.forEach((rule) => {
+  // Find the rule wich is the longest prefix of scope.
+  if (rule.scope.length <= scope.length &&
+  scope.substr(0, rule.scope.length) === rule.scope &&
+  rule.scope.length > bestRule.scope.length)
+// This rule matches and is more specific than the old rule.
+bestRule = rule;
+});
+this.bestRuleCache.set(scope, bestRule);
+return bestRule;
+  }
+}
+
 // Get all token color rules provided by the theme.
 function 

[PATCH] D65856: [clangd] Added class for mapping TokenColorRules to their associated clangd TextMate scope

2019-08-13 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom updated this revision to Diff 214833.
jvikstrom marked 4 inline comments as done.
jvikstrom added a comment.

Address comments.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65856/new/

https://reviews.llvm.org/D65856

Files:
  clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
  
clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts

Index: clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
@@ -1,13 +1,13 @@
 import * as assert from 'assert';
 import * as path from 'path';
 
-import * as TM from '../src/semantic-highlighting';
+import * as SM from '../src/semantic-highlighting';
 
 suite('SemanticHighlighting Tests', () => {
   test('Parses arrays of textmate themes.', async () => {
 const themePath =
 path.join(__dirname, '../../test/assets/includeTheme.jsonc');
-const scopeColorRules = await TM.parseThemeFile(themePath);
+const scopeColorRules = await SM.parseThemeFile(themePath);
 const getScopeRule = (scope: string) =>
 scopeColorRules.find((v) => v.scope === scope);
 assert.equal(scopeColorRules.length, 3);
@@ -33,6 +33,21 @@
   ]
 ];
 testCases.forEach((testCase, i) => assert.deepEqual(
-  TM.decodeTokens(testCase), expected[i]));
+  SM.decodeTokens(testCase), expected[i]));
+  });
+  test('ScopeRules overrides for more specific themes', () => {
+const rules = [
+  {scope : 'c.b', foreground : '1'},
+  {scope : 'a', foreground : '2'},
+  {scope : 'a.b', foreground : '3'},
+  {scope : 'a', foreground : '4'},
+  {scope : 'c.b.a', foreground : '5'},
+];
+const tm = new SM.ThemeRuleMatcher(rules);
+assert.deepEqual(tm.getBestThemeRule('c.b'), rules[0]);
+assert.deepEqual(tm.getBestThemeRule('a.b'), rules[2]);
+assert.deepEqual(tm.getBestThemeRule('a'), rules[1]);
+assert.deepEqual(tm.getBestThemeRule('c.b.a'), rules[4]);
+assert.deepEqual(tm.getBestThemeRule('c.b.a.d.f'), rules[4]);
   });
 });
Index: clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
@@ -47,6 +47,8 @@
   // The TextMate scope lookup table. A token with scope index i has the scopes
   // on index i in the lookup table.
   scopeLookupTable: string[][];
+  // The rules for the current theme.
+  themeRules: ThemeRuleMatcher;
   fillClientCapabilities(capabilities: vscodelc.ClientCapabilities) {
 // Extend the ClientCapabilities type and add semantic highlighting
 // capability to the object.
@@ -58,6 +60,12 @@
 };
   }
 
+  async loadCurrentTheme() {
+this.themeRules = new ThemeRuleMatcher(
+await loadTheme(vscode.workspace.getConfiguration('workbench')
+.get('colorTheme')));
+  }
+
   initialize(capabilities: vscodelc.ServerCapabilities,
  documentSelector: vscodelc.DocumentSelector|undefined) {
 // The semantic highlighting capability information is in the capabilities
@@ -68,6 +76,7 @@
 if (!serverCapabilities.semanticHighlighting)
   return;
 this.scopeLookupTable = serverCapabilities.semanticHighlighting.scopes;
+this.loadCurrentTheme();
   }
 
   handleNotification(params: SemanticHighlightingParams) {}
@@ -101,8 +110,34 @@
   foreground: string;
 }
 
+export class ThemeRuleMatcher {
+  // The rules for the theme.
+  private rules: TokenColorRule[];
+  // A cache for the getBestThemeRule function.
+  private bestRuleCache: Map = new Map();
+  constructor(rules: TokenColorRule[]) { this.rules = rules; }
+  // Returns the best rule for a scope. The best rule for a scope is the rule
+  // that is the longest prefix of the scope (unless a perfect match exists in
+  // which case the perfect match is the best).
+  getBestThemeRule(scope: string): TokenColorRule {
+if (this.bestRuleCache.has(scope))
+  return this.bestRuleCache.get(scope);
+let bestRule: TokenColorRule = {scope : '', foreground : ''};
+this.rules.forEach((rule) => {
+  // Find the rule wich is the longest prefix of scope.
+  if (rule.scope.length <= scope.length &&
+  scope.substr(0, rule.scope.length) === rule.scope &&
+  rule.scope.length > bestRule.scope.length)
+// This rule matches and is more specific than the old rule.
+bestRule = rule;
+});
+this.bestRuleCache.set(scope, bestRule);
+return bestRule;
+  }
+}
+
 // Get all token color rules 

[PATCH] D65856: [clangd] Added class for mapping TokenColorRules to their associated clangd TextMate scope

2019-08-13 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom updated this revision to Diff 214814.
jvikstrom added a comment.

Added a missing test case.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65856/new/

https://reviews.llvm.org/D65856

Files:
  clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
  
clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts

Index: clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
@@ -1,13 +1,13 @@
 import * as assert from 'assert';
 import * as path from 'path';
 
-import * as TM from '../src/semantic-highlighting';
+import * as SM from '../src/semantic-highlighting';
 
 suite('SemanticHighlighting Tests', () => {
   test('Parses arrays of textmate themes.', async () => {
 const themePath =
 path.join(__dirname, '../../test/assets/includeTheme.jsonc');
-const scopeColorRules = await TM.parseThemeFile(themePath);
+const scopeColorRules = await SM.parseThemeFile(themePath);
 const getScopeRule = (scope: string) =>
 scopeColorRules.find((v) => v.scope === scope);
 assert.equal(scopeColorRules.length, 3);
@@ -33,6 +33,21 @@
   ]
 ];
 testCases.forEach((testCase, i) => assert.deepEqual(
-  TM.decodeTokens(testCase), expected[i]));
+  SM.decodeTokens(testCase), expected[i]));
+  });
+  test('ScopeRules overrides for more specific themes', () => {
+const rules = [
+  {scope : 'c.b', foreground : '1'},
+  {scope : 'a', foreground : '2'},
+  {scope : 'a.b', foreground : '3'},
+  {scope : 'a', foreground : '4'},
+  {scope : 'c.b.a', foreground : '5'},
+];
+const tm = new SM.ThemeRules(rules);
+assert.deepEqual(tm.getBestThemeRule('c.b'), rules[0]);
+assert.deepEqual(tm.getBestThemeRule('a.b'), rules[2]);
+assert.deepEqual(tm.getBestThemeRule('a'), rules[1]);
+assert.deepEqual(tm.getBestThemeRule('c.b.a'), rules[4]);
+assert.deepEqual(tm.getBestThemeRule('c.b.a.d.f'), rules[4]);
   });
 });
Index: clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
@@ -47,6 +47,8 @@
   // The TextMate scope lookup table. A token with scope index i has the scopes
   // on index i in the lookup table.
   scopeLookupTable: string[][];
+  // The rules for the current theme.
+  themeRules: ThemeRules;
   fillClientCapabilities(capabilities: vscodelc.ClientCapabilities) {
 // Extend the ClientCapabilities type and add semantic highlighting
 // capability to the object.
@@ -58,6 +60,18 @@
 };
   }
 
+  async loadCurrentTheme() {
+const name =
+vscode.workspace.getConfiguration('workbench').get('colorTheme');
+if (typeof name != 'string') {
+  console.warn('The current theme name is not a string, is:' +
+   (typeof name) + ', value: ',
+   name);
+  return;
+}
+this.themeRules = await loadTheme(name);
+  }
+
   initialize(capabilities: vscodelc.ServerCapabilities,
  documentSelector: vscodelc.DocumentSelector|undefined) {
 // The semantic highlighting capability information is in the capabilities
@@ -68,6 +82,7 @@
 if (!serverCapabilities.semanticHighlighting)
   return;
 this.scopeLookupTable = serverCapabilities.semanticHighlighting.scopes;
+this.loadCurrentTheme();
   }
 
   handleNotification(params: SemanticHighlightingParams) {}
@@ -101,8 +116,31 @@
   foreground: string;
 }
 
+export class ThemeRules {
+  // The rules for the theme.
+  private rules: TokenColorRule[];
+  // A cache for the getBestThemeRule function.
+  private bestRuleCache: Map = new Map();
+  constructor(rules: TokenColorRule[]) { this.rules = rules; }
+  // Returns the best rule for a scope.
+  getBestThemeRule(scope: string): TokenColorRule {
+if (this.bestRuleCache.has(scope))
+  return this.bestRuleCache.get(scope);
+let bestRule: TokenColorRule = {scope : '', foreground : ''};
+this.rules.forEach((rule) => {
+  if (rule.scope.length <= scope.length &&
+  scope.substr(0, rule.scope.length) === rule.scope &&
+  rule.scope.length > bestRule.scope.length)
+// This rule matches and is more specific than the old rule.
+bestRule = rule;
+});
+this.bestRuleCache.set(scope, bestRule);
+return bestRule;
+  }
+}
+
 // Get all token color rules provided by the theme.
-function loadTheme(themeName: string): Promise {
+async function loadTheme(themeName: 

[PATCH] D65856: [clangd] Added class for mapping TokenColorRules to their associated clangd TextMate scope

2019-08-13 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom updated this revision to Diff 214813.
jvikstrom added a comment.

Lazy load the best theme rule for a scope.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65856/new/

https://reviews.llvm.org/D65856

Files:
  clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
  
clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts

Index: clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
@@ -1,13 +1,13 @@
 import * as assert from 'assert';
 import * as path from 'path';
 
-import * as TM from '../src/semantic-highlighting';
+import * as SM from '../src/semantic-highlighting';
 
 suite('SemanticHighlighting Tests', () => {
   test('Parses arrays of textmate themes.', async () => {
 const themePath =
 path.join(__dirname, '../../test/assets/includeTheme.jsonc');
-const scopeColorRules = await TM.parseThemeFile(themePath);
+const scopeColorRules = await SM.parseThemeFile(themePath);
 const getScopeRule = (scope: string) =>
 scopeColorRules.find((v) => v.scope === scope);
 assert.equal(scopeColorRules.length, 3);
@@ -33,6 +33,20 @@
   ]
 ];
 testCases.forEach((testCase, i) => assert.deepEqual(
-  TM.decodeTokens(testCase), expected[i]));
+  SM.decodeTokens(testCase), expected[i]));
+  });
+  test('ScopeRules overrides for more specific themes', () => {
+const rules = [
+  {scope : 'c.b', foreground : '1'},
+  {scope : 'a', foreground : '2'},
+  {scope : 'a.b', foreground : '3'},
+  {scope : 'a', foreground : '4'},
+  {scope : 'c.b.a', foreground : '5'},
+];
+const tm = new SM.ThemeRules(rules);
+assert.deepEqual(tm.getBestThemeRule('c.b'), rules[0]);
+assert.deepEqual(tm.getBestThemeRule('a.b'), rules[2]);
+assert.deepEqual(tm.getBestThemeRule('a'), rules[1]);
+assert.deepEqual(tm.getBestThemeRule('c.b.a'), rules[4]);
   });
 });
Index: clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
@@ -47,6 +47,8 @@
   // The TextMate scope lookup table. A token with scope index i has the scopes
   // on index i in the lookup table.
   scopeLookupTable: string[][];
+  // The rules for the current theme.
+  themeRules: ThemeRules;
   fillClientCapabilities(capabilities: vscodelc.ClientCapabilities) {
 // Extend the ClientCapabilities type and add semantic highlighting
 // capability to the object.
@@ -58,6 +60,18 @@
 };
   }
 
+  async loadCurrentTheme() {
+const name =
+vscode.workspace.getConfiguration('workbench').get('colorTheme');
+if (typeof name != 'string') {
+  console.warn('The current theme name is not a string, is:' +
+   (typeof name) + ', value: ',
+   name);
+  return;
+}
+this.themeRules = await loadTheme(name);
+  }
+
   initialize(capabilities: vscodelc.ServerCapabilities,
  documentSelector: vscodelc.DocumentSelector|undefined) {
 // The semantic highlighting capability information is in the capabilities
@@ -68,6 +82,7 @@
 if (!serverCapabilities.semanticHighlighting)
   return;
 this.scopeLookupTable = serverCapabilities.semanticHighlighting.scopes;
+this.loadCurrentTheme();
   }
 
   handleNotification(params: SemanticHighlightingParams) {}
@@ -101,8 +116,31 @@
   foreground: string;
 }
 
+export class ThemeRules {
+  // The rules for the theme.
+  private rules: TokenColorRule[];
+  // A cache for the getBestThemeRule function.
+  private bestRuleCache: Map = new Map();
+  constructor(rules: TokenColorRule[]) { this.rules = rules; }
+  // Returns the best rule for a scope.
+  getBestThemeRule(scope: string): TokenColorRule {
+if (this.bestRuleCache.has(scope))
+  return this.bestRuleCache.get(scope);
+let bestRule: TokenColorRule = {scope : '', foreground : ''};
+this.rules.forEach((rule) => {
+  if (rule.scope.length <= scope.length &&
+  scope.substr(0, rule.scope.length) === rule.scope &&
+  rule.scope.length > bestRule.scope.length)
+// This rule matches and is more specific than the old rule.
+bestRule = rule;
+});
+this.bestRuleCache.set(scope, bestRule);
+return bestRule;
+  }
+}
+
 // Get all token color rules provided by the theme.
-function loadTheme(themeName: string): Promise {
+async function loadTheme(themeName: string): Promise {
   const extension =
   

[PATCH] D65856: [clangd] Added class for mapping TokenColorRules to their associated clangd TextMate scope

2019-08-13 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom updated this revision to Diff 214779.
jvikstrom added a comment.

Updated patch description.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65856/new/

https://reviews.llvm.org/D65856

Files:
  clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
  
clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts

Index: clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
@@ -1,13 +1,13 @@
 import * as assert from 'assert';
 import * as path from 'path';
 
-import * as TM from '../src/semantic-highlighting';
+import * as SM from '../src/semantic-highlighting';
 
 suite('SemanticHighlighting Tests', () => {
   test('Parses arrays of textmate themes.', async () => {
 const themePath =
 path.join(__dirname, '../../test/assets/includeTheme.jsonc');
-const scopeColorRules = await TM.parseThemeFile(themePath);
+const scopeColorRules = await SM.parseThemeFile(themePath);
 const getScopeRule = (scope: string) =>
 scopeColorRules.find((v) => v.scope === scope);
 assert.equal(scopeColorRules.length, 3);
@@ -33,6 +33,21 @@
   ]
 ];
 testCases.forEach((testCase, i) => assert.deepEqual(
-  TM.decodeTokens(testCase), expected[i]));
+  SM.decodeTokens(testCase), expected[i]));
+  });
+  test('ScopeRules overrides for more specific themes', () => {
+const scopes = [ [ 'a.b', 'a.b' ], [ 'a', 'a.b', 'c.b.a' ], [ 'c.b.a' ] ];
+const rules = [
+  {scope : 'c.b', foreground : '1'},
+  {scope : 'a', foreground : '2'},
+  {scope : 'a.b', foreground : '3'},
+  {scope : 'a', foreground : '4'},
+  {scope : 'c.b.a', foreground : '5'},
+];
+const tm = new SM.ScopeRules(scopes);
+rules.forEach((r) => tm.addRule(r));
+assert.deepEqual(tm.getRule(0), rules[2]);
+assert.deepEqual(tm.getRule(1), rules[1]);
+assert.deepEqual(tm.getRule(2), rules[4]);
   });
 });
Index: clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
@@ -47,6 +47,8 @@
   // The TextMate scope lookup table. A token with scope index i has the scopes
   // on index i in the lookup table.
   scopeLookupTable: string[][];
+  // The rules for the scopes given the current theme.
+  scopeRules: ScopeRules;
   fillClientCapabilities(capabilities: vscodelc.ClientCapabilities) {
 // Extend the ClientCapabilities type and add semantic highlighting
 // capability to the object.
@@ -58,6 +60,18 @@
 };
   }
 
+  async loadCurrentTheme() {
+const name =
+vscode.workspace.getConfiguration('workbench').get('colorTheme');
+if (typeof name != 'string') {
+  console.warn('The current theme name is not a string, is:' +
+   (typeof name) + ', value: ',
+   name);
+  return;
+}
+this.scopeRules = await loadTheme(name, this.scopeLookupTable);
+  }
+
   initialize(capabilities: vscodelc.ServerCapabilities,
  documentSelector: vscodelc.DocumentSelector|undefined) {
 // The semantic highlighting capability information is in the capabilities
@@ -68,6 +82,7 @@
 if (!serverCapabilities.semanticHighlighting)
   return;
 this.scopeLookupTable = serverCapabilities.semanticHighlighting.scopes;
+this.loadCurrentTheme();
   }
 
   handleNotification(params: SemanticHighlightingParams) {}
@@ -101,8 +116,55 @@
   foreground: string;
 }
 
+export class ScopeRules {
+  // The TextMate scopes that should be mapped to a color.
+  private scopeLookupTable: string[][];
+  // Contains the current best matching scope for the scope at the corresponding
+  // index.
+  private scopeRules: TokenColorRule[];
+  // Each list of scopes can only have one rule matching. The actual scope that
+  // matches for each index should be as close to zero as possible.
+  private currentScopeRuleIdx: number[];
+  constructor(scopeLookupTable: string[][]) {
+this.scopeLookupTable = scopeLookupTable;
+this.currentScopeRuleIdx =
+this.scopeLookupTable.map(() => Number.POSITIVE_INFINITY);
+this.scopeRules =
+this.scopeLookupTable.map(() => ({scope : '', foreground : '#000'}));
+  }
+
+  // Associates rule to the scopeLookupTable if possible. For a rule to be
+  // associated to an array of scopes it must be a prefix of any of the scopes.
+  // Be the earliest match in the array of scopes and be the most specific
+  // match.
+  addRule(rule: 

[PATCH] D65856: [clangd] Added class for mapping TokenColorRules to their associated clangd TextMate scope

2019-08-13 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom updated this revision to Diff 214778.
jvikstrom added a comment.

Updated to use string[][] as scopes.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65856/new/

https://reviews.llvm.org/D65856

Files:
  clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
  
clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts

Index: clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
@@ -1,13 +1,13 @@
 import * as assert from 'assert';
 import * as path from 'path';
 
-import * as TM from '../src/semantic-highlighting';
+import * as SM from '../src/semantic-highlighting';
 
 suite('SemanticHighlighting Tests', () => {
   test('Parses arrays of textmate themes.', async () => {
 const themePath =
 path.join(__dirname, '../../test/assets/includeTheme.jsonc');
-const scopeColorRules = await TM.parseThemeFile(themePath);
+const scopeColorRules = await SM.parseThemeFile(themePath);
 const getScopeRule = (scope: string) =>
 scopeColorRules.find((v) => v.scope === scope);
 assert.equal(scopeColorRules.length, 3);
@@ -33,6 +33,21 @@
   ]
 ];
 testCases.forEach((testCase, i) => assert.deepEqual(
-  TM.decodeTokens(testCase), expected[i]));
+  SM.decodeTokens(testCase), expected[i]));
+  });
+  test('ScopeRules overrides for more specific themes', () => {
+const scopes = [ [ 'a.b', 'a.b' ], [ 'a', 'a.b', 'c.b.a' ], [ 'c.b.a' ] ];
+const rules = [
+  {scope : 'c.b', foreground : '1'},
+  {scope : 'a', foreground : '2'},
+  {scope : 'a.b', foreground : '3'},
+  {scope : 'a', foreground : '4'},
+  {scope : 'c.b.a', foreground : '5'},
+];
+const tm = new SM.ScopeRules(scopes);
+rules.forEach((r) => tm.addRule(r));
+assert.deepEqual(tm.getRule(0), rules[2]);
+assert.deepEqual(tm.getRule(1), rules[1]);
+assert.deepEqual(tm.getRule(2), rules[4]);
   });
 });
Index: clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
@@ -47,6 +47,8 @@
   // The TextMate scope lookup table. A token with scope index i has the scopes
   // on index i in the lookup table.
   scopeLookupTable: string[][];
+  // The rules for the scopes given the current theme.
+  scopeRules: ScopeRules;
   fillClientCapabilities(capabilities: vscodelc.ClientCapabilities) {
 // Extend the ClientCapabilities type and add semantic highlighting
 // capability to the object.
@@ -58,6 +60,18 @@
 };
   }
 
+  async loadCurrentTheme() {
+const name =
+vscode.workspace.getConfiguration('workbench').get('colorTheme');
+if (typeof name != 'string') {
+  console.warn('The current theme name is not a string, is:' +
+   (typeof name) + ', value: ',
+   name);
+  return;
+}
+this.scopeRules = await loadTheme(name, this.scopeLookupTable);
+  }
+
   initialize(capabilities: vscodelc.ServerCapabilities,
  documentSelector: vscodelc.DocumentSelector|undefined) {
 // The semantic highlighting capability information is in the capabilities
@@ -68,6 +82,7 @@
 if (!serverCapabilities.semanticHighlighting)
   return;
 this.scopeLookupTable = serverCapabilities.semanticHighlighting.scopes;
+this.loadCurrentTheme();
   }
 
   handleNotification(params: SemanticHighlightingParams) {}
@@ -101,8 +116,55 @@
   foreground: string;
 }
 
+export class ScopeRules {
+  // The TextMate scopes that should be mapped to a color.
+  private scopeLookupTable: string[][];
+  // Contains the current best matching scope for the scope at the corresponding
+  // index.
+  private scopeRules: TokenColorRule[];
+  // Each list of scopes can only have one rule matching. The actual scope that
+  // matches for each index should be as close to zero as possible.
+  private currentScopeRuleIdx: number[];
+  constructor(scopeLookupTable: string[][]) {
+this.scopeLookupTable = scopeLookupTable;
+this.currentScopeRuleIdx =
+this.scopeLookupTable.map(() => Number.POSITIVE_INFINITY);
+this.scopeRules =
+this.scopeLookupTable.map(() => ({scope : '', foreground : '#000'}));
+  }
+
+  // Associates rule to the scopeLookupTable if possible. For a rule to be
+  // associated to an array of scopes it must be a prefix of any of the scopes.
+  // Be the earliest match in the array of scopes and be the most specific
+  // match.
+  

[PATCH] D65856: [clangd] Added class for mapping TokenColorRules to their associated clangd TextMate scope

2019-08-13 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom updated this revision to Diff 214774.
jvikstrom added a comment.

Rebased into master.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65856/new/

https://reviews.llvm.org/D65856

Files:
  clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
  
clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts


Index: 
clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
===
--- 
clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
+++ 
clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
@@ -35,4 +35,19 @@
 testCases.forEach((testCase, i) => assert.deepEqual(
   TM.decodeTokens(testCase), expected[i]));
   });
+  test('ScopeRules overrides for more specific themes', () => {
+const scopes = [ 'a.b.c.d', 'a.b.f', 'a' ];
+const rules = [
+  {scope : 'a.b.c', foreground : '1'},
+  {scope : 'a.b', foreground : '2'},
+  {scope : 'a.b.c.d', foreground : '3'},
+  {scope : 'a', foreground : '4'},
+];
+
+const tm = new TM.ScopeRules(scopes);
+rules.forEach((r) => tm.addRule(r));
+assert.deepEqual(tm.getRule(0), rules[2]);
+assert.deepEqual(tm.getRule(1), rules[1]);
+assert.deepEqual(tm.getRule(2), rules[3]);
+  });
 });
Index: 
clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
@@ -101,6 +101,39 @@
   foreground: string;
 }
 
+export class ScopeRules {
+  // The TextMate scopes that should be mapped to a color.
+  private scopes: string[];
+  // Contains the current best matching scope for the scope at the 
corresponding
+  // index.
+  private scopeRules: TokenColorRule[];
+
+  constructor(scopes: string[]) {
+this.scopes = scopes;
+this.scopeRules =
+this.scopes.map(() => ({scope : '', foreground : '#000'}));
+  }
+
+  addRule(rule: TokenColorRule) {
+// Find the associated clangd scope(s) index for this scope. A scope being 
a
+// possible candidate means that the clangd scope must have the rule's 
scope
+// as a prefix.
+const allCandidates =
+this.scopes.map((s, i) => ({s : s, i : i}))
+.filter(({s}) => s.substr(0, rule.scope.length) === rule.scope);
+// If this scope is more specific than any of current scopes for the clangd
+// scopes it should be replaced. As both options are prefixes of the clangd
+// scope it's enough to compare lengths.
+allCandidates.forEach(({i}) => {
+  if (rule.scope.length > this.scopeRules[i].scope.length) {
+this.scopeRules[i] = rule;
+  }
+});
+  }
+
+  getRule(idx: number) { return this.scopeRules[idx]; }
+}
+
 // Get all token color rules provided by the theme.
 function loadTheme(themeName: string): Promise {
   const extension =


Index: clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
@@ -35,4 +35,19 @@
 testCases.forEach((testCase, i) => assert.deepEqual(
   TM.decodeTokens(testCase), expected[i]));
   });
+  test('ScopeRules overrides for more specific themes', () => {
+const scopes = [ 'a.b.c.d', 'a.b.f', 'a' ];
+const rules = [
+  {scope : 'a.b.c', foreground : '1'},
+  {scope : 'a.b', foreground : '2'},
+  {scope : 'a.b.c.d', foreground : '3'},
+  {scope : 'a', foreground : '4'},
+];
+
+const tm = new TM.ScopeRules(scopes);
+rules.forEach((r) => tm.addRule(r));
+assert.deepEqual(tm.getRule(0), rules[2]);
+assert.deepEqual(tm.getRule(1), rules[1]);
+assert.deepEqual(tm.getRule(2), rules[3]);
+  });
 });
Index: clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
@@ -101,6 +101,39 @@
   foreground: string;
 }
 
+export class ScopeRules {
+  // The TextMate scopes that should be mapped to a color.
+  private scopes: string[];
+  // Contains the current best matching scope for the scope at the corresponding
+  // index.
+  private scopeRules: TokenColorRule[];
+
+  constructor(scopes: string[]) {
+this.scopes = scopes;
+this.scopeRules =
+this.scopes.map(() => ({scope : '', foreground : '#000'}));
+  }
+
+  

[PATCH] D65998: [clangd] Added the vscode SemanticHighlighting feature code but did not enable it in the client.

2019-08-12 Thread Johan Vikström via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
jvikstrom marked 5 inline comments as done.
Closed by commit rL368568: [clangd] Added the vscode SemanticHighlighting 
feature code but did not enable… (authored by jvikstrom, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D65998?vs=214613=214624#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65998/new/

https://reviews.llvm.org/D65998

Files:
  clang-tools-extra/trunk/clangd/clients/clangd-vscode/package.json
  
clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
  
clang-tools-extra/trunk/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts

Index: clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
===
--- clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
+++ clang-tools-extra/trunk/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
@@ -2,6 +2,95 @@
 import * as jsonc from "jsonc-parser";
 import * as path from 'path';
 import * as vscode from 'vscode';
+import * as vscodelc from 'vscode-languageclient';
+import * as vscodelct from 'vscode-languageserver-types';
+
+// Parameters for the semantic highlighting (server-side) push notification.
+// Mirrors the structure in the semantic highlighting proposal for LSP.
+interface SemanticHighlightingParams {
+  // The text document that has to be decorated with the semantic highlighting
+  // information.
+  textDocument: vscodelct.VersionedTextDocumentIdentifier;
+  // An array of semantic highlighting information.
+  lines: SemanticHighlightingInformation[];
+}
+// Contains the highlighting information for a specified line. Mirrors the
+// structure in the semantic highlighting proposal for LSP.
+interface SemanticHighlightingInformation {
+  // The zero-based line position in the text document.
+  line: number;
+  // A base64 encoded string representing every single highlighted characters
+  // with its start position, length and the "lookup table" index of of the
+  // semantic highlighting Text Mate scopes.
+  tokens?: string;
+}
+
+// A SemanticHighlightingToken decoded from the base64 data sent by clangd.
+interface SemanticHighlightingToken {
+  // Start column for this token.
+  character: number;
+  // Length of the token.
+  length: number;
+  // The TextMate scope index to the clangd scope lookup table.
+  scopeIndex: number;
+}
+
+// Language server push notification providing the semantic highlighting
+// information for a text document.
+export const NotificationType =
+new vscodelc.NotificationType(
+'textDocument/semanticHighlighting');
+
+// The feature that should be registered in the vscode lsp for enabling
+// experimental semantic highlighting.
+export class SemanticHighlightingFeature implements vscodelc.StaticFeature {
+  // The TextMate scope lookup table. A token with scope index i has the scopes
+  // on index i in the lookup table.
+  scopeLookupTable: string[][];
+  fillClientCapabilities(capabilities: vscodelc.ClientCapabilities) {
+// Extend the ClientCapabilities type and add semantic highlighting
+// capability to the object.
+const textDocumentCapabilities: vscodelc.TextDocumentClientCapabilities&
+{semanticHighlightingCapabilities?: {semanticHighlighting : boolean}} =
+capabilities.textDocument;
+textDocumentCapabilities.semanticHighlightingCapabilities = {
+  semanticHighlighting : true,
+};
+  }
+
+  initialize(capabilities: vscodelc.ServerCapabilities,
+ documentSelector: vscodelc.DocumentSelector|undefined) {
+// The semantic highlighting capability information is in the capabilities
+// object but to access the data we must first extend the ServerCapabilities
+// type.
+const serverCapabilities: vscodelc.ServerCapabilities&
+{semanticHighlighting?: {scopes : string[][]}} = capabilities;
+if (!serverCapabilities.semanticHighlighting)
+  return;
+this.scopeLookupTable = serverCapabilities.semanticHighlighting.scopes;
+  }
+
+  handleNotification(params: SemanticHighlightingParams) {}
+}
+
+// Converts a string of base64 encoded tokens into the corresponding array of
+// HighlightingTokens.
+export function decodeTokens(tokens: string): SemanticHighlightingToken[] {
+  const scopeMask = 0x;
+  const lenShift = 0x10;
+  const uint32Size = 4;
+  const buf = Buffer.from(tokens, 'base64');
+  const retTokens = [];
+  for (let i = 0, end = buf.length / uint32Size; i < end; i += 2) {
+const start = buf.readUInt32BE(i * uint32Size);
+const lenKind = buf.readUInt32BE((i + 1) * uint32Size);
+const scopeIndex = lenKind & scopeMask;
+const len = lenKind >>> lenShift;
+retTokens.push({character : start, scopeIndex : scopeIndex, length : len});

[PATCH] D64741: [clangd] Added highlighting for tokens that are macro arguments.

2019-08-12 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom added a comment.

@ilya-biryukov @hokein pinging about this cl (I had completely forgotten about 
it somehow. Just updated it to the new master though)


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64741/new/

https://reviews.llvm.org/D64741



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D64741: [clangd] Added highlighting for tokens that are macro arguments.

2019-08-12 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom updated this revision to Diff 214620.
jvikstrom added a comment.

Moved comment.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64741/new/

https://reviews.llvm.org/D64741

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
@@ -323,6 +323,57 @@
   $Primitive[[auto]] $Variable[[Form]] = 10.2 + 2 * 4;
   $Primitive[[decltype]]($Variable[[Form]]) $Variable[[F]] = 10;
   auto $Variable[[Fun]] = []()->$Primitive[[void]]{};
+)cpp",
+// Tokens that share a source range but have conflicting Kinds are not
+// highlighted.
+R"cpp(
+  #define DEF_MULTIPLE(X) namespace X { class X { int X; }; }
+  #define DEF_CLASS(T) class T {};
+  DEF_MULTIPLE(XYZ);
+  DEF_MULTIPLE(XYZW);
+  DEF_CLASS($Class[[A]])
+  #define MACRO_CONCAT(X, V, T) T foo##X = V
+  #define DEF_VAR(X, V) int X = V
+  #define DEF_VAR_T(T, X, V) T X = V
+  #define DEF_VAR_REV(V, X) DEF_VAR(X, V)
+  #define CPY(X) X
+  #define DEF_VAR_TYPE(X, Y) X Y
+  #define SOME_NAME variable
+  #define SOME_NAME_SET variable2 = 123
+  #define INC_VAR(X) X += 2
+  $Primitive[[void]] $Function[[foo]]() {
+DEF_VAR($Variable[[X]],  123);
+DEF_VAR_REV(908, $Variable[[XY]]);
+$Primitive[[int]] CPY( $Variable[[XX]] );
+DEF_VAR_TYPE($Class[[A]], $Variable[[AA]]);
+$Primitive[[double]] SOME_NAME;
+$Primitive[[int]] SOME_NAME_SET;
+$Variable[[variable]] = 20.1;
+MACRO_CONCAT(var, 2, $Primitive[[float]]);
+DEF_VAR_T($Class[[A]], CPY(CPY($Variable[[Nested]])),
+  CPY($Class[[A]]()));
+INC_VAR($Variable[[variable]]);
+  }
+  $Primitive[[void]] SOME_NAME();
+  DEF_VAR($Variable[[XYZ]], 567);
+  DEF_VAR_REV(756, $Variable[[AB]]);
+
+  #define CALL_FN(F) F();
+  #define DEF_FN(F) void F ()
+  DEF_FN($Function[[g]]) {
+CALL_FN($Function[[foo]]);
+  }
+)cpp", 
+R"cpp(
+  #define fail(expr) expr
+  #define assert(COND) if (!(COND)) { fail("assertion failed" #COND); }
+  $Primitive[[int]] $Variable[[x]];
+  $Primitive[[int]] $Variable[[y]];
+  $Primitive[[int]] $Function[[f]]();
+  $Primitive[[void]] $Function[[foo]]() {
+assert($Variable[[x]] != $Variable[[y]]);
+assert($Variable[[x]] != $Function[[f]]());
+  }
 )cpp"};
   for (const auto  : TestCases) {
 checkHighlightings(TestCase);
@@ -338,6 +389,19 @@
 int someMethod();
 void otherMethod();
   )cpp"}});
+
+  // A separate test for macros in headers.
+  checkHighlightings(R"cpp(
+#include "imp.h"
+DEFINE_Y
+DXYZ_Y(A);
+  )cpp",
+ {{"imp.h", R"cpp(
+#define DXYZ(X) class X {};
+#define DXYZ_Y(Y) DXYZ(x##Y)
+#define DEFINE(X) int X;
+#define DEFINE_Y DEFINE(Y)
+  )cpp"}});
 }
 
 TEST(SemanticHighlighting, GeneratesHighlightsWhenFileChange) {
Index: clang-tools-extra/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -38,6 +38,25 @@
 llvm::sort(Tokens);
 auto Last = std::unique(Tokens.begin(), Tokens.end());
 Tokens.erase(Last, Tokens.end());
+
+// Macros can give tokens that have the same source range but conflicting
+// kinds. In this case all tokens sharing this source range should be
+// removed.
+for (unsigned I = 0; I < Tokens.size(); ++I) {
+  ArrayRef TokRef(Tokens);
+  ArrayRef Conflicting =
+  llvm::ArrayRef(TokRef.begin() + I, TokRef.end())
+  .take_while([&](const HighlightingToken ) {
+return T.R == Tokens[I].R;
+  });
+
+  if (Conflicting.size() > 1) {
+Tokens.erase(Tokens.begin() + I,
+ Tokens.begin() + I + Conflicting.size());
+--I;
+  }
+}
+
 return Tokens;
   }
 
@@ -227,13 +246,18 @@
   }
 
   void addToken(SourceLocation Loc, HighlightingKind Kind) {
-if (Loc.isMacroID())
-  // FIXME: skip tokens inside macros for now.
-  return;
+if(Loc.isMacroID()) {
+  // Only intereseted in highlighting arguments in macros (DEF_X(arg)).
+  if (!SM.isMacroArgExpansion(Loc))
+return;
+  Loc = SM.getSpellingLoc(Loc);
+}
 
 // Non top level decls that are included from a header are not filtered by
 // topLevelDecls. (example: method declarations being included from another
 // file for a class from another file)
+// There are also cases with macros where 

[PATCH] D64741: [clangd] Added highlighting for tokens that are macro arguments.

2019-08-12 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom updated this revision to Diff 214619.
jvikstrom added a comment.

Rebased to master.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64741/new/

https://reviews.llvm.org/D64741

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
@@ -323,6 +323,57 @@
   $Primitive[[auto]] $Variable[[Form]] = 10.2 + 2 * 4;
   $Primitive[[decltype]]($Variable[[Form]]) $Variable[[F]] = 10;
   auto $Variable[[Fun]] = []()->$Primitive[[void]]{};
+)cpp",
+  // Tokens that share a source range but have conflicting Kinds are not
+  // highlighted.
+R"cpp(
+  #define DEF_MULTIPLE(X) namespace X { class X { int X; }; }
+  #define DEF_CLASS(T) class T {};
+  DEF_MULTIPLE(XYZ);
+  DEF_MULTIPLE(XYZW);
+  DEF_CLASS($Class[[A]])
+  #define MACRO_CONCAT(X, V, T) T foo##X = V
+  #define DEF_VAR(X, V) int X = V
+  #define DEF_VAR_T(T, X, V) T X = V
+  #define DEF_VAR_REV(V, X) DEF_VAR(X, V)
+  #define CPY(X) X
+  #define DEF_VAR_TYPE(X, Y) X Y
+  #define SOME_NAME variable
+  #define SOME_NAME_SET variable2 = 123
+  #define INC_VAR(X) X += 2
+  $Primitive[[void]] $Function[[foo]]() {
+DEF_VAR($Variable[[X]],  123);
+DEF_VAR_REV(908, $Variable[[XY]]);
+$Primitive[[int]] CPY( $Variable[[XX]] );
+DEF_VAR_TYPE($Class[[A]], $Variable[[AA]]);
+$Primitive[[double]] SOME_NAME;
+$Primitive[[int]] SOME_NAME_SET;
+$Variable[[variable]] = 20.1;
+MACRO_CONCAT(var, 2, $Primitive[[float]]);
+DEF_VAR_T($Class[[A]], CPY(CPY($Variable[[Nested]])),
+  CPY($Class[[A]]()));
+INC_VAR($Variable[[variable]]);
+  }
+  $Primitive[[void]] SOME_NAME();
+  DEF_VAR($Variable[[XYZ]], 567);
+  DEF_VAR_REV(756, $Variable[[AB]]);
+
+  #define CALL_FN(F) F();
+  #define DEF_FN(F) void F ()
+  DEF_FN($Function[[g]]) {
+CALL_FN($Function[[foo]]);
+  }
+)cpp", 
+R"cpp(
+  #define fail(expr) expr
+  #define assert(COND) if (!(COND)) { fail("assertion failed" #COND); }
+  $Primitive[[int]] $Variable[[x]];
+  $Primitive[[int]] $Variable[[y]];
+  $Primitive[[int]] $Function[[f]]();
+  $Primitive[[void]] $Function[[foo]]() {
+assert($Variable[[x]] != $Variable[[y]]);
+assert($Variable[[x]] != $Function[[f]]());
+  }
 )cpp"};
   for (const auto  : TestCases) {
 checkHighlightings(TestCase);
@@ -338,6 +389,19 @@
 int someMethod();
 void otherMethod();
   )cpp"}});
+
+  // A separate test for macros in headers.
+  checkHighlightings(R"cpp(
+#include "imp.h"
+DEFINE_Y
+DXYZ_Y(A);
+  )cpp",
+ {{"imp.h", R"cpp(
+#define DXYZ(X) class X {};
+#define DXYZ_Y(Y) DXYZ(x##Y)
+#define DEFINE(X) int X;
+#define DEFINE_Y DEFINE(Y)
+  )cpp"}});
 }
 
 TEST(SemanticHighlighting, GeneratesHighlightsWhenFileChange) {
Index: clang-tools-extra/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -38,6 +38,25 @@
 llvm::sort(Tokens);
 auto Last = std::unique(Tokens.begin(), Tokens.end());
 Tokens.erase(Last, Tokens.end());
+
+// Macros can give tokens that have the same source range but conflicting
+// kinds. In this case all tokens sharing this source range should be
+// removed.
+for (unsigned I = 0; I < Tokens.size(); ++I) {
+  ArrayRef TokRef(Tokens);
+  ArrayRef Conflicting =
+  llvm::ArrayRef(TokRef.begin() + I, TokRef.end())
+  .take_while([&](const HighlightingToken ) {
+return T.R == Tokens[I].R;
+  });
+
+  if (Conflicting.size() > 1) {
+Tokens.erase(Tokens.begin() + I,
+ Tokens.begin() + I + Conflicting.size());
+--I;
+  }
+}
+
 return Tokens;
   }
 
@@ -227,13 +246,18 @@
   }
 
   void addToken(SourceLocation Loc, HighlightingKind Kind) {
-if (Loc.isMacroID())
-  // FIXME: skip tokens inside macros for now.
-  return;
+if(Loc.isMacroID()) {
+  // Only intereseted in highlighting arguments in macros (DEF_X(arg)).
+  if (!SM.isMacroArgExpansion(Loc))
+return;
+  Loc = SM.getSpellingLoc(Loc);
+}
 
 // Non top level decls that are included from a header are not filtered by
 // topLevelDecls. (example: method declarations being included from another
 // file for a class from another file)
+// There are also cases with 

[PATCH] D66083: [clangd] Remove highlightings coming from non topLevelDecls from included files.

2019-08-12 Thread Johan Vikström via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
jvikstrom marked 3 inline comments as done.
Closed by commit rL368563: [clangd] Remove highlightings coming from non 
topLevelDecls from included files. (authored by jvikstrom, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D66083?vs=214608=214616#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66083/new/

https://reviews.llvm.org/D66083

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


Index: clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
@@ -231,6 +231,12 @@
   // FIXME: skip tokens inside macros for now.
   return;
 
+// Non top level decls that are included from a header are not filtered by
+// topLevelDecls. (example: method declarations being included from another
+// file for a class from another file)
+if (!isInsideMainFile(Loc, SM))
+  return;
+
 auto R = getTokenRange(SM, Ctx.getLangOpts(), Loc);
 if (!R) {
   // R should always have a value, if it doesn't something is very wrong.
Index: clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
===
--- clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
+++ clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
@@ -51,9 +51,15 @@
   return ExpectedTokens;
 }
 
-void checkHighlightings(llvm::StringRef Code) {
+void checkHighlightings(llvm::StringRef Code,
+std::vector>
+AdditionalFiles = {}) {
   Annotations Test(Code);
-  auto AST = TestTU::withCode(Test.code()).build();
+  auto TU = TestTU::withCode(Test.code());
+  for (auto File : AdditionalFiles)
+TU.AdditionalFiles.insert({File.first, File.second});
+  auto AST = TU.build();
   std::vector ActualTokens = getSemanticHighlightings(AST);
   EXPECT_THAT(ActualTokens, getExpectedTokens(Test)) << Code;
 }
@@ -321,6 +327,17 @@
   for (const auto  : TestCases) {
 checkHighlightings(TestCase);
   }
+
+  checkHighlightings(R"cpp(
+class $Class[[A]] {
+  #include "imp.h"
+};
+#endif
+  )cpp",
+ {{"imp.h", R"cpp(
+int someMethod();
+void otherMethod();
+  )cpp"}});
 }
 
 TEST(SemanticHighlighting, GeneratesHighlightsWhenFileChange) {


Index: clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
@@ -231,6 +231,12 @@
   // FIXME: skip tokens inside macros for now.
   return;
 
+// Non top level decls that are included from a header are not filtered by
+// topLevelDecls. (example: method declarations being included from another
+// file for a class from another file)
+if (!isInsideMainFile(Loc, SM))
+  return;
+
 auto R = getTokenRange(SM, Ctx.getLangOpts(), Loc);
 if (!R) {
   // R should always have a value, if it doesn't something is very wrong.
Index: clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
===
--- clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
+++ clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
@@ -51,9 +51,15 @@
   return ExpectedTokens;
 }
 
-void checkHighlightings(llvm::StringRef Code) {
+void checkHighlightings(llvm::StringRef Code,
+std::vector>
+AdditionalFiles = {}) {
   Annotations Test(Code);
-  auto AST = TestTU::withCode(Test.code()).build();
+  auto TU = TestTU::withCode(Test.code());
+  for (auto File : AdditionalFiles)
+TU.AdditionalFiles.insert({File.first, File.second});
+  auto AST = TU.build();
   std::vector ActualTokens = getSemanticHighlightings(AST);
   EXPECT_THAT(ActualTokens, getExpectedTokens(Test)) << Code;
 }
@@ -321,6 +327,17 @@
   for (const auto  : TestCases) {
 checkHighlightings(TestCase);
   }
+
+  checkHighlightings(R"cpp(
+class $Class[[A]] {
+  #include "imp.h"
+};
+#endif
+  )cpp",
+ {{"imp.h", R"cpp(
+int someMethod();
+void otherMethod();
+  )cpp"}});
 }
 
 TEST(SemanticHighlighting, GeneratesHighlightsWhenFileChange) {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D65998: [clangd] Added the vscode SemanticHighlighting feature code but did not enable it in the client.

2019-08-12 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom updated this revision to Diff 214613.
jvikstrom marked 4 inline comments as done.
jvikstrom added a comment.

Mirror the LSP proposal SemanticHighlightingParams/Information types.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65998/new/

https://reviews.llvm.org/D65998

Files:
  clang-tools-extra/clangd/clients/clangd-vscode/package.json
  clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
  
clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts

Index: clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
@@ -3,7 +3,7 @@
 
 import * as TM from '../src/semantic-highlighting';
 
-suite('TextMate Tests', () => {
+suite('SemanticHighlighting Tests', () => {
   test('Parses arrays of textmate themes.', async () => {
 const themePath =
 path.join(__dirname, '../../test/assets/includeTheme.jsonc');
@@ -15,4 +15,24 @@
 assert.deepEqual(getScopeRule('b'), {scope : 'b', textColor : '#000'});
 assert.deepEqual(getScopeRule('c'), {scope : 'c', textColor : '#bcd'});
   });
+  test('Decodes tokens correctly', () => {
+const testCases: string[] = [
+  'AAABAAA=', 'AAADAAkEAAEAAA==',
+  'AAADAAkEAAEAAAoAAQAA'
+];
+const expected = [
+  [ {character : 0, scope : 0, length : 1} ],
+  [
+{character : 0, scope : 9, length : 3},
+{character : 4, scope : 0, length : 1}
+  ],
+  [
+{character : 0, scope : 9, length : 3},
+{character : 4, scope : 0, length : 1},
+{character : 10, scope : 0, length : 1}
+  ]
+];
+testCases.forEach((testCase, i) => assert.deepEqual(
+  TM.decodeTokens(testCase), expected[i]));
+  });
 });
Index: clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
@@ -2,6 +2,94 @@
 import * as jsonc from "jsonc-parser";
 import * as path from 'path';
 import * as vscode from 'vscode';
+import * as vscodelc from 'vscode-languageclient';
+import * as vscodelct from 'vscode-languageserver-types';
+
+// Parameters for the semantic highlighting (server-side) push notification.
+interface SemanticHighlightingParams {
+  // The text document that has to be decorated with the semantic highlighting
+  // information.
+  textDocument: vscodelct.VersionedTextDocumentIdentifier;
+  // An array of semantic highlighting information.
+  lines: SemanticHighlightingInformation[];
+}
+
+// Contains the highlighting information for a specified line.
+interface SemanticHighlightingInformation {
+  // The zero-based line position in the text document.
+  line: number;
+  // A base64 encoded string representing every single highlighted characters
+  // with its start position, length and the "lookup table" index of of the
+  // semantic highlighting Text Mate scopes.
+  tokens?: string;
+}
+
+// A single SemanticHighlightingToken that clangd sent.
+interface SemanticHighlightingToken {
+  // Start column for this token.
+  character: number;
+  // Length of the token.
+  length: number;
+  // The TextMate scope index to the clangd scopes.
+  scope: number;
+}
+
+// Language server push notification providing the semantic highlighting
+// information for a text document.
+export const NotificationType =
+new vscodelc.NotificationType(
+'textDocument/semanticHighlighting');
+
+// The feature that should be registered in the vscode lsp for enabling
+// experimental semantic highlighting.
+export class SemanticHighlightingFeature implements vscodelc.StaticFeature {
+  // The TextMate scope lookup table. A token with scope index i has the scopes
+  // on index i in the lookup table.
+  scopeLookupTable: string[][];
+  fillClientCapabilities(capabilities: vscodelc.ClientCapabilities) {
+// Extend the ClientCapabilities type and add semantic highlighting
+// capability to the object.
+const textDocumentCapabilities: vscodelc.TextDocumentClientCapabilities&
+{semanticHighlightingCapabilities?: {semanticHighlighting : boolean}} =
+capabilities.textDocument;
+textDocumentCapabilities.semanticHighlightingCapabilities = {
+  semanticHighlighting : true,
+};
+  }
+
+  initialize(capabilities: vscodelc.ServerCapabilities,
+ documentSelector: vscodelc.DocumentSelector|undefined) {
+// The semantic highlighting capability information is in the capabilities
+// object but to access the data we must first 

[PATCH] D66083: [clangd] Remove highlightings coming from non topLevelDecls from included files.

2019-08-12 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom created this revision.
jvikstrom added reviewers: hokein, ilya-biryukov.
Herald added subscribers: cfe-commits, kadircet, arphaman, jkorous, MaskRay.
Herald added a project: clang.

It is possible to write include code from other files so that the decls from 
there do not become topLevelDecls (For example by including methods for a 
class). These Decls are not filtered by topLevelDecls and therefore 
SemanticHighlighting must manually check that every SLoc belongs in the main 
file. Otherwise there can be highlightings appearing in places where they 
should not.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D66083

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
@@ -51,9 +51,16 @@
   return ExpectedTokens;
 }
 
-void checkHighlightings(llvm::StringRef Code) {
+// AdditionalFiles are key-value-pair that are included in the TU where the key
+// is the filename and the value is the code for the file.
+void checkHighlightings(llvm::StringRef Code,
+std::vector>
+AdditionalFiles = {}) {
   Annotations Test(Code);
-  auto AST = TestTU::withCode(Test.code()).build();
+  auto TU = TestTU::withCode(Test.code());
+  for (auto File : AdditionalFiles)
+TU.AdditionalFiles.insert({File.first, File.second});
+  auto AST = TU.build();
   std::vector ActualTokens = getSemanticHighlightings(AST);
   EXPECT_THAT(ActualTokens, getExpectedTokens(Test)) << Code;
 }
@@ -321,6 +328,17 @@
   for (const auto  : TestCases) {
 checkHighlightings(TestCase);
   }
+
+  checkHighlightings(R"cpp(
+class $Class[[A]] {
+  #include "imp.h"
+};
+#endif
+  )cpp",
+ {{"imp.h", R"cpp(
+int someMethod();
+void otherMethod();
+  )cpp"}});
 }
 
 TEST(SemanticHighlighting, GeneratesHighlightsWhenFileChange) {
Index: clang-tools-extra/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -231,6 +231,12 @@
   // FIXME: skip tokens inside macros for now.
   return;
 
+// Non top level decls that are included from a header are not filtered by
+// topLevelDecls. (example: method declarations being included from another
+// file for a class) from another file)
+if (!SM.isWrittenInMainFile(Loc))
+  return;
+
 auto R = getTokenRange(SM, Ctx.getLangOpts(), Loc);
 if (!R) {
   // R should always have a value, if it doesn't something is very wrong.


Index: clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
===
--- clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
+++ clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
@@ -51,9 +51,16 @@
   return ExpectedTokens;
 }
 
-void checkHighlightings(llvm::StringRef Code) {
+// AdditionalFiles are key-value-pair that are included in the TU where the key
+// is the filename and the value is the code for the file.
+void checkHighlightings(llvm::StringRef Code,
+std::vector>
+AdditionalFiles = {}) {
   Annotations Test(Code);
-  auto AST = TestTU::withCode(Test.code()).build();
+  auto TU = TestTU::withCode(Test.code());
+  for (auto File : AdditionalFiles)
+TU.AdditionalFiles.insert({File.first, File.second});
+  auto AST = TU.build();
   std::vector ActualTokens = getSemanticHighlightings(AST);
   EXPECT_THAT(ActualTokens, getExpectedTokens(Test)) << Code;
 }
@@ -321,6 +328,17 @@
   for (const auto  : TestCases) {
 checkHighlightings(TestCase);
   }
+
+  checkHighlightings(R"cpp(
+class $Class[[A]] {
+  #include "imp.h"
+};
+#endif
+  )cpp",
+ {{"imp.h", R"cpp(
+int someMethod();
+void otherMethod();
+  )cpp"}});
 }
 
 TEST(SemanticHighlighting, GeneratesHighlightsWhenFileChange) {
Index: clang-tools-extra/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -231,6 +231,12 @@
   // FIXME: skip tokens inside macros for now.
   return;
 
+// Non top level decls that are included from a header are not filtered by
+// topLevelDecls. (example: method declarations being included from another
+// file for a class) from another file)
+if (!SM.isWrittenInMainFile(Loc))
+  return;
+
 auto R = getTokenRange(SM, Ctx.getLangOpts(), Loc);
 if (!R) {
   // 

[PATCH] D65996: [clangd] Highlighting auto variables as the deduced type.

2019-08-12 Thread Johan Vikström via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL368546: [clangd] Highlighting auto variables as the deduced 
type. (authored by jvikstrom, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D65996?vs=214373=214582#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65996/new/

https://reviews.llvm.org/D65996

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

Index: clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
@@ -97,8 +97,8 @@
   }
 
   bool VisitTypedefNameDecl(TypedefNameDecl *TD) {
-if(const auto *TSI = TD->getTypeSourceInfo())
-  addTypeLoc(TD->getLocation(), TSI->getTypeLoc());
+if (const auto *TSI = TD->getTypeSourceInfo())
+  addType(TD->getLocation(), TSI->getTypeLoc().getTypePtr());
 return true;
   }
 
@@ -120,10 +120,8 @@
 // structs. It also makes us not highlight certain namespace qualifiers
 // twice. For elaborated types the actual type is highlighted as an inner
 // TypeLoc.
-if (TL.getTypeLocClass() == TypeLoc::TypeLocClass::Elaborated)
-  return true;
-
-addTypeLoc(TL.getBeginLoc(), TL);
+if (TL.getTypeLocClass() != TypeLoc::TypeLocClass::Elaborated)
+  addType(TL.getBeginLoc(), TL.getTypePtr());
 return true;
   }
 
@@ -144,15 +142,27 @@
 HighlightingTokenCollector>::TraverseConstructorInitializer(CI);
   }
 
-private:
-  void addTypeLoc(SourceLocation Loc, const TypeLoc ) {
-if (const Type *TP = TL.getTypePtr()) {
-  if (const TagDecl *TD = TP->getAsTagDecl())
-addToken(Loc, TD);
-  if (TP->isBuiltinType())
-// Builtins must be special cased as they do not have a TagDecl.
-addToken(Loc, HighlightingKind::Primitive);
+  bool VisitDeclaratorDecl(DeclaratorDecl *D) {
+if ((!D->getTypeSourceInfo()))
+  return true;
+
+if (auto *AT = D->getType()->getContainedAutoType()) {
+  const auto Deduced = AT->getDeducedType();
+  if (!Deduced.isNull())
+addType(D->getTypeSpecStartLoc(), Deduced.getTypePtr());
 }
+return true;
+  }
+
+private:
+  void addType(SourceLocation Loc, const Type *TP) {
+if (!TP)
+  return;
+if (TP->isBuiltinType())
+  // Builtins must be special cased as they do not have a TagDecl.
+  addToken(Loc, HighlightingKind::Primitive);
+if (const TagDecl *TD = TP->getAsTagDecl())
+  addToken(Loc, TD);
   }
 
   void addToken(SourceLocation Loc, const NamedDecl *D) {
Index: clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
===
--- clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
+++ clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
@@ -99,9 +99,9 @@
   struct {
   } $Variable[[S]];
   $Primitive[[void]] $Function[[foo]]($Primitive[[int]] $Variable[[A]], $Class[[AS]] $Variable[[As]]) {
-auto $Variable[[VeryLongVariableName]] = 12312;
+$Primitive[[auto]] $Variable[[VeryLongVariableName]] = 12312;
 $Class[[AS]] $Variable[[AA]];
-auto $Variable[[L]] = $Variable[[AA]].$Field[[SomeMember]] + $Variable[[A]];
+$Primitive[[auto]] $Variable[[L]] = $Variable[[AA]].$Field[[SomeMember]] + $Variable[[A]];
 auto $Variable[[FN]] = [ $Variable[[AA]]]($Primitive[[int]] $Variable[[A]]) -> $Primitive[[void]] {};
 $Variable[[FN]](12312);
   }
@@ -303,6 +303,20 @@
   class $Class[[Bar2]] : public $Class[[Bar]] {
 $Class[[Bar2]]() : $Class[[Bar]]($Class[[Foo]](), $EnumConstant[[EC]]) {}
   };
+)cpp",
+R"cpp(
+  enum $Enum[[E]] {
+$EnumConstant[[E]],
+  };
+  class $Class[[Foo]] {};
+  $Enum[[auto]] $Variable[[AE]] = $Enum[[E]]::$EnumConstant[[E]];
+  $Class[[auto]] $Variable[[AF]] = $Class[[Foo]]();
+  $Class[[decltype]](auto) $Variable[[AF2]] = $Class[[Foo]]();
+  $Class[[auto]] *$Variable[[AFP]] = &$Variable[[AF]];
+  $Enum[[auto]] &$Variable[[AER]] = $Variable[[AE]];
+  $Primitive[[auto]] $Variable[[Form]] = 10.2 + 2 * 4;
+  $Primitive[[decltype]]($Variable[[Form]]) $Variable[[F]] = 10;
+  auto $Variable[[Fun]] = []()->$Primitive[[void]]{};
 )cpp"};
   for (const auto  : TestCases) {
 checkHighlightings(TestCase);
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D65996: [clangd] Highlighting auto variables as the deduced type.

2019-08-09 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom updated this revision to Diff 214373.
jvikstrom added a comment.

Removed ending whitespace on a line.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65996/new/

https://reviews.llvm.org/D65996

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
@@ -99,9 +99,9 @@
   struct {
   } $Variable[[S]];
   $Primitive[[void]] $Function[[foo]]($Primitive[[int]] $Variable[[A]], $Class[[AS]] $Variable[[As]]) {
-auto $Variable[[VeryLongVariableName]] = 12312;
+$Primitive[[auto]] $Variable[[VeryLongVariableName]] = 12312;
 $Class[[AS]] $Variable[[AA]];
-auto $Variable[[L]] = $Variable[[AA]].$Field[[SomeMember]] + $Variable[[A]];
+$Primitive[[auto]] $Variable[[L]] = $Variable[[AA]].$Field[[SomeMember]] + $Variable[[A]];
 auto $Variable[[FN]] = [ $Variable[[AA]]]($Primitive[[int]] $Variable[[A]]) -> $Primitive[[void]] {};
 $Variable[[FN]](12312);
   }
@@ -276,6 +276,20 @@
 $Class[[Foo]] *$Variable[[FP]] = ($Class[[Foo]]*)$Variable[[B]];
 $Primitive[[int]] $Variable[[I]] = ($Primitive[[int]])$Variable[[B]];
   }
+)cpp",
+R"cpp(
+  enum $Enum[[E]] {
+$EnumConstant[[E]],
+  };
+  class $Class[[Foo]] {};
+  $Enum[[auto]] $Variable[[AE]] = $Enum[[E]]::$EnumConstant[[E]];
+  $Class[[auto]] $Variable[[AF]] = $Class[[Foo]]();
+  $Class[[decltype]](auto) $Variable[[AF2]] = $Class[[Foo]]();
+  $Class[[auto]] *$Variable[[AFP]] = &$Variable[[AF]];
+  $Enum[[auto]] &$Variable[[AER]] = $Variable[[AE]];
+  $Primitive[[auto]] $Variable[[Form]] = 10.2 + 2 * 4;
+  $Primitive[[decltype]]($Variable[[Form]]) $Variable[[F]] = 10;
+  auto $Variable[[Fun]] = []()->$Primitive[[void]]{};
 )cpp"};
   for (const auto  : TestCases) {
 checkHighlightings(TestCase);
Index: clang-tools-extra/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -96,8 +96,8 @@
   }
 
   bool VisitTypedefNameDecl(TypedefNameDecl *TD) {
-if(const auto *TSI = TD->getTypeSourceInfo())
-  addTypeLoc(TD->getLocation(), TSI->getTypeLoc());
+if (const auto *TSI = TD->getTypeSourceInfo())
+  addType(TD->getLocation(), TSI->getTypeLoc().getTypePtr());
 return true;
   }
 
@@ -119,10 +119,8 @@
 // structs. It also makes us not highlight certain namespace qualifiers
 // twice. For elaborated types the actual type is highlighted as an inner
 // TypeLoc.
-if (TL.getTypeLocClass() == TypeLoc::TypeLocClass::Elaborated)
-  return true;
-
-addTypeLoc(TL.getBeginLoc(), TL);
+if (TL.getTypeLocClass() != TypeLoc::TypeLocClass::Elaborated)
+  addType(TL.getBeginLoc(), TL.getTypePtr());
 return true;
   }
 
@@ -136,15 +134,28 @@
 HighlightingTokenCollector>::TraverseNestedNameSpecifierLoc(NNSLoc);
   }
 
-private:
-  void addTypeLoc(SourceLocation Loc, const TypeLoc ) {
-if (const Type *TP = TL.getTypePtr()) {
-  if (const TagDecl *TD = TP->getAsTagDecl())
-addToken(Loc, TD);
-  if (TP->isBuiltinType())
-// Builtins must be special cased as they do not have a TagDecl.
-addToken(Loc, HighlightingKind::Primitive);
+  bool VisitDeclaratorDecl(DeclaratorDecl *D) {
+if ((!D->getTypeSourceInfo()))
+  return true;
+
+if (auto *AT = D->getType()->getContainedAutoType()) {
+  const auto Deduced = AT->getDeducedType();
+  if (Deduced.isNull())
+return true;
+  addType(D->getTypeSpecStartLoc(), Deduced.getTypePtr());
 }
+return true;
+  }
+
+private:
+  void addType(SourceLocation Loc, const Type *TP) {
+if (!TP)
+  return;
+if (TP->isBuiltinType())
+  // Builtins must be special cased as they do not have a TagDecl.
+  addToken(Loc, HighlightingKind::Primitive);
+if (const TagDecl *TD = TP->getAsTagDecl())
+  addToken(Loc, TD);
   }
 
   void addToken(SourceLocation Loc, const NamedDecl *D) {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D65996: [clangd] Highlighting auto variables as the deduced type.

2019-08-09 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom updated this revision to Diff 214372.
jvikstrom marked 3 inline comments as done.
jvikstrom added a comment.

Address comments.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65996/new/

https://reviews.llvm.org/D65996

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
@@ -99,9 +99,9 @@
   struct {
   } $Variable[[S]];
   $Primitive[[void]] $Function[[foo]]($Primitive[[int]] $Variable[[A]], 
$Class[[AS]] $Variable[[As]]) {
-auto $Variable[[VeryLongVariableName]] = 12312;
+$Primitive[[auto]] $Variable[[VeryLongVariableName]] = 12312;
 $Class[[AS]] $Variable[[AA]];
-auto $Variable[[L]] = $Variable[[AA]].$Field[[SomeMember]] + 
$Variable[[A]];
+$Primitive[[auto]] $Variable[[L]] = 
$Variable[[AA]].$Field[[SomeMember]] + $Variable[[A]];
 auto $Variable[[FN]] = [ $Variable[[AA]]]($Primitive[[int]] 
$Variable[[A]]) -> $Primitive[[void]] {};
 $Variable[[FN]](12312);
   }
@@ -276,6 +276,20 @@
 $Class[[Foo]] *$Variable[[FP]] = ($Class[[Foo]]*)$Variable[[B]];
 $Primitive[[int]] $Variable[[I]] = ($Primitive[[int]])$Variable[[B]];
   }
+)cpp",
+R"cpp(
+  enum $Enum[[E]] {
+$EnumConstant[[E]],
+  };
+  class $Class[[Foo]] {};
+  $Enum[[auto]] $Variable[[AE]] = $Enum[[E]]::$EnumConstant[[E]];
+  $Class[[auto]] $Variable[[AF]] = $Class[[Foo]]();
+  $Class[[decltype]](auto) $Variable[[AF2]] = $Class[[Foo]]();
+  $Class[[auto]] *$Variable[[AFP]] = &$Variable[[AF]];
+  $Enum[[auto]] &$Variable[[AER]] = $Variable[[AE]];
+  $Primitive[[auto]] $Variable[[Form]] = 10.2 + 2 * 4;
+  $Primitive[[decltype]]($Variable[[Form]]) $Variable[[F]] = 10;
+  auto $Variable[[Fun]] = []()->$Primitive[[void]]{};
 )cpp"};
   for (const auto  : TestCases) {
 checkHighlightings(TestCase);
Index: clang-tools-extra/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -97,7 +97,7 @@
 
   bool VisitTypedefNameDecl(TypedefNameDecl *TD) {
 if(const auto *TSI = TD->getTypeSourceInfo())
-  addTypeLoc(TD->getLocation(), TSI->getTypeLoc());
+  addType(TD->getLocation(), TSI->getTypeLoc().getTypePtr());  
 return true;
   }
 
@@ -119,10 +119,8 @@
 // structs. It also makes us not highlight certain namespace qualifiers
 // twice. For elaborated types the actual type is highlighted as an inner
 // TypeLoc.
-if (TL.getTypeLocClass() == TypeLoc::TypeLocClass::Elaborated)
-  return true;
-
-addTypeLoc(TL.getBeginLoc(), TL);
+if (TL.getTypeLocClass() != TypeLoc::TypeLocClass::Elaborated)
+  addType(TL.getBeginLoc(), TL.getTypePtr());
 return true;
   }
 
@@ -136,15 +134,28 @@
 HighlightingTokenCollector>::TraverseNestedNameSpecifierLoc(NNSLoc);
   }
 
-private:
-  void addTypeLoc(SourceLocation Loc, const TypeLoc ) {
-if (const Type *TP = TL.getTypePtr()) {
-  if (const TagDecl *TD = TP->getAsTagDecl())
-addToken(Loc, TD);
-  if (TP->isBuiltinType())
-// Builtins must be special cased as they do not have a TagDecl.
-addToken(Loc, HighlightingKind::Primitive);
+  bool VisitDeclaratorDecl(DeclaratorDecl *D) {
+if ((!D->getTypeSourceInfo()))
+  return true;
+
+if (auto *AT = D->getType()->getContainedAutoType()) {
+  const auto Deduced = AT->getDeducedType();
+  if (Deduced.isNull())
+return true;
+  addType(D->getTypeSpecStartLoc(), Deduced.getTypePtr());
 }
+return true;
+  }
+
+private:
+  void addType(SourceLocation Loc, const Type *TP) {
+if (!TP)
+  return;
+if (TP->isBuiltinType())
+  // Builtins must be special cased as they do not have a TagDecl.
+  addToken(Loc, HighlightingKind::Primitive);
+if (const TagDecl *TD = TP->getAsTagDecl())
+  addToken(Loc, TD);
   }
 
   void addToken(SourceLocation Loc, const NamedDecl *D) {


Index: clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
===
--- clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
+++ clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
@@ -99,9 +99,9 @@
   struct {
   } $Variable[[S]];
   $Primitive[[void]] $Function[[foo]]($Primitive[[int]] $Variable[[A]], $Class[[AS]] $Variable[[As]]) {
-auto $Variable[[VeryLongVariableName]] = 12312;
+$Primitive[[auto]] 

[PATCH] D65998: [clangd] Added the vscode SemanticHighlighting feature code but did not enable it in the client.

2019-08-09 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom updated this revision to Diff 214364.
jvikstrom marked 4 inline comments as done.
jvikstrom added a comment.

Address comments.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65998/new/

https://reviews.llvm.org/D65998

Files:
  clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
  
clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts

Index: clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
@@ -3,7 +3,7 @@
 
 import * as TM from '../src/semantic-highlighting';
 
-suite('TextMate Tests', () => {
+suite('SemanticHighlighting Tests', () => {
   test('Parses arrays of textmate themes.', async () => {
 const themePath =
 path.join(__dirname, '../../test/assets/includeTheme.jsonc');
@@ -15,4 +15,24 @@
 assert.deepEqual(getScopeRule('b'), {scope : 'b', textColor : '#000'});
 assert.deepEqual(getScopeRule('c'), {scope : 'c', textColor : '#bcd'});
   });
+  test('Decodes tokens correctly', () => {
+const testCases: string[] = [
+  'AAABAAA=', 'AAADAAkEAAEAAA==',
+  'AAADAAkEAAEAAAoAAQAA'
+];
+const expected = [
+  [ {character : 0, scope : 0, length : 1} ],
+  [
+{character : 0, scope : 9, length : 3},
+{character : 4, scope : 0, length : 1}
+  ],
+  [
+{character : 0, scope : 9, length : 3},
+{character : 4, scope : 0, length : 1},
+{character : 10, scope : 0, length : 1}
+  ]
+];
+testCases.forEach((testCase, i) => assert.deepEqual(
+  TM.decodeTokens(testCase), expected[i]));
+  });
 });
Index: clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
@@ -2,6 +2,89 @@
 import * as jsonc from "jsonc-parser";
 import * as path from 'path';
 import * as vscode from 'vscode';
+import * as vscodelc from 'vscode-languageclient';
+
+// The information clangd sends when highlightings should be updated.
+interface SemanticHighlightingParams {
+  // The information about the text document where these highlightings should be
+  // applied.
+  textDocument: {uri: string;};
+  // All the lines of highlightings that should be applied.
+  lines: [ {
+line: number;
+tokens: string;
+  } ];
+}
+// A single SemanticHighlightingToken that clangd sent.
+interface SemanticHighlightingToken {
+  // Start column for this token.
+  character: number;
+  // The TextMate scope index to the clangd scopes.
+  scope: number;
+  length: number;
+}
+// All highlightings for line.
+interface SemanticHighlightingInformation {
+  line: number;
+  tokens: SemanticHighlightingToken[];
+}
+
+export const NotificationType = new vscodelc.NotificationType<{}, void>(
+'textDocument/semanticHighlighting');
+
+// The feature that should be registered in the vscode lsp for enabling
+// experimental semantic highlighting.
+export class SemanticHighlightingFeature implements vscodelc.StaticFeature {
+  scopeLookupTable: string[][];
+  fillClientCapabilities(capabilities: vscodelc.ClientCapabilities) {
+// Extend the ClientCapabilities type and add semantic highlighting
+// capability to the object.
+const textDocumentCapabilities: vscodelc.TextDocumentClientCapabilities&
+{semanticHighlightingCapabilities?: {semanticHighlighting : boolean}} =
+capabilities.textDocument;
+textDocumentCapabilities.semanticHighlightingCapabilities = {
+  semanticHighlighting : true,
+};
+  }
+
+  initialize(capabilities: vscodelc.ServerCapabilities,
+ documentSelector: vscodelc.DocumentSelector|undefined) {
+// The semantic highlighting capability information is in the capabilities
+// object but to access the data we must first extend the ServerCapabilities
+// type.
+const serverCapabilities: vscodelc.ServerCapabilities&
+{semanticHighlighting?: {scopes : string[][]}} = capabilities;
+if (!serverCapabilities.semanticHighlighting)
+  return;
+this.scopeLookupTable = serverCapabilities.semanticHighlighting.scopes;
+  }
+
+  handleNotification(params: SemanticHighlightingParams) {
+const tokenLines =
+params.lines.map((line): SemanticHighlightingInformation => {
+  return { line: line.line, tokens: decodeTokens(line.tokens), }
+});
+  }
+}
+
+// Converts a string of base64 encoded tokens into the corresponding array of
+// HighlightingTokens.
+export function decodeTokens(tokens: 

[PATCH] D65998: [clangd] Added the vscode SemanticHighlighting feature code but did not enable it in the client.

2019-08-09 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom added inline comments.



Comment at: 
clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts:62
+
+  handleNotification(params: HighlightingInformation) {
+const tokenLines = params.lines.map((line): HighlightingLine => {

hokein wrote:
> I think the params here is defined as `SemanticHighlightingParams` from the 
> LSP proposal, could we use the names as defined in the LSP for these 
> structures (e.g. `SemanticHighlightingParams`, 
> `SemanticHighlightingInformation`)?
Renaming HighlightingToken to SemanticHighlightingToken to be consistent with 
those names as well.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65998/new/

https://reviews.llvm.org/D65998



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D66001: [clangd] Added highlighting for constructor initializers.

2019-08-09 Thread Johan Vikström via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL368434: [clangd] Added highlighting for constructor 
initializers. (authored by jvikstrom, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D66001?vs=214346=214362#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66001/new/

https://reviews.llvm.org/D66001

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


Index: clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
===
--- clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
+++ clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
@@ -285,6 +285,24 @@
   };
 
   $Class[[A]] &$Class[[A]]::operator=($Class[[A]] &&$Variable[[O]]) = 
default;
+)cpp",
+R"cpp(
+  enum $Enum[[En]] {
+$EnumConstant[[EC]],
+  };
+  class $Class[[Foo]] {};
+  class $Class[[Bar]] {
+$Class[[Foo]] $Field[[Fo]];
+$Enum[[En]] $Field[[E]];
+$Primitive[[int]] $Field[[I]];
+$Class[[Bar]] ($Class[[Foo]] $Variable[[F]],
+$Enum[[En]] $Variable[[E]])
+: $Field[[Fo]] ($Variable[[F]]), $Field[[E]] ($Variable[[E]]),
+  $Field[[I]] (123) {}
+  };
+  class $Class[[Bar2]] : public $Class[[Bar]] {
+$Class[[Bar2]]() : $Class[[Bar]]($Class[[Foo]](), $EnumConstant[[EC]]) 
{}
+  };
 )cpp"};
   for (const auto  : TestCases) {
 checkHighlightings(TestCase);
Index: clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
@@ -11,6 +11,7 @@
 #include "Protocol.h"
 #include "SourceCode.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclCXX.h"
 #include "clang/AST/RecursiveASTVisitor.h"
 #include 
 
@@ -136,6 +137,13 @@
 HighlightingTokenCollector>::TraverseNestedNameSpecifierLoc(NNSLoc);
   }
 
+  bool TraverseConstructorInitializer(CXXCtorInitializer *CI) {
+if (const FieldDecl *FD = CI->getMember())
+  addToken(CI->getSourceLocation(), FD);
+return RecursiveASTVisitor<
+HighlightingTokenCollector>::TraverseConstructorInitializer(CI);
+  }
+
 private:
   void addTypeLoc(SourceLocation Loc, const TypeLoc ) {
 if (const Type *TP = TL.getTypePtr()) {


Index: clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
===
--- clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
+++ clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
@@ -285,6 +285,24 @@
   };
 
   $Class[[A]] &$Class[[A]]::operator=($Class[[A]] &&$Variable[[O]]) = default;
+)cpp",
+R"cpp(
+  enum $Enum[[En]] {
+$EnumConstant[[EC]],
+  };
+  class $Class[[Foo]] {};
+  class $Class[[Bar]] {
+$Class[[Foo]] $Field[[Fo]];
+$Enum[[En]] $Field[[E]];
+$Primitive[[int]] $Field[[I]];
+$Class[[Bar]] ($Class[[Foo]] $Variable[[F]],
+$Enum[[En]] $Variable[[E]])
+: $Field[[Fo]] ($Variable[[F]]), $Field[[E]] ($Variable[[E]]),
+  $Field[[I]] (123) {}
+  };
+  class $Class[[Bar2]] : public $Class[[Bar]] {
+$Class[[Bar2]]() : $Class[[Bar]]($Class[[Foo]](), $EnumConstant[[EC]]) {}
+  };
 )cpp"};
   for (const auto  : TestCases) {
 checkHighlightings(TestCase);
Index: clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
@@ -11,6 +11,7 @@
 #include "Protocol.h"
 #include "SourceCode.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclCXX.h"
 #include "clang/AST/RecursiveASTVisitor.h"
 #include 
 
@@ -136,6 +137,13 @@
 HighlightingTokenCollector>::TraverseNestedNameSpecifierLoc(NNSLoc);
   }
 
+  bool TraverseConstructorInitializer(CXXCtorInitializer *CI) {
+if (const FieldDecl *FD = CI->getMember())
+  addToken(CI->getSourceLocation(), FD);
+return RecursiveASTVisitor<
+HighlightingTokenCollector>::TraverseConstructorInitializer(CI);
+  }
+
 private:
   void addTypeLoc(SourceLocation Loc, const TypeLoc ) {
 if (const Type *TP = TL.getTypePtr()) {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D66001: [clangd] Added highlighting for constructor initializers.

2019-08-09 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom updated this revision to Diff 214346.
jvikstrom added a comment.

Fixed case where initializer was base class initializer which would cause crash.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66001/new/

https://reviews.llvm.org/D66001

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
@@ -285,6 +285,24 @@
   };
 
   $Class[[A]] &$Class[[A]]::operator=($Class[[A]] &&$Variable[[O]]) = 
default;
+)cpp",
+R"cpp(
+  enum $Enum[[En]] {
+$EnumConstant[[EC]],
+  };
+  class $Class[[Foo]] {};
+  class $Class[[Bar]] {
+$Class[[Foo]] $Field[[Fo]];
+$Enum[[En]] $Field[[E]];
+$Primitive[[int]] $Field[[I]];
+$Class[[Bar]] ($Class[[Foo]] $Variable[[F]],
+$Enum[[En]] $Variable[[E]])
+: $Field[[Fo]] ($Variable[[F]]), $Field[[E]] ($Variable[[E]]),
+  $Field[[I]] (123) {}
+  };
+  class $Class[[Bar2]] : public $Class[[Bar]] {
+$Class[[Bar2]]() : $Class[[Bar]]($Class[[Foo]](), $EnumConstant[[EC]]) 
{}
+  };
 )cpp"};
   for (const auto  : TestCases) {
 checkHighlightings(TestCase);
Index: clang-tools-extra/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -11,6 +11,7 @@
 #include "Protocol.h"
 #include "SourceCode.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclCXX.h"
 #include "clang/AST/RecursiveASTVisitor.h"
 #include 
 
@@ -136,6 +137,13 @@
 HighlightingTokenCollector>::TraverseNestedNameSpecifierLoc(NNSLoc);
   }
 
+  bool TraverseConstructorInitializer(CXXCtorInitializer *CI) {
+if (const FieldDecl *FD = CI->getMember())
+  addToken(CI->getSourceLocation(), FD);
+return RecursiveASTVisitor<
+HighlightingTokenCollector>::TraverseConstructorInitializer(CI);
+  }
+
 private:
   void addTypeLoc(SourceLocation Loc, const TypeLoc ) {
 if (const Type *TP = TL.getTypePtr()) {


Index: clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
===
--- clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
+++ clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
@@ -285,6 +285,24 @@
   };
 
   $Class[[A]] &$Class[[A]]::operator=($Class[[A]] &&$Variable[[O]]) = default;
+)cpp",
+R"cpp(
+  enum $Enum[[En]] {
+$EnumConstant[[EC]],
+  };
+  class $Class[[Foo]] {};
+  class $Class[[Bar]] {
+$Class[[Foo]] $Field[[Fo]];
+$Enum[[En]] $Field[[E]];
+$Primitive[[int]] $Field[[I]];
+$Class[[Bar]] ($Class[[Foo]] $Variable[[F]],
+$Enum[[En]] $Variable[[E]])
+: $Field[[Fo]] ($Variable[[F]]), $Field[[E]] ($Variable[[E]]),
+  $Field[[I]] (123) {}
+  };
+  class $Class[[Bar2]] : public $Class[[Bar]] {
+$Class[[Bar2]]() : $Class[[Bar]]($Class[[Foo]](), $EnumConstant[[EC]]) {}
+  };
 )cpp"};
   for (const auto  : TestCases) {
 checkHighlightings(TestCase);
Index: clang-tools-extra/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -11,6 +11,7 @@
 #include "Protocol.h"
 #include "SourceCode.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclCXX.h"
 #include "clang/AST/RecursiveASTVisitor.h"
 #include 
 
@@ -136,6 +137,13 @@
 HighlightingTokenCollector>::TraverseNestedNameSpecifierLoc(NNSLoc);
   }
 
+  bool TraverseConstructorInitializer(CXXCtorInitializer *CI) {
+if (const FieldDecl *FD = CI->getMember())
+  addToken(CI->getSourceLocation(), FD);
+return RecursiveASTVisitor<
+HighlightingTokenCollector>::TraverseConstructorInitializer(CI);
+  }
+
 private:
   void addTypeLoc(SourceLocation Loc, const TypeLoc ) {
 if (const Type *TP = TL.getTypePtr()) {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D66001: [clangd] Added highlighting for constructor initializers.

2019-08-09 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom created this revision.
jvikstrom added reviewers: hokein, ilya-biryukov.
Herald added subscribers: cfe-commits, kadircet, arphaman, jkorous, MaskRay.
Herald added a project: clang.

Constructor initializers were not being highlighted. This adds highlighting for 
them by using TraverseConstructorInitializer. Uses the Traverse* because there 
is no visit for CXXCtorInitializer.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D66001

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
@@ -285,6 +285,19 @@
   };
 
   $Class[[A]] &$Class[[A]]::operator=($Class[[A]] &&$Variable[[O]]) = 
default;
+)cpp",
+R"cpp(
+  enum $Enum[[En]] {};
+  class $Class[[Foo]] {};
+  class $Class[[Bar]] {
+$Class[[Foo]] $Field[[Fo]];
+$Enum[[En]] $Field[[E]];
+$Primitive[[int]] $Field[[I]];
+$Class[[Bar]] ($Class[[Foo]] $Variable[[F]],
+$Enum[[En]] $Variable[[E]])
+: $Field[[Fo]] ($Variable[[F]]), $Field[[E]] ($Variable[[E]]),
+  $Field[[I]] (123) {}
+  };
 )cpp"};
   for (const auto  : TestCases) {
 checkHighlightings(TestCase);
Index: clang-tools-extra/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -11,6 +11,7 @@
 #include "Protocol.h"
 #include "SourceCode.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclCXX.h"
 #include "clang/AST/RecursiveASTVisitor.h"
 #include 
 
@@ -136,6 +137,12 @@
 HighlightingTokenCollector>::TraverseNestedNameSpecifierLoc(NNSLoc);
   }
 
+  bool TraverseConstructorInitializer(CXXCtorInitializer *CI) {
+addToken(CI->getSourceLocation(), CI->getMember());
+return RecursiveASTVisitor<
+HighlightingTokenCollector>::TraverseConstructorInitializer(CI);
+  }
+
 private:
   void addTypeLoc(SourceLocation Loc, const TypeLoc ) {
 if (const Type *TP = TL.getTypePtr()) {


Index: clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
===
--- clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
+++ clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
@@ -285,6 +285,19 @@
   };
 
   $Class[[A]] &$Class[[A]]::operator=($Class[[A]] &&$Variable[[O]]) = default;
+)cpp",
+R"cpp(
+  enum $Enum[[En]] {};
+  class $Class[[Foo]] {};
+  class $Class[[Bar]] {
+$Class[[Foo]] $Field[[Fo]];
+$Enum[[En]] $Field[[E]];
+$Primitive[[int]] $Field[[I]];
+$Class[[Bar]] ($Class[[Foo]] $Variable[[F]],
+$Enum[[En]] $Variable[[E]])
+: $Field[[Fo]] ($Variable[[F]]), $Field[[E]] ($Variable[[E]]),
+  $Field[[I]] (123) {}
+  };
 )cpp"};
   for (const auto  : TestCases) {
 checkHighlightings(TestCase);
Index: clang-tools-extra/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -11,6 +11,7 @@
 #include "Protocol.h"
 #include "SourceCode.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclCXX.h"
 #include "clang/AST/RecursiveASTVisitor.h"
 #include 
 
@@ -136,6 +137,12 @@
 HighlightingTokenCollector>::TraverseNestedNameSpecifierLoc(NNSLoc);
   }
 
+  bool TraverseConstructorInitializer(CXXCtorInitializer *CI) {
+addToken(CI->getSourceLocation(), CI->getMember());
+return RecursiveASTVisitor<
+HighlightingTokenCollector>::TraverseConstructorInitializer(CI);
+  }
+
 private:
   void addTypeLoc(SourceLocation Loc, const TypeLoc ) {
 if (const Type *TP = TL.getTypePtr()) {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D65998: [clangd] Added the vscode SemanticHighlighting feature code but did not enable it in the client.

2019-08-09 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom updated this revision to Diff 214334.
jvikstrom added a comment.

Added comment to decodeTokens function.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65998/new/

https://reviews.llvm.org/D65998

Files:
  clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
  
clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts

Index: clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
@@ -3,7 +3,7 @@
 
 import * as TM from '../src/semantic-highlighting';
 
-suite('TextMate Tests', () => {
+suite('SemanticHighlighting Tests', () => {
   test('Parses arrays of textmate themes.', async () => {
 const themePath =
 path.join(__dirname, '../../test/assets/includeTheme.jsonc');
@@ -15,4 +15,24 @@
 assert.deepEqual(getScopeRule('b'), {scope : 'b', textColor : '#000'});
 assert.deepEqual(getScopeRule('c'), {scope : 'c', textColor : '#bcd'});
   });
+  test('Decodes tokens correctly', () => {
+const testCases: string[] = [
+  'AAABAAA=', 'AAADAAkEAAEAAA==',
+  'AAADAAkEAAEAAAoAAQAA'
+];
+const expected = [
+  [ {character : 0, scope : 0, length : 1} ],
+  [
+{character : 0, scope : 9, length : 3},
+{character : 4, scope : 0, length : 1}
+  ],
+  [
+{character : 0, scope : 9, length : 3},
+{character : 4, scope : 0, length : 1},
+{character : 10, scope : 0, length : 1}
+  ]
+];
+testCases.forEach((testCase, i) => assert.deepEqual(
+  TM.decodeTokens(testCase), expected[i]));
+  });
 });
Index: clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
@@ -2,6 +2,88 @@
 import * as jsonc from "jsonc-parser";
 import * as path from 'path';
 import * as vscode from 'vscode';
+import * as vscodelc from 'vscode-languageclient';
+
+// The information clangd sends when highlightings should be updated.
+interface HighlightingInformation {
+  // The information about the text document where these highlightings should be
+  // applied.
+  textDocument: {uri: string;};
+  // All the lines of highlightings that should be applied.
+  lines: [ {
+line: number;
+tokens: string;
+  } ];
+}
+// A single HighlightingToken that clangd sent.
+interface HighlightingToken {
+  // Start column for this token.
+  character: number;
+  // The TextMate scope index to the clangd scopes.
+  scope: number;
+  length: number;
+}
+// All highlightings for line.
+interface HighlightingLine {
+  line: number;
+  tokens: HighlightingToken[];
+}
+
+export const NotificationType = new vscodelc.NotificationType<{}, void>(
+'textDocument/semanticHighlighting');
+
+// The feature that should be registered in the vscode lsp for enabling
+// experimental semantic highlighting.
+export class Feature implements vscodelc.StaticFeature {
+  scopes: string[];
+  fillClientCapabilities(capabilities: vscodelc.ClientCapabilities) {
+// Extend the ClientCapabilities type and add semantic highlighting
+// capability to the object.
+const textDocumentCapabilities: vscodelc.TextDocumentClientCapabilities&
+{semanticHighlightingCapabilities?: {semanticHighlighting : boolean}} =
+capabilities.textDocument;
+textDocumentCapabilities.semanticHighlightingCapabilities = {
+  semanticHighlighting : true,
+};
+  }
+
+  initialize(capabilities: vscodelc.ServerCapabilities,
+ documentSelector: vscodelc.DocumentSelector|undefined) {
+// The semantic highlighting capability information is in the capabilities
+// object but to access the data we must first extend the ServerCapabilities
+// type.
+const serverCapabilities: vscodelc.ServerCapabilities&
+{semanticHighlighting?: {scopes : string[]}} = capabilities;
+if (!serverCapabilities.semanticHighlighting)
+  return;
+this.scopes = serverCapabilities.semanticHighlighting.scopes;
+  }
+
+  handleNotification(params: HighlightingInformation) {
+const tokenLines = params.lines.map((line): HighlightingLine => {
+  return { line: line.line, tokens: decodeTokens(line.tokens), }
+});
+  }
+}
+
+// Converts a string of base64 encoded tokens into the corresponding array of
+// HighlightingTokens.
+export function decodeTokens(tokens: string): HighlightingToken[] {
+  const scopeMask = 0x;
+  const lenShift = 0x10;
+  const uint32Size = 4;
+  const buf = 

[PATCH] D65998: [clangd] Added the vscode SemanticHighlighting feature code but did not enable it in the client.

2019-08-09 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom created this revision.
jvikstrom added reviewers: hokein, ilya-biryukov.
Herald added subscribers: cfe-commits, kadircet, arphaman, jkorous, MaskRay.
Herald added a project: clang.
jvikstrom updated this revision to Diff 214334.
jvikstrom added a comment.

Added comment to decodeTokens function.


Added the code for the StaticFeature that must be registered to the client. 
Also decoding the notification data into objects. Did not register it to the 
client yet.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D65998

Files:
  clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
  
clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts

Index: clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/test/semantic-highlighting.test.ts
@@ -3,7 +3,7 @@
 
 import * as TM from '../src/semantic-highlighting';
 
-suite('TextMate Tests', () => {
+suite('SemanticHighlighting Tests', () => {
   test('Parses arrays of textmate themes.', async () => {
 const themePath =
 path.join(__dirname, '../../test/assets/includeTheme.jsonc');
@@ -15,4 +15,24 @@
 assert.deepEqual(getScopeRule('b'), {scope : 'b', textColor : '#000'});
 assert.deepEqual(getScopeRule('c'), {scope : 'c', textColor : '#bcd'});
   });
+  test('Decodes tokens correctly', () => {
+const testCases: string[] = [
+  'AAABAAA=', 'AAADAAkEAAEAAA==',
+  'AAADAAkEAAEAAAoAAQAA'
+];
+const expected = [
+  [ {character : 0, scope : 0, length : 1} ],
+  [
+{character : 0, scope : 9, length : 3},
+{character : 4, scope : 0, length : 1}
+  ],
+  [
+{character : 0, scope : 9, length : 3},
+{character : 4, scope : 0, length : 1},
+{character : 10, scope : 0, length : 1}
+  ]
+];
+testCases.forEach((testCase, i) => assert.deepEqual(
+  TM.decodeTokens(testCase), expected[i]));
+  });
 });
Index: clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
===
--- clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
+++ clang-tools-extra/clangd/clients/clangd-vscode/src/semantic-highlighting.ts
@@ -2,6 +2,88 @@
 import * as jsonc from "jsonc-parser";
 import * as path from 'path';
 import * as vscode from 'vscode';
+import * as vscodelc from 'vscode-languageclient';
+
+// The information clangd sends when highlightings should be updated.
+interface HighlightingInformation {
+  // The information about the text document where these highlightings should be
+  // applied.
+  textDocument: {uri: string;};
+  // All the lines of highlightings that should be applied.
+  lines: [ {
+line: number;
+tokens: string;
+  } ];
+}
+// A single HighlightingToken that clangd sent.
+interface HighlightingToken {
+  // Start column for this token.
+  character: number;
+  // The TextMate scope index to the clangd scopes.
+  scope: number;
+  length: number;
+}
+// All highlightings for line.
+interface HighlightingLine {
+  line: number;
+  tokens: HighlightingToken[];
+}
+
+export const NotificationType = new vscodelc.NotificationType<{}, void>(
+'textDocument/semanticHighlighting');
+
+// The feature that should be registered in the vscode lsp for enabling
+// experimental semantic highlighting.
+export class Feature implements vscodelc.StaticFeature {
+  scopes: string[];
+  fillClientCapabilities(capabilities: vscodelc.ClientCapabilities) {
+// Extend the ClientCapabilities type and add semantic highlighting
+// capability to the object.
+const textDocumentCapabilities: vscodelc.TextDocumentClientCapabilities&
+{semanticHighlightingCapabilities?: {semanticHighlighting : boolean}} =
+capabilities.textDocument;
+textDocumentCapabilities.semanticHighlightingCapabilities = {
+  semanticHighlighting : true,
+};
+  }
+
+  initialize(capabilities: vscodelc.ServerCapabilities,
+ documentSelector: vscodelc.DocumentSelector|undefined) {
+// The semantic highlighting capability information is in the capabilities
+// object but to access the data we must first extend the ServerCapabilities
+// type.
+const serverCapabilities: vscodelc.ServerCapabilities&
+{semanticHighlighting?: {scopes : string[]}} = capabilities;
+if (!serverCapabilities.semanticHighlighting)
+  return;
+this.scopes = serverCapabilities.semanticHighlighting.scopes;
+  }
+
+  handleNotification(params: HighlightingInformation) {
+const tokenLines = params.lines.map((line): HighlightingLine => {
+  return { line: line.line, tokens: decodeTokens(line.tokens), }
+});

[PATCH] D65926: [clangd] Fixed printTemplateSpecializationArgs not printing partial variable specialization arguments.

2019-08-09 Thread Johan Vikström via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL368403: [clangd] Fixed printTemplateSpecializationArgs not 
printing partial variable… (authored by jvikstrom, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D65926?vs=214132=214323#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65926/new/

https://reviews.llvm.org/D65926

Files:
  clang-tools-extra/trunk/clangd/AST.cpp
  clang-tools-extra/trunk/clangd/unittests/ClangdUnitTests.cpp
  clang-tools-extra/trunk/clangd/unittests/PrintASTTests.cpp


Index: clang-tools-extra/trunk/clangd/unittests/ClangdUnitTests.cpp
===
--- clang-tools-extra/trunk/clangd/unittests/ClangdUnitTests.cpp
+++ clang-tools-extra/trunk/clangd/unittests/ClangdUnitTests.cpp
@@ -188,7 +188,7 @@
 AllOf(DeclNamed("foo"), WithTemplateArgs("")),
 AllOf(DeclNamed("i"), WithTemplateArgs("")),
 AllOf(DeclNamed("d"), WithTemplateArgs("")),
-AllOf(DeclNamed("foo"), WithTemplateArgs("<>")),
+AllOf(DeclNamed("foo"), WithTemplateArgs("")),
 AllOf(DeclNamed("foo"), WithTemplateArgs(""))}));
 }
 
Index: clang-tools-extra/trunk/clangd/unittests/PrintASTTests.cpp
===
--- clang-tools-extra/trunk/clangd/unittests/PrintASTTests.cpp
+++ clang-tools-extra/trunk/clangd/unittests/PrintASTTests.cpp
@@ -95,6 +95,15 @@
   struct Bar { friend class Foo; };
   template <> struct ^Foo {};)cpp",
 {""}},
+{
+R"cpp(
+  template
+  T S = T(10);
+  template 
+  int ^S = 0;
+  template <>
+  int ^S = 0;)cpp",
+{"", ""}},
 })),);
 } // namespace
 } // namespace clangd
Index: clang-tools-extra/trunk/clangd/AST.cpp
===
--- clang-tools-extra/trunk/clangd/AST.cpp
+++ clang-tools-extra/trunk/clangd/AST.cpp
@@ -36,6 +36,10 @@
  llvm::dyn_cast()) {
 if (auto *Args = Cls->getTemplateArgsAsWritten())
   return Args->arguments();
+  } else if (auto *Var =
+ llvm::dyn_cast()) {
+if (auto *Args = Var->getTemplateArgsAsWritten())
+  return Args->arguments();
   } else if (auto *Var = llvm::dyn_cast())
 return Var->getTemplateArgsInfo().arguments();
   // We return None for ClassTemplateSpecializationDecls because it does not


Index: clang-tools-extra/trunk/clangd/unittests/ClangdUnitTests.cpp
===
--- clang-tools-extra/trunk/clangd/unittests/ClangdUnitTests.cpp
+++ clang-tools-extra/trunk/clangd/unittests/ClangdUnitTests.cpp
@@ -188,7 +188,7 @@
 AllOf(DeclNamed("foo"), WithTemplateArgs("")),
 AllOf(DeclNamed("i"), WithTemplateArgs("")),
 AllOf(DeclNamed("d"), WithTemplateArgs("")),
-AllOf(DeclNamed("foo"), WithTemplateArgs("<>")),
+AllOf(DeclNamed("foo"), WithTemplateArgs("")),
 AllOf(DeclNamed("foo"), WithTemplateArgs(""))}));
 }
 
Index: clang-tools-extra/trunk/clangd/unittests/PrintASTTests.cpp
===
--- clang-tools-extra/trunk/clangd/unittests/PrintASTTests.cpp
+++ clang-tools-extra/trunk/clangd/unittests/PrintASTTests.cpp
@@ -95,6 +95,15 @@
   struct Bar { friend class Foo; };
   template <> struct ^Foo {};)cpp",
 {""}},
+{
+R"cpp(
+  template
+  T S = T(10);
+  template 
+  int ^S = 0;
+  template <>
+  int ^S = 0;)cpp",
+{"", ""}},
 })),);
 } // namespace
 } // namespace clangd
Index: clang-tools-extra/trunk/clangd/AST.cpp
===
--- clang-tools-extra/trunk/clangd/AST.cpp
+++ clang-tools-extra/trunk/clangd/AST.cpp
@@ -36,6 +36,10 @@
  llvm::dyn_cast()) {
 if (auto *Args = Cls->getTemplateArgsAsWritten())
   return Args->arguments();
+  } else 

[PATCH] D65938: [AST] No longer visiting CXXMethodDecl bodies created by compiler when method was default created.

2019-08-09 Thread Johan Vikström via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
jvikstrom marked 2 inline comments as done.
Closed by commit rL368402: [AST] No longer visiting CXXMethodDecl bodies 
created by compiler when method… (authored by jvikstrom, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D65938?vs=214109=214322#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65938/new/

https://reviews.llvm.org/D65938

Files:
  cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
  cfe/trunk/unittests/Tooling/CMakeLists.txt
  cfe/trunk/unittests/Tooling/RecursiveASTVisitorTests/CXXMethodDecl.cpp
  clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp

Index: cfe/trunk/unittests/Tooling/RecursiveASTVisitorTests/CXXMethodDecl.cpp
===
--- cfe/trunk/unittests/Tooling/RecursiveASTVisitorTests/CXXMethodDecl.cpp
+++ cfe/trunk/unittests/Tooling/RecursiveASTVisitorTests/CXXMethodDecl.cpp
@@ -0,0 +1,58 @@
+//=-- unittest/Tooling/RecursiveASTVisitorTests/CXXMethodDecl.cpp --=//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "TestVisitor.h"
+#include "clang/AST/Expr.h"
+
+using namespace clang;
+
+namespace {
+
+class CXXMethodDeclVisitor
+: public ExpectedLocationVisitor {
+public:
+  CXXMethodDeclVisitor(bool VisitImplicitCode)
+  : VisitImplicitCode(VisitImplicitCode) {}
+
+  bool shouldVisitImplicitCode() const { return VisitImplicitCode; }
+
+  bool VisitDeclRefExpr(DeclRefExpr *D) {
+Match("declref", D->getLocation());
+return true;
+  }
+  bool VisitParmVarDecl(ParmVarDecl *P) {
+Match("parm", P->getLocation());
+return true;
+  }
+
+private:
+  bool VisitImplicitCode;
+};
+
+TEST(RecursiveASTVisitor, CXXMethodDeclNoDefaultBodyVisited) {
+  for (bool VisitImplCode : {false, true}) {
+CXXMethodDeclVisitor Visitor(VisitImplCode);
+if (VisitImplCode)
+  Visitor.ExpectMatch("declref", 8, 28);
+else
+  Visitor.DisallowMatch("declref", 8, 28);
+
+Visitor.ExpectMatch("parm", 8, 27);
+llvm::StringRef Code = R"cpp(
+  struct B {};
+  struct A {
+B BB;
+A =(A &);
+  };
+
+  A ::operator=(A &) = default;
+)cpp";
+EXPECT_TRUE(Visitor.runOver(Code, CXXMethodDeclVisitor::Lang_CXX11));
+  }
+}
+} // end anonymous namespace
Index: cfe/trunk/unittests/Tooling/CMakeLists.txt
===
--- cfe/trunk/unittests/Tooling/CMakeLists.txt
+++ cfe/trunk/unittests/Tooling/CMakeLists.txt
@@ -28,6 +28,7 @@
   RecursiveASTVisitorTests/ConstructExpr.cpp
   RecursiveASTVisitorTests/CXXBoolLiteralExpr.cpp
   RecursiveASTVisitorTests/CXXMemberCall.cpp
+  RecursiveASTVisitorTests/CXXMethodDecl.cpp
   RecursiveASTVisitorTests/CXXOperatorCallExprTraverser.cpp
   RecursiveASTVisitorTests/DeclRefExpr.cpp
   RecursiveASTVisitorTests/ImplicitCtor.cpp
Index: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
===
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
@@ -2027,7 +2027,13 @@
 }
   }
 
-  if (D->isThisDeclarationADefinition()) {
+  bool VisitBody = D->isThisDeclarationADefinition();
+  // If a method is set to default outside the class definition the compiler
+  // generates the method body and adds it to the AST.
+  if (const auto *MD = dyn_cast(D))
+VisitBody &= !MD->isDefaulted() || getDerived().shouldVisitImplicitCode();
+
+  if (VisitBody) {
 TRY_TO(TraverseStmt(D->getBody())); // Function body.
   }
   return true;
Index: clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
===
--- clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
+++ clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
@@ -55,7 +55,7 @@
   Annotations Test(Code);
   auto AST = TestTU::withCode(Test.code()).build();
   std::vector ActualTokens = getSemanticHighlightings(AST);
-  EXPECT_THAT(ActualTokens, getExpectedTokens(Test));
+  EXPECT_THAT(ActualTokens, getExpectedTokens(Test)) << Code;
 }
 
 // Any annotations in OldCode and NewCode are converted into their corresponding
@@ -276,6 +276,15 @@
 $Class[[Foo]] *$Variable[[FP]] = ($Class[[Foo]]*)$Variable[[B]];
 $Primitive[[int]] $Variable[[I]] = ($Primitive[[int]])$Variable[[B]];
   }
+)cpp"
+R"cpp(
+  struct $Class[[B]] {};
+  struct $Class[[A]] {
+$Class[[B]] $Field[[BB]];
+$Class[[A]] =($Class[[A]] &&$Variable[[O]]);

[PATCH] D65996: [clangd] Highlighting auto variables as the deduced type.

2019-08-09 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom updated this revision to Diff 214319.
jvikstrom added a comment.

Finished comment.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65996/new/

https://reviews.llvm.org/D65996

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
@@ -99,9 +99,9 @@
   struct {
   } $Variable[[S]];
   $Primitive[[void]] $Function[[foo]]($Primitive[[int]] $Variable[[A]], $Class[[AS]] $Variable[[As]]) {
-auto $Variable[[VeryLongVariableName]] = 12312;
+$Primitive[[auto]] $Variable[[VeryLongVariableName]] = 12312;
 $Class[[AS]] $Variable[[AA]];
-auto $Variable[[L]] = $Variable[[AA]].$Field[[SomeMember]] + $Variable[[A]];
+$Primitive[[auto]] $Variable[[L]] = $Variable[[AA]].$Field[[SomeMember]] + $Variable[[A]];
 auto $Variable[[FN]] = [ $Variable[[AA]]]($Primitive[[int]] $Variable[[A]]) -> $Primitive[[void]] {};
 $Variable[[FN]](12312);
   }
@@ -276,6 +276,20 @@
 $Class[[Foo]] *$Variable[[FP]] = ($Class[[Foo]]*)$Variable[[B]];
 $Primitive[[int]] $Variable[[I]] = ($Primitive[[int]])$Variable[[B]];
   }
+)cpp",
+R"cpp(
+  enum $Enum[[E]] {
+$EnumConstant[[E]],
+  };
+  class $Class[[Foo]] {};
+  $Enum[[auto]] $Variable[[AE]] = $Enum[[E]]::$EnumConstant[[E]];
+  $Class[[auto]] $Variable[[AF]] = $Class[[Foo]]();
+  decltype($Class[[auto]]) $Variable[[AF2]] = $Class[[Foo]]();
+  $Class[[auto]] *$Variable[[AFP]] = &$Variable[[AF]];
+  $Enum[[auto]] &$Variable[[AER]] = $Variable[[AE]];
+  $Primitive[[auto]] $Variable[[Form]] = 10.2 + 2 * 4;
+  $Primitive[[decltype]]($Variable[[Form]]) $Variable[[F]] = 10;
+  auto $Variable[[Fun]] = []()->$Primitive[[void]]{};
 )cpp"};
   for (const auto  : TestCases) {
 checkHighlightings(TestCase);
Index: clang-tools-extra/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -97,7 +97,8 @@
 
   bool VisitTypedefNameDecl(TypedefNameDecl *TD) {
 if(const auto *TSI = TD->getTypeSourceInfo())
-  addTypeLoc(TD->getLocation(), TSI->getTypeLoc());
+  if (const Type *TP = TSI->getTypeLoc().getTypePtr())
+addType(TD->getLocation(), TP);
 return true;
   }
 
@@ -121,8 +122,8 @@
 // TypeLoc.
 if (TL.getTypeLocClass() == TypeLoc::TypeLocClass::Elaborated)
   return true;
-
-addTypeLoc(TL.getBeginLoc(), TL);
+if (const Type *TP = TL.getTypePtr())
+  addType(TL.getBeginLoc(), TP);
 return true;
   }
 
@@ -136,14 +137,33 @@
 HighlightingTokenCollector>::TraverseNestedNameSpecifierLoc(NNSLoc);
   }
 
+  bool VisitDeclaratorDecl(DeclaratorDecl *D) {
+if ((!D->getTypeSourceInfo()))
+  return true;
+
+if (auto *AT = D->getType()->getContainedAutoType()) {
+  const auto Deduced = AT->getDeducedType();
+  if (Deduced.isNull())
+return true;
+  SourceLocation Loc = D->getTypeSpecStartLoc();
+  if (AT->isDecltypeAuto())
+// If this is a decltype(auto) it's still the "auto" keyword that should
+// get the highlightings. But there is no way to get the SLoc of the
+// "auto" keyword other than using an offset.
+Loc = Loc.getLocWithOffset(9);
+  Deduced.getTypePtr()->dump();
+  addType(Loc, Deduced.getTypePtr());
+}
+return true;
+  }
+
 private:
-  void addTypeLoc(SourceLocation Loc, const TypeLoc ) {
-if (const Type *TP = TL.getTypePtr()) {
-  if (const TagDecl *TD = TP->getAsTagDecl())
-addToken(Loc, TD);
-  if (TP->isBuiltinType())
-// Builtins must be special cased as they do not have a TagDecl.
-addToken(Loc, HighlightingKind::Primitive);
+  void addType(SourceLocation Loc, const Type *TP) {
+if (TP->isBuiltinType())
+  // Builtins must be special cased as they do not have a TagDecl.
+  addToken(Loc, HighlightingKind::Primitive);
+if (const TagDecl *TD = TP->getAsTagDecl()) {
+  addToken(Loc, TD);
 }
   }
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D65996: [clangd] Highlighting auto variables as the deduced type.

2019-08-09 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom created this revision.
jvikstrom added reviewers: hokein, ilya-biryukov.
Herald added subscribers: cfe-commits, kadircet, arphaman, jkorous, MaskRay.
Herald added a project: clang.
jvikstrom updated this revision to Diff 214319.
jvikstrom added a comment.

Finished comment.


Done in VisitDeclaratorDecl as the AutoTypeLoc is not deduced.
Scoped to only work for variables.
auto function return values need to be handled in a special way (separate patch 
for that).
auto's that are in lambdas ar enot highlighted as we don't highlight their 
underlying type (it's a RecordDecl, but the name is not an identifier so it 
returns in addToken).


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D65996

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
@@ -99,9 +99,9 @@
   struct {
   } $Variable[[S]];
   $Primitive[[void]] $Function[[foo]]($Primitive[[int]] $Variable[[A]], $Class[[AS]] $Variable[[As]]) {
-auto $Variable[[VeryLongVariableName]] = 12312;
+$Primitive[[auto]] $Variable[[VeryLongVariableName]] = 12312;
 $Class[[AS]] $Variable[[AA]];
-auto $Variable[[L]] = $Variable[[AA]].$Field[[SomeMember]] + $Variable[[A]];
+$Primitive[[auto]] $Variable[[L]] = $Variable[[AA]].$Field[[SomeMember]] + $Variable[[A]];
 auto $Variable[[FN]] = [ $Variable[[AA]]]($Primitive[[int]] $Variable[[A]]) -> $Primitive[[void]] {};
 $Variable[[FN]](12312);
   }
@@ -276,6 +276,20 @@
 $Class[[Foo]] *$Variable[[FP]] = ($Class[[Foo]]*)$Variable[[B]];
 $Primitive[[int]] $Variable[[I]] = ($Primitive[[int]])$Variable[[B]];
   }
+)cpp",
+R"cpp(
+  enum $Enum[[E]] {
+$EnumConstant[[E]],
+  };
+  class $Class[[Foo]] {};
+  $Enum[[auto]] $Variable[[AE]] = $Enum[[E]]::$EnumConstant[[E]];
+  $Class[[auto]] $Variable[[AF]] = $Class[[Foo]]();
+  decltype($Class[[auto]]) $Variable[[AF2]] = $Class[[Foo]]();
+  $Class[[auto]] *$Variable[[AFP]] = &$Variable[[AF]];
+  $Enum[[auto]] &$Variable[[AER]] = $Variable[[AE]];
+  $Primitive[[auto]] $Variable[[Form]] = 10.2 + 2 * 4;
+  $Primitive[[decltype]]($Variable[[Form]]) $Variable[[F]] = 10;
+  auto $Variable[[Fun]] = []()->$Primitive[[void]]{};
 )cpp"};
   for (const auto  : TestCases) {
 checkHighlightings(TestCase);
Index: clang-tools-extra/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -97,7 +97,8 @@
 
   bool VisitTypedefNameDecl(TypedefNameDecl *TD) {
 if(const auto *TSI = TD->getTypeSourceInfo())
-  addTypeLoc(TD->getLocation(), TSI->getTypeLoc());
+  if (const Type *TP = TSI->getTypeLoc().getTypePtr())
+addType(TD->getLocation(), TP);
 return true;
   }
 
@@ -121,8 +122,8 @@
 // TypeLoc.
 if (TL.getTypeLocClass() == TypeLoc::TypeLocClass::Elaborated)
   return true;
-
-addTypeLoc(TL.getBeginLoc(), TL);
+if (const Type *TP = TL.getTypePtr())
+  addType(TL.getBeginLoc(), TP);
 return true;
   }
 
@@ -136,14 +137,33 @@
 HighlightingTokenCollector>::TraverseNestedNameSpecifierLoc(NNSLoc);
   }
 
+  bool VisitDeclaratorDecl(DeclaratorDecl *D) {
+if ((!D->getTypeSourceInfo()))
+  return true;
+
+if (auto *AT = D->getType()->getContainedAutoType()) {
+  const auto Deduced = AT->getDeducedType();
+  if (Deduced.isNull())
+return true;
+  SourceLocation Loc = D->getTypeSpecStartLoc();
+  if (AT->isDecltypeAuto())
+// If this is a decltype(auto) it's still the "auto" keyword that should
+// get the highlightings. But there is no way to get the SLoc of the
+// "auto" keyword other than using an offset.
+Loc = Loc.getLocWithOffset(9);
+  Deduced.getTypePtr()->dump();
+  addType(Loc, Deduced.getTypePtr());
+}
+return true;
+  }
+
 private:
-  void addTypeLoc(SourceLocation Loc, const TypeLoc ) {
-if (const Type *TP = TL.getTypePtr()) {
-  if (const TagDecl *TD = TP->getAsTagDecl())
-addToken(Loc, TD);
-  if (TP->isBuiltinType())
-// Builtins must be special cased as they do not have a TagDecl.
-addToken(Loc, HighlightingKind::Primitive);
+  void addType(SourceLocation Loc, const Type *TP) {
+if (TP->isBuiltinType())
+  // Builtins must be special cased as they do not have a TagDecl.
+  addToken(Loc, HighlightingKind::Primitive);
+if (const TagDecl *TD = TP->getAsTagDecl()) {
+  addToken(Loc, TD);
 }
   }
 

[PATCH] D65926: [clangd] Fixed printTemplateSpecializationArgs not printing partial variable specialization arguments.

2019-08-08 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom added inline comments.



Comment at: clang-tools-extra/clangd/unittests/ASTTests.cpp:40
 
+TEST(PrintTemplateSpecializationArgs, PrintsTemplateArgs) {
+  TestTU TU;

hokein wrote:
> looks like the related tests are in `PrintASTTests.cpp`, could you move the 
> test there?
Oh I didn't see that test file. Seems like a lot of this is already tested, so 
just removing everything that isn't related to template variables.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65926/new/

https://reviews.llvm.org/D65926



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D65926: [clangd] Fixed printTemplateSpecializationArgs not printing partial variable specialization arguments.

2019-08-08 Thread Johan Vikström via Phabricator via cfe-commits
jvikstrom updated this revision to Diff 214132.
jvikstrom marked 2 inline comments as done.
jvikstrom added a comment.

Merged test with PrintASTTest.cpp.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65926/new/

https://reviews.llvm.org/D65926

Files:
  clang-tools-extra/clangd/AST.cpp
  clang-tools-extra/clangd/unittests/ClangdUnitTests.cpp
  clang-tools-extra/clangd/unittests/PrintASTTests.cpp


Index: clang-tools-extra/clangd/unittests/PrintASTTests.cpp
===
--- clang-tools-extra/clangd/unittests/PrintASTTests.cpp
+++ clang-tools-extra/clangd/unittests/PrintASTTests.cpp
@@ -96,6 +96,15 @@
   struct Bar { friend class Foo; };
   template <> struct ^Foo {};)cpp",
 {""}},
+{
+R"cpp(
+  template
+  T S = T(10);
+  template 
+  int ^S = 0;
+  template <>
+  int ^S = 0;)cpp",
+{"", ""}},
 })),);
 } // namespace
 } // namespace clangd
Index: clang-tools-extra/clangd/unittests/ClangdUnitTests.cpp
===
--- clang-tools-extra/clangd/unittests/ClangdUnitTests.cpp
+++ clang-tools-extra/clangd/unittests/ClangdUnitTests.cpp
@@ -188,7 +188,7 @@
 AllOf(DeclNamed("foo"), WithTemplateArgs("")),
 AllOf(DeclNamed("i"), WithTemplateArgs("")),
 AllOf(DeclNamed("d"), WithTemplateArgs("")),
-AllOf(DeclNamed("foo"), WithTemplateArgs("<>")),
+AllOf(DeclNamed("foo"), WithTemplateArgs("")),
 AllOf(DeclNamed("foo"), WithTemplateArgs(""))}));
 }
 
Index: clang-tools-extra/clangd/AST.cpp
===
--- clang-tools-extra/clangd/AST.cpp
+++ clang-tools-extra/clangd/AST.cpp
@@ -36,6 +36,10 @@
  llvm::dyn_cast()) {
 if (auto *Args = Cls->getTemplateArgsAsWritten())
   return Args->arguments();
+  } else if (auto *Var =
+ llvm::dyn_cast()) {
+if (auto *Args = Var->getTemplateArgsAsWritten())
+  return Args->arguments();
   } else if (auto *Var = llvm::dyn_cast())
 return Var->getTemplateArgsInfo().arguments();
   // We return None for ClassTemplateSpecializationDecls because it does not


Index: clang-tools-extra/clangd/unittests/PrintASTTests.cpp
===
--- clang-tools-extra/clangd/unittests/PrintASTTests.cpp
+++ clang-tools-extra/clangd/unittests/PrintASTTests.cpp
@@ -96,6 +96,15 @@
   struct Bar { friend class Foo; };
   template <> struct ^Foo {};)cpp",
 {""}},
+{
+R"cpp(
+  template
+  T S = T(10);
+  template 
+  int ^S = 0;
+  template <>
+  int ^S = 0;)cpp",
+{"", ""}},
 })),);
 } // namespace
 } // namespace clangd
Index: clang-tools-extra/clangd/unittests/ClangdUnitTests.cpp
===
--- clang-tools-extra/clangd/unittests/ClangdUnitTests.cpp
+++ clang-tools-extra/clangd/unittests/ClangdUnitTests.cpp
@@ -188,7 +188,7 @@
 AllOf(DeclNamed("foo"), WithTemplateArgs("")),
 AllOf(DeclNamed("i"), WithTemplateArgs("")),
 AllOf(DeclNamed("d"), WithTemplateArgs("")),
-AllOf(DeclNamed("foo"), WithTemplateArgs("<>")),
+AllOf(DeclNamed("foo"), WithTemplateArgs("")),
 AllOf(DeclNamed("foo"), WithTemplateArgs(""))}));
 }
 
Index: clang-tools-extra/clangd/AST.cpp
===
--- clang-tools-extra/clangd/AST.cpp
+++ clang-tools-extra/clangd/AST.cpp
@@ -36,6 +36,10 @@
  llvm::dyn_cast()) {
 if (auto *Args = Cls->getTemplateArgsAsWritten())
   return Args->arguments();
+  } else if (auto *Var =
+ llvm::dyn_cast()) {
+if (auto *Args = Var->getTemplateArgsAsWritten())
+  return Args->arguments();
   } else if (auto *Var = llvm::dyn_cast())
 return Var->getTemplateArgsInfo().arguments();
   // We return None for ClassTemplateSpecializationDecls because it does not

[PATCH] D65943: [clangd] Added semantic highlighting support for primitives.

2019-08-08 Thread Johan Vikström via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
jvikstrom marked an inline comment as done.
Closed by commit rL368291: [clangd] Added semantic highlighting support for 
primitives. (authored by jvikstrom, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D65943?vs=214121=214130#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65943/new/

https://reviews.llvm.org/D65943

Files:
  clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
  clang-tools-extra/trunk/clangd/SemanticHighlighting.h
  clang-tools-extra/trunk/clangd/test/semantic-highlighting.test
  clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
  clang-tools-extra/trunk/clangd/unittests/TweakTests.cpp

Index: clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
===
--- clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp
@@ -138,9 +138,13 @@
 
 private:
   void addTypeLoc(SourceLocation Loc, const TypeLoc ) {
-if (const Type *TP = TL.getTypePtr())
+if (const Type *TP = TL.getTypePtr()) {
   if (const TagDecl *TD = TP->getAsTagDecl())
 addToken(Loc, TD);
+  if (TP->isBuiltinType())
+// Builtins must be special cased as they do not have a TagDecl.
+addToken(Loc, HighlightingKind::Primitive);
+}
   }
 
   void addToken(SourceLocation Loc, const NamedDecl *D) {
@@ -386,6 +390,8 @@
 return "entity.name.namespace.cpp";
   case HighlightingKind::TemplateParameter:
 return "entity.name.type.template.cpp";
+  case HighlightingKind::Primitive:
+return "storage.type.primitive.cpp";
   case HighlightingKind::NumKinds:
 llvm_unreachable("must not pass NumKinds to the function");
   }
Index: clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
===
--- clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
+++ clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp
@@ -39,7 +39,8 @@
   {HighlightingKind::EnumConstant, "EnumConstant"},
   {HighlightingKind::Field, "Field"},
   {HighlightingKind::Method, "Method"},
-  {HighlightingKind::TemplateParameter, "TemplateParameter"}};
+  {HighlightingKind::TemplateParameter, "TemplateParameter"},
+  {HighlightingKind::Primitive, "Primitive"}};
   std::vector ExpectedTokens;
   for (const auto  : KindToString) {
 std::vector Toks = makeHighlightingTokens(
@@ -93,26 +94,26 @@
   const char *TestCases[] = {
 R"cpp(
   struct $Class[[AS]] {
-double $Field[[SomeMember]];
+$Primitive[[double]] $Field[[SomeMember]];
   };
   struct {
   } $Variable[[S]];
-  void $Function[[foo]](int $Variable[[A]], $Class[[AS]] $Variable[[As]]) {
+  $Primitive[[void]] $Function[[foo]]($Primitive[[int]] $Variable[[A]], $Class[[AS]] $Variable[[As]]) {
 auto $Variable[[VeryLongVariableName]] = 12312;
 $Class[[AS]] $Variable[[AA]];
 auto $Variable[[L]] = $Variable[[AA]].$Field[[SomeMember]] + $Variable[[A]];
-auto $Variable[[FN]] = [ $Variable[[AA]]](int $Variable[[A]]) -> void {};
+auto $Variable[[FN]] = [ $Variable[[AA]]]($Primitive[[int]] $Variable[[A]]) -> $Primitive[[void]] {};
 $Variable[[FN]](12312);
   }
 )cpp",
 R"cpp(
-  void $Function[[foo]](int);
-  void $Function[[Gah]]();
-  void $Function[[foo]]() {
+  $Primitive[[void]] $Function[[foo]]($Primitive[[int]]);
+  $Primitive[[void]] $Function[[Gah]]();
+  $Primitive[[void]] $Function[[foo]]() {
 auto $Variable[[Bou]] = $Function[[Gah]];
   }
   struct $Class[[A]] {
-void $Method[[abc]]();
+$Primitive[[void]] $Method[[abc]]();
   };
 )cpp",
 R"cpp(
@@ -126,17 +127,17 @@
   struct $Class[[C]] : $Namespace[[abc]]::$Class[[A]]<$TemplateParameter[[T]]> {
 typename $TemplateParameter[[T]]::A* $Field[[D]];
   };
-  $Namespace[[abc]]::$Class[[A]] $Variable[[AA]];
-  typedef $Namespace[[abc]]::$Class[[A]] $Class[[AAA]];
+  $Namespace[[abc]]::$Class[[A]]<$Primitive[[int]]> $Variable[[AA]];
+  typedef $Namespace[[abc]]::$Class[[A]]<$Primitive[[int]]> $Class[[AAA]];
   struct $Class[[B]] {
 $Class[[B]]();
 ~$Class[[B]]();
-void operator<<($Class[[B]]);
+$Primitive[[void]] operator<<($Class[[B]]);
 $Class[[AAA]] $Field[[AA]];
   };
   $Class[[B]]::$Class[[B]]() {}
   $Class[[B]]::~$Class[[B]]() {}
-  void $Function[[f]] () {
+  $Primitive[[void]] $Function[[f]] () {
 $Class[[B]] $Variable[[BB]] = $Class[[B]]();
 $Variable[[BB]].~$Class[[B]]();
 $Class[[B]]();
@@ -154,7 +155,7 @@
 $Enum[[E]] $Field[[EEE]];
 

  1   2   3   4   >