libdparse integration experiments

This commit is contained in:
Vadim Lopatin 2015-02-18 14:07:19 +03:00
parent e8cd7b882c
commit be2e3cdc54
5 changed files with 103 additions and 13 deletions

View File

@ -66,7 +66,7 @@
<debuglevel>0</debuglevel>
<debugids>DebugInfo DCD</debugids>
<versionlevel>0</versionlevel>
<versionids>Unicode USE_FREETYPE</versionids>
<versionids>Unicode USE_FREETYPE USE_LIBDPARSE</versionids>
<dump_source>0</dump_source>
<mapverbosity>3</mapverbosity>
<createImplib>0</createImplib>

View File

@ -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));

View File

@ -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:

View File

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

View File

@ -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(); }