Skip to content

Commit

Permalink
Add ice2slice warnings when const values appears in .ice file (#3116)
Browse files Browse the repository at this point in the history
  • Loading branch information
pepone authored Nov 12, 2024
1 parent 55ecf16 commit a6bdeb2
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 38 deletions.
64 changes: 43 additions & 21 deletions cpp/src/ice2slice/Gen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#include "Gen.h"
#include "../Slice/Util.h"

#include <algorithm>
#include <cassert>

using namespace std;
Expand Down Expand Up @@ -345,61 +344,61 @@ Gen::Gen(const std::string& fileBase) : _fileBase(fileBase) {}
void
Gen::generate(const UnitPtr& p)
{
OutputVisitor outputVisitor;
p->visit(&outputVisitor);
OutputModulesVisitor outputModulesVisitor;
p->visit(&outputModulesVisitor);

TypesVisitor typesVisitor(_fileBase, outputVisitor.modules());
TypesVisitor typesVisitor(_fileBase, outputModulesVisitor.modules());
p->visit(&typesVisitor);
}

bool
Gen::OutputVisitor::visitClassDefStart(const ClassDefPtr& p)
Gen::OutputModulesVisitor::visitClassDefStart(const ClassDefPtr& p)
{
_modules.insert(p->scope());
return false;
}

bool
Gen::OutputVisitor::visitInterfaceDefStart(const InterfaceDefPtr& p)
Gen::OutputModulesVisitor::visitInterfaceDefStart(const InterfaceDefPtr& p)
{
_modules.insert(p->scope());
return false;
}

bool
Gen::OutputVisitor::visitExceptionStart(const ExceptionPtr& p)
Gen::OutputModulesVisitor::visitExceptionStart(const ExceptionPtr& p)
{
_modules.insert(p->scope());
return false;
}

bool
Gen::OutputVisitor::visitStructStart(const StructPtr& p)
Gen::OutputModulesVisitor::visitStructStart(const StructPtr& p)
{
_modules.insert(p->scope());
return false;
}

void
Gen::OutputVisitor::visitSequence(const SequencePtr& p)
Gen::OutputModulesVisitor::visitSequence(const SequencePtr& p)
{
_modules.insert(p->scope());
}

void
Gen::OutputVisitor::visitDictionary(const DictionaryPtr& p)
Gen::OutputModulesVisitor::visitDictionary(const DictionaryPtr& p)
{
_modules.insert(p->scope());
}

void
Gen::OutputVisitor::visitEnum(const EnumPtr& p)
Gen::OutputModulesVisitor::visitEnum(const EnumPtr& p)
{
_modules.insert(p->scope());
}

set<string>
Gen::OutputVisitor::modules() const
Gen::OutputModulesVisitor::modules() const
{
return _modules;
}
Expand All @@ -410,13 +409,24 @@ Gen::TypesVisitor::TypesVisitor(const std::string& fileBase, const std::set<std:
{
}

void
Gen::TypesVisitor::visitUnitEnd(const UnitPtr&)
{
// Append a newline to each generated file to ensure it ends properly.
for (const auto& [_, output] : _outputs)
{
*output << nl;
}
}

bool
Gen::TypesVisitor::visitClassDefStart(const ClassDefPtr& p)
{
ClassDefPtr base = p->base();
const string scope = p->scope();
Output& out = getOutput(p);

out << sp;
writeComment(p, out);

out << nl << "class " << p->name();
Expand All @@ -431,7 +441,6 @@ Gen::TypesVisitor::visitClassDefStart(const ClassDefPtr& p)

out.dec();
out << nl << "}";
out << nl;
return false;
}

Expand All @@ -442,6 +451,7 @@ Gen::TypesVisitor::visitInterfaceDefStart(const InterfaceDefPtr& p)
const string scope = p->scope();
Output& out = getOutput(p);

out << sp;
writeComment(p, out);
out << nl << "interface " << p->name();
if (bases.size() > 0)
Expand Down Expand Up @@ -518,11 +528,10 @@ Gen::TypesVisitor::visitInterfaceDefStart(const InterfaceDefPtr& p)
}
out.dec();
out << nl << "}";
out << sp;

out << sp;
out << nl << "[cs::type(\"" << typeToCsString(p->declaration(), false) << "\")]";
out << nl << "custom " << p->name() << "Proxy";
out << nl;
return false;
}

Expand All @@ -531,6 +540,8 @@ Gen::TypesVisitor::visitExceptionStart(const ExceptionPtr& p)
{
const string scope = p->scope();
Output& out = getOutput(p);

out << sp;
writeComment(p, out);
out << nl << "exception " << p->name();
if (ExceptionPtr base = p->base())
Expand All @@ -544,7 +555,6 @@ Gen::TypesVisitor::visitExceptionStart(const ExceptionPtr& p)

out.dec();
out << nl << "}";
out << nl;
return false;
}

Expand All @@ -553,6 +563,8 @@ Gen::TypesVisitor::visitStructStart(const StructPtr& p)
{
const string scope = p->scope();
Output& out = getOutput(p);

out << sp;
writeComment(p, out);
out << nl << "compact struct " << p->name() << " {";
out.inc();
Expand All @@ -561,7 +573,6 @@ Gen::TypesVisitor::visitStructStart(const StructPtr& p)

out.dec();
out << nl << "}";
out << nl;
return false;
}

Expand All @@ -571,6 +582,7 @@ Gen::TypesVisitor::visitSequence(const SequencePtr& p)
const string scope = p->scope();
Output& out = getOutput(p);

out << sp;
writeComment(p, out);
out << nl << "typealias " << p->name() << " = ";

Expand Down Expand Up @@ -601,7 +613,6 @@ Gen::TypesVisitor::visitSequence(const SequencePtr& p)
}
}
out << " Sequence<" << typeToString(p->type(), p->scope(), false) << ">";
out << nl;
}

void
Expand All @@ -610,6 +621,7 @@ Gen::TypesVisitor::visitDictionary(const DictionaryPtr& p)
const string scope = p->scope();
Output& out = getOutput(p);

out << sp;
writeComment(p, out);
out << nl << "typealias " << p->name() << " = ";

Expand All @@ -626,7 +638,6 @@ Gen::TypesVisitor::visitDictionary(const DictionaryPtr& p)
}
out << " Dictionary<" << typeToString(p->keyType(), p->scope(), false) << ", "
<< typeToString(p->valueType(), p->scope(), false) << ">";
out << nl;
}

void
Expand All @@ -635,6 +646,7 @@ Gen::TypesVisitor::visitEnum(const EnumPtr& p)
const string scope = p->scope();
Output& out = getOutput(p);

out << sp;
writeComment(p, out);
out << nl << "enum " << p->name() << " {";
out.inc();
Expand All @@ -649,7 +661,18 @@ Gen::TypesVisitor::visitEnum(const EnumPtr& p)
}
out.dec();
out << nl << "}";
out << nl;
}

void
Slice::Gen::TypesVisitor::visitConst(const ConstPtr& p)
{
Output& out = getOutput(p);
out << sp;
out << nl << "// ice2slice could not convert:";
out << nl << "// const " << p->type()->typeId() << " " << p->name() << " = " << p->value();

p->unit()
->warning(p->file(), p->line(), WarningCategory::All, "ice2slice could not convert constant: " + p->name());
}

// Get the output stream where to write the mapped Slice construct, creating a new output stream if necessary. The
Expand Down Expand Up @@ -687,7 +710,6 @@ Gen::TypesVisitor::getOutput(const ContainedPtr& contained)
string moduleName = scope.substr(2).substr(0, scope.size() - 4);

*out << nl << "module " << moduleName;
*out << nl;
auto inserted = _outputs.emplace(scope, std::move(out));
return *(inserted.first->second);
}
Expand Down
51 changes: 34 additions & 17 deletions cpp/src/ice2slice/Gen.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,35 +22,52 @@ namespace Slice
private:
std::string _fileBase;

class OutputVisitor : public ParserVisitor
/// The OutputModulesVisitor class gathers a list of modules requiring the generation of output `.slice` files.
/// Each `.ice` file may correspond to multiple `.slice` files, with one for each module that contains Slice
/// definitions.
class OutputModulesVisitor final : public ParserVisitor
{
public:
virtual bool visitClassDefStart(const ClassDefPtr&);
virtual bool visitInterfaceDefStart(const InterfaceDefPtr&);
virtual bool visitExceptionStart(const ExceptionPtr&);
virtual bool visitStructStart(const StructPtr&);
virtual void visitSequence(const SequencePtr&);
virtual void visitDictionary(const DictionaryPtr&);
virtual void visitEnum(const EnumPtr&);
bool visitClassDefStart(const ClassDefPtr&) final;
bool visitInterfaceDefStart(const InterfaceDefPtr&) final;
bool visitExceptionStart(const ExceptionPtr&) final;
bool visitStructStart(const StructPtr&) final;
void visitSequence(const SequencePtr&) final;
void visitDictionary(const DictionaryPtr&) final;
void visitEnum(const EnumPtr&) final;

/// After visiting all definitions, return the list of scopes corresponding to modules for which we need
/// to generate an output `.slice`.
/// @return The list of modules for which we need to generate an output `.slice`.
std::set<std::string> modules() const;

private:
std::set<std::string> _modules;
};

class TypesVisitor : public ParserVisitor
/// The TypesVisitor class converts Slice definitions in `.ice` files to corresponding Slice definitions in
/// `.slice` files.
///
/// If the `.ice` file contains a single module, the output is a single `.slice` file with the same base name,
/// replacing the `.ice` extension with `.slice`.
///
/// If the `.ice` file contains multiple modules, it generates a `.slice` file for each module. Each file uses
/// the base name of the `.ice` file, appending the module scope with "::" replaced by "_" and the `.slice`
/// extension.
class TypesVisitor final : public ParserVisitor
{
public:
TypesVisitor(const std::string&, const std::set<std::string>&);
TypesVisitor(const std::string& fileBase, const std::set<std::string>& modules);

virtual bool visitClassDefStart(const ClassDefPtr&);
virtual bool visitInterfaceDefStart(const InterfaceDefPtr&);
virtual bool visitExceptionStart(const ExceptionPtr&);
virtual bool visitStructStart(const StructPtr&);
virtual void visitSequence(const SequencePtr&);
virtual void visitDictionary(const DictionaryPtr&);
virtual void visitEnum(const EnumPtr&);
void visitUnitEnd(const UnitPtr&) final;
bool visitClassDefStart(const ClassDefPtr&) final;
bool visitInterfaceDefStart(const InterfaceDefPtr&) final;
bool visitExceptionStart(const ExceptionPtr&) final;
bool visitStructStart(const StructPtr&) final;
void visitSequence(const SequencePtr&) final;
void visitDictionary(const DictionaryPtr&) final;
void visitEnum(const EnumPtr&) final;
void visitConst(const ConstPtr&) final;

private:
IceInternal::Output& getOutput(const ContainedPtr&);
Expand Down

0 comments on commit a6bdeb2

Please sign in to comment.