DCD async access - for #93

This commit is contained in:
Vadim Lopatin 2016-01-28 10:26:12 +03:00
parent d828af306e
commit 4394f834cb
3 changed files with 143 additions and 86 deletions

View File

@ -12,7 +12,7 @@
"stringImportPaths": ["views", "views/res", "views/res/i18n", "views/res/mdpi", "views/res/hdpi"], "stringImportPaths": ["views", "views/res", "views/res/i18n", "views/res/mdpi", "views/res/hdpi"],
"dependencies": { "dependencies": {
"dlangui": "~>0.7.59", "dlangui": "~>0.7.60",
"dcd": "~>0.7.5" "dcd": "~>0.7.5"
}, },

View File

@ -2,6 +2,7 @@ module dlangide.tools.d.dcdinterface;
import dlangui.core.logger; import dlangui.core.logger;
import dlangui.core.files; import dlangui.core.files;
import dlangui.platforms.common.platform;
import ddebug.common.queue; import ddebug.common.queue;
import core.thread; import core.thread;
@ -20,13 +21,19 @@ alias DocCommentsResultSet = Tuple!(DCDResult, "result", string[], "docComments"
alias FindDeclarationResultSet = Tuple!(DCDResult, "result", string, "fileName", ulong, "offset"); alias FindDeclarationResultSet = Tuple!(DCDResult, "result", string, "fileName", ulong, "offset");
alias ResultSet = Tuple!(DCDResult, "result", dstring[], "output"); alias ResultSet = Tuple!(DCDResult, "result", dstring[], "output");
import server.autocomplete;
import common.messages;
class DCDTask { class DCDTask {
protected bool _cancelled; protected bool _cancelled;
protected CustomEventTarget _guiExecutor;
protected string[] _importPaths; protected string[] _importPaths;
protected string _filename; protected string _filename;
protected string _content; protected string _content;
protected int _index; protected int _index;
this(string[] importPaths, in string filename, in string content, int index) { protected AutocompleteRequest request;
this(CustomEventTarget guiExecutor, string[] importPaths, in string filename, in string content, int index) {
_guiExecutor = guiExecutor;
_importPaths = importPaths; _importPaths = importPaths;
_filename = filename; _filename = filename;
_content = content; _content = content;
@ -34,14 +41,35 @@ class DCDTask {
} }
@property bool cancelled() { return _cancelled; } @property bool cancelled() { return _cancelled; }
void cancel() { void cancel() {
synchronized(this) {
_cancelled = true; _cancelled = true;
} }
void execute() { }
void createRequest() {
request.sourceCode = cast(ubyte[])_content;
request.fileName = _filename;
request.cursorPosition = _index;
}
void performRequest() {
// override // override
} }
void postResults() {
// override
}
void execute() {
if (_cancelled)
return;
createRequest();
performRequest();
synchronized(this) {
if (_cancelled)
return;
_guiExecutor.executeInUiThread(&postResults);
}
}
} }
/// Interface to DCD /// Async interface to DCD
class DCDInterface : Thread { class DCDInterface : Thread {
import dsymbol.modulecache; import dsymbol.modulecache;
@ -51,6 +79,7 @@ class DCDInterface : Thread {
this() { this() {
super(&threadFunc); super(&threadFunc);
_queue = new BlockingQueue!DCDTask(); _queue = new BlockingQueue!DCDTask();
name = "DCDthread";
start(); start();
} }
@ -74,15 +103,15 @@ class DCDInterface : Thread {
DCDTask task; DCDTask task;
if (!_queue.get(task)) if (!_queue.get(task))
break; break;
if (task && !task.cancelled) if (task && !task.cancelled) {
Log.d("Execute DCD task");
task.execute(); task.execute();
Log.d("DCD task execution finished");
}
} }
Log.d("Exiting DCD tasks thread"); Log.d("Exiting DCD tasks thread");
} }
import server.autocomplete;
import common.messages;
import dsymbol.modulecache; import dsymbol.modulecache;
protected string dumpContext(string content, int pos) { protected string dumpContext(string content, int pos) {
@ -98,7 +127,7 @@ class DCDInterface : Thread {
return ""; return "";
} }
DocCommentsResultSet getDocComments(in string[] importPaths, in string filename, in string content, int index) { DocCommentsResultSet getDocComments(CustomEventTarget guiExecutor, in string[] importPaths, in string filename, in string content, int index) {
debug(DCD) Log.d("getDocComments: ", dumpContext(content, index)); debug(DCD) Log.d("getDocComments: ", dumpContext(content, index));
AutocompleteRequest request; AutocompleteRequest request;
request.sourceCode = cast(ubyte[])content; request.sourceCode = cast(ubyte[])content;
@ -119,17 +148,20 @@ class DCDInterface : Thread {
return result; return result;
} }
void goToDefinition(in string[] importPaths, in string filename, in string content, int index, void delegate(FindDeclarationResultSet res) callback) { /// DCD go to definition task
class GoToDefinitionTask : DCDTask {
debug(DCD) Log.d("DCD Context: ", dumpContext(content, index)); protected void delegate(FindDeclarationResultSet output) _callback;
AutocompleteRequest request; protected FindDeclarationResultSet result;
request.sourceCode = cast(ubyte[])content;
request.fileName = filename;
request.cursorPosition = index;
AutocompleteResponse response = findDeclaration(request, *getModuleCache(importPaths)); this(CustomEventTarget guiExecutor, string[] importPaths, in string filename, in string content, int index, void delegate(FindDeclarationResultSet output) callback) {
super(guiExecutor, importPaths, filename, content, index);
_callback = callback;
}
override void performRequest() {
AutocompleteResponse response = findDeclaration(request, *getModuleCache(_importPaths));
FindDeclarationResultSet result;
result.fileName = response.symbolFilePath; result.fileName = response.symbolFilePath;
result.offset = response.symbolLocation; result.offset = response.symbolLocation;
result.result = DCDResult.SUCCESS; result.result = DCDResult.SUCCESS;
@ -139,10 +171,21 @@ class DCDInterface : Thread {
if (result.fileName is null) { if (result.fileName is null) {
result.result = DCDResult.NO_RESULT; result.result = DCDResult.NO_RESULT;
} }
callback(result); }
override void postResults() {
_callback(result);
}
} }
ResultSet getCompletions(in string[] importPaths, in string filename, in string content, int index) { DCDTask goToDefinition(CustomEventTarget guiExecutor, string[] importPaths, in string filename, in string content, int index, void delegate(FindDeclarationResultSet res) callback) {
debug(DCD) Log.d("DCD Context: ", dumpContext(content, index));
GoToDefinitionTask task = new GoToDefinitionTask(guiExecutor, importPaths, filename, content, index, callback);
_queue.put(task);
return task;
}
ResultSet getCompletions(CustomEventTarget guiExecutor, in string[] importPaths, in string filename, in string content, int index) {
debug(DCD) Log.d("DCD Context: ", dumpContext(content, index)); debug(DCD) Log.d("DCD Context: ", dumpContext(content, index));
ResultSet result; ResultSet result;
@ -175,14 +218,12 @@ class DCDInterface : Thread {
protected void delegate(DocCommentsResultSet output) _callback; protected void delegate(DocCommentsResultSet output) _callback;
protected DocCommentsResultSet result; protected DocCommentsResultSet result;
this(string[] importPaths, in string filename, in string content, int index, void delegate(DocCommentsResultSet output) callback) { this(CustomEventTarget guiExecutor, string[] importPaths, in string filename, in string content, int index, void delegate(DocCommentsResultSet output) callback) {
super(importPaths, filename, content, index); super(guiExecutor, importPaths, filename, content, index);
_callback = callback; _callback = callback;
} }
override void execute() { override void performRequest() {
if (_cancelled)
return;
AutocompleteRequest request; AutocompleteRequest request;
request.sourceCode = cast(ubyte[])_content; request.sourceCode = cast(ubyte[])_content;
request.fileName = _filename; request.fileName = _filename;
@ -198,9 +239,10 @@ class DCDInterface : Thread {
if (result.docComments is null) { if (result.docComments is null) {
result.result = DCDResult.NO_RESULT; result.result = DCDResult.NO_RESULT;
} }
}
if (!_cancelled) override void postResults() {
_callback(result); _callback(result);
} }
} }
} }

View File

@ -21,12 +21,16 @@ class DEditorTool : EditorTool
super(frame); super(frame);
} }
~this() {
cancelGoToDefinition();
}
override string[] getDocComments(DSourceEdit editor, TextPosition caretPosition) { override string[] getDocComments(DSourceEdit editor, TextPosition caretPosition) {
string[] importPaths = editor.importPaths(); string[] importPaths = editor.importPaths();
string content = toUTF8(editor.text); string content = toUTF8(editor.text);
auto byteOffset = caretPositionToByteOffset(content, caretPosition); auto byteOffset = caretPositionToByteOffset(content, caretPosition);
DocCommentsResultSet output = _frame.dcdInterface.getDocComments(importPaths, editor.filename, content, byteOffset); DocCommentsResultSet output = _frame.dcdInterface.getDocComments(editor.window, importPaths, editor.filename, content, byteOffset);
switch(output.result) { switch(output.result) {
//TODO: Show dialog //TODO: Show dialog
@ -45,14 +49,21 @@ class DEditorTool : EditorTool
override void cancelGoToDefinition() { override void cancelGoToDefinition() {
// override it // override it
if (_goToDefinitionTask) {
_goToDefinitionTask.cancel();
_goToDefinitionTask = null;
}
} }
DCDTask _goToDefinitionTask;
override void goToDefinition(DSourceEdit editor, TextPosition caretPosition) { override void goToDefinition(DSourceEdit editor, TextPosition caretPosition) {
cancelGoToDefinition();
string[] importPaths = editor.importPaths(); string[] importPaths = editor.importPaths();
string content = toUTF8(editor.text); string content = toUTF8(editor.text);
auto byteOffset = caretPositionToByteOffset(content, caretPosition); auto byteOffset = caretPositionToByteOffset(content, caretPosition);
_frame.dcdInterface.goToDefinition(importPaths, editor.filename, content, byteOffset, delegate(FindDeclarationResultSet output) {
_goToDefinitionTask = _frame.dcdInterface.goToDefinition(editor.window, importPaths, editor.filename, content, byteOffset, delegate(FindDeclarationResultSet output) {
// handle result // handle result
switch(output.result) { switch(output.result) {
//TODO: Show dialog //TODO: Show dialog
@ -80,6 +91,7 @@ class DEditorTool : EditorTool
default: default:
break; break;
} }
_goToDefinitionTask = null;
}); });
} }
@ -89,7 +101,7 @@ class DEditorTool : EditorTool
string content = toUTF8(editor.text); string content = toUTF8(editor.text);
auto byteOffset = caretPositionToByteOffset(content, caretPosition); auto byteOffset = caretPositionToByteOffset(content, caretPosition);
ResultSet output = _frame.dcdInterface.getCompletions(importPaths, editor.filename, content, byteOffset); ResultSet output = _frame.dcdInterface.getCompletions(editor.window, importPaths, editor.filename, content, byteOffset);
switch(output.result) { switch(output.result) {
//TODO: Show dialog //TODO: Show dialog
case DCDResult.FAIL: case DCDResult.FAIL:
@ -102,7 +114,10 @@ class DEditorTool : EditorTool
private: private:
static int caretPositionToByteOffset(string content, TextPosition caretPosition) { }
/// convert caret position to byte offset in utf8 content
int caretPositionToByteOffset(string content, TextPosition caretPosition) {
auto line = 0; auto line = 0;
auto pos = 0; auto pos = 0;
auto bytes = 0; auto bytes = 0;
@ -123,7 +138,8 @@ private:
return bytes; return bytes;
} }
static TextPosition byteOffsetToCaret(string content, int byteOffset) { /// convert byte offset in utf8 content to caret position
TextPosition byteOffsetToCaret(string content, int byteOffset) {
int bytes = 0; int bytes = 0;
int line = 0; int line = 0;
int pos = 0; int pos = 0;
@ -147,4 +163,3 @@ private:
} }
return textPos; return textPos;
} }
}