[PATCH] D76304: [clangd] Update TUStatus api to accommodate preamble thread

2020-04-06 Thread Kadir Cetinkaya via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG6b85032c95be: [clangd] Update TUStatus api to accommodate 
preamble thread (authored by kadircet).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D76304

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/TUScheduler.cpp
  clang-tools-extra/clangd/TUScheduler.h
  clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp

Index: clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp
===
--- clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp
+++ clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp
@@ -24,6 +24,7 @@
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 #include 
+#include 
 #include 
 #include 
 
@@ -40,13 +41,14 @@
 using ::testing::Pointee;
 using ::testing::UnorderedElementsAre;
 
-MATCHER_P2(TUState, State, ActionName, "") {
-  if (arg.Action.S != State) {
-*result_listener << "state is " << arg.Action.S;
+MATCHER_P2(TUState, PreambleActivity, ASTActivity, "") {
+  if (arg.PreambleActivity != PreambleActivity) {
+*result_listener << "preamblestate is "
+ << static_cast(arg.PreambleActivity);
 return false;
   }
-  if (arg.Action.Name != ActionName) {
-*result_listener << "name is " << arg.Action.Name;
+  if (arg.ASTActivity.K != ASTActivity) {
+*result_listener << "aststate is " << arg.ASTActivity.K;
 return false;
   }
   return true;
@@ -732,14 +734,13 @@
 
   // Update the source contents, which should trigger an initial build with
   // the header file missing.
-  updateWithDiags(S, Source, Inputs, WantDiagnostics::Yes,
-  [](std::vector Diags) {
-EXPECT_THAT(
-Diags,
-ElementsAre(
-Field(::Message, "'foo.h' file not found"),
-Field(::Message, "use of undeclared identifier 'a'")));
-  });
+  updateWithDiags(
+  S, Source, Inputs, WantDiagnostics::Yes, [](std::vector Diags) {
+EXPECT_THAT(Diags,
+ElementsAre(Field(::Message, "'foo.h' file not found"),
+Field(::Message,
+  "use of undeclared identifier 'a'")));
+  });
 
   // Add the header file. We need to recreate the inputs since we changed a
   // file from underneath the test FS.
@@ -749,18 +750,17 @@
 
   // The addition of the missing header file shouldn't trigger a rebuild since
   // we don't track missing files.
-  updateWithDiags(S, Source, Inputs, WantDiagnostics::Yes,
-  [](std::vector Diags) {
-ADD_FAILURE() << "Did not expect diagnostics for missing header update";
-  });
+  updateWithDiags(
+  S, Source, Inputs, WantDiagnostics::Yes, [](std::vector Diags) {
+ADD_FAILURE() << "Did not expect diagnostics for missing header update";
+  });
 
   // Forcing the reload should should cause a rebuild which no longer has any
   // errors.
   Inputs.ForceRebuild = true;
-  updateWithDiags(S, Source, Inputs, WantDiagnostics::Yes,
-  [](std::vector Diags) {
-EXPECT_THAT(Diags, IsEmpty());
-  });
+  updateWithDiags(
+  S, Source, Inputs, WantDiagnostics::Yes,
+  [](std::vector Diags) { EXPECT_THAT(Diags, IsEmpty()); });
 
   ASSERT_TRUE(S.blockUntilIdle(timeoutSeconds(10)));
 }
@@ -848,14 +848,21 @@
 
   EXPECT_THAT(CaptureTUStatus.allStatus(),
   ElementsAre(
-  // Statuses of "Update" action.
-  TUState(TUAction::RunningAction, "Update (1)"),
-  TUState(TUAction::BuildingPreamble, "Update (1)"),
-  TUState(TUAction::BuildingFile, "Update (1)"),
-
-  // Statuses of "Definitions" action
-  TUState(TUAction::RunningAction, "Definitions"),
-  TUState(TUAction::Idle, /*No action*/ "")));
+  // Everything starts with ASTWorker starting to execute an
+  // update
+  TUState(PreambleAction::Idle, ASTAction::RunningAction),
+  // We build the preamble
+  TUState(PreambleAction::Building, ASTAction::RunningAction),
+  // Preamble worker goes idle
+  TUState(PreambleAction::Idle, ASTAction::RunningAction),
+  // We start building the ast
+  TUState(PreambleAction::Idle, ASTAction::Building),
+  // Built finished succesffully
+  TUState(PreambleAction::Idle, ASTAction::Building),
+  // Rnning go to def
+  TUState(PreambleAction::Idle, ASTAction::RunningAction),
+  // both workers go idle
+  TUState(PreambleAction::Idle, ASTAction::Idle)));
 }
 
 TEST_F(TUSchedulerTests, CommandLineErrors) {
@@ -868,8 +875,7 @@
   TUScheduler S(CDB, optsForTest(), 

[PATCH] D76304: [clangd] Update TUStatus api to accommodate preamble thread

2020-04-02 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 254519.
kadircet added a comment.

- Rebase


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D76304

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/TUScheduler.cpp
  clang-tools-extra/clangd/TUScheduler.h
  clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp

Index: clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp
===
--- clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp
+++ clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp
@@ -24,6 +24,7 @@
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 #include 
+#include 
 #include 
 #include 
 
@@ -40,13 +41,14 @@
 using ::testing::Pointee;
 using ::testing::UnorderedElementsAre;
 
-MATCHER_P2(TUState, State, ActionName, "") {
-  if (arg.Action.S != State) {
-*result_listener << "state is " << arg.Action.S;
+MATCHER_P2(TUState, PreambleActivity, ASTActivity, "") {
+  if (arg.PreambleActivity != PreambleActivity) {
+*result_listener << "preamblestate is "
+ << static_cast(arg.PreambleActivity);
 return false;
   }
-  if (arg.Action.Name != ActionName) {
-*result_listener << "name is " << arg.Action.Name;
+  if (arg.ASTActivity.K != ASTActivity) {
+*result_listener << "aststate is " << arg.ASTActivity.K;
 return false;
   }
   return true;
@@ -732,14 +734,13 @@
 
   // Update the source contents, which should trigger an initial build with
   // the header file missing.
-  updateWithDiags(S, Source, Inputs, WantDiagnostics::Yes,
-  [](std::vector Diags) {
-EXPECT_THAT(
-Diags,
-ElementsAre(
-Field(::Message, "'foo.h' file not found"),
-Field(::Message, "use of undeclared identifier 'a'")));
-  });
+  updateWithDiags(
+  S, Source, Inputs, WantDiagnostics::Yes, [](std::vector Diags) {
+EXPECT_THAT(Diags,
+ElementsAre(Field(::Message, "'foo.h' file not found"),
+Field(::Message,
+  "use of undeclared identifier 'a'")));
+  });
 
   // Add the header file. We need to recreate the inputs since we changed a
   // file from underneath the test FS.
@@ -749,18 +750,17 @@
 
   // The addition of the missing header file shouldn't trigger a rebuild since
   // we don't track missing files.
-  updateWithDiags(S, Source, Inputs, WantDiagnostics::Yes,
-  [](std::vector Diags) {
-ADD_FAILURE() << "Did not expect diagnostics for missing header update";
-  });
+  updateWithDiags(
+  S, Source, Inputs, WantDiagnostics::Yes, [](std::vector Diags) {
+ADD_FAILURE() << "Did not expect diagnostics for missing header update";
+  });
 
   // Forcing the reload should should cause a rebuild which no longer has any
   // errors.
   Inputs.ForceRebuild = true;
-  updateWithDiags(S, Source, Inputs, WantDiagnostics::Yes,
-  [](std::vector Diags) {
-EXPECT_THAT(Diags, IsEmpty());
-  });
+  updateWithDiags(
+  S, Source, Inputs, WantDiagnostics::Yes,
+  [](std::vector Diags) { EXPECT_THAT(Diags, IsEmpty()); });
 
   ASSERT_TRUE(S.blockUntilIdle(timeoutSeconds(10)));
 }
@@ -848,14 +848,21 @@
 
   EXPECT_THAT(CaptureTUStatus.allStatus(),
   ElementsAre(
-  // Statuses of "Update" action.
-  TUState(TUAction::RunningAction, "Update (1)"),
-  TUState(TUAction::BuildingPreamble, "Update (1)"),
-  TUState(TUAction::BuildingFile, "Update (1)"),
-
-  // Statuses of "Definitions" action
-  TUState(TUAction::RunningAction, "Definitions"),
-  TUState(TUAction::Idle, /*No action*/ "")));
+  // Everything starts with ASTWorker starting to execute an
+  // update
+  TUState(PreambleAction::Idle, ASTAction::RunningAction),
+  // We build the preamble
+  TUState(PreambleAction::Building, ASTAction::RunningAction),
+  // Preamble worker goes idle
+  TUState(PreambleAction::Idle, ASTAction::RunningAction),
+  // We start building the ast
+  TUState(PreambleAction::Idle, ASTAction::Building),
+  // Built finished succesffully
+  TUState(PreambleAction::Idle, ASTAction::Building),
+  // Rnning go to def
+  TUState(PreambleAction::Idle, ASTAction::RunningAction),
+  // both workers go idle
+  TUState(PreambleAction::Idle, ASTAction::Idle)));
 }
 
 TEST_F(TUSchedulerTests, CommandLineErrors) {
@@ -868,8 +875,7 @@
   TUScheduler S(CDB, optsForTest(), captureDiags());
   std::vector Diagnostics;
   updateWithDiags(S, testPath("foo.cpp"), "void test() {}",
-  

[PATCH] D76304: [clangd] Update TUStatus api to accommodate preamble thread

2020-03-24 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet added inline comments.



Comment at: clang-tools-extra/clangd/TUScheduler.cpp:277
   build(std::move(*CurrentReq));
+  bool IsEmpty = false;
+  {

sammccall wrote:
> kadircet wrote:
> > sammccall wrote:
> > > Seems clearer to do this immediately before blocking?
> > > 
> > > at the top:
> > > 
> > > ```
> > > if (!NextReq) {
> > >   Lock.unlock();
> > >   StatusManager.setPreambleAction(Idle);
> > >   Lock.lock();
> > >   ReqCV.wait(NextReq || Done);
> > > }
> > > if (Done)
> > >   break;
> > > ```
> > i agree, but I wanted to keep the current semantics. we only start emitting 
> > tustatuses after thread starts executing the first request.
> > 
> > happy to change *both* preamblethread and astworker to emit before blocking 
> > though. wdyt?
> I think the difference is moot - we never create either the AST or preamble 
> worker until there's something to do.
> 
> The code around scheduling/sleeping in the AST worker thread is way more 
> complicated, and I'm not confident moving the status broadcast to the top of 
> the loop would be clearer there.
> 
> Up to you: if you think both are clearer, move both. If you think the 
> preamble is clearer at the top and AST worker at the bottom, then you can 
> choose between consistency and clarity :-)
as discussed offline, this might make tests flaky due to a possible race 
between this thread and the thread issuing the write. so leaving it as it is.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D76304



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


[PATCH] D76304: [clangd] Update TUStatus api to accommodate preamble thread

2020-03-24 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 252248.
kadircet marked 14 inline comments as done.
kadircet added a comment.

- Address comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D76304

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/TUScheduler.cpp
  clang-tools-extra/clangd/TUScheduler.h
  clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp

Index: clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp
===
--- clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp
+++ clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp
@@ -24,6 +24,7 @@
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 #include 
+#include 
 #include 
 #include 
 
@@ -40,13 +41,14 @@
 using ::testing::Pointee;
 using ::testing::UnorderedElementsAre;
 
-MATCHER_P2(TUState, State, ActionName, "") {
-  if (arg.Action.S != State) {
-*result_listener << "state is " << arg.Action.S;
+MATCHER_P2(TUState, PreambleActivity, ASTActivity, "") {
+  if (arg.PreambleActivity != PreambleActivity) {
+*result_listener << "preamblestate is "
+ << static_cast(arg.PreambleActivity);
 return false;
   }
-  if (arg.Action.Name != ActionName) {
-*result_listener << "name is " << arg.Action.Name;
+  if (arg.ASTActivity.K != ASTActivity) {
+*result_listener << "aststate is " << arg.ASTActivity.K;
 return false;
   }
   return true;
@@ -732,14 +734,13 @@
 
   // Update the source contents, which should trigger an initial build with
   // the header file missing.
-  updateWithDiags(S, Source, Inputs, WantDiagnostics::Yes,
-  [](std::vector Diags) {
-EXPECT_THAT(
-Diags,
-ElementsAre(
-Field(::Message, "'foo.h' file not found"),
-Field(::Message, "use of undeclared identifier 'a'")));
-  });
+  updateWithDiags(
+  S, Source, Inputs, WantDiagnostics::Yes, [](std::vector Diags) {
+EXPECT_THAT(Diags,
+ElementsAre(Field(::Message, "'foo.h' file not found"),
+Field(::Message,
+  "use of undeclared identifier 'a'")));
+  });
 
   // Add the header file. We need to recreate the inputs since we changed a
   // file from underneath the test FS.
@@ -749,18 +750,17 @@
 
   // The addition of the missing header file shouldn't trigger a rebuild since
   // we don't track missing files.
-  updateWithDiags(S, Source, Inputs, WantDiagnostics::Yes,
-  [](std::vector Diags) {
-ADD_FAILURE() << "Did not expect diagnostics for missing header update";
-  });
+  updateWithDiags(
+  S, Source, Inputs, WantDiagnostics::Yes, [](std::vector Diags) {
+ADD_FAILURE() << "Did not expect diagnostics for missing header update";
+  });
 
   // Forcing the reload should should cause a rebuild which no longer has any
   // errors.
   Inputs.ForceRebuild = true;
-  updateWithDiags(S, Source, Inputs, WantDiagnostics::Yes,
-  [](std::vector Diags) {
-EXPECT_THAT(Diags, IsEmpty());
-  });
+  updateWithDiags(
+  S, Source, Inputs, WantDiagnostics::Yes,
+  [](std::vector Diags) { EXPECT_THAT(Diags, IsEmpty()); });
 
   ASSERT_TRUE(S.blockUntilIdle(timeoutSeconds(10)));
 }
@@ -848,14 +848,21 @@
 
   EXPECT_THAT(CaptureTUStatus.allStatus(),
   ElementsAre(
-  // Statuses of "Update" action.
-  TUState(TUAction::RunningAction, "Update (1)"),
-  TUState(TUAction::BuildingPreamble, "Update (1)"),
-  TUState(TUAction::BuildingFile, "Update (1)"),
-
-  // Statuses of "Definitions" action
-  TUState(TUAction::RunningAction, "Definitions"),
-  TUState(TUAction::Idle, /*No action*/ "")));
+  // Everything starts with ASTWorker starting to execute an
+  // update
+  TUState(PreambleAction::Idle, ASTAction::RunningAction),
+  // We build the preamble
+  TUState(PreambleAction::Building, ASTAction::RunningAction),
+  // Preamble worker goes idle
+  TUState(PreambleAction::Idle, ASTAction::RunningAction),
+  // We start building the ast
+  TUState(PreambleAction::Idle, ASTAction::Building),
+  // Built finished succesffully
+  TUState(PreambleAction::Idle, ASTAction::Building),
+  // Rnning go to def
+  TUState(PreambleAction::Idle, ASTAction::RunningAction),
+  // both workers go idle
+  TUState(PreambleAction::Idle, ASTAction::Idle)));
 }
 
 TEST_F(TUSchedulerTests, CommandLineErrors) {
@@ -868,8 +875,7 @@
   TUScheduler S(CDB, optsForTest(), captureDiags());
   std::vector Diagnostics;
   

[PATCH] D76304: [clangd] Update TUStatus api to accommodate preamble thread

2020-03-18 Thread Sam McCall via Phabricator via cfe-commits
sammccall accepted this revision.
sammccall added inline comments.
This revision is now accepted and ready to land.



Comment at: clang-tools-extra/clangd/TUScheduler.cpp:277
   build(std::move(*CurrentReq));
+  bool IsEmpty = false;
+  {

kadircet wrote:
> sammccall wrote:
> > Seems clearer to do this immediately before blocking?
> > 
> > at the top:
> > 
> > ```
> > if (!NextReq) {
> >   Lock.unlock();
> >   StatusManager.setPreambleAction(Idle);
> >   Lock.lock();
> >   ReqCV.wait(NextReq || Done);
> > }
> > if (Done)
> >   break;
> > ```
> i agree, but I wanted to keep the current semantics. we only start emitting 
> tustatuses after thread starts executing the first request.
> 
> happy to change *both* preamblethread and astworker to emit before blocking 
> though. wdyt?
I think the difference is moot - we never create either the AST or preamble 
worker until there's something to do.

The code around scheduling/sleeping in the AST worker thread is way more 
complicated, and I'm not confident moving the status broadcast to the top of 
the loop would be clearer there.

Up to you: if you think both are clearer, move both. If you think the preamble 
is clearer at the top and AST worker at the bottom, then you can choose between 
consistency and clarity :-)



Comment at: clang-tools-extra/clangd/TUScheduler.cpp:357
+
+  SynchronizedTUStatus 
 };

StatusManager -> Status



Comment at: clang-tools-extra/clangd/TUScheduler.cpp:490
 
+  SynchronizedTUStatus StatusManager;
   PreambleThread PW;

StatusManager -> Status



Comment at: clang-tools-extra/clangd/TUScheduler.cpp:698
+  // buildAST fails.
+  if (!(*AST)) {
+StatusManager.update(

(might be clearer to call once and make the logic conditional)



Comment at: clang-tools-extra/clangd/TUScheduler.cpp:1053
+  llvm::SmallVector Result;
+  if (PA == PreambleAction::Building)
+Result.push_back("parsing includes");

nit: write this as a switch  for consistency plus the covered warning?



Comment at: clang-tools-extra/clangd/TUScheduler.h:122
 
-  TUAction Action;
-  BuildDetails Details;
+  /// Stores the status of preamble thread.
+  PreambleAction PreambleState = PreambleAction::Idle;

comment just repeats the declaration, drop it?



Comment at: clang-tools-extra/clangd/TUScheduler.h:123
+  /// Stores the status of preamble thread.
+  PreambleAction PreambleState = PreambleAction::Idle;
+  ASTAction ASTState;

I think these variables are still best described at a high level actions, not 
states. (Well, the state of the thread is that it is running this action, but 
that's a little roundabout. TUAction::State probably should have been called 
Kind instead).

Unfortunate that we need both a type name and a variable name though. 
`ASTAction ASTActivity; PreambleAction PreambleActivity;`?



Comment at: clang-tools-extra/clangd/TUScheduler.h:126
+  /// Stores status of the last build for the translation unit.
+  BuildStatus BS = None;
 };

If keeping the enum, this variable needs a real name.
I'd suggest `LastBuild` and dropping the comment.



Comment at: clang-tools-extra/clangd/TUScheduler.h:104
 struct TUStatus {
-  struct BuildDetails {
-/// Indicates whether clang failed to build the TU.
-bool BuildFailed = false;
-/// Indicates whether we reused the prebuilt AST.
-bool ReuseAST = false;
+  enum BuildStatus {
+/// Haven't run a built yet

kadircet wrote:
> sammccall wrote:
> > What's the purpose of this change? It seems to make the build details 
> > harder to maintain/extend.
> > 
> > (In particular, say we were going to add a "fallback command was used" bit, 
> > where would it go after this change?)
> this was to narrow down the interface. Currently builddetails is only being 
> used to report buildstatus, and those cases are mutually exclusive(a build 
> can't be both a reuse and failure). Therefore i wanted to make that more 
> explicit.
> 
> if we decide to add more details, I would say we should rather get 
> BuildDetails struct back, with a Status enum and a couple more state to 
> signal any other information.
OK, I understand but don't really agree - the fact that these are exclusive is 
a coincidence that we don't need to model APIs around. This doesn't seem 
related to the rest of this patch, either.

I think we're going around in circles on this though, will leave this up to you.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D76304



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


[PATCH] D76304: [clangd] Update TUStatus api to accommodate preamble thread

2020-03-18 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet added inline comments.



Comment at: clang-tools-extra/clangd/TUScheduler.cpp:161
+/// update.
+class TUStatusManager {
+public:

sammccall wrote:
> nit: "manager" doesn't really explain what this is, and it's used both as the 
> class name and the main description in the comment.
> 
> Maybe TUStatusTracker or something - "Threadsafe holder for TUStatus..."
NAMNG !!! :(((



Comment at: clang-tools-extra/clangd/TUScheduler.cpp:198
+
+  mutable std::mutex StatusMu;
+  TUStatus Status;

sammccall wrote:
> why mutable with  no const functions?
I had a readable version at some point, just leftover from those days :P



Comment at: clang-tools-extra/clangd/TUScheduler.cpp:277
   build(std::move(*CurrentReq));
+  bool IsEmpty = false;
+  {

sammccall wrote:
> Seems clearer to do this immediately before blocking?
> 
> at the top:
> 
> ```
> if (!NextReq) {
>   Lock.unlock();
>   StatusManager.setPreambleAction(Idle);
>   Lock.lock();
>   ReqCV.wait(NextReq || Done);
> }
> if (Done)
>   break;
> ```
i agree, but I wanted to keep the current semantics. we only start emitting 
tustatuses after thread starts executing the first request.

happy to change *both* preamblethread and astworker to emit before blocking 
though. wdyt?



Comment at: clang-tools-extra/clangd/TUScheduler.cpp:285
+StatusManager.setPreambleAction({TUAction::Idle, /*Name=*/""});
+  BuiltFirst.notify();
+  ReqCV.notify_all();

sammccall wrote:
> why this change?
this needs to happen after resetting `CurrentReq` and previously this was part 
of `build`. It makes more sense to hanlde this resetting as part of the worker 
thread, rather than as part of the preamble build logic.

but I suppose it doesn't belong into this patch. moving it to the 
https://reviews.llvm.org/D76125



Comment at: clang-tools-extra/clangd/TUScheduler.h:104
 struct TUStatus {
-  struct BuildDetails {
-/// Indicates whether clang failed to build the TU.
-bool BuildFailed = false;
-/// Indicates whether we reused the prebuilt AST.
-bool ReuseAST = false;
+  enum BuildStatus {
+/// Haven't run a built yet

sammccall wrote:
> What's the purpose of this change? It seems to make the build details harder 
> to maintain/extend.
> 
> (In particular, say we were going to add a "fallback command was used" bit, 
> where would it go after this change?)
this was to narrow down the interface. Currently builddetails is only being 
used to report buildstatus, and those cases are mutually exclusive(a build 
can't be both a reuse and failure). Therefore i wanted to make that more 
explicit.

if we decide to add more details, I would say we should rather get BuildDetails 
struct back, with a Status enum and a couple more state to signal any other 
information.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D76304



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


[PATCH] D76304: [clangd] Update TUStatus api to accommodate preamble thread

2020-03-18 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet updated this revision to Diff 251022.
kadircet marked 8 inline comments as done.
kadircet added a comment.

- Address comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D76304

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/TUScheduler.cpp
  clang-tools-extra/clangd/TUScheduler.h
  clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp

Index: clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp
===
--- clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp
+++ clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp
@@ -24,6 +24,7 @@
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 #include 
+#include 
 #include 
 #include 
 
@@ -40,13 +41,18 @@
 using ::testing::Pointee;
 using ::testing::UnorderedElementsAre;
 
-MATCHER_P2(TUState, State, ActionName, "") {
-  if (arg.Action.S != State) {
-*result_listener << "state is " << arg.Action.S;
+MATCHER_P3(TUState, PreambleState, ASTState, BS, "") {
+  if (arg.PreambleState != PreambleState) {
+*result_listener << "preamblestate is "
+ << static_cast(arg.PreambleState);
 return false;
   }
-  if (arg.Action.Name != ActionName) {
-*result_listener << "name is " << arg.Action.Name;
+  if (arg.ASTState.S != ASTState) {
+*result_listener << "aststate is " << arg.ASTState.S;
+return false;
+  }
+  if (arg.BS != BS) {
+*result_listener << "builddetail is " << arg.BS;
 return false;
   }
   return true;
@@ -732,14 +738,13 @@
 
   // Update the source contents, which should trigger an initial build with
   // the header file missing.
-  updateWithDiags(S, Source, Inputs, WantDiagnostics::Yes,
-  [](std::vector Diags) {
-EXPECT_THAT(
-Diags,
-ElementsAre(
-Field(::Message, "'foo.h' file not found"),
-Field(::Message, "use of undeclared identifier 'a'")));
-  });
+  updateWithDiags(
+  S, Source, Inputs, WantDiagnostics::Yes, [](std::vector Diags) {
+EXPECT_THAT(Diags,
+ElementsAre(Field(::Message, "'foo.h' file not found"),
+Field(::Message,
+  "use of undeclared identifier 'a'")));
+  });
 
   // Add the header file. We need to recreate the inputs since we changed a
   // file from underneath the test FS.
@@ -749,18 +754,17 @@
 
   // The addition of the missing header file shouldn't trigger a rebuild since
   // we don't track missing files.
-  updateWithDiags(S, Source, Inputs, WantDiagnostics::Yes,
-  [](std::vector Diags) {
-ADD_FAILURE() << "Did not expect diagnostics for missing header update";
-  });
+  updateWithDiags(
+  S, Source, Inputs, WantDiagnostics::Yes, [](std::vector Diags) {
+ADD_FAILURE() << "Did not expect diagnostics for missing header update";
+  });
 
   // Forcing the reload should should cause a rebuild which no longer has any
   // errors.
   Inputs.ForceRebuild = true;
-  updateWithDiags(S, Source, Inputs, WantDiagnostics::Yes,
-  [](std::vector Diags) {
-EXPECT_THAT(Diags, IsEmpty());
-  });
+  updateWithDiags(
+  S, Source, Inputs, WantDiagnostics::Yes,
+  [](std::vector Diags) { EXPECT_THAT(Diags, IsEmpty()); });
 
   ASSERT_TRUE(S.blockUntilIdle(timeoutSeconds(10)));
 }
@@ -846,16 +850,28 @@
 
   ASSERT_TRUE(Server.blockUntilIdleForTest());
 
-  EXPECT_THAT(CaptureTUStatus.allStatus(),
-  ElementsAre(
-  // Statuses of "Update" action.
-  TUState(TUAction::RunningAction, "Update (1)"),
-  TUState(TUAction::BuildingPreamble, "Update (1)"),
-  TUState(TUAction::BuildingFile, "Update (1)"),
-
-  // Statuses of "Definitions" action
-  TUState(TUAction::RunningAction, "Definitions"),
-  TUState(TUAction::Idle, /*No action*/ "")));
+  EXPECT_THAT(
+  CaptureTUStatus.allStatus(),
+  ElementsAre(
+  // Everything starts with ASTWorker starting to execute an
+  // update
+  TUState(PreambleAction::Idle, ASTAction::RunningAction,
+  TUStatus::None),
+  // We build the preamble
+  TUState(PreambleAction::Building, ASTAction::RunningAction,
+  TUStatus::None),
+  // Preamble worker goes idle
+  TUState(PreambleAction::Idle, ASTAction::RunningAction,
+  TUStatus::None),
+  // We start building the ast
+  TUState(PreambleAction::Idle, ASTAction::Building, TUStatus::None),
+  // Built finished succesffully
+  TUState(PreambleAction::Idle, ASTAction::Building, TUStatus::Built),
+  // Rnning go to def
+  TUState(PreambleAction::Idle, ASTAction::RunningAction,
+  TUStatus::Built),
+   

[PATCH] D76304: [clangd] Update TUStatus api to accommodate preamble thread

2020-03-17 Thread Sam McCall via Phabricator via cfe-commits
sammccall added inline comments.



Comment at: clang-tools-extra/clangd/TUScheduler.cpp:161
+/// update.
+class TUStatusManager {
+public:

nit: "manager" doesn't really explain what this is, and it's used both as the 
class name and the main description in the comment.

Maybe TUStatusTracker or something - "Threadsafe holder for TUStatus..."



Comment at: clang-tools-extra/clangd/TUScheduler.cpp:166
+
+  void setPreambleAction(TUAction A) {
+std::lock_guard Lock(StatusMu);

you could consider a slightly more general version:

```
StatusMgr.update([&](TUStatus ) {
  S.PreambleAction = Idle;
});
```

it's a bit more wordy at the callsite but it makes the correspondence much more 
direct.



Comment at: clang-tools-extra/clangd/TUScheduler.cpp:198
+
+  mutable std::mutex StatusMu;
+  TUStatus Status;

why mutable with  no const functions?



Comment at: clang-tools-extra/clangd/TUScheduler.cpp:277
   build(std::move(*CurrentReq));
+  bool IsEmpty = false;
+  {

Seems clearer to do this immediately before blocking?

at the top:

```
if (!NextReq) {
  Lock.unlock();
  StatusManager.setPreambleAction(Idle);
  Lock.lock();
  ReqCV.wait(NextReq || Done);
}
if (Done)
  break;
```



Comment at: clang-tools-extra/clangd/TUScheduler.cpp:285
+StatusManager.setPreambleAction({TUAction::Idle, /*Name=*/""});
+  BuiltFirst.notify();
+  ReqCV.notify_all();

why this change?



Comment at: clang-tools-extra/clangd/TUScheduler.h:104
 struct TUStatus {
-  struct BuildDetails {
-/// Indicates whether clang failed to build the TU.
-bool BuildFailed = false;
-/// Indicates whether we reused the prebuilt AST.
-bool ReuseAST = false;
+  enum BuildStatus {
+/// Haven't run a built yet

What's the purpose of this change? It seems to make the build details harder to 
maintain/extend.

(In particular, say we were going to add a "fallback command was used" bit, 
where would it go after this change?)



Comment at: clang-tools-extra/clangd/TUScheduler.h:117
 
-  TUAction Action;
-  BuildDetails Details;
+  TUAction PreambleAction;
+  TUAction ASTAction;

why TUAction rather than a PreambleAction enum { Building, Idle }?
It seems Name will never be used, RunningAction/Queued are not possible etc.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D76304



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


[PATCH] D76304: [clangd] Update TUStatus api to accommodate preamble thread

2020-03-17 Thread Kadir Cetinkaya via Phabricator via cfe-commits
kadircet created this revision.
kadircet added a reviewer: sammccall.
Herald added subscribers: cfe-commits, usaxena95, arphaman, jkorous, MaskRay, 
javed.absar, ilya-biryukov.
Herald added a project: clang.

TUStatus api had a single thread in mind. This introudces a section
action to represent state of the preamble thread. In the file status extension,
we keep old behavior almost the same. We only prepend current task with a
`parsing includes` if preamble thread is working. We omit the idle thread in the
output unless both threads are idle.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D76304

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/TUScheduler.cpp
  clang-tools-extra/clangd/TUScheduler.h
  clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp

Index: clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp
===
--- clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp
+++ clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp
@@ -40,13 +40,17 @@
 using ::testing::Pointee;
 using ::testing::UnorderedElementsAre;
 
-MATCHER_P2(TUState, State, ActionName, "") {
-  if (arg.Action.S != State) {
-*result_listener << "state is " << arg.Action.S;
+MATCHER_P3(TUState, PreambleState, ASTState, BS, "") {
+  if (arg.PreambleAction.S != PreambleState) {
+*result_listener << "preamblestate is " << arg.PreambleAction.S;
 return false;
   }
-  if (arg.Action.Name != ActionName) {
-*result_listener << "name is " << arg.Action.Name;
+  if (arg.ASTAction.S != ASTState) {
+*result_listener << "aststate is " << arg.ASTAction.S;
+return false;
+  }
+  if (arg.BS != BS) {
+*result_listener << "builddetail is " << arg.BS;
 return false;
   }
   return true;
@@ -732,14 +736,13 @@
 
   // Update the source contents, which should trigger an initial build with
   // the header file missing.
-  updateWithDiags(S, Source, Inputs, WantDiagnostics::Yes,
-  [](std::vector Diags) {
-EXPECT_THAT(
-Diags,
-ElementsAre(
-Field(::Message, "'foo.h' file not found"),
-Field(::Message, "use of undeclared identifier 'a'")));
-  });
+  updateWithDiags(
+  S, Source, Inputs, WantDiagnostics::Yes, [](std::vector Diags) {
+EXPECT_THAT(Diags,
+ElementsAre(Field(::Message, "'foo.h' file not found"),
+Field(::Message,
+  "use of undeclared identifier 'a'")));
+  });
 
   // Add the header file. We need to recreate the inputs since we changed a
   // file from underneath the test FS.
@@ -749,18 +752,17 @@
 
   // The addition of the missing header file shouldn't trigger a rebuild since
   // we don't track missing files.
-  updateWithDiags(S, Source, Inputs, WantDiagnostics::Yes,
-  [](std::vector Diags) {
-ADD_FAILURE() << "Did not expect diagnostics for missing header update";
-  });
+  updateWithDiags(
+  S, Source, Inputs, WantDiagnostics::Yes, [](std::vector Diags) {
+ADD_FAILURE() << "Did not expect diagnostics for missing header update";
+  });
 
   // Forcing the reload should should cause a rebuild which no longer has any
   // errors.
   Inputs.ForceRebuild = true;
-  updateWithDiags(S, Source, Inputs, WantDiagnostics::Yes,
-  [](std::vector Diags) {
-EXPECT_THAT(Diags, IsEmpty());
-  });
+  updateWithDiags(
+  S, Source, Inputs, WantDiagnostics::Yes,
+  [](std::vector Diags) { EXPECT_THAT(Diags, IsEmpty()); });
 
   ASSERT_TRUE(S.blockUntilIdle(timeoutSeconds(10)));
 }
@@ -846,16 +848,24 @@
 
   ASSERT_TRUE(Server.blockUntilIdleForTest());
 
-  EXPECT_THAT(CaptureTUStatus.allStatus(),
-  ElementsAre(
-  // Statuses of "Update" action.
-  TUState(TUAction::RunningAction, "Update (1)"),
-  TUState(TUAction::BuildingPreamble, "Update (1)"),
-  TUState(TUAction::BuildingFile, "Update (1)"),
-
-  // Statuses of "Definitions" action
-  TUState(TUAction::RunningAction, "Definitions"),
-  TUState(TUAction::Idle, /*No action*/ "")));
+  EXPECT_THAT(
+  CaptureTUStatus.allStatus(),
+  ElementsAre(
+  // Everything starts with ASTWorker starting to execute an
+  // update
+  TUState(TUAction::Idle, TUAction::RunningAction, TUStatus::None),
+  // We build the preamble
+  TUState(TUAction::Building, TUAction::RunningAction, TUStatus::None),
+  // Preamble worker goes idle
+  TUState(TUAction::Idle, TUAction::RunningAction, TUStatus::None),
+  // We start building the ast
+  TUState(TUAction::Idle, TUAction::Building, TUStatus::None),
+  // Built finished succesffully
+  TUState(TUAction::Idle, TUAction::Building, TUStatus::Built),
+  // Rnning go to