mirror of https://gitlab.com/basile.b/dexed.git
new widget tool designed to replace the static explorer and based on libdparse
This commit is contained in:
parent
c98dd3c7bc
commit
f28a83e8d8
|
@ -0,0 +1,24 @@
|
|||
object CurrentProject: TCEProject
|
||||
OptionsCollection = <
|
||||
item
|
||||
name = 'release'
|
||||
outputOptions.inlining = True
|
||||
outputOptions.boundsCheck = offAlways
|
||||
outputOptions.optimizations = True
|
||||
outputOptions.release = True
|
||||
pathsOptions.outputFilename = '..\lazproj\cesyms'
|
||||
preBuildProcess.options = []
|
||||
preBuildProcess.showWindow = swoNone
|
||||
postBuildProcess.options = []
|
||||
postBuildProcess.showWindow = swoNone
|
||||
runOptions.options = []
|
||||
runOptions.showWindow = swoNone
|
||||
end>
|
||||
Sources.Strings = (
|
||||
'cesyms.d'
|
||||
)
|
||||
ConfigurationIndex = 0
|
||||
LibraryAliases.Strings = (
|
||||
'libdparse'
|
||||
)
|
||||
end
|
|
@ -0,0 +1,270 @@
|
|||
module cesyms;
|
||||
|
||||
import std.stdio, std.path, std.file, std.array, std.string;
|
||||
import std.d.lexer, std.d.ast, std.d.parser;
|
||||
static import std.conv;
|
||||
|
||||
interface I{}
|
||||
|
||||
alias Int32 = int;
|
||||
//alias long Int64;
|
||||
|
||||
enum E
|
||||
{
|
||||
e1,
|
||||
e2,
|
||||
e3,
|
||||
}
|
||||
|
||||
enum {opt1,opt2}
|
||||
|
||||
class A
|
||||
{
|
||||
class AA
|
||||
{
|
||||
class AA1{}
|
||||
class AA2{}
|
||||
}
|
||||
|
||||
class BB
|
||||
{
|
||||
class BB1{}
|
||||
class BB2{}
|
||||
}
|
||||
}
|
||||
|
||||
enum SymbolType
|
||||
{
|
||||
_alias, // X
|
||||
_class, // X
|
||||
_enum, // X
|
||||
_function, // X
|
||||
_interface, // X
|
||||
_import, // X
|
||||
_mixin,
|
||||
_struct, // X
|
||||
_template, // X
|
||||
_union, // X
|
||||
_variable // X
|
||||
}
|
||||
|
||||
struct Symbol
|
||||
{
|
||||
int line;
|
||||
int col;
|
||||
string name;
|
||||
SymbolType type;
|
||||
Symbol * [] subs;
|
||||
|
||||
void serialize(ref Appender!string lfmApp)
|
||||
{
|
||||
lfmApp.put(" \r item\r");
|
||||
|
||||
lfmApp.put(format(" line = %d\r", line));
|
||||
lfmApp.put(format(" col = %d\r", col));
|
||||
lfmApp.put(format(" name = '%s'\r", name));
|
||||
lfmApp.put(format(" symType = %s\r", type));
|
||||
|
||||
lfmApp.put(" subs = <");
|
||||
if (subs.length) foreach(Symbol * sub; subs)
|
||||
sub.serialize(lfmApp);
|
||||
lfmApp.put(">\r");
|
||||
lfmApp.put(" end\r");
|
||||
}
|
||||
}
|
||||
|
||||
void main(string[] args)
|
||||
{
|
||||
if (args.length < 2) return;
|
||||
auto fname = args[1];
|
||||
if (!fname.exists) return;
|
||||
|
||||
// load and parse the file
|
||||
auto config = LexerConfig(fname, StringBehavior.source, WhitespaceBehavior.include);
|
||||
auto source = cast(ubyte[]) read(fname, size_t.max);
|
||||
auto scache = StringCache(StringCache.defaultBucketCount);
|
||||
auto ast = parseModule(getTokensForParser(source, config, &scache), fname);
|
||||
|
||||
// visit each root member
|
||||
auto slb = new SymbolListBuilder;
|
||||
foreach(Declaration decl; ast.declarations)
|
||||
{
|
||||
slb.resetRoot;
|
||||
slb.visit(decl);
|
||||
}
|
||||
|
||||
|
||||
// TODO-cfeature: Outputs the symbol tree in a format handlable by a Coedit widget
|
||||
|
||||
int level = -1;
|
||||
void print(Symbol * s)
|
||||
{
|
||||
foreach(i; 0 .. level) write(".");
|
||||
level++;
|
||||
write(s.name, '\r');
|
||||
foreach(ss; s.subs)
|
||||
print(ss);
|
||||
|
||||
level--;
|
||||
}
|
||||
//print(&slb.root);
|
||||
|
||||
auto str = slb.serialize;
|
||||
|
||||
//std.file.write(r"C:\too.txt",cast(ubyte[])str);
|
||||
|
||||
write(str);
|
||||
stdout.flush;
|
||||
}
|
||||
|
||||
class SymbolListBuilder : ASTVisitor
|
||||
{
|
||||
Symbol root;
|
||||
Symbol * parent;
|
||||
size_t count;
|
||||
|
||||
alias visit = ASTVisitor.visit;
|
||||
|
||||
this(){resetRoot;}
|
||||
|
||||
void resetRoot(){parent = &root;}
|
||||
|
||||
string serialize()
|
||||
{
|
||||
Appender!string lfmApp;
|
||||
lfmApp.reserve(count * 64);
|
||||
|
||||
lfmApp.put("object TSymbolList\r symbols = <");
|
||||
foreach(Symbol * sym; root.subs) sym.serialize(lfmApp);
|
||||
lfmApp.put(">\rend\r\n");
|
||||
|
||||
return lfmApp.data;
|
||||
|
||||
}
|
||||
|
||||
/// returns a new symbol if the declarator is based on a Token named "name".
|
||||
Symbol * addDeclaration(DT)(DT adt)
|
||||
{
|
||||
static if
|
||||
(
|
||||
is(DT == const(AliasInitializer)) ||
|
||||
is(DT == const(ClassDeclaration)) ||
|
||||
is(DT == const(Declarator)) ||
|
||||
is(DT == const(EnumDeclaration)) ||
|
||||
is(DT == const(FunctionDeclaration)) ||
|
||||
is(DT == const(InterfaceDeclaration)) ||
|
||||
is(DT == const(StructDeclaration)) ||
|
||||
is(DT == const(TemplateDeclaration)) ||
|
||||
is(DT == const(UnionDeclaration))
|
||||
|
||||
)
|
||||
{
|
||||
count++;
|
||||
auto result = new Symbol;
|
||||
result.name = adt.name.text.idup;
|
||||
result.line = adt.name.line;
|
||||
result.col = adt.name.column;
|
||||
parent.subs ~= result;
|
||||
return result;
|
||||
}
|
||||
|
||||
assert(0, "addDeclaration no implemented for " ~ DT.stringof);
|
||||
}
|
||||
|
||||
/// visitor implementation if the declarator is based on a Token named "name".
|
||||
void namedVisitorImpl(DT, SymbolType st, bool dig = true)(const(DT) dt)
|
||||
{
|
||||
auto newSymbol = addDeclaration(dt);
|
||||
newSymbol.type = st;
|
||||
//
|
||||
static if (dig)
|
||||
{
|
||||
auto previousParent = parent;
|
||||
scope(exit) parent = previousParent;
|
||||
parent = newSymbol;
|
||||
dt.accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
final override void visit(const AliasDeclaration decl)
|
||||
{
|
||||
// old alias syntax not supported by this.
|
||||
// why is initializers an array ?
|
||||
if (decl.initializers.length == 1)
|
||||
namedVisitorImpl!(AliasInitializer, SymbolType._alias)(decl.initializers[0]);
|
||||
}
|
||||
|
||||
final override void visit(const ClassDeclaration decl)
|
||||
{
|
||||
namedVisitorImpl!(ClassDeclaration, SymbolType._class)(decl);
|
||||
}
|
||||
|
||||
final override void visit(const EnumDeclaration decl)
|
||||
{
|
||||
// TODO-ctest: try to see if what dmd outputs as , "enum member" is handled.
|
||||
namedVisitorImpl!(EnumDeclaration, SymbolType._class)(decl);
|
||||
}
|
||||
|
||||
final override void visit(const FunctionDeclaration decl)
|
||||
{
|
||||
namedVisitorImpl!(FunctionDeclaration, SymbolType._function)(decl);
|
||||
}
|
||||
|
||||
final override void visit(const InterfaceDeclaration decl)
|
||||
{
|
||||
namedVisitorImpl!(InterfaceDeclaration, SymbolType._interface)(decl);
|
||||
}
|
||||
|
||||
final override void visit(const ImportDeclaration decl)
|
||||
{
|
||||
foreach(const(SingleImport) si; decl.singleImports)
|
||||
{
|
||||
if (!si.identifierChain.identifiers.length)
|
||||
continue;
|
||||
//
|
||||
string[] modules;
|
||||
foreach(ident; si.identifierChain.identifiers)
|
||||
{
|
||||
modules ~= ident.text;
|
||||
modules ~= ".";
|
||||
}
|
||||
//
|
||||
count++;
|
||||
auto result = new Symbol;
|
||||
result.name = modules[0..$-1].join;
|
||||
result.line = si.identifierChain.identifiers[0].line;
|
||||
result.col = si.identifierChain.identifiers[0].column;
|
||||
result.type = SymbolType._import;
|
||||
parent.subs ~= result;
|
||||
}
|
||||
}
|
||||
|
||||
final override void visit(const MixinDeclaration decl)
|
||||
{
|
||||
// TODO-cfeature: MixinDeclaration, just display the name of the mixed template.
|
||||
// the template might be implemented in another module so their ùeùbrs cant be displayed.
|
||||
}
|
||||
|
||||
final override void visit(const StructDeclaration decl)
|
||||
{
|
||||
namedVisitorImpl!(StructDeclaration, SymbolType._struct)(decl);
|
||||
}
|
||||
|
||||
final override void visit(const TemplateDeclaration decl)
|
||||
{
|
||||
namedVisitorImpl!(TemplateDeclaration, SymbolType._function)(decl);
|
||||
}
|
||||
|
||||
final override void visit(const UnionDeclaration decl)
|
||||
{
|
||||
namedVisitorImpl!(UnionDeclaration, SymbolType._function)(decl);
|
||||
}
|
||||
|
||||
final override void visit(const VariableDeclaration decl)
|
||||
{
|
||||
foreach(elem; decl.declarators)
|
||||
namedVisitorImpl!(Declarator, SymbolType._variable, false)(elem);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
ceSyms
|
||||
======
|
||||
|
||||
Tool designed to build a symbol tree for a particular D module.
|
||||
It's written in D using Coedit. To build it, [libdparse](https://github.com/Hackerpilot/libdparse)
|
||||
must be setup in the [libman](https://github.com/BBasile/Coedit/wiki#library-manager-widget)
|
||||
as described in this [tutorial](https://github.com/BBasile/Coedit/wiki#lets-build-a-static-library).
|
||||
|
||||
This tool is mandatory to enable the new _Symbol list widget_.
|
||||
If missing, the old _static explorer widget_ still does the same but it's from far less
|
||||
efficient since it actually compiles while only the AST is needed.
|
||||
|
||||
The new tool does not take the module correctness in account.
|
Loading…
Reference in New Issue