mirror of https://gitlab.com/basile.b/dexed.git
202 lines
6.3 KiB
D
202 lines
6.3 KiB
D
module ddoc_template;
|
|
|
|
import
|
|
core.stdc.string;
|
|
import
|
|
std.array, std.conv, std.string;
|
|
import
|
|
iz.memory, iz.sugar;
|
|
import
|
|
dparse.ast, dparse.lexer, dparse.parser, dparse.rollback_allocator;
|
|
import
|
|
common;
|
|
|
|
/**
|
|
* Finds the declaration at caretLine and write its ddoc template
|
|
* and returns its DDOC template as a C string.
|
|
*
|
|
* Params:
|
|
* src = the module source code, as a C string.
|
|
* caretLine = the line where the declaration is located.
|
|
* plusComment = indicates if the template use the "*" or the "+" decoration.
|
|
*/
|
|
export extern(C) const(char)* ddocTemplate(const(char)* src, int caretLine, bool plusComment)
|
|
{
|
|
LexerConfig config;
|
|
RollbackAllocator rba;
|
|
StringCache sCache = StringCache(StringCache.defaultBucketCount);
|
|
|
|
scope mod = src[0 .. src.strlen]
|
|
.getTokensForParser(config, &sCache)
|
|
.parseModule("", &rba, &ignoreErrors);
|
|
|
|
DDocTemplateGenerator dtg = construct!DDocTemplateGenerator(caretLine, plusComment);
|
|
scope(exit) destruct(dtg);
|
|
dtg.visit(mod);
|
|
|
|
return dtg.result;
|
|
}
|
|
|
|
private void putLine(T...)(ref Appender!string a, T t)
|
|
{
|
|
static foreach (i; 0 .. T.length)
|
|
a.put(t[i].to!string);
|
|
a.put("\n");
|
|
}
|
|
|
|
final class DDocTemplateGenerator: ASTVisitor
|
|
{
|
|
alias visit = ASTVisitor.visit;
|
|
|
|
private:
|
|
|
|
immutable int _caretline;
|
|
immutable char c1;
|
|
immutable char[2] c2;
|
|
Appender!string app;
|
|
bool _throws;
|
|
|
|
public:
|
|
|
|
this(int caretline, bool plusComment)
|
|
{
|
|
_caretline = caretline;
|
|
c1 = plusComment ? '+' : '*';
|
|
c2 = plusComment ? "++" : "**";
|
|
}
|
|
|
|
const(char)* result() { return app.data.toStringz(); }
|
|
|
|
override void visit(const(ThrowStatement) ts)
|
|
{
|
|
_throws = true;
|
|
}
|
|
|
|
override void visit(const(Catch) c)
|
|
{
|
|
_throws = false;
|
|
}
|
|
|
|
override void visit(const(FunctionDeclaration) decl)
|
|
{
|
|
_throws = false;
|
|
if (decl.name.line == _caretline)
|
|
{
|
|
decl.accept(this);
|
|
app.putLine("/", c2, "\n ", c1, " <short description> \n ", c1, " \n ", c1, " <detailed description>", c1);
|
|
|
|
const TemplateParameterList tpl = safeAccess(decl).templateParameters.templateParameterList;
|
|
if ((tpl && tpl.items.length) ||
|
|
(decl.parameters && decl.parameters.parameters.length))
|
|
{
|
|
app.putLine(" ", c1, " \n ", c1, " Params:");
|
|
|
|
if (tpl)
|
|
{
|
|
foreach(const TemplateParameter p; tpl.items)
|
|
{
|
|
if (p.templateAliasParameter)
|
|
app.putLine(" ", c1, " ", p.templateAliasParameter.identifier.text, " = <description>");
|
|
else if (p.templateTupleParameter)
|
|
app.putLine(" ", c1, " ", p.templateTupleParameter.identifier.text, " = <description>");
|
|
else if (p.templateTypeParameter)
|
|
app.putLine(" ", c1, " ", p.templateTypeParameter.identifier.text, " = <description>");
|
|
else if (p.templateValueParameter)
|
|
app.putLine(" ", c1, " ", p.templateValueParameter.identifier.text, " = <description>");
|
|
}
|
|
}
|
|
if (decl.parameters)
|
|
{
|
|
foreach(i, const Parameter p; decl.parameters.parameters)
|
|
{
|
|
if (p.name.text != "")
|
|
app.putLine(" ", c1, " ", p.name.text, " = <description>");
|
|
else
|
|
app.putLine(" ", c1, " __param", i, " = <description>");
|
|
}
|
|
}
|
|
}
|
|
|
|
if (const Type2 tp2 = safeAccess(decl).returnType.type2)
|
|
{
|
|
if (tp2.builtinType != tok!"void")
|
|
app.putLine(" ", c1, " \n ", c1, " Returns: <return description>");
|
|
}
|
|
|
|
if (_throws)
|
|
{
|
|
app.putLine(" ", c1, " \n ", c1, " Throws: <exception type as hint for catch>");
|
|
}
|
|
|
|
app.putLine(" ", c1, "/");
|
|
|
|
}
|
|
else if (decl.name.line > _caretline)
|
|
return;
|
|
}
|
|
|
|
override void visit(const(TemplateDeclaration) decl)
|
|
{
|
|
visitTemplateOrAggregate(decl);
|
|
}
|
|
|
|
override void visit(const(ClassDeclaration) decl)
|
|
{
|
|
visitTemplateOrAggregate(decl);
|
|
}
|
|
|
|
override void visit(const(StructDeclaration) decl)
|
|
{
|
|
visitTemplateOrAggregate(decl);
|
|
}
|
|
|
|
override void visit(const(UnionDeclaration) decl)
|
|
{
|
|
visitTemplateOrAggregate(decl);
|
|
}
|
|
|
|
override void visit(const(AutoDeclarationPart) decl)
|
|
{
|
|
if (decl.templateParameters)
|
|
visitTemplateOrAggregate(decl);
|
|
}
|
|
|
|
private void visitTemplateOrAggregate(T)(const(T) decl)
|
|
{
|
|
size_t line;
|
|
static if (__traits(hasMember, T, "name"))
|
|
line = decl.name.line;
|
|
else
|
|
line = decl.identifier.line;
|
|
|
|
if (_caretline == line)
|
|
{
|
|
app.putLine("/", c2, "\n ", c1, " <short description> \n ", c1, " \n ", c1, " <detailed description>", c1);
|
|
|
|
const TemplateParameterList tpl = safeAccess(decl).templateParameters.templateParameterList;
|
|
if (tpl && tpl.items.length)
|
|
{
|
|
app.putLine(" ", c1, " \n ", c1, " Params:");
|
|
|
|
foreach(const TemplateParameter p; tpl.items)
|
|
{
|
|
if (p.templateAliasParameter)
|
|
app.putLine(" ", c1, " ", p.templateAliasParameter.identifier.text, " = <description>");
|
|
else if (p.templateTupleParameter)
|
|
app.putLine(" ", c1, " ", p.templateTupleParameter.identifier.text, " = <description>");
|
|
else if (p.templateTypeParameter)
|
|
app.putLine(" ", c1, " ", p.templateTypeParameter.identifier.text, " = <description>");
|
|
else if (p.templateValueParameter)
|
|
app.putLine(" ", c1, " ", p.templateValueParameter.identifier.text, " = <description>");
|
|
}
|
|
}
|
|
app.putLine(" ", c1, "/");
|
|
|
|
}
|
|
else if (line > _caretline)
|
|
return;
|
|
decl.accept(this);
|
|
}
|
|
}
|
|
|