[clang-tools-extra] r315214 - [clangd] Added a command-line arg to mirror clangd input into a file.

Bruno Cardoso Lopes via cfe-commits cfe-commits at lists.llvm.org
Mon Oct 9 11:45:57 PDT 2017


Hi,

On Mon, Oct 9, 2017 at 9:58 AM, Ilya Biryukov via cfe-commits
<cfe-commits at lists.llvm.org> wrote:
> Author: ibiryukov
> Date: Mon Oct  9 09:58:16 2017
> New Revision: 315214
>
> URL: http://llvm.org/viewvc/llvm-project?rev=315214&view=rev
> Log:
> [clangd] Added a command-line arg to mirror clangd input into a file.
>
> Summary: The arg is useful for debugging and creating test cases.
>
> Reviewers: bkramer, krasimir
>
> Reviewed By: bkramer
>
> Subscribers: klimek, cfe-commits
>
> Differential Revision: https://reviews.llvm.org/D37970
>
> Added:
>     clang-tools-extra/trunk/test/clangd/input-mirror.test
> Modified:
>     clang-tools-extra/trunk/clangd/JSONRPCDispatcher.cpp
>     clang-tools-extra/trunk/clangd/JSONRPCDispatcher.h
>     clang-tools-extra/trunk/clangd/tool/ClangdMain.cpp
>
> Modified: clang-tools-extra/trunk/clangd/JSONRPCDispatcher.cpp
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/JSONRPCDispatcher.cpp?rev=315214&r1=315213&r2=315214&view=diff
> ==============================================================================
> --- clang-tools-extra/trunk/clangd/JSONRPCDispatcher.cpp (original)
> +++ clang-tools-extra/trunk/clangd/JSONRPCDispatcher.cpp Mon Oct  9 09:58:16 2017
> @@ -37,6 +37,14 @@ void JSONOutput::log(const Twine &Messag
>    Logs.flush();
>  }
>
> +void JSONOutput::mirrorInput(const Twine &Message) {
> +  if (!InputMirror)
> +    return;
> +
> +  *InputMirror << Message;
> +  InputMirror->flush();
> +}
> +
>  void Handler::handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) {
>    Output.log("Method ignored.\n");
>    // Return that this method is unsupported.
> @@ -147,6 +155,14 @@ void clangd::runLanguageServerLoop(std::
>          continue;
>        }
>
> +      Out.mirrorInput(Line);
> +      // Mirror '\n' that gets consumed by std::getline, but is not included in
> +      // the resulting Line.
> +      // Note that '\r' is part of Line, so we don't need to mirror it
> +      // separately.
> +      if (!In.eof())
> +        Out.mirrorInput("\n");
> +
>        llvm::StringRef LineRef(Line);
>
>        // We allow YAML-style comments in headers. Technically this isn't part
> @@ -163,9 +179,8 @@ void clangd::runLanguageServerLoop(std::
>        if (LineRef.consume_front("Content-Length: ")) {
>          if (ContentLength != 0) {
>            Out.log("Warning: Duplicate Content-Length header received. "
> -                  "The previous value for this message ("
> -                  + std::to_string(ContentLength)
> -                  + ") was ignored.\n");
> +                  "The previous value for this message (" +
> +                  std::to_string(ContentLength) + ") was ignored.\n");
>          }
>
>          llvm::getAsUnsignedInteger(LineRef.trim(), 0, ContentLength);
> @@ -185,15 +200,13 @@ void clangd::runLanguageServerLoop(std::
>        // parser.
>        std::vector<char> JSON(ContentLength + 1, '\0');
>        In.read(JSON.data(), ContentLength);
> +      Out.mirrorInput(StringRef(JSON.data(), In.gcount()));
>
>        // If the stream is aborted before we read ContentLength bytes, In
>        // will have eofbit and failbit set.
>        if (!In) {
> -        Out.log("Input was aborted. Read only "
> -                + std::to_string(In.gcount())
> -                + " bytes of expected "
> -                + std::to_string(ContentLength)
> -                + ".\n");
> +        Out.log("Input was aborted. Read only " + std::to_string(In.gcount()) +
> +                " bytes of expected " + std::to_string(ContentLength) + ".\n");
>          break;
>        }
>
> @@ -209,8 +222,8 @@ void clangd::runLanguageServerLoop(std::
>        if (IsDone)
>          break;
>      } else {
> -      Out.log( "Warning: Missing Content-Length header, or message has zero "
> -               "length.\n" );
> +      Out.log("Warning: Missing Content-Length header, or message has zero "
> +              "length.\n");
>      }
>    }
>  }
>
> Modified: clang-tools-extra/trunk/clangd/JSONRPCDispatcher.h
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/JSONRPCDispatcher.h?rev=315214&r1=315213&r2=315214&view=diff
> ==============================================================================
> --- clang-tools-extra/trunk/clangd/JSONRPCDispatcher.h (original)
> +++ clang-tools-extra/trunk/clangd/JSONRPCDispatcher.h Mon Oct  9 09:58:16 2017
> @@ -24,8 +24,9 @@ namespace clangd {
>  /// them.
>  class JSONOutput : public Logger {
>  public:
> -  JSONOutput(llvm::raw_ostream &Outs, llvm::raw_ostream &Logs)
> -      : Outs(Outs), Logs(Logs) {}
> +  JSONOutput(llvm::raw_ostream &Outs, llvm::raw_ostream &Logs,
> +             llvm::raw_ostream *InputMirror = nullptr)
> +      : Outs(Outs), Logs(Logs), InputMirror(InputMirror) {}
>
>    /// Emit a JSONRPC message.
>    void writeMessage(const Twine &Message);
> @@ -33,9 +34,15 @@ public:
>    /// Write to the logging stream.
>    void log(const Twine &Message) override;
>
> +  /// Mirror \p Message into InputMirror stream. Does nothing if InputMirror is
> +  /// null.
> +  /// Unlike other methods of JSONOutput, mirrorInput is not thread-safe.
> +  void mirrorInput(const Twine &Message);
> +
>  private:
>    llvm::raw_ostream &Outs;
>    llvm::raw_ostream &Logs;
> +  llvm::raw_ostream *InputMirror;
>
>    std::mutex StreamMutex;
>  };
>
> Modified: clang-tools-extra/trunk/clangd/tool/ClangdMain.cpp
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/tool/ClangdMain.cpp?rev=315214&r1=315213&r2=315214&view=diff
> ==============================================================================
> --- clang-tools-extra/trunk/clangd/tool/ClangdMain.cpp (original)
> +++ clang-tools-extra/trunk/clangd/tool/ClangdMain.cpp Mon Oct  9 09:58:16 2017
> @@ -9,10 +9,12 @@
>
>  #include "ClangdLSPServer.h"
>  #include "JSONRPCDispatcher.h"
> +#include "Path.h"
>  #include "llvm/Support/CommandLine.h"
>  #include "llvm/Support/FileSystem.h"
>  #include "llvm/Support/Path.h"
>  #include "llvm/Support/Program.h"
> +#include "llvm/Support/raw_ostream.h"
>  #include <iostream>
>  #include <memory>
>  #include <string>
> @@ -43,11 +45,17 @@ static llvm::cl::opt<bool> RunSynchronou
>      llvm::cl::desc("Parse on main thread. If set, -j is ignored"),
>      llvm::cl::init(false), llvm::cl::Hidden);
>
> -static llvm::cl::opt<std::string>
> +static llvm::cl::opt<Path>
>      ResourceDir("resource-dir",
>                  llvm::cl::desc("Directory for system clang headers"),
>                  llvm::cl::init(""), llvm::cl::Hidden);
>
> +static llvm::cl::opt<Path> InputMirrorFile(
> +    "input-mirror-file",
> +    llvm::cl::desc(
> +        "Mirror all LSP input to the specified file. Useful for debugging."),
> +    llvm::cl::init(""), llvm::cl::Hidden);
> +
>  int main(int argc, char *argv[]) {
>    llvm::cl::ParseCommandLineOptions(argc, argv, "clangd");
>
> @@ -63,9 +71,21 @@ int main(int argc, char *argv[]) {
>      WorkerThreadsCount = 0;
>
>    /// Validate command line arguments.
> +  llvm::Optional<llvm::raw_fd_ostream> InputMirrorStream;
> +  if (!InputMirrorFile.empty()) {
> +    std::error_code EC;
> +    InputMirrorStream.emplace(InputMirrorFile, /*ref*/ EC, llvm::sys::fs::F_RW);
> +    if (EC) {
> +      InputMirrorStream.reset();
> +      llvm::errs() << "Error while opening an input mirror file: "
> +                   << EC.message();
> +    }
> +  }
> +
>    llvm::raw_ostream &Outs = llvm::outs();
>    llvm::raw_ostream &Logs = llvm::errs();
> -  JSONOutput Out(Outs, Logs);
> +  JSONOutput Out(Outs, Logs,
> +                 InputMirrorStream ? InputMirrorStream.getPointer() : nullptr);
>
>    // If --compile-commands-dir arg was invoked, check value and override default
>    // path.
>
> Added: clang-tools-extra/trunk/test/clangd/input-mirror.test
> URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clangd/input-mirror.test?rev=315214&view=auto
> ==============================================================================
> --- clang-tools-extra/trunk/test/clangd/input-mirror.test (added)
> +++ clang-tools-extra/trunk/test/clangd/input-mirror.test Mon Oct  9 09:58:16 2017
> @@ -0,0 +1,154 @@
> +# RUN: clangd -run-synchronously -input-mirror-file %t < %s
> +# Note that we have to use '-Z' as -input-mirror-file does not have a newline at the end of file.

"-Z" isn't supported in some versions of diff, I tested "-b" and it
seems to do the job here, can you change that?

Thanks,

> +# RUN: diff -Z %t %s
> +# It is absolutely vital that this file has CRLF line endings.
> +#
> +Content-Length: 125
> +
> +{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
> +
> +Content-Length: 172
> +
> +{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///main.cpp","languageId":"cpp","version":1,"text":"int main() {\nint a;\na;\n}\n"}}}
> +
> +Content-Length: 148
> +
> +{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":2,"character":0}}}
> +# Go to local variable
> +
> +Content-Length: 148
> +
> +{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":2,"character":1}}}
> +# Go to local variable, end of token
> +
> +Content-Length: 214
> +
> +{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":2},"contentChanges":[{"text":"struct Foo {\nint x;\n};\nint main() {\n  Foo bar = { x : 1 };\n}\n"}]}}
> +
> +Content-Length: 149
> +
> +{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":4,"character":14}}}
> +# Go to field, GNU old-style field designator
> +
> +Content-Length: 215
> +
> +{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":3},"contentChanges":[{"text":"struct Foo {\nint x;\n};\nint main() {\n  Foo baz = { .x = 2 };\n}\n"}]}}
> +
> +Content-Length: 149
> +
> +{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":4,"character":15}}}
> +# Go to field, field designator
> +
> +Content-Length: 187
> +
> +{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":4},"contentChanges":[{"text":"int main() {\n   main();\n   return 0;\n}"}]}}
> +
> +Content-Length: 148
> +
> +{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":1,"character":3}}}
> +# Go to function declaration, function call
> +
> +Content-Length: 208
> +
> +{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":5},"contentChanges":[{"text":"struct Foo {\n};\nint main() {\n   Foo bar;\n   return 0;\n}\n"}]}}
> +
> +Content-Length: 148
> +
> +{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":3,"character":3}}}
> +# Go to struct declaration, new struct instance
> +
> +Content-Length: 231
> +
> +{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":5},"contentChanges":[{"text":"namespace n1 {\nstruct Foo {\n};\n}\nint main() {\n   n1::Foo bar;\n   return 0;\n}\n"}]}}
> +
> +Content-Length: 148
> +
> +{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":5,"character":4}}}
> +# Go to struct declaration, new struct instance, qualified name
> +
> +Content-Length: 215
> +
> +{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":6},"contentChanges":[{"text":"struct Foo {\n  int x;\n};\nint main() {\n   Foo bar;\n   bar.x;\n}\n"}]}}
> +
> +Content-Length: 148
> +
> +{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":5,"character":7}}}
> +# Go to field declaration, field reference
> +
> +Content-Length: 220
> +
> +{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":7},"contentChanges":[{"text":"struct Foo {\n  void x();\n};\nint main() {\n   Foo bar;\n   bar.x();\n}\n"}]}}
> +
> +Content-Length: 148
> +
> +{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":5,"character":7}}}
> +# Go to method declaration, method call
> +
> +Content-Length: 240
> +
> +{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":7},"contentChanges":[{"text":"struct Foo {\n};\ntypedef Foo TypedefFoo;\nint main() {\n   TypedefFoo bar;\n   return 0;\n}\n"}]}}
> +
> +Content-Length: 149
> +
> +{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":4,"character":10}}}
> +# Go to typedef
> +
> +Content-Length: 254
> +
> +{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":7},"contentChanges":[{"text":"template <typename MyTemplateParam>\nvoid foo() {\n MyTemplateParam a;\n}\nint main() {\n   return 0;\n}\n"}]}}
> +
> +Content-Length: 149
> +
> +{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":2,"character":13}}}
> +# Go to template type parameter. Fails until clangIndex is modified to handle those.
> +# no-CHECK: {"jsonrpc":"2.0","id":1,"result":[{"uri": "file:///main.cpp", "range": {"start": {"line": 0, "character": 10}, "end": {"line": 0, "character": 34}}}]}
> +
> +Content-Length: 256
> +
> +{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":7},"contentChanges":[{"text":"namespace ns {\nstruct Foo {\nstatic void bar() {}\n};\n}\nint main() {\n   ns::Foo::bar();\n   return 0;\n}\n"}]}}
> +
> +Content-Length: 148
> +
> +{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":6,"character":4}}}
> +# Go to namespace, static method call
> +
> +Content-Length: 265
> +
> +{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":7},"contentChanges":[{"text":"namespace ns {\nstruct Foo {\n  int field;\n  Foo(int param) : field(param) {}\n};\n}\nint main() {\n   return 0;\n}\n"}]}}
> +
> +Content-Length: 149
> +
> +{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":3,"character":21}}}
> +# Go to field, member initializer
> +
> +Content-Length: 204
> +
> +{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":7},"contentChanges":[{"text":"#define MY_MACRO 0\nint main() {\n  return MY_MACRO;\n}\n"}]}}
> +
> +Content-Length: 148
> +
> +{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":2,"character":9}}}
> +# Go to macro.
> +
> +Content-Length: 217
> +
> +{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///main.cpp","version":7},"contentChanges":[{"text":"#define FOO 1\nint a = FOO;\n#define FOO 2\nint b = FOO;\n#undef FOO\n"}]}}
> +
> +Content-Length: 148
> +
> +{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":1,"character":8}}}
> +# Go to macro, re-defined later
> +
> +Content-Length: 148
> +
> +{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":3,"character":8}}}
> +# Go to macro, undefined later
> +
> +Content-Length: 148
> +
> +{"jsonrpc":"2.0","id":1,"method":"textDocument/definition","params":{"textDocument":{"uri":"file:///main.cpp"},"position":{"line":4,"character":7}}}
> +# Go to macro, being undefined
> +
> +Content-Length: 44
> +
> +{"jsonrpc":"2.0","id":3,"method":"shutdown"}
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits



-- 
Bruno Cardoso Lopes
http://www.brunocardoso.cc


More information about the cfe-commits mailing list