mirror of https://github.com/buggins/dlangide.git
libdparse integration experiments
This commit is contained in:
parent
e8cd7b882c
commit
be2e3cdc54
|
|
@ -66,7 +66,7 @@
|
||||||
<debuglevel>0</debuglevel>
|
<debuglevel>0</debuglevel>
|
||||||
<debugids>DebugInfo DCD</debugids>
|
<debugids>DebugInfo DCD</debugids>
|
||||||
<versionlevel>0</versionlevel>
|
<versionlevel>0</versionlevel>
|
||||||
<versionids>Unicode USE_FREETYPE</versionids>
|
<versionids>Unicode USE_FREETYPE USE_LIBDPARSE</versionids>
|
||||||
<dump_source>0</dump_source>
|
<dump_source>0</dump_source>
|
||||||
<mapverbosity>3</mapverbosity>
|
<mapverbosity>3</mapverbosity>
|
||||||
<createImplib>0</createImplib>
|
<createImplib>0</createImplib>
|
||||||
|
|
|
||||||
|
|
@ -73,9 +73,15 @@ class DCDInterface {
|
||||||
return output;
|
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;
|
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));
|
debug(DCD) Log.d("DCD Context: ", dumpContext(content, index));
|
||||||
|
|
||||||
string[] arguments = ["-l", "-c"];
|
string[] arguments = ["-l", "-c"];
|
||||||
|
|
@ -122,7 +128,7 @@ class DCDInterface {
|
||||||
return result;
|
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));
|
debug(DCD) Log.d("DCD Context: ", dumpContext(content, index));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ class DEditorTool : EditorTool
|
||||||
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);
|
||||||
ResultSet output = _dcd.goToDefinition(importPaths, content, byteOffset);
|
ResultSet output = _dcd.goToDefinition(importPaths, editor.filename, content, byteOffset);
|
||||||
|
|
||||||
|
|
||||||
switch(output.result) {
|
switch(output.result) {
|
||||||
|
|
@ -66,7 +66,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 = _dcd.getCompletions(importPaths, content, byteOffset);
|
ResultSet output = _dcd.getCompletions(importPaths, editor.filename, content, byteOffset);
|
||||||
switch(output.result) {
|
switch(output.result) {
|
||||||
//TODO: Show dialog
|
//TODO: Show dialog
|
||||||
case DCDResult.FAIL:
|
case DCDResult.FAIL:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
module dlangide.tools.d.dparser;
|
module dlangide.tools.d.dparser;
|
||||||
|
|
||||||
|
import dlangui.core.logger;
|
||||||
|
|
||||||
import std.d.lexer;
|
import std.d.lexer;
|
||||||
import std.d.parser;
|
import std.d.parser;
|
||||||
import std.d.ast;
|
import std.d.ast;
|
||||||
|
|
@ -14,21 +16,64 @@ class DParsedModule {
|
||||||
protected string _moduleFile;
|
protected string _moduleFile;
|
||||||
protected StringCache* _cache;
|
protected StringCache* _cache;
|
||||||
protected Module _ast;
|
protected Module _ast;
|
||||||
|
protected string[] _imports;
|
||||||
const(Token)[] _tokens;
|
const(Token)[] _tokens;
|
||||||
LexerConfig _lexerConfig;
|
LexerConfig _lexerConfig;
|
||||||
|
|
||||||
@property string filename() {
|
@property string filename() { return _moduleFile; }
|
||||||
return _moduleFile;
|
/// module name, e.g. "std.stdio"
|
||||||
}
|
@property string moduleName() { return _moduleName; }
|
||||||
|
|
||||||
this(StringCache* cache, string filename) {
|
this(StringCache* cache, string filename) {
|
||||||
_cache = cache;
|
_cache = cache;
|
||||||
_moduleFile = filename;
|
_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) {
|
void parse(ubyte[] sourceCode) {
|
||||||
_tokens = getTokensForParser(sourceCode, _lexerConfig, _cache);
|
_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] _moduleByName;
|
||||||
protected DParsedModule[string] _moduleByFile;
|
protected DParsedModule[string] _moduleByFile;
|
||||||
protected bool[string] _notFoundModules;
|
protected bool[string] _notFoundModules;
|
||||||
|
protected DParsedModule _currentModule; // current module
|
||||||
|
|
||||||
this() {
|
this() {
|
||||||
_cache = StringCache(16);
|
_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) {
|
DParsedModule scan(ubyte[] sourceCode, string filename) {
|
||||||
|
Log.d("scanning ", filename);
|
||||||
destroy(_notFoundModules);
|
destroy(_notFoundModules);
|
||||||
DParsedModule res = new DParsedModule(&_cache, filename);
|
DParsedModule res = new DParsedModule(&_cache, filename);
|
||||||
res.parse(sourceCode);
|
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;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -77,21 +144,36 @@ class DParsingService {
|
||||||
string findModuleFile(string moduleName) {
|
string findModuleFile(string moduleName) {
|
||||||
string packagePath = moduleNameToPackagePath(moduleName);
|
string packagePath = moduleNameToPackagePath(moduleName);
|
||||||
foreach(ip; _importPaths) {
|
foreach(ip; _importPaths) {
|
||||||
|
//Log.d("packagePath: ", packagePath, " importPath: ", ip);
|
||||||
string path = buildNormalizedPath(ip, packagePath);
|
string path = buildNormalizedPath(ip, packagePath);
|
||||||
if (path.exists && path.isFile)
|
if (path.exists && path.isFile) {
|
||||||
|
//Log.d("found ", path);
|
||||||
return path;
|
return path;
|
||||||
|
}
|
||||||
|
string pathImports = path ~ "i";
|
||||||
|
if (pathImports.exists && pathImports.isFile) {
|
||||||
|
//Log.d("found ", pathImports);
|
||||||
|
return pathImports;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
DParsedModule getOrParseModule(string moduleName) {
|
DParsedModule getOrParseModule(string moduleName) {
|
||||||
|
if (_currentModule) {
|
||||||
|
if (moduleName.equal(_currentModule.moduleName))
|
||||||
|
return _currentModule; // module being scanned
|
||||||
|
}
|
||||||
if (auto m = moduleName in _moduleByName) {
|
if (auto m = moduleName in _moduleByName) {
|
||||||
return *m;
|
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
|
return null; // already listed as not found
|
||||||
|
}
|
||||||
string filename = findModuleFile(moduleName);
|
string filename = findModuleFile(moduleName);
|
||||||
if (!filename) {
|
if (!filename) {
|
||||||
|
Log.d("module not found: ", moduleName);
|
||||||
_notFoundModules[moduleName] = true;
|
_notFoundModules[moduleName] = true;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
@ -103,12 +185,14 @@ class DParsingService {
|
||||||
_moduleByFile[filename] = res;
|
_moduleByFile[filename] = res;
|
||||||
return res;
|
return res;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
Log.d("exception while parsing: ", moduleName, " : ", e);
|
||||||
_notFoundModules[moduleName] = true;
|
_notFoundModules[moduleName] = true;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void addImportPaths(string[] paths) {
|
void addImportPaths(in string[] paths) {
|
||||||
|
Log.d("addImportPaths: ", paths);
|
||||||
foreach(p; paths) {
|
foreach(p; paths) {
|
||||||
string ap = absolutePath(buildNormalizedPath(p));
|
string ap = absolutePath(buildNormalizedPath(p));
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
|
||||||
|
|
@ -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();
}
|
// 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();
}
|
||||||
Loading…
Reference in New Issue