Skip to content

Commit

Permalink
Merge pull request #175 from snowball-lang/170-finish-for-variables
Browse files Browse the repository at this point in the history
Added support for variables in documentation generator
  • Loading branch information
mauro-balades authored Dec 25, 2023
2 parents c28ec52 + dbddcbd commit a910e3e
Show file tree
Hide file tree
Showing 10 changed files with 144 additions and 32 deletions.
2 changes: 1 addition & 1 deletion app/commands/docgen.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ int docgen(app::Options::DocsOptions p_opts) {

auto start = high_resolution_clock::now();

int status = compiler->emitDocs(folder, baseURL, package_name, p_opts.silent);
int status = compiler->emitDocs(folder, baseURL, {.name = package_name, .version = package_version}, p_opts.silent);
auto stop = high_resolution_clock::now();

// Get duration. Substart timepoints to
Expand Down
5 changes: 3 additions & 2 deletions src/compiler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ void Compiler::compile(bool silent) {

using recursive_directory_iterator = std::filesystem::recursive_directory_iterator;

int Compiler::emitDocs(std::string folder, std::string baseURL, std::string package_name, bool silent) {
int Compiler::emitDocs(std::string folder, std::string baseURL, BasicPackageInfo package, bool silent) {
auto path = cwd / folder;
auto outputFolder = configFolder / "docs";

Expand All @@ -153,7 +153,7 @@ int Compiler::emitDocs(std::string folder, std::string baseURL, std::string pack
}
}
}
fs::path relativePath = package_name;
fs::path relativePath = package.name;
int i = 0;
for (auto& part : relative) {
if (i == 0) {
Expand Down Expand Up @@ -183,6 +183,7 @@ int Compiler::emitDocs(std::string folder, std::string baseURL, std::string pack
.currentModulePath = relativePath.string(),

.baseURL = baseURL,
.packageVersion = package.version,
};
auto docGen = new Syntax::DocGen(context);
docGen->run(ast);
Expand Down
7 changes: 6 additions & 1 deletion src/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,17 @@ class Compiler {
std::vector<std::string> linkedLibraries;
fs::path configFolder;

struct BasicPackageInfo {
std::string name;
std::string version;
};

int emitBinary(std::string, bool = true);
int emitObject(std::string, bool = true);
int emitLLVMIr(std::string, bool = true);
int emitASM(std::string, bool = true);
int emitSnowballIr(std::string, bool = true);
int emitDocs(std::string, std::string, std::string, bool = true);
int emitDocs(std::string, std::string, BasicPackageInfo, bool = true);

GlobalContext* getGlobalContext() { return globalContext; }

Expand Down
2 changes: 1 addition & 1 deletion src/parser/parseClass.cc
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ Syntax::Statement::DefinedTypeDef* Parser::parseClass() {
);
}

if (pk.type != TokenType::KWORD_FUNC && pk.type != TokenType::KWORD_VAR &&
if (pk.type != TokenType::KWORD_FUNC &&
pk.type != TokenType::KWORD_OPERATOR && pk.type != TokenType::KWORD_UNSAFE && (!IS_CONSTRUCTOR(pk))) {
next();
createError<SYNTAX_ERROR>("expected keyword \"fn\", \"let\", \"operator\", \"unsafe\" or a "
Expand Down
14 changes: 14 additions & 0 deletions src/parser/parseConstant.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,26 @@ Syntax::Statement::VariableDecl* Parser::parseConstant() {
next();
bool isPublic = false;
bool isExternal = false;
bool isStatic = false;
if (is<TokenType::KWORD_PUBLIC, TokenType::KWORD_PRIVATE>(peek(-3, true))) {
isPublic = is<TokenType::KWORD_PUBLIC>(peek(-3, true));
} else if (is<TokenType::KWORD_EXTERN>(peek(-3, true))) {
isExternal = true;
isPublic = is<TokenType::KWORD_PUBLIC>(peek(-4, true));
} else if (is<TokenType::KWORD_STATIC>(peek(-3, true))) {
isStatic = true;
isPublic = is<TokenType::KWORD_PUBLIC>(peek(-4, true));
}

if (!isStatic && m_current_class != nullptr) {
createError<SYNTAX_ERROR>("Cannot declare a non-static constant inside a class", {
.info = "Not static constant",
.note = "This is because constants are not tied to a specific instance of a class,\n"
"and therefore cannot be accessed from an instance of a class",
.help = "Make the constant static by adding the 'static' keyword\nbefore the 'const' keyword",
});
}

auto token = assert_tok<TokenType::IDENTIFIER>("an identifier");
next(); // consume identifier
auto name = token.to_string();
Expand Down
15 changes: 14 additions & 1 deletion src/visitors/documentation/DocGen.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,19 @@ SN_DOCGEN_VISIT(Statement::ForLoop) {}
SN_DOCGEN_VISIT(Statement::Conditional) {}
SN_DOCGEN_VISIT(Statement::LoopFlow) {}

SN_DOCGEN_VISIT(Statement::VariableDecl) {} // TODO:
SN_DOCGEN_VISIT(Statement::VariableDecl) {
auto rawName = p_node->getName();
auto [name, path] = getFullName(rawName);

auto newPage = DocumentationPage {
.name = name,
.path = path + "-var.html",
.type = DocumentationPage::Type::Function,
};

docgen::createVariablePage(p_node, context, newPage);
result.pages.push_back(newPage);
}

SN_DOCGEN_VISIT(Statement::Namespace) {
auto [name, path] = getFullName(p_node->getName());
Expand Down Expand Up @@ -65,6 +77,7 @@ SN_DOCGEN_VISIT(Statement::DefinedTypeDef) {
context.currentType = name;
context.currentTypePath = path;
for (auto& func : p_node->getFunctions()) { func->accept(this); }
for (auto& var : p_node->getVariables()) { var->accept(this); }

context.currentType = backup;
context.currentTypePath = backupPath;
Expand Down
1 change: 1 addition & 0 deletions src/visitors/documentation/DocGen.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ struct DocGenContext {
std::string currentTypePath = "";

std::string baseURL;
std::string packageVersion;
};

/**
Expand Down
105 changes: 81 additions & 24 deletions src/visitors/documentation/DocTemplates.cc
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ std::string getPageTemplate(DocGenContext context, std::string title, std::strin
linksHTML += "<a href=\"" + resultLink + ".html\">" + resultName + "</a> ";
}
nameCount.clear();
return FMT(pageTemplate.c_str(), title.c_str(), context.baseURL.c_str(), parent.c_str(), linksHTML.c_str(), body.c_str());
return FMT(pageTemplate.c_str(), title.c_str(), context.baseURL.c_str(), context.currentModule.c_str(), context.packageVersion.c_str(), linksHTML.c_str(), body.c_str());
}

namespace {
Expand Down Expand Up @@ -337,7 +337,7 @@ void createTypePage(Statement::DefinedTypeDef* node, DocGenContext context, Docu
}

if (publicMembers.size() > 0)
body += " {\npublic:";
body += " {\n public:";
else body += " {\n";
for (auto& field : publicMembers) {
if (field->getComment()) {
Expand Down Expand Up @@ -374,19 +374,32 @@ void createTypePage(Statement::DefinedTypeDef* node, DocGenContext context, Docu
}
}

if (publicMembers.size() > 0) {
body += "<hr/><h1 style=\"color:rgb(14 116 144);\">Public Fields</h1>";
for (auto& field : publicMembers) {
body += "<div style=\"display: grid; grid-template-columns: 1fr 1fr 1fr;\"><a href=\"" + page.path.string().substr(0, page.path.string().size() - 5) + "/" + field->getName() + "-var.html\"><h1 style=\"color:rgb(14 116 144);margin-right: 10px;font-weight: normal;\">" + field->getName();
if (field->isContantDecl()) body += "<span class=\"tag\">static const</span>";
body += "</h1></a>";
if (field->getComment()) {
auto values = field->getComment()->getValues();
if (values.count("brief")) {
auto brief = sanitize(values["brief"]);
utils::replaceAll(brief, "<br/>", " ");
body += "<span>" + brief + "</span>";
}
}
body += "</div>";
}
}

if (node->getFunctions().size() > 0) {
std::vector<Statement::FunctionDef*> publicFunctions;
std::vector<Statement::FunctionDef*> publicStaticFunctions;
std::vector<Statement::FunctionDef*> privateFunctions;
std::vector<Statement::FunctionDef*> privateStaticFunctions;

for (auto& func : node->getFunctions()) {
if (func->isPublic()) {
if (func->isStatic()) publicStaticFunctions.push_back(func);
else publicFunctions.push_back(func);
} else {
if (func->isStatic()) privateStaticFunctions.push_back(func);
else privateFunctions.push_back(func);
}
}

Expand All @@ -404,20 +417,6 @@ void createTypePage(Statement::DefinedTypeDef* node, DocGenContext context, Docu
}
}

if (privateFunctions.size() > 0) {
body += "<hr/><h1 style=\"color:rgb(14 116 144);\">Private Functions</h1>";
for (auto& func : privateFunctions) {
createSmallPictureFn(func, context, body);
}
}

if (privateStaticFunctions.size() > 0) {
body += "<hr/><h1 style=\"color:rgb(14 116 144);\">Private Static Functions</h1>";
for (auto& func : privateStaticFunctions) {
createSmallPictureFn(func, context, body);
}
}

body += "<br/><br/><br/>";
}

Expand Down Expand Up @@ -549,7 +548,7 @@ void createModulePage(std::vector<Syntax::Node*> nodes, DocGenContext context, D
if (variables.size() > 0) {
body += "<br/><h1 style=\"font-size: 25px;\">Variables exported from " + utils::join(nameParts.begin(), nameParts.end(), "::") + "</h1><br/>";
for (auto& var : variables) {
auto varUrl = page.path.string().substr(0, page.path.string().size() - 5) + "/" + var->getName() + ".html";
auto varUrl = page.path.string().substr(0, page.path.string().size() - 5) + "/" + var->getName() + "-var.html";
body += "<div style=\"display: grid; grid-template-columns: 1fr 1fr 1fr;\"><a href=" + varUrl + "><h1 style=\"color:rgb(14 116 144);margin-right: 10px;font-weight: normal;\">" + var->getName() + "</h1></a>";
if (var->getComment()) {
auto values = var->getComment()->getValues();
Expand Down Expand Up @@ -715,7 +714,7 @@ void createNamespacePage(Statement::Namespace* node, DocGenContext context, Docu
if (types.size() > 0) {
body += "<br/><h1 style=\"font-size: 25px;\">Types exported from " + utils::join(nameParts.begin(), nameParts.end(), "::") + "</h1><br/>";
for (auto& type : types) {
auto typeUrl = page.path.string().substr(0, page.path.string().size() - 5) + "/" + type->getName() + ".html";
auto typeUrl = page.path.string().substr(0, page.path.string().size() - 5) + "/" + type->getName() + "-var.html";
body += "<div style=\"display: grid; grid-template-columns: 1fr 1fr 1fr;\"><a href=" + typeUrl + "><h1 style=\"color:rgb(14 116 144);margin-right: 10px;font-weight: normal;\">" + type->getName() + "</h1></a>";
if (type->getComment()) {
auto values = type->getComment()->getValues();
Expand Down Expand Up @@ -766,7 +765,7 @@ void createNamespacePage(Statement::Namespace* node, DocGenContext context, Docu
if (variables.size() > 0) {
body += "<br/><h1 style=\"font-size: 25px;\">Variables exported from " + utils::join(nameParts.begin(), nameParts.end(), "::") + "</h1><br/>";
for (auto& var : variables) {
auto varUrl = page.path.string().substr(0, page.path.string().size() - 5) + "/" + var->getName() + ".html";
auto varUrl = page.path.string().substr(0, page.path.string().size() - 5) + "/" + var->getName() + "-var.html";
body += "<div style=\"display: grid; grid-template-columns: 1fr 1fr 1fr;\"><a href=" + varUrl + "><h1 style=\"color:rgb(14 116 144);margin-right: 10px;font-weight: normal;\">" + var->getName() + "</h1></a>";
if (var->getComment()) {
auto values = var->getComment()->getValues();
Expand Down Expand Up @@ -802,6 +801,64 @@ void createNamespacePage(Statement::Namespace* node, DocGenContext context, Docu
page.html = getPageTemplate(context, page.name, body);
}

void createVariablePage(Statement::VariableDecl* node, DocGenContext context, DocumentationPage& page) {
std::string body = "";
body += "<h1>";

auto pathParts = page.path;
auto nameParts = utils::list2vec(utils::split(page.name, "::"));
int i = 0;
for (auto _:pathParts) {
std::string url = "";
int j = 0;
for (auto part : pathParts) {
if (j == i) {
url += part.string();
if (utils::endsWith(part.string(), ".html"))
url = url.substr(0, url.size() - 5);
break;
} else {
url += part.string() + "/";
}
j++;
}
body += "<a style=\"color:rgb(14 116 144);\" href=\"" + url + ".html\">" + nameParts[i] + "</a>::";
i++;
}
body = body.substr(0, body.size() - 2) + ";"; // remove the last "::"
if (!context.currentType.empty()) {
if (node->isContantDecl())
body += "<span class=\"tag\">static object constant</span> ";
else body += "<span class=\"tag\">object field</span> ";
}
body += "</h1><hr/><div><pre><code class=\"language-snowball\">";

auto varName = node->getName();
if (!context.currentType.empty()) {
varName = "Self::" + varName;
}
body += (std::string)(node->isContantDecl() ? "const " : "let ") + varName + ": " + typeToHtml(node->getDefinedType()) + " = ...";

body += "</code></pre></div><br><div class=\"doc\">";

if (auto docString = node->getComment()) {
auto values = docString->getValues();
if (values.count("brief")) {
body += "<h1 style=\"color:rgb(14 116 144);\">Brief Description for <quote>" + node->getName() + "</quote></h1>";
body += "<p>" + sanitize(values["brief"]) + "</p>";
}
body += "<p>" + sanitize(docString->getBody()) + "</p>";

for (auto& [tag, value] : values) {
if (tag == "brief") continue;
}
}

body += "<br/><br/></div>";

page.html = getPageTemplate(context, page.name, body);
}

} // namespace docgen
} // namespace Syntax
} // namespace snowball
14 changes: 12 additions & 2 deletions src/visitors/documentation/DocTemplates.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ static const std::string pageTemplate = R"(
</head>
<body>
<sidenav>
<h1>
%s
<h1 style="display: flex; align-items: center;">
%s <span class="tag">version %s</span>
</h1>
<hr />
%s
Expand Down Expand Up @@ -109,6 +109,16 @@ void createMacroPage(Macro* node, DocGenContext context, DocumentationPage& page
* @ingroup docgen
*/
void createNamespacePage(Statement::Namespace* node, DocGenContext context, DocumentationPage& page);
/**
* @brief Creates a documentation page for a variable.
*
* @param node The variable node.
* @param context The documentation generator context.
* @param page The documentation page.
* @return DocumentationPage The documentation page.
* @ingroup docgen
*/
void createVariablePage(Statement::VariableDecl* node, DocGenContext context, DocumentationPage& page);

} // namespace docgen
} // namespace Syntax
Expand Down
11 changes: 11 additions & 0 deletions tests/cls.sn
Original file line number Diff line number Diff line change
Expand Up @@ -131,4 +131,15 @@ func inheritance_virtual() i32 {
return t.test();
}

class StaticVariableAccessTest {
public:
static const A: i32 = 0;
StaticVariableAccessTest() {}
}

@test(expect = 0)
func static_variable_access() i32 {
return StaticVariableAccessTest::A;
}

}

0 comments on commit a910e3e

Please sign in to comment.