diff --git a/dlangide-monod-linux.dproj b/dlangide-monod-linux.dproj index 03c5274..31c3989 100644 --- a/dlangide-monod-linux.dproj +++ b/dlangide-monod-linux.dproj @@ -199,7 +199,6 @@ - @@ -231,4 +230,4 @@ - \ No newline at end of file + diff --git a/dlangide-monod-osx.dproj b/dlangide-monod-osx.dproj index 753e7e6..670bf91 100644 --- a/dlangide-monod-osx.dproj +++ b/dlangide-monod-osx.dproj @@ -126,7 +126,6 @@ - @@ -148,4 +147,4 @@ - \ No newline at end of file + diff --git a/dlangide_msvc.visualdproj b/dlangide_msvc.visualdproj index 238f2fc..b07be13 100644 --- a/dlangide_msvc.visualdproj +++ b/dlangide_msvc.visualdproj @@ -444,7 +444,6 @@ - diff --git a/dub.json b/dub.json index 784eafe..3929dac 100644 --- a/dub.json +++ b/dub.json @@ -11,11 +11,9 @@ "stringImportPaths": ["views", "views/res", "views/res/i18n", "views/res/mdpi", "views/res/hdpi"], - "copyFiles-windows": ["lib/win32/dcd-server.exe", "lib/win32/dcd-client.exe"], - "dependencies": { - "dlangui": "~>0.7.30", - "libdparse": "==0.2.0" + "dlangui": "~>0.7.31", + "dcd": "~>0.7.4" }, "versions": ["EmbedStandardResources"], diff --git a/lib/win32/dcd-client.exe b/lib/win32/dcd-client.exe deleted file mode 100644 index de1e75a..0000000 Binary files a/lib/win32/dcd-client.exe and /dev/null differ diff --git a/lib/win32/dcd-server.exe b/lib/win32/dcd-server.exe deleted file mode 100644 index 1188a98..0000000 Binary files a/lib/win32/dcd-server.exe and /dev/null differ diff --git a/src/dlangide/tools/d/dcdinterface.d b/src/dlangide/tools/d/dcdinterface.d index 9677f75..25daae2 100644 --- a/src/dlangide/tools/d/dcdinterface.d +++ b/src/dlangide/tools/d/dcdinterface.d @@ -3,36 +3,26 @@ module dlangide.tools.d.dcdinterface; import dlangui.core.logger; import dlangui.core.files; -import dlangide.builders.extprocess; - import std.typecons; import std.conv; import std.string; -const DCD_SERVER_PORT_FOR_DLANGIDE = 9167; -const DCD_DEFAULT_PORT = 9166; - enum DCDResult : int { - DCD_NOT_RUNNING = 0, SUCCESS, NO_RESULT, FAIL, } + +alias FindDeclarationResultSet = Tuple!(DCDResult, "result", string, "fileName", ulong, "offset"); alias ResultSet = Tuple!(DCDResult, "result", dstring[], "output"); //Interface to DCD -//TODO: Check if server is running, start server if needed etc. class DCDInterface { + import server.autocomplete; + import common.messages; - private int _port; - //ExternalProcess dcdProcess; - //ProtectedTextStorage stdoutTarget; - this(int port = DCD_SERVER_PORT_FOR_DLANGIDE) { - _port = port; - //dcdProcess = new ExternalProcess(); - //stdoutTarget = new ProtectedTextStorage(); - } + import dsymbol.modulecache; protected string dumpContext(string content, int pos) { if (pos >= 0 && pos <= content.length) { @@ -47,137 +37,59 @@ class DCDInterface { return ""; } - protected dstring[] invokeDcd(string[] arguments, string content, out bool success) { - success = false; - ExternalProcess dcdProcess = new ExternalProcess(); - - ProtectedTextStorage stdoutTarget = new ProtectedTextStorage(); - - version(Windows) { - string dcd_client_name = "dcd-client.exe"; - string dcd_client_dir = null; - } else { - string dcd_client_name = "dcd-client"; - string dcd_client_dir = "/usr/bin"; - } - dcdProcess.run(dcd_client_name, arguments, dcd_client_dir, stdoutTarget); - - dcdProcess.write(content); - dcdProcess.wait(); - - dstring[] output = stdoutTarget.readText.splitLines(); - - if(dcdProcess.poll() == ExternalProcessState.Stopped) { - success = true; - } - return output; - } - - ResultSet goToDefinition(in string[] importPaths, in string filename, in string content, int index) { - ResultSet result; + FindDeclarationResultSet goToDefinition(in string[] importPaths, in string filename, in string content, int index, ref ModuleCache moduleCache) { version(USE_LIBDPARSE) { import dlangide.tools.d.dparser; DParsingService.instance.addImportPaths(importPaths); DParsedModule m = DParsingService.instance.findDeclaration(cast(ubyte[])content, filename, index); } - debug(DCD) Log.d("DCD Context: ", dumpContext(content, index)); + + AutocompleteRequest request; + request.sourceCode = cast(ubyte[])content; + request.fileName = filename; + request.cursorPosition = index; - string[] arguments = ["-l", "-c"]; - arguments ~= [to!string(index)]; + AutocompleteResponse response = findDeclaration(request,moduleCache); + + FindDeclarationResultSet result; + result.fileName = response.symbolFilePath; + result.offset = response.symbolLocation; + result.result = DCDResult.SUCCESS; - foreach(p; importPaths) { - arguments ~= "-I" ~ p; - } - if (_port != DCD_DEFAULT_PORT) - arguments ~= "-p" ~ to!string(_port); + debug(DCD) Log.d("DCD fileName:\n", result.fileName); - bool success = false; - dstring[] output = invokeDcd(arguments, content, success); - - if (success) { - result.result = DCDResult.SUCCESS; - } else { - result.result = DCDResult.FAIL; - return result; - } - - debug(DCD) Log.d("DCD output:\n", output); - - if(output.length > 0) { - dstring firstLine = output[0]; - if(firstLine.startsWith("Not Found") || firstLine.startsWith("Not found")) { - result.result = DCDResult.NO_RESULT; - return result; - } - auto split = firstLine.indexOf("\t"); - if(split == -1) { - Log.d("DCD output format error."); - result.result = DCDResult.FAIL; - return result; - } - - result.output ~= output[0][0 .. split]; - result.output ~= output[0][split+1 .. $]; - } else { + if (result.fileName is null) { result.result = DCDResult.NO_RESULT; - //result.result = DCDResult.FAIL; } - return result; } - ResultSet getCompletions(in string[] importPaths, in string filename, in string content, int index) { + ResultSet getCompletions(in string[] importPaths, in string filename, in string content, int index, ref ModuleCache moduleCache) { debug(DCD) Log.d("DCD Context: ", dumpContext(content, index)); ResultSet result; - - string[] arguments = ["-c"]; - arguments ~= [to!string(index)]; - - foreach(p; importPaths) { - arguments ~= "-I" ~ p; - } - if (_port != DCD_DEFAULT_PORT) - arguments ~= "-p" ~ to!string(_port); - - bool success = false; - dstring[] output = invokeDcd(arguments, content, success); - - if (success) { - result.result = DCDResult.SUCCESS; - } else { - result.result = DCDResult.FAIL; - return result; - } - debug(DCD) Log.d("DCD output:\n", output); - - if (output.length == 0) { + AutocompleteRequest request; + request.sourceCode = cast(ubyte[])content; + request.fileName = filename; + request.cursorPosition = index; + + AutocompleteResponse response = complete(request,moduleCache); + if(response.completions is null || response.completions.length == 0){ result.result = DCDResult.NO_RESULT; return result; } - enum State : int {None = 0, Identifiers, Calltips} - State state = State.None; - foreach(dstring outputLine ; output) { - if(outputLine == "identifiers") { - state = State.Identifiers; - } - else if(outputLine == "calltips") { - state = State.Calltips; - } - else { - auto split = outputLine.indexOf("\t"); - if(split < 0) { - break; - } - if(state == State.Identifiers) { - result.output ~= outputLine[0 .. split]; - } - } + result.result = DCDResult.SUCCESS; + result.output.length = response.completions.length; + int i=0; + foreach(s;response.completions){ + result.output[i++]=to!dstring(s); } + debug(DCD) Log.d("DCD output:\n", response.completions); + return result; } } diff --git a/src/dlangide/tools/d/dcdserver.d b/src/dlangide/tools/d/dcdserver.d deleted file mode 100644 index a510f90..0000000 --- a/src/dlangide/tools/d/dcdserver.d +++ /dev/null @@ -1,91 +0,0 @@ -module dlangide.tools.d.dcdserver; - -import dlangui.core.logger; -import dlangui.core.files; -import dlangide.builders.extprocess; -import dlangide.workspace.project; -import std.conv : to; -import dlangide.tools.d.dcdinterface; - - -/// encapsulates running DCD server access -class DCDServer { - private ExternalProcess dcdProcess; - private ProtectedTextStorage stdoutTarget; - private int _port; - private bool _running; - private bool _error; - - /// port to connect to DCD - @property int port() { - return _port; - } - this(int port = DCD_SERVER_PORT_FOR_DLANGIDE) { - _port = port; - } - /// returns true if there was error while trying to run server last time - @property bool isError() { - return _error; - } - /// returns true if server seems running - @property bool isRunning() { - return _running; - } - /// start DCD server - bool start() { - if (dcdProcess || stdoutTarget) { - Log.e("Already started"); - return false; - } - _error = false; - _running = false; - string dcdServerExecutable = findExecutablePath("dcd-server"); - if (!dcdServerExecutable) { - Log.e("dcd-server executable is not found"); - _error = true; - return false; - } - - string[] srcPaths = dmdSourcePaths(); - string[] arguments; - foreach(p; srcPaths) - arguments ~= "-I" ~ p; - if (_port != DCD_DEFAULT_PORT) - arguments ~= "-p" ~ to!string(_port); - Log.i("starting dcd-server: executable path is ", dcdServerExecutable, " args: ", arguments); - dcdProcess = new ExternalProcess(); - stdoutTarget = new ProtectedTextStorage(); - ExternalProcessState state = dcdProcess.run(dcdServerExecutable, arguments, null, stdoutTarget); - if (state != ExternalProcessState.Running) { - Log.e("Error while starting DCD: process state reported is ", state); - _error = true; - dcdProcess.kill(); - dcdProcess.wait(); - destroy(dcdProcess); - dcdProcess = null; - stdoutTarget = null; - return false; - } - Log.i("DCD server is started successfully"); - _running = true; - return true; - } - - /// stop DCD server - bool stop() { - if (!dcdProcess) { - Log.e("Cannot stop DCD server - it's not started"); - return false; - } - debug(DCD) Log.i("Current DCD server state: ", dcdProcess.poll()); - Log.i("Stopping DCD server"); - ExternalProcessState state = dcdProcess.kill(); - state = dcdProcess.wait(); - debug(DCD) Log.i("DCD server state: ", state); - destroy(dcdProcess); - dcdProcess = null; - stdoutTarget = null; - _running = false; - return true; - } -} diff --git a/src/dlangide/tools/d/deditortool.d b/src/dlangide/tools/d/deditortool.d index 0e4d1a3..b9ae789 100644 --- a/src/dlangide/tools/d/deditortool.d +++ b/src/dlangide/tools/d/deditortool.d @@ -20,41 +20,38 @@ class DEditorTool : EditorTool this(IDEFrame frame) { - _dcd = new DCDInterface(DCD_SERVER_PORT_FOR_DLANGIDE); + _dcd = new DCDInterface(); super(frame); } override bool goToDefinition(DSourceEdit editor, TextPosition caretPosition) { string[] importPaths = editor.importPaths(); + _frame.moduleCache.addImportPaths(importPaths); + string content = toUTF8(editor.text); auto byteOffset = caretPositionToByteOffset(content, caretPosition); - ResultSet output = _dcd.goToDefinition(importPaths, editor.filename, content, byteOffset); + FindDeclarationResultSet output = _dcd.goToDefinition(importPaths, editor.filename, content, byteOffset, _frame.moduleCache); switch(output.result) { //TODO: Show dialog case DCDResult.FAIL: - case DCDResult.DCD_NOT_RUNNING: case DCDResult.NO_RESULT: editor.setFocus(); return false; case DCDResult.SUCCESS: - auto target = to!int(output.output[1]); - if(output.output[0].indexOf("stdin".dup) != -1) { + auto fileName = output.fileName; + if(fileName.indexOf("stdin") == 0) { Log.d("Declaration is in current file. Jumping to it."); - auto destPos = byteOffsetToCaret(content, target); - editor.setCaretPos(destPos.line,destPos.pos); - editor.setFocus(); - } - else { + } else { //Must open file first to get the content for finding the correct caret position. - _frame.openSourceFile(to!string(output.output[0])); - string txt; - txt = toUTF8(_frame.currentEditor.text); - auto destPos = byteOffsetToCaret(txt, target); - _frame.currentEditor.setCaretPos(destPos.line,destPos.pos); - _frame.currentEditor.setFocus(); + _frame.openSourceFile(to!string(fileName)); + content = toUTF8(_frame.currentEditor.text); } + auto target = to!int(output.offset); + auto destPos = byteOffsetToCaret(content, target); + _frame.currentEditor.setCaretPos(destPos.line,destPos.pos); + _frame.currentEditor.setFocus(); return true; default: return false; @@ -63,14 +60,14 @@ class DEditorTool : EditorTool override dstring[] getCompletions(DSourceEdit editor, TextPosition caretPosition) { string[] importPaths = editor.importPaths(); + _frame.moduleCache.addImportPaths(importPaths); string content = toUTF8(editor.text); auto byteOffset = caretPositionToByteOffset(content, caretPosition); - ResultSet output = _dcd.getCompletions(importPaths, editor.filename, content, byteOffset); + ResultSet output = _dcd.getCompletions(importPaths, editor.filename, content, byteOffset, _frame.moduleCache); switch(output.result) { //TODO: Show dialog case DCDResult.FAIL: - case DCDResult.DCD_NOT_RUNNING: case DCDResult.NO_RESULT: case DCDResult.SUCCESS: default: diff --git a/src/dlangide/ui/frame.d b/src/dlangide/ui/frame.d index 29f1fe0..5035671 100644 --- a/src/dlangide/ui/frame.d +++ b/src/dlangide/ui/frame.d @@ -26,7 +26,7 @@ import dlangide.ui.dsourceedit; import dlangide.ui.homescreen; import dlangide.ui.settings; import dlangide.ui.debuggerui; -import dlangide.tools.d.dcdserver; + import dlangide.workspace.workspace; import dlangide.workspace.project; import dlangide.builders.builder; @@ -76,7 +76,11 @@ class IDEFrame : AppFrame, ProgramExecutionStatusListener, BreakpointListChangeL OutputPanel _logPanel; DockHost _dockHost; TabWidget _tabs; - DCDServer _dcdServer; + + ///Cache for parsed D files for autocomplete and symbol finding + import dsymbol.modulecache; + ModuleCache _moduleCache = ModuleCache(new ASTAllocator); + IDESettings _settings; ProgramExecution _execution; @@ -91,6 +95,7 @@ class IDEFrame : AppFrame, ProgramExecutionStatusListener, BreakpointListChangeL applySettings(_settings); } + @property ref ModuleCache moduleCache() { return _moduleCache; } @property DockHost dockHost() { return _dockHost; } @property OutputPanel logPanel() { return _logPanel; } @@ -260,7 +265,6 @@ class IDEFrame : AppFrame, ProgramExecutionStatusListener, BreakpointListChangeL override protected void init() { _appName = "dlangide"; //_editorTool = new DEditorTool(this); - _dcdServer = new DCDServer(); _settings = new IDESettings(buildNormalizedPath(settingsDir, "settings.json")); _settings.load(); _settings.updateDefaults(); @@ -553,12 +557,6 @@ class IDEFrame : AppFrame, ProgramExecutionStatusListener, BreakpointListChangeL _logPanel.appendText(null, ldcPath ? ("ldc path: "d ~ toUTF32(ldcPath) ~ "\n"d) : ("ldc compiler is not found!\n"d)); _logPanel.appendText(null, gdcPath ? ("gdc path: "d ~ toUTF32(gdcPath) ~ "\n"d) : ("gdc compiler is not found!\n"d)); - if (_dcdServer.start()) { - _logPanel.appendText(null, "dcd-server is started on port "d ~ to!dstring(_dcdServer.port) ~ "\n"d); - } else { - _logPanel.appendText(null, "cannot start dcd-server: code completion for D code will not work"d); - } - _dockHost.addDockedWindow(_logPanel); return _dockHost; @@ -1299,12 +1297,6 @@ class IDEFrame : AppFrame, ProgramExecutionStatusListener, BreakpointListChangeL void onWindowClose() { Log.i("onWindowClose()"); stopExecution(); - if (_dcdServer) { - if (_dcdServer.isRunning) - _dcdServer.stop(); - destroy(_dcdServer); - _dcdServer = null; - } } }