From 1b943fcab25d6d1e3002304238755348e20746a8 Mon Sep 17 00:00:00 2001 From: Hackerpilot Date: Mon, 2 Sep 2013 22:55:05 -0700 Subject: [PATCH 1/6] Update server.d Fix #31 --- server.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server.d b/server.d index 3bdbc01..689dcbf 100644 --- a/server.d +++ b/server.d @@ -63,7 +63,7 @@ int main(string[] args) auto socket = new TcpSocket(AddressFamily.INET); socket.blocking = true; socket.setOption(SocketOptionLevel.SOCKET, SocketOption.REUSEADDR, true); - socket.bind(new InternetAddress("127.0.0.1", port)); + socket.bind(new InternetAddress("localhost", port)); socket.listen(0); scope (exit) { From 0de3d52c9b5df8b18efe0e72cba7eaa1c473265b Mon Sep 17 00:00:00 2001 From: Hackerpilot Date: Tue, 3 Sep 2013 13:42:25 -0700 Subject: [PATCH 2/6] Update client.d Moved socket operations out to their own functions where they should have been from the beginning. Changed "127.0.0.1" to "localhost" to make DCD work on certain Windows configurations. --- client.d | 82 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 43 insertions(+), 39 deletions(-) diff --git a/client.d b/client.d index fe6cd1f..1280b10 100644 --- a/client.d +++ b/client.d @@ -100,34 +100,18 @@ int /*_*/main(string[] args) request.kind = RequestKind.shutdown; else if (clearCache) request.kind = RequestKind.clearCache; - auto socket = new TcpSocket(AddressFamily.INET); + TcpSocket socket = createSocket(port); scope (exit) { socket.shutdown(SocketShutdown.BOTH); socket.close(); } - socket.connect(new InternetAddress("127.0.0.1", port)); - socket.blocking = true; - socket.setOption(SocketOptionLevel.TCP, SocketOption.TCP_NODELAY, 1); - ubyte[] message = msgpack.pack(request); - ubyte[] messageBuffer = new ubyte[message.length + message.length.sizeof]; - auto messageLength = message.length; - messageBuffer[0 .. size_t.sizeof] = (cast(ubyte*) &messageLength)[0 .. size_t.sizeof]; - messageBuffer[size_t.sizeof .. $] = message[]; - return socket.send(messageBuffer) == messageBuffer.length ? 0 : 1; + return sendRequest(socket, request) ? 0 : 1; } else if (importPaths.length > 0) { AutocompleteRequest request; request.kind = RequestKind.addImport; request.importPaths = importPaths.map!(a => isRooted(a) ? a : absolutePath(a)).array; - auto socket = new TcpSocket(AddressFamily.INET); + TcpSocket socket = createSocket(port); scope (exit) { socket.shutdown(SocketShutdown.BOTH); socket.close(); } - socket.connect(new InternetAddress("127.0.0.1", port)); - socket.blocking = true; - socket.setOption(SocketOptionLevel.TCP, SocketOption.TCP_NODELAY, 1); - ubyte[] message = msgpack.pack(request); - ubyte[] messageBuffer = new ubyte[message.length + message.length.sizeof]; - auto messageLength = message.length; - messageBuffer[0 .. size_t.sizeof] = (cast(ubyte*) &messageLength)[0 .. size_t.sizeof]; - messageBuffer[size_t.sizeof .. $] = message[]; - return socket.send(messageBuffer) == messageBuffer.length ? 0 : 1; + return sendRequest(socket, request) ? 0 : 1; } else if (cursorPos == size_t.max) { @@ -169,30 +153,14 @@ int /*_*/main(string[] args) request.importPaths = importPaths; request.sourceCode = sourceCode; request.cursorPosition = cursorPos; - ubyte[] message = msgpack.pack(request); // Send message to server - TcpSocket socket = new TcpSocket(AddressFamily.INET); - socket.setOption(SocketOptionLevel.SOCKET, SocketOption.RCVTIMEO, dur!"seconds"(5)); + TcpSocket socket = createSocket(port); scope (exit) { socket.shutdown(SocketShutdown.BOTH); socket.close(); } - socket.connect(new InternetAddress("127.0.0.1", port)); - socket.blocking = true; - ubyte[] messageBuffer = new ubyte[message.length + message.length.sizeof]; - auto messageLength = message.length; - messageBuffer[0 .. size_t.sizeof] = (cast(ubyte*) &messageLength)[0 .. size_t.sizeof]; - messageBuffer[size_t.sizeof .. $] = message[]; - auto bytesSent = socket.send(messageBuffer); - - // Get response and write it out - ubyte[1024 * 16] buffer; - auto bytesReceived = socket.receive(buffer); - if (bytesReceived == Socket.ERROR) - { + if (!sendRequest(socket, request)) return 1; - } - AutocompleteResponse response; - msgpack.unpack(buffer[0..bytesReceived], response); + AutocompleteResponse response = getResponse(socket); if (response.completions.length > 0) { @@ -249,3 +217,39 @@ Options: Uses PORTNUMBER to communicate with the server instead of the default port 9166.`, programName); } + +TcpSocket createSocket(ushort port) +{ + TcpSocket socket = new TcpSocket(AddressFamily.INET); + socket.setOption(SocketOptionLevel.SOCKET, SocketOption.RCVTIMEO, dur!"seconds"(5)); + socket.connect(new InternetAddress("localhost", port)); + socket.blocking = true; + return socket; +} + +/** + * Returns: true on success + */ +bool sendRequest(TcpSocket socket, AutocompleteRequest request) +{ + ubyte[] message = msgpack.pack(request); + ubyte[] messageBuffer = new ubyte[message.length + message.length.sizeof]; + auto messageLength = message.length; + messageBuffer[0 .. size_t.sizeof] = (cast(ubyte*) &messageLength)[0 .. size_t.sizeof]; + messageBuffer[size_t.sizeof .. $] = message[]; + return socket.send(messageBuffer) == messageBuffer.length; +} + +/** + * Gets the response from the server + */ +AutocompleteResponse getResponse(TcpSocket socket) +{ + ubyte[1024 * 16] buffer; + auto bytesReceived = socket.receive(buffer); + if (bytesReceived == Socket.ERROR) + throw new Exception("Incorrect number of bytes received"); + AutocompleteResponse response; + msgpack.unpack(buffer[0..bytesReceived], response); + return response; +} From 17c2c3e5fb7b16e71ad0010d0f31578d5ddd5435 Mon Sep 17 00:00:00 2001 From: Hackerpilot Date: Tue, 3 Sep 2013 13:46:44 -0700 Subject: [PATCH 3/6] Update dcd.lua "wb" on Windows, "w" everywhere else (Otherwise the CRLF goblins will eat you) --- editors/textadept/modules/dmd/dcd.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/editors/textadept/modules/dmd/dcd.lua b/editors/textadept/modules/dmd/dcd.lua index 3ed6f29..77f15b9 100644 --- a/editors/textadept/modules/dmd/dcd.lua +++ b/editors/textadept/modules/dmd/dcd.lua @@ -111,7 +111,11 @@ function M.autocomplete(ch) if buffer:get_lexer() ~= "dmd" then return end local fileName = os.tmpname() local command = M.PATH_TO_DCD_CLIENT .. " -c" .. buffer.current_pos .. " > " .. fileName - local p = io.popen(command, "wb") + local mode = "w" + if _G.WIN32 then + mode = "wb" + end + local p = io.popen(command, mode) p:write(buffer:get_text()) p:flush() p:close() From b28590234d6aa44fc00ba65bb2ff7e2d5af027cb Mon Sep 17 00:00:00 2001 From: Hackerpilot Date: Tue, 3 Sep 2013 13:56:57 -0700 Subject: [PATCH 4/6] Don't rely on unimplement toString, use Formatter instead --- acvisitor.d | 22 ++++++++++++++++------ build.bat | 2 +- build.sh | 2 +- dscanner | 2 +- 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/acvisitor.d b/acvisitor.d index 95c7331..1cf90e6 100644 --- a/acvisitor.d +++ b/acvisitor.d @@ -257,7 +257,7 @@ class AutocompleteVisitor : ASTVisitor if (dec.parameters !is null && parentSymbol !is null) { symbol.calltip = format("%s this%s", parentSymbol.name, - dec.parameters.toString()); + formatNode(dec.parameters)); } auto p = parentSymbol; parentSymbol = symbol; @@ -318,7 +318,7 @@ class AutocompleteVisitor : ASTVisitor { string returnType; if (dec.returnType !is null) - returnType = dec.returnType.toString(); + returnType = formatNode(dec.returnType); else { if (dec.hasAuto) @@ -331,7 +331,7 @@ class AutocompleteVisitor : ASTVisitor returnType = "ref"; } symbol.calltip = format("%s %s%s", returnType, - dec.name.value, dec.parameters.toString()); + dec.name.value, formatNode(dec.parameters)); } auto p = parentSymbol; parentSymbol = symbol; @@ -378,7 +378,7 @@ class AutocompleteVisitor : ASTVisitor dec.type.typeSuffixes = dec.type.typeSuffixes[0 .. $ - 1]; symbol.calltip = "%s %s%s".format(dec.type, suffix.delegateOrFunction.value, - suffix.parameters.toString()); + formatNode(suffix.parameters)); } symbol.kind = CompletionKind.variableName; @@ -409,7 +409,7 @@ class AutocompleteVisitor : ASTVisitor aliasPart.type.typeSuffixes = aliasPart.type.typeSuffixes[0 .. $ - 1]; aliasSymbol.calltip = "%s %s%s".format(dec.type, suffix.delegateOrFunction.value, - suffix.parameters.toString()); + formatNode(suffix.parameters)); } if (parentSymbol is null) symbols ~= aliasSymbol; @@ -431,7 +431,7 @@ class AutocompleteVisitor : ASTVisitor dec.type.typeSuffixes = dec.type.typeSuffixes[0 .. $ - 1]; aliasSymbol.calltip = "%s %s%s".format(dec.type, suffix.delegateOrFunction.value, - suffix.parameters.toString()); + formatNode(suffix.parameters)); } aliasSymbol.location = dec.name.startIndex; if (parentSymbol is null) @@ -509,6 +509,16 @@ class AutocompleteVisitor : ASTVisitor bool currentFile = false; private: + + static string formatNode(T)(T node) + { + import formatter; + auto app = appender!(char[])(); + auto f = new Formatter!(typeof(app))(app); + f.format(node); + return app.data.idup; + } + static enum string visitAndAdd = q{ auto p = parentSymbol; parentSymbol = symbol; diff --git a/build.bat b/build.bat index e47abc3..35660b9 100644 --- a/build.bat +++ b/build.bat @@ -1,2 +1,2 @@ dmd -wi client.d messages.d msgpack-d/src/msgpack.d -Imsgpack-d/src -ofdcd-client -L/exet:nt/su:windows:4.0 -dmd -wi -g server.d modulecache.d actypes.d messages.d constants.d acvisitor.d autocomplete.d dscanner/stdx/d/ast.d dscanner/stdx/d/parser.d dscanner/stdx/d/lexer.d dscanner/stdx/d/entities.d msgpack-d/src/msgpack.d -Imsgpack-d/src -Idscanner/ -ofdcd-server +dmd -wi -g server.d modulecache.d actypes.d messages.d constants.d acvisitor.d autocomplete.d dscanner/stdx/d/ast.d dscanner/stdx/d/parser.d dscanner/stdx/d/lexer.d dscanner/stdx/d/entities.d dscanner/formatter.d msgpack-d/src/msgpack.d -Imsgpack-d/src -Idscanner/ -ofdcd-server diff --git a/build.sh b/build.sh index da57e14..67ca672 100755 --- a/build.sh +++ b/build.sh @@ -1,2 +1,2 @@ dmd -wi client.d messages.d msgpack-d/src/msgpack.d -Imsgpack-d/src -ofdcd-client -dmd -wi -g server.d modulecache.d actypes.d messages.d constants.d acvisitor.d autocomplete.d dscanner/stdx/d/ast.d dscanner/stdx/d/parser.d dscanner/stdx/d/lexer.d dscanner/stdx/d/entities.d msgpack-d/src/msgpack.d -Imsgpack-d/src -Idscanner/ -ofdcd-server +dmd -wi -g server.d modulecache.d actypes.d messages.d constants.d acvisitor.d autocomplete.d dscanner/stdx/d/ast.d dscanner/stdx/d/parser.d dscanner/stdx/d/lexer.d dscanner/stdx/d/entities.d dscanner/formatter.d msgpack-d/src/msgpack.d -Imsgpack-d/src -Idscanner/ -ofdcd-server diff --git a/dscanner b/dscanner index 2088089..80c2462 160000 --- a/dscanner +++ b/dscanner @@ -1 +1 @@ -Subproject commit 2088089e368e5621673bf83472e441b28c43c81a +Subproject commit 80c2462445a937eaf339890edf4282c4e6878d08 From 35b890e6578183a78021a81ee9e6d8f1aa6de415 Mon Sep 17 00:00:00 2001 From: Hackerpilot Date: Tue, 3 Sep 2013 15:26:39 -0700 Subject: [PATCH 5/6] Fix #9 --- client.d | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/client.d b/client.d index 1280b10..c60c0b6 100644 --- a/client.d +++ b/client.d @@ -27,6 +27,7 @@ import std.algorithm; import std.path; import std.file; import std.conv; +import std.string; //version(Windows) //{ // import core.runtime; @@ -86,6 +87,7 @@ int /*_*/main(string[] args) catch (Exception e) { stderr.writeln(e.msg); + return 1; } if (help) @@ -165,20 +167,22 @@ int /*_*/main(string[] args) if (response.completions.length > 0) { writeln(response.completionType); + auto app = appender!(string[])(); if (response.completionType == CompletionType.identifiers) { for (size_t i = 0; i < response.completions.length; i++) - { - writefln("%s\t%s", response.completions[i], response.completionKinds[i]); - } + app.put(format("%s\t%s", response.completions[i], response.completionKinds[i])); } else { foreach (completion; response.completions) { - writeln(completion); + app.put(completion); } } + // Deduplicate overloaded methods + foreach (line; app.data.sort.uniq) + writeln(line); } return 0; } From 6a7827a2960a9177af6cbae7fb959e76805e4b21 Mon Sep 17 00:00:00 2001 From: Hackerpilot Date: Tue, 3 Sep 2013 16:55:28 -0700 Subject: [PATCH 6/6] Fixed display of identifier lists after a left paren --- editors/textadept/modules/dmd/dcd.lua | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/editors/textadept/modules/dmd/dcd.lua b/editors/textadept/modules/dmd/dcd.lua index 77f15b9..2b62d77 100644 --- a/editors/textadept/modules/dmd/dcd.lua +++ b/editors/textadept/modules/dmd/dcd.lua @@ -58,8 +58,10 @@ local function showCompletionList(r) end table.sort(completions, function(a, b) return string.upper(a) < string.upper(b) end) local charactersEntered = buffer.current_pos - buffer:word_start_position(buffer.current_pos) - if buffer.char_at[buffer.current_pos - 1] == string.byte('.') then charactersEntered = 0 end - print(charactersEntered) + if buffer.char_at[buffer.current_pos - 1] == string.byte('.') + or buffer.char_at[buffer.current_pos - 1] == string.byte('(') then + charactersEntered = 0 + end buffer:auto_c_show(charactersEntered, table.concat(completions, " ")) --buffer.auto_c_fill_ups = "(.[" buffer.auto_c_choose_single = setting @@ -121,7 +123,6 @@ function M.autocomplete(ch) p:close() local tmpFile = io.open(fileName, "r") local r = tmpFile:read("*a") - print(r) if r ~= "\n" then if r:match("^identifiers.*") then showCompletionList(r)