mirror of https://github.com/buggins/dlangide.git
libdparser
This commit is contained in:
parent
e88b72f629
commit
b217c895c2
|
|
@ -80,15 +80,212 @@ class DParsedModule {
|
|||
}
|
||||
|
||||
|
||||
static class ImportInfo {
|
||||
|
||||
private IdentPositionIterator _identPositionIterator;
|
||||
IdentDefinitionLookupResult findTokenNode(const(Token)* tokenToFindPositionFor, const(Token)* tokenToFindReferencesFor) {
|
||||
if (!_identPositionIterator)
|
||||
_identPositionIterator = new IdentPositionIterator();
|
||||
auto foundNode = _identPositionIterator.run(this, _ast, tokenToFindPositionFor, tokenToFindReferencesFor);
|
||||
return foundNode;
|
||||
}
|
||||
|
||||
|
||||
void findDeclaration(int bytePosition, DParsedModule[string] scanned) {
|
||||
const(Token) * token = findIdentTokenByBytePosition(bytePosition);
|
||||
if (!token)
|
||||
return;
|
||||
|
||||
Log.d("Identifier token found by position: ", token.text);
|
||||
IdentDefinitionLookupResult res = findTokenNode(token, token);
|
||||
if (!res.found)
|
||||
return;
|
||||
Log.d("Found in node:");
|
||||
res.found.dump();
|
||||
}
|
||||
|
||||
const(Token) * findIdentTokenByBytePosition(int bytePosition) {
|
||||
const(Token) * res = null;
|
||||
for(int i = 0; i < _tokens.length; i++) {
|
||||
auto t = &_tokens[i];
|
||||
if (t.index >= bytePosition) {
|
||||
if (res && *res == tok!"identifier")
|
||||
return res; // return this or previous identifier token
|
||||
if (t.index == bytePosition && (*t) == tok!"identifier")
|
||||
return t; // return next identifier token
|
||||
}
|
||||
res = t;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void parse(ubyte[] sourceCode) {
|
||||
_sourceCode = sourceCode;
|
||||
_tokens = getTokensForParser(sourceCode, _lexerConfig, _cache);
|
||||
uint errorCount;
|
||||
uint warningCount;
|
||||
_ast = parseModule(_tokens, _moduleFile, null, &msgFunction, &errorCount, &warningCount);
|
||||
_moduleName = _ast.moduleDeclaration ? importDeclToModuleName(_ast.moduleDeclaration.moduleName) : null;
|
||||
scanImports();
|
||||
}
|
||||
|
||||
private void addImport(string m) {
|
||||
foreach(imp; _imports)
|
||||
if (imp.equal(m))
|
||||
return;
|
||||
_imports ~= m;
|
||||
}
|
||||
|
||||
@property string[] imports() {
|
||||
return _imports;
|
||||
}
|
||||
}
|
||||
|
||||
/// D source code parsing service
|
||||
class DParsingService {
|
||||
|
||||
protected static __gshared DParsingService _instance;
|
||||
/// singleton
|
||||
static @property DParsingService instance() {
|
||||
if (!_instance) {
|
||||
_instance = new DParsingService();
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
/// destroy singleton
|
||||
static void shutdown() {
|
||||
destroy(_instance);
|
||||
_instance = null;
|
||||
}
|
||||
|
||||
protected StringCache _cache;
|
||||
protected string[] _importPaths;
|
||||
protected DParsedModule[] _modules;
|
||||
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, ref DParsedModule[string] scanned) {
|
||||
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:");
|
||||
scanned[res.moduleName] = res;
|
||||
scanDeps(res, scanned);
|
||||
foreach(key, value; scanned) {
|
||||
Log.d(" module ", key, " : ", value ? value.filename : "NOT FOUND");
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
DParsedModule findDeclaration(ubyte[] sourceCode, string filename, int bytePosition) {
|
||||
DParsedModule[string] scanned;
|
||||
DParsedModule m = scan(sourceCode, filename, scanned);
|
||||
m.findDeclaration(bytePosition, scanned);
|
||||
return m;
|
||||
}
|
||||
|
||||
/// converts some.module.name to some/module/name.d
|
||||
string moduleNameToPackagePath(string moduleName) {
|
||||
string[] pathSegments = moduleName.split(".");
|
||||
string normalized = buildNormalizedPath(pathSegments);
|
||||
return normalized ~ ".d";
|
||||
}
|
||||
|
||||
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) {
|
||||
//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) {
|
||||
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;
|
||||
}
|
||||
try {
|
||||
DParsedModule res = new DParsedModule(&_cache, filename);
|
||||
ubyte[] sourceCode = cast(ubyte[])read(filename);
|
||||
res.parse(sourceCode);
|
||||
_moduleByName[moduleName] = res;
|
||||
_moduleByFile[filename] = res;
|
||||
return res;
|
||||
} catch (Exception e) {
|
||||
Log.d("exception while parsing: ", moduleName, " : ", e);
|
||||
_notFoundModules[moduleName] = true;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
void addImportPaths(in string[] paths) {
|
||||
Log.d("addImportPaths: ", paths);
|
||||
foreach(p; paths) {
|
||||
string ap = absolutePath(buildNormalizedPath(p));
|
||||
bool found = false;
|
||||
foreach(ip; _importPaths)
|
||||
if (ip.equal(ap)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if (!found)
|
||||
_importPaths ~= ap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static class ImportInfo {
|
||||
string moduleName;
|
||||
const ImportDeclaration decl;
|
||||
this(const ImportDeclaration decl, string moduleName) {
|
||||
this.decl = decl;
|
||||
this.moduleName = moduleName;
|
||||
}
|
||||
}
|
||||
enum DeclarationType {
|
||||
}
|
||||
enum DeclarationType {
|
||||
none,
|
||||
classVariableDeclaration,
|
||||
structVariableDeclaration,
|
||||
|
|
@ -103,8 +300,8 @@ class DParsedModule {
|
|||
classTemplateTypeParameter,
|
||||
structTemplateTypeParameter,
|
||||
templateTypeParameter,
|
||||
}
|
||||
static class IdentContext {
|
||||
}
|
||||
static class IdentContext {
|
||||
DParsedModule mod;
|
||||
Token token;
|
||||
ImportInfo[] imports;
|
||||
|
|
@ -214,9 +411,24 @@ class DParsedModule {
|
|||
" declNode: ", declarationNode, " baseDeclNode: ", baseDeclarationNode,
|
||||
"\n\timports: ", imports, "\n\tcontext: ", stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class IdentPositionIterator : ASTVisitor {
|
||||
static class IdentDefinitionLookupResult {
|
||||
DParsedModule mod;
|
||||
const(Token) tokenToFind;
|
||||
const(Token) tokenToFindReferences;
|
||||
IdentContext found;
|
||||
IdentContext[] references;
|
||||
this(DParsedModule mod, const(Token) * tokenToFind, const(Token) * tokenToFindReferences, IdentContext found, IdentContext[] references) {
|
||||
this.mod = mod;
|
||||
this.tokenToFind = *tokenToFind;
|
||||
this.tokenToFindReferences = *tokenToFindReferences;
|
||||
this.found = found;
|
||||
this.references = references;
|
||||
}
|
||||
}
|
||||
|
||||
static class IdentPositionIterator : ASTVisitor {
|
||||
|
||||
private const(Token) * _tokenToFind;
|
||||
private const(Token) * _tokenToFindReferences;
|
||||
|
|
@ -245,7 +457,7 @@ class DParsedModule {
|
|||
return res;
|
||||
}
|
||||
|
||||
IdentContext run(DParsedModule mod, Module ast, const(Token) * tokenToFind, const(Token) * tokenToFindReferences) {
|
||||
IdentDefinitionLookupResult run(DParsedModule mod, Module ast, const(Token) * tokenToFind, const(Token) * tokenToFindReferences) {
|
||||
_mod = mod;
|
||||
_stack.length = 0;
|
||||
_references.length = 0;
|
||||
|
|
@ -258,7 +470,7 @@ class DParsedModule {
|
|||
foreach(r; _references)
|
||||
r.dump();
|
||||
}
|
||||
return _found;
|
||||
return new IdentDefinitionLookupResult(_mod, _tokenToFind, _tokenToFindReferences, _found, _references);
|
||||
}
|
||||
|
||||
//alias visit = ASTVisitor.visit;
|
||||
|
|
@ -542,199 +754,4 @@ class DParsedModule {
|
|||
override void visit(const WhileStatement whileStatement) { mixin(def("whileStatement")); }
|
||||
override void visit(const WithStatement withStatement) { mixin(def("withStatement")); }
|
||||
override void visit(const XorExpression xorExpression) { mixin(def("xorExpression")); }
|
||||
}
|
||||
|
||||
private IdentPositionIterator _identPositionIterator;
|
||||
IdentContext findTokenNode(const(Token)* tokenToFindPositionFor, const(Token)* tokenToFindReferencesFor) {
|
||||
if (!_identPositionIterator)
|
||||
_identPositionIterator = new IdentPositionIterator();
|
||||
auto foundNode = _identPositionIterator.run(this, _ast, tokenToFindPositionFor, tokenToFindReferencesFor);
|
||||
return foundNode;
|
||||
}
|
||||
|
||||
|
||||
void findDeclaration(int bytePosition, DParsedModule[string] scanned) {
|
||||
const(Token) * token = findIdentTokenByBytePosition(bytePosition);
|
||||
if (!token)
|
||||
return;
|
||||
|
||||
Log.d("Identifier token found by position: ", token.text);
|
||||
auto found = findTokenNode(token, token);
|
||||
if (!found)
|
||||
return;
|
||||
Log.d("Found in node:");
|
||||
found.dump();
|
||||
}
|
||||
|
||||
const(Token) * findIdentTokenByBytePosition(int bytePosition) {
|
||||
const(Token) * res = null;
|
||||
for(int i = 0; i < _tokens.length; i++) {
|
||||
auto t = &_tokens[i];
|
||||
if (t.index >= bytePosition) {
|
||||
if (res && *res == tok!"identifier")
|
||||
return res; // return this or previous identifier token
|
||||
if (t.index == bytePosition && (*t) == tok!"identifier")
|
||||
return t; // return next identifier token
|
||||
}
|
||||
res = t;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void parse(ubyte[] sourceCode) {
|
||||
_sourceCode = sourceCode;
|
||||
_tokens = getTokensForParser(sourceCode, _lexerConfig, _cache);
|
||||
uint errorCount;
|
||||
uint warningCount;
|
||||
_ast = parseModule(_tokens, _moduleFile, null, &msgFunction, &errorCount, &warningCount);
|
||||
_moduleName = _ast.moduleDeclaration ? importDeclToModuleName(_ast.moduleDeclaration.moduleName) : null;
|
||||
scanImports();
|
||||
}
|
||||
|
||||
private void addImport(string m) {
|
||||
foreach(imp; _imports)
|
||||
if (imp.equal(m))
|
||||
return;
|
||||
_imports ~= m;
|
||||
}
|
||||
|
||||
@property string[] imports() {
|
||||
return _imports;
|
||||
}
|
||||
}
|
||||
|
||||
/// D source code parsing service
|
||||
class DParsingService {
|
||||
|
||||
protected static __gshared DParsingService _instance;
|
||||
/// singleton
|
||||
static @property DParsingService instance() {
|
||||
if (!_instance) {
|
||||
_instance = new DParsingService();
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
/// destroy singleton
|
||||
static void shutdown() {
|
||||
destroy(_instance);
|
||||
_instance = null;
|
||||
}
|
||||
|
||||
protected StringCache _cache;
|
||||
protected string[] _importPaths;
|
||||
protected DParsedModule[] _modules;
|
||||
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, ref DParsedModule[string] scanned) {
|
||||
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:");
|
||||
scanned[res.moduleName] = res;
|
||||
scanDeps(res, scanned);
|
||||
foreach(key, value; scanned) {
|
||||
Log.d(" module ", key, " : ", value ? value.filename : "NOT FOUND");
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
DParsedModule findDeclaration(ubyte[] sourceCode, string filename, int bytePosition) {
|
||||
DParsedModule[string] scanned;
|
||||
DParsedModule m = scan(sourceCode, filename, scanned);
|
||||
m.findDeclaration(bytePosition, scanned);
|
||||
return m;
|
||||
}
|
||||
|
||||
/// converts some.module.name to some/module/name.d
|
||||
string moduleNameToPackagePath(string moduleName) {
|
||||
string[] pathSegments = moduleName.split(".");
|
||||
string normalized = buildNormalizedPath(pathSegments);
|
||||
return normalized ~ ".d";
|
||||
}
|
||||
|
||||
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) {
|
||||
//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) {
|
||||
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;
|
||||
}
|
||||
try {
|
||||
DParsedModule res = new DParsedModule(&_cache, filename);
|
||||
ubyte[] sourceCode = cast(ubyte[])read(filename);
|
||||
res.parse(sourceCode);
|
||||
_moduleByName[moduleName] = res;
|
||||
_moduleByFile[filename] = res;
|
||||
return res;
|
||||
} catch (Exception e) {
|
||||
Log.d("exception while parsing: ", moduleName, " : ", e);
|
||||
_notFoundModules[moduleName] = true;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
void addImportPaths(in string[] paths) {
|
||||
Log.d("addImportPaths: ", paths);
|
||||
foreach(p; paths) {
|
||||
string ap = absolutePath(buildNormalizedPath(p));
|
||||
bool found = false;
|
||||
foreach(ip; _importPaths)
|
||||
if (ip.equal(ap)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if (!found)
|
||||
_importPaths ~= ap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue