[PATCH] D29990: [clangd] Implement format on type
This revision was automatically updated to reflect the committed changes. Closed by commit rL295304: [clangd] Implement format on type (authored by krasimir). Changed prior to commit: https://reviews.llvm.org/D29990?vs=88703=88708#toc Repository: rL LLVM https://reviews.llvm.org/D29990 Files: clang-tools-extra/trunk/clangd/ClangDMain.cpp clang-tools-extra/trunk/clangd/Protocol.cpp clang-tools-extra/trunk/clangd/Protocol.h clang-tools-extra/trunk/clangd/ProtocolHandlers.cpp clang-tools-extra/trunk/clangd/ProtocolHandlers.h clang-tools-extra/trunk/test/clangd/formatting.test Index: clang-tools-extra/trunk/test/clangd/formatting.test === --- clang-tools-extra/trunk/test/clangd/formatting.test +++ clang-tools-extra/trunk/test/clangd/formatting.test @@ -4,11 +4,12 @@ Content-Length: 125 {"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} -# CHECK: Content-Length: 191 +# CHECK: Content-Length: 294 # CHECK: {"jsonrpc":"2.0","id":0,"result":{"capabilities":{ # CHECK: "textDocumentSync": 1, # CHECK: "documentFormattingProvider": true, -# CHECK: "documentRangeFormattingProvider": true +# CHECK: "documentRangeFormattingProvider": true, +# CHECK: "documentOnTypeFormattingProvider": {"firstTriggerCharacter":"}","moreTriggerCharacter":[]} # CHECK: }}} # Content-Length: 193 @@ -48,6 +49,17 @@ {"jsonrpc":"2.0","id":4,"method":"textDocument/formatting","params":{"textDocument":{"uri":"file:///foo.c"},"options":{"tabSize":4,"insertSpaces":true}}} # CHECK: {"jsonrpc":"2.0","id":4,"result":[]} # +Content-Length: 193 + +{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///foo.c","version":5},"contentChanges":[{"text":"int foo ( int x ) {\n x = x + 1;\n return x;\n}"}]}} +# +# +Content-Length: 204 + +{"jsonrpc":"2.0","id":5,"method":"textDocument/onTypeFormatting","params":{"textDocument":{"uri":"file:///foo.c"},"position":{"line":3,"character":1},"ch":"}","options":{"tabSize":4,"insertSpaces":true}}} +# CHECK: {"jsonrpc":"2.0","id":5,"result":[{"range": {"start": {"line": 0, "character": 7}, "end": {"line": 0, "character": 8}}, "newText": ""},{"range": {"start": {"line": 0, "character": 9}, "end": {"line": 0, "character": 10}}, "newText": ""},{"range": {"start": {"line": 0, "character": 15}, "end": {"line": 0, "character": 16}}, "newText": ""}]} +# + Content-Length: 44 -{"jsonrpc":"2.0","id":5,"method":"shutdown"} +{"jsonrpc":"2.0","id":6,"method":"shutdown"} Index: clang-tools-extra/trunk/clangd/ClangDMain.cpp === --- clang-tools-extra/trunk/clangd/ClangDMain.cpp +++ clang-tools-extra/trunk/clangd/ClangDMain.cpp @@ -47,6 +47,9 @@ "textDocument/rangeFormatting", llvm::make_unique(Out, Store)); Dispatcher.registerHandler( + "textDocument/onTypeFormatting", + llvm::make_unique(Out, Store)); + Dispatcher.registerHandler( "textDocument/formatting", llvm::make_unique(Out, Store)); Index: clang-tools-extra/trunk/clangd/ProtocolHandlers.h === --- clang-tools-extra/trunk/clangd/ProtocolHandlers.h +++ clang-tools-extra/trunk/clangd/ProtocolHandlers.h @@ -33,7 +33,8 @@ R"(,"result":{"capabilities":{ "textDocumentSync": 1, "documentFormattingProvider": true, - "documentRangeFormattingProvider": true + "documentRangeFormattingProvider": true, + "documentOnTypeFormattingProvider": {"firstTriggerCharacter":"}","moreTriggerCharacter":[]} }}})"); } }; @@ -71,6 +72,16 @@ DocumentStore }; +struct TextDocumentOnTypeFormattingHandler : Handler { + TextDocumentOnTypeFormattingHandler(JSONOutput , DocumentStore ) + : Handler(Output), Store(Store) {} + + void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override; + +private: + DocumentStore +}; + struct TextDocumentRangeFormattingHandler : Handler { TextDocumentRangeFormattingHandler(JSONOutput , DocumentStore ) : Handler(Output), Store(Store) {} Index: clang-tools-extra/trunk/clangd/Protocol.h === --- clang-tools-extra/trunk/clangd/Protocol.h +++ clang-tools-extra/trunk/clangd/Protocol.h @@ -144,6 +144,23 @@ parse(llvm::yaml::MappingNode *Params); }; +struct DocumentOnTypeFormattingParams { + /// The document to format. + TextDocumentIdentifier textDocument; + + /// The position at which this request was sent. + Position position; + + /// The character that has been typed. + std::string ch; + + /// The format options. + FormattingOptions options; + + static llvm::Optional + parse(llvm::yaml::MappingNode *Params); +}; + struct DocumentFormattingParams { /// The document to format. TextDocumentIdentifier
[PATCH] D29990: [clangd] Implement format on type
bkramer accepted this revision. bkramer added a comment. This revision is now accepted and ready to land. lg https://reviews.llvm.org/D29990 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D29990: [clangd] Implement format on type
krasimir updated this revision to Diff 88703. krasimir edited the summary of this revision. krasimir added a comment. - Address review comments https://reviews.llvm.org/D29990 Files: clangd/ClangDMain.cpp clangd/Protocol.cpp clangd/Protocol.h clangd/ProtocolHandlers.cpp clangd/ProtocolHandlers.h test/clangd/formatting.test Index: test/clangd/formatting.test === --- test/clangd/formatting.test +++ test/clangd/formatting.test @@ -4,11 +4,12 @@ Content-Length: 125 {"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}} -# CHECK: Content-Length: 191 +# CHECK: Content-Length: 294 # CHECK: {"jsonrpc":"2.0","id":0,"result":{"capabilities":{ # CHECK: "textDocumentSync": 1, # CHECK: "documentFormattingProvider": true, -# CHECK: "documentRangeFormattingProvider": true +# CHECK: "documentRangeFormattingProvider": true, +# CHECK: "documentOnTypeFormattingProvider": {"firstTriggerCharacter":"}","moreTriggerCharacter":[]} # CHECK: }}} # Content-Length: 193 @@ -48,6 +49,17 @@ {"jsonrpc":"2.0","id":4,"method":"textDocument/formatting","params":{"textDocument":{"uri":"file:///foo.c"},"options":{"tabSize":4,"insertSpaces":true}}} # CHECK: {"jsonrpc":"2.0","id":4,"result":[]} # +Content-Length: 193 + +{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///foo.c","version":5},"contentChanges":[{"text":"int foo ( int x ) {\n x = x + 1;\n return x;\n}"}]}} +# +# +Content-Length: 204 + +{"jsonrpc":"2.0","id":5,"method":"textDocument/onTypeFormatting","params":{"textDocument":{"uri":"file:///foo.c"},"position":{"line":3,"character":1},"ch":"}","options":{"tabSize":4,"insertSpaces":true}}} +# CHECK: {"jsonrpc":"2.0","id":5,"result":[{"range": {"start": {"line": 0, "character": 7}, "end": {"line": 0, "character": 8}}, "newText": ""},{"range": {"start": {"line": 0, "character": 9}, "end": {"line": 0, "character": 10}}, "newText": ""},{"range": {"start": {"line": 0, "character": 15}, "end": {"line": 0, "character": 16}}, "newText": ""}]} +# + Content-Length: 44 -{"jsonrpc":"2.0","id":5,"method":"shutdown"} +{"jsonrpc":"2.0","id":6,"method":"shutdown"} Index: clangd/ProtocolHandlers.h === --- clangd/ProtocolHandlers.h +++ clangd/ProtocolHandlers.h @@ -33,7 +33,8 @@ R"(,"result":{"capabilities":{ "textDocumentSync": 1, "documentFormattingProvider": true, - "documentRangeFormattingProvider": true + "documentRangeFormattingProvider": true, + "documentOnTypeFormattingProvider": {"firstTriggerCharacter":"}","moreTriggerCharacter":[]} }}})"); } }; @@ -71,6 +72,16 @@ DocumentStore }; +struct TextDocumentOnTypeFormattingHandler : Handler { + TextDocumentOnTypeFormattingHandler(JSONOutput , DocumentStore ) + : Handler(Output), Store(Store) {} + + void handleMethod(llvm::yaml::MappingNode *Params, StringRef ID) override; + +private: + DocumentStore +}; + struct TextDocumentRangeFormattingHandler : Handler { TextDocumentRangeFormattingHandler(JSONOutput , DocumentStore ) : Handler(Output), Store(Store) {} Index: clangd/ProtocolHandlers.cpp === --- clangd/ProtocolHandlers.cpp +++ clangd/ProtocolHandlers.cpp @@ -104,6 +104,27 @@ {clang::tooling::Range(Begin, Len)}, ID)); } +void TextDocumentOnTypeFormattingHandler::handleMethod( +llvm::yaml::MappingNode *Params, StringRef ID) { + auto DOTFP = DocumentOnTypeFormattingParams::parse(Params); + if (!DOTFP) { +Output.logs() << "Failed to decode DocumentOnTypeFormattingParams!\n"; +return; + } + + // Look for the previous opening brace from the character position and format + // starting from there. + std::string Code = Store.getDocument(DOTFP->textDocument.uri); + size_t CursorPos = positionToOffset(Code, DOTFP->position); + size_t PreviousLBracePos = StringRef(Code).find_last_of('{', CursorPos); + if (PreviousLBracePos == StringRef::npos) +PreviousLBracePos = CursorPos; + size_t Len = 1 + CursorPos - PreviousLBracePos; + + writeMessage(formatCode(Code, DOTFP->textDocument.uri, + {clang::tooling::Range(PreviousLBracePos, Len)}, ID)); +} + void TextDocumentFormattingHandler::handleMethod( llvm::yaml::MappingNode *Params, StringRef ID) { auto DFP = DocumentFormattingParams::parse(Params); Index: clangd/Protocol.h === --- clangd/Protocol.h +++ clangd/Protocol.h @@ -144,6 +144,23 @@ parse(llvm::yaml::MappingNode *Params); }; +struct DocumentOnTypeFormattingParams { + /// The document to format. + TextDocumentIdentifier textDocument; + + /// The position at which this request was sent. + Position position; + +
[PATCH] D29990: [clangd] Implement format on type
bkramer added inline comments. Comment at: clangd/ProtocolHandlers.cpp:117 + // starting from there. + StringRef Code = Store.getDocument(DOTFP->textDocument.uri); + size_t CursorPos = positionToOffset(Code, DOTFP->position); This should be a std::string in trunk, StringRef gives you a use after free. Comment at: clangd/ProtocolHandlers.cpp:119 + size_t CursorPos = positionToOffset(Code, DOTFP->position); + size_t PreviousLBracePos = Code.find_last_of("{", CursorPos); + if (PreviousLBracePos == StringRef::npos) nit: use the character overload of this function (`Code.find_last_of('{'...`) https://reviews.llvm.org/D29990 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits