diff --git a/dlangide.visualdproj b/dlangide.visualdproj
index a37a585..014ed4d 100644
--- a/dlangide.visualdproj
+++ b/dlangide.visualdproj
@@ -66,7 +66,7 @@
0
DebugInfo DCD
0
- Unicode USE_FREETYPE
+ Unicode USE_FREETYPE USE_LIBDPARSE
0
3
0
diff --git a/src/dlangide/tools/d/dcdinterface.d b/src/dlangide/tools/d/dcdinterface.d
index b87a6d4..b0e089e 100644
--- a/src/dlangide/tools/d/dcdinterface.d
+++ b/src/dlangide/tools/d/dcdinterface.d
@@ -73,8 +73,14 @@ class DCDInterface {
return output;
}
- ResultSet goToDefinition(in string[] importPaths, in string content, int index) {
+ ResultSet goToDefinition(in string[] importPaths, in string filename, in string content, int index) {
ResultSet result;
+
+ version(USE_LIBDPARSE) {
+ import dlangide.tools.d.dparser;
+ DParsingService.instance.addImportPaths(importPaths);
+ DParsedModule m = DParsingService.instance.scan(cast(ubyte[])content, filename);
+ }
debug(DCD) Log.d("DCD Context: ", dumpContext(content, index));
@@ -122,7 +128,7 @@ class DCDInterface {
return result;
}
- ResultSet getCompletions(in string[] importPaths, in string content, int index) {
+ ResultSet getCompletions(in string[] importPaths, in string filename, in string content, int index) {
debug(DCD) Log.d("DCD Context: ", dumpContext(content, index));
diff --git a/src/dlangide/tools/d/deditortool.d b/src/dlangide/tools/d/deditortool.d
index c3acc30..15d840e 100644
--- a/src/dlangide/tools/d/deditortool.d
+++ b/src/dlangide/tools/d/deditortool.d
@@ -28,7 +28,7 @@ class DEditorTool : EditorTool
string[] importPaths = editor.importPaths();
string content = toUTF8(editor.text);
auto byteOffset = caretPositionToByteOffset(content, caretPosition);
- ResultSet output = _dcd.goToDefinition(importPaths, content, byteOffset);
+ ResultSet output = _dcd.goToDefinition(importPaths, editor.filename, content, byteOffset);
switch(output.result) {
@@ -66,7 +66,7 @@ class DEditorTool : EditorTool
string content = toUTF8(editor.text);
auto byteOffset = caretPositionToByteOffset(content, caretPosition);
- ResultSet output = _dcd.getCompletions(importPaths, content, byteOffset);
+ ResultSet output = _dcd.getCompletions(importPaths, editor.filename, content, byteOffset);
switch(output.result) {
//TODO: Show dialog
case DCDResult.FAIL:
diff --git a/src/dlangide/tools/d/dparser.d b/src/dlangide/tools/d/dparser.d
index 9451410..9848eb0 100644
--- a/src/dlangide/tools/d/dparser.d
+++ b/src/dlangide/tools/d/dparser.d
@@ -1,5 +1,7 @@
module dlangide.tools.d.dparser;
+import dlangui.core.logger;
+
import std.d.lexer;
import std.d.parser;
import std.d.ast;
@@ -14,21 +16,64 @@ class DParsedModule {
protected string _moduleFile;
protected StringCache* _cache;
protected Module _ast;
+ protected string[] _imports;
const(Token)[] _tokens;
LexerConfig _lexerConfig;
- @property string filename() {
- return _moduleFile;
- }
+ @property string filename() { return _moduleFile; }
+ /// module name, e.g. "std.stdio"
+ @property string moduleName() { return _moduleName; }
this(StringCache* cache, string filename) {
_cache = cache;
_moduleFile = filename;
}
+ private static string importDeclToModuleName(IdentifierChain chain) {
+ char[] buf;
+ foreach(token; chain.identifiers) {
+ if (buf.length)
+ buf ~= '.';
+ buf ~= token.text;
+ }
+ return buf.dup;
+ }
+
+ void scanImports(Declaration[] declarations) {
+ foreach(d; declarations) {
+ if (d.importDeclaration) {
+ foreach(imp; d.importDeclaration.singleImports) {
+ addImport(importDeclToModuleName(imp.identifierChain));
+ }
+ } else if (d.declarations) {
+ scanImports(d.declarations);
+ }
+ }
+ }
+
+ static void msgFunction(string fn, size_t line, size_t col, string msg, bool isError) {
+ debug(DParseErrors) Log.d("parser error: ", fn, "(", line, ":", col, ") : ", isError ? "Error: ": "Warning: ", msg);
+ }
+
void parse(ubyte[] sourceCode) {
_tokens = getTokensForParser(sourceCode, _lexerConfig, _cache);
- _ast = parseModule(_tokens, _moduleFile);
+ uint errorCount;
+ uint warningCount;
+ _ast = parseModule(_tokens, _moduleFile, null, &msgFunction, &errorCount, &warningCount);
+ _moduleName = importDeclToModuleName(_ast.moduleDeclaration.moduleName);
+ scanImports(_ast.declarations);
+
+ }
+
+ private void addImport(string m) {
+ foreach(imp; _imports)
+ if (imp.equal(m))
+ return;
+ _imports ~= m;
+ }
+
+ @property string[] imports() {
+ return _imports;
}
}
@@ -55,15 +100,37 @@ class DParsingService {
protected DParsedModule[string] _moduleByName;
protected DParsedModule[string] _moduleByFile;
protected bool[string] _notFoundModules;
+ protected DParsedModule _currentModule; // current module
this() {
_cache = StringCache(16);
}
+ void scanDeps(DParsedModule m, ref DParsedModule[string]scanned) {
+ foreach(imp; m.imports) {
+ if (imp !in scanned) {
+ DParsedModule impModule = getOrParseModule(imp);
+ scanned[imp] = impModule;
+ if (impModule)
+ scanDeps(impModule, scanned);
+ }
+ }
+ }
+
DParsedModule scan(ubyte[] sourceCode, string filename) {
+ Log.d("scanning ", filename);
destroy(_notFoundModules);
DParsedModule res = new DParsedModule(&_cache, filename);
res.parse(sourceCode);
+ _currentModule = res;
+ Log.d("moduleName: ", res.moduleName, " imports: ", res.imports);
+ Log.d("deps:");
+ DParsedModule[string] scanned;
+ scanned[res.moduleName] = res;
+ scanDeps(res, scanned);
+ foreach(key, value; scanned) {
+ Log.d(" module ", key, " : ", value ? value.filename : "NOT FOUND");
+ }
return res;
}
@@ -77,21 +144,36 @@ class DParsingService {
string findModuleFile(string moduleName) {
string packagePath = moduleNameToPackagePath(moduleName);
foreach(ip; _importPaths) {
+ //Log.d("packagePath: ", packagePath, " importPath: ", ip);
string path = buildNormalizedPath(ip, packagePath);
- if (path.exists && path.isFile)
+ if (path.exists && path.isFile) {
+ //Log.d("found ", path);
return path;
+ }
+ string pathImports = path ~ "i";
+ if (pathImports.exists && pathImports.isFile) {
+ //Log.d("found ", pathImports);
+ return pathImports;
+ }
}
return null;
}
DParsedModule getOrParseModule(string moduleName) {
+ if (_currentModule) {
+ if (moduleName.equal(_currentModule.moduleName))
+ return _currentModule; // module being scanned
+ }
if (auto m = moduleName in _moduleByName) {
return *m;
}
- if (moduleName in _notFoundModules)
+ if (moduleName in _notFoundModules) {
+ Log.d("module is in not found: ", moduleName);
return null; // already listed as not found
+ }
string filename = findModuleFile(moduleName);
if (!filename) {
+ Log.d("module not found: ", moduleName);
_notFoundModules[moduleName] = true;
return null;
}
@@ -103,12 +185,14 @@ class DParsingService {
_moduleByFile[filename] = res;
return res;
} catch (Exception e) {
+ Log.d("exception while parsing: ", moduleName, " : ", e);
_notFoundModules[moduleName] = true;
return null;
}
}
- void addImportPaths(string[] paths) {
+ void addImportPaths(in string[] paths) {
+ Log.d("addImportPaths: ", paths);
foreach(p; paths) {
string ap = absolutePath(buildNormalizedPath(p));
bool found = false;
diff --git a/workspaces/tetris/src/tetris.d b/workspaces/tetris/src/tetris.d
index 58fa71c..3341ce1 100644
--- a/workspaces/tetris/src/tetris.d
+++ b/workspaces/tetris/src/tetris.d
@@ -1 +1 @@
-// Written in the D programming language.
/**
This app is a Tetris demo for DlangUI library.
Synopsis:
----
dub run dlangui:tetris
----
Copyright: Vadim Lopatin, 2014
License: Boost License 1.0
Authors: Vadim Lopatin, coolreader.org@gmail.com
*/
module main;
import dlangui.all;
import model;
import gui;
/// Required for Windows platform: DMD cannot find WinMain if it's in library
mixin APP_ENTRY_POINT;
/// entry point for dlangui based application
extern (C) int UIAppMain(string[] args) {
//auto power2 = delegate(int X) { return X * X; };
auto power2 = (int X) => X * X;
// embed resources listed in views/resources.list into executable
embeddedResourceList.addResources(embedResourcesFromList!("resources.list")());
// select translation file - for english language
Platform.instance.uiLanguage = "en";
// load theme from file "theme_default.xml"
Platform.instance.uiTheme = "theme_default";
// create window
Window window = Platform.instance.createWindow("DLangUI: Tetris game example"d, null, WindowFlag.Modal);
window.mainWidget = new GameWidget();
window.windowIcon = drawableCache.getImage("dtetris-logo1");
window.show();
// run message loop
return Platform.instance.enterMessageLoop();
}
\ No newline at end of file
+// Written in the D programming language.
/**
This app is a Tetris demo for DlangUI library.
Synopsis:
----
dub run dlangui:tetris
----
Copyright: Vadim Lopatin, 2014
License: Boost License 1.0
Authors: Vadim Lopatin, coolreader.org@gmail.com
*/
module main;
import dlangui.all;
import model;
import gui;
import std.stdio;
/// Required for Windows platform: DMD cannot find WinMain if it's in library
mixin APP_ENTRY_POINT;
/// entry point for dlangui based application
extern (C) int UIAppMain(string[] args) {
//auto power2 = delegate(int X) { return X * X; };
auto power2 = (int X) => X * X;
// embed resources listed in views/resources.list into executable
embeddedResourceList.addResources(embedResourcesFromList!("resources.list")());
// select translation file - for english language
Platform.instance.uiLanguage = "en";
// load theme from file "theme_default.xml"
Platform.instance.uiTheme = "theme_default";
// create window
Window window = Platform.instance.createWindow("DLangUI: Tetris game example"d, null, WindowFlag.Modal);
window.mainWidget = new GameWidget();
window.windowIcon = drawableCache.getImage("dtetris-logo1");
window.show();
// run message loop
return Platform.instance.enterMessageLoop();
}
\ No newline at end of file