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;
- }
}
}