-
Notifications
You must be signed in to change notification settings - Fork 592
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use the 'New' Metadata Validator for slice2swift
#3530
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ | |
|
||
#include "SwiftUtil.h" | ||
#include "../Ice/OutputUtil.h" | ||
#include "../Slice/MetadataValidation.h" | ||
#include "../Slice/Util.h" | ||
|
||
#include <algorithm> | ||
|
@@ -615,8 +616,104 @@ SwiftGenerator::writeServantDocSummary(IceInternal::Output& out, const Interface | |
void | ||
SwiftGenerator::validateMetadata(const UnitPtr& u) | ||
{ | ||
MetadataVisitor visitor; | ||
u->visit(&visitor); | ||
map<string, MetadataInfo> knownMetadata; | ||
|
||
// "swift:attribute" | ||
MetadataInfo attributeInfo = { | ||
.validOn = {typeid(ClassDecl), typeid(Struct), typeid(Slice::Exception), typeid(Enum)}, | ||
.acceptedArgumentKind = MetadataArgumentKind::RequiredTextArgument, | ||
.mustBeUnique = false, | ||
}; | ||
knownMetadata.emplace("swift:attribute", attributeInfo); | ||
|
||
// "swift:class-resolver-prefix" | ||
MetadataInfo classResolverPrefixInfo = { | ||
.validOn = {typeid(Unit)}, | ||
.acceptedArgumentKind = MetadataArgumentKind::SingleArgument, | ||
}; | ||
knownMetadata.emplace("swift:class-resolver-prefix", classResolverPrefixInfo); | ||
|
||
// "swift:inherits" | ||
MetadataInfo inheritsInfo = { | ||
.validOn = {typeid(InterfaceDecl)}, | ||
.acceptedArgumentKind = MetadataArgumentKind::RequiredTextArgument, | ||
.mustBeUnique = false, | ||
}; | ||
knownMetadata.emplace("swift:inherits", inheritsInfo); | ||
|
||
// "swift:module" | ||
MetadataInfo moduleInfo = { | ||
.validOn = {typeid(Module)}, | ||
// Even though it's really 'module:prefix' the validator sees this as a single argument since there's no commas. | ||
.acceptedArgumentKind = MetadataArgumentKind::SingleArgument, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should drop the MetadataArgumentKind::MultipleArguments (?) option since we don't use it for any Slice metadata except support warnings. |
||
}; | ||
knownMetadata.emplace("swift:module", moduleInfo); | ||
|
||
// Pass this information off to the parser's metadata validation logic. | ||
Slice::validateMetadata(u, "swift", knownMetadata); | ||
} | ||
|
||
void | ||
SwiftGenerator::validateSwiftModuleMappings(const UnitPtr& unit) | ||
Comment on lines
+656
to
+657
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All this code was just moved out of |
||
{ | ||
using ModuleMap = std::map<std::string, std::string>; | ||
// Each Slice unit has to map all top-level modules to a single Swift module | ||
ModuleMap mappedModules; | ||
// With a given Swift module a Slice module has to map to a single prefix | ||
std::map<std::string, ModuleMap> mappedModulePrefixes; | ||
|
||
// Any modules that are directly contained on the unit are (by definition) top-level modules. | ||
// And since there is only one unit per compilation, this must be all the top-level modules. | ||
for (const auto& module : unit->modules()) | ||
{ | ||
string swiftPrefix; | ||
string swiftModule = getSwiftModule(module, swiftPrefix); | ||
|
||
const string filename = module->definitionContext()->filename(); | ||
auto current = mappedModules.find(filename); | ||
|
||
if (current == mappedModules.end()) | ||
{ | ||
mappedModules[filename] = swiftModule; | ||
} | ||
else if (current->second != swiftModule) | ||
{ | ||
ostringstream os; | ||
os << "invalid module mapping:\n Slice module '" << module->scoped() << "' should map to Swift module '" | ||
<< current->second << "'" << endl; | ||
unit->error(module->file(), module->line(), os.str()); | ||
} | ||
|
||
auto prefixes = mappedModulePrefixes.find(swiftModule); | ||
if (prefixes == mappedModulePrefixes.end()) | ||
{ | ||
ModuleMap mappings; | ||
mappings[module->name()] = swiftPrefix; | ||
mappedModulePrefixes[swiftModule] = mappings; | ||
} | ||
else | ||
{ | ||
current = prefixes->second.find(module->name()); | ||
if (current == prefixes->second.end()) | ||
{ | ||
prefixes->second[module->name()] = swiftPrefix; | ||
} | ||
else if (current->second != swiftPrefix) | ||
{ | ||
ostringstream os; | ||
os << "invalid module prefix:\n Slice module '" << module->scoped() << "' is already using"; | ||
if (current->second.empty()) | ||
{ | ||
os << " no prefix " << endl; | ||
} | ||
else | ||
{ | ||
os << " a different Swift module prefix '" << current->second << "'" << endl; | ||
} | ||
unit->error(module->file(), module->line(), os.str()); | ||
} | ||
} | ||
} | ||
} | ||
|
||
string | ||
|
@@ -1265,78 +1362,6 @@ SwiftGenerator::writeMarshalUnmarshalCode( | |
} | ||
} | ||
|
||
bool | ||
SwiftGenerator::MetadataVisitor::visitUnitStart(const UnitPtr& unit) | ||
{ | ||
using ModuleMap = std::map<std::string, std::string>; | ||
// Each Slice unit has to map all top-level modules to a single Swift module | ||
ModuleMap mappedModules; | ||
// With a given Swift module a Slice module has to map to a single prefix | ||
std::map<std::string, ModuleMap> mappedModulePrefixes; | ||
|
||
// Any modules that are directly contained on the unit are (by definition) top-level modules. | ||
// And since there is only one unit per compilation, this must be all the top-level modules. | ||
for (const auto& module : unit->modules()) | ||
{ | ||
string swiftPrefix; | ||
string swiftModule = getSwiftModule(module, swiftPrefix); | ||
|
||
const string filename = module->definitionContext()->filename(); | ||
auto current = mappedModules.find(filename); | ||
|
||
if (current == mappedModules.end()) | ||
{ | ||
mappedModules[filename] = swiftModule; | ||
} | ||
else if (current->second != swiftModule) | ||
{ | ||
ostringstream os; | ||
os << "invalid module mapping:\n Slice module '" << module->scoped() << "' should map to Swift module '" | ||
<< current->second << "'" << endl; | ||
unit->error(module->file(), module->line(), os.str()); | ||
} | ||
|
||
auto prefixes = mappedModulePrefixes.find(swiftModule); | ||
if (prefixes == mappedModulePrefixes.end()) | ||
{ | ||
ModuleMap mappings; | ||
mappings[module->name()] = swiftPrefix; | ||
mappedModulePrefixes[swiftModule] = mappings; | ||
} | ||
else | ||
{ | ||
current = prefixes->second.find(module->name()); | ||
if (current == prefixes->second.end()) | ||
{ | ||
prefixes->second[module->name()] = swiftPrefix; | ||
} | ||
else if (current->second != swiftPrefix) | ||
{ | ||
ostringstream os; | ||
os << "invalid module prefix:\n Slice module '" << module->scoped() << "' is already using"; | ||
if (current->second.empty()) | ||
{ | ||
os << " no prefix " << endl; | ||
} | ||
else | ||
{ | ||
os << " a different Swift module prefix '" << current->second << "'" << endl; | ||
} | ||
unit->error(module->file(), module->line(), os.str()); | ||
} | ||
} | ||
} | ||
|
||
return true; | ||
} | ||
|
||
bool | ||
SwiftGenerator::MetadataVisitor::visitModuleStart(const ModulePtr& p) | ||
{ | ||
p->setMetadata(validate(p, p)); | ||
return true; | ||
} | ||
|
||
string | ||
SwiftGenerator::paramLabel(const string& param, const ParameterList& params) | ||
{ | ||
|
@@ -2018,143 +2043,3 @@ SwiftGenerator::writeDispatchOperation(::IceInternal::Output& out, const Operati | |
|
||
out << eb; | ||
} | ||
|
||
bool | ||
SwiftGenerator::MetadataVisitor::visitClassDefStart(const ClassDefPtr& p) | ||
{ | ||
p->setMetadata(validate(p, p)); | ||
for (const auto& member : p->dataMembers()) | ||
{ | ||
// TODO we should probably be passing `member` instead of `member->type()`. | ||
// Otherwise I'm pretty sure we're just skipping the data-member metadata. | ||
member->setMetadata(validate(member->type(), member)); | ||
} | ||
return true; | ||
} | ||
|
||
bool | ||
SwiftGenerator::MetadataVisitor::visitInterfaceDefStart(const InterfaceDefPtr& p) | ||
{ | ||
p->setMetadata(validate(p, p)); | ||
return true; | ||
} | ||
|
||
void | ||
SwiftGenerator::MetadataVisitor::visitOperation(const OperationPtr& p) | ||
{ | ||
p->setMetadata(validate(p, p)); | ||
for (const auto& param : p->parameters()) | ||
{ | ||
param->setMetadata(validate(param->type(), param)); | ||
} | ||
} | ||
|
||
bool | ||
SwiftGenerator::MetadataVisitor::visitExceptionStart(const ExceptionPtr& p) | ||
{ | ||
p->setMetadata(validate(p, p)); | ||
for (const auto& member : p->dataMembers()) | ||
{ | ||
member->setMetadata(validate(member->type(), member)); | ||
} | ||
return true; | ||
} | ||
|
||
bool | ||
SwiftGenerator::MetadataVisitor::visitStructStart(const StructPtr& p) | ||
{ | ||
p->setMetadata(validate(p, p)); | ||
for (const auto& member : p->dataMembers()) | ||
{ | ||
member->setMetadata(validate(member->type(), member)); | ||
} | ||
return true; | ||
} | ||
|
||
void | ||
SwiftGenerator::MetadataVisitor::visitSequence(const SequencePtr& p) | ||
{ | ||
p->setMetadata(validate(p, p)); | ||
} | ||
|
||
void | ||
SwiftGenerator::MetadataVisitor::visitDictionary(const DictionaryPtr& p) | ||
{ | ||
const string prefix = "swift:"; | ||
|
||
for (const auto& metadata : p->keyMetadata()) | ||
{ | ||
if (metadata->directive().find(prefix) == 0) | ||
{ | ||
ostringstream msg; | ||
msg << "ignoring invalid metadata '" << *metadata << "' for dictionary key type"; | ||
p->unit()->warning(metadata->file(), metadata->line(), InvalidMetadata, msg.str()); | ||
} | ||
} | ||
|
||
for (const auto& metadata : p->valueMetadata()) | ||
{ | ||
if (metadata->directive().find(prefix) == 0) | ||
{ | ||
ostringstream msg; | ||
msg << "ignoring invalid metadata '" << *metadata << "' for dictionary value type"; | ||
p->unit()->warning(metadata->file(), metadata->line(), InvalidMetadata, msg.str()); | ||
} | ||
} | ||
|
||
p->setMetadata(validate(p, p)); | ||
} | ||
|
||
void | ||
SwiftGenerator::MetadataVisitor::visitEnum(const EnumPtr& p) | ||
{ | ||
p->setMetadata(validate(p, p)); | ||
} | ||
|
||
void | ||
SwiftGenerator::MetadataVisitor::visitConst(const ConstPtr& p) | ||
{ | ||
p->setMetadata(validate(p, p)); | ||
} | ||
|
||
MetadataList | ||
SwiftGenerator::MetadataVisitor::validate(const SyntaxTreeBasePtr& p, const ContainedPtr& cont) | ||
{ | ||
MetadataList newMetadata = cont->getMetadata(); | ||
|
||
for (auto m = newMetadata.begin(); m != newMetadata.end();) | ||
{ | ||
MetadataPtr meta = *m++; | ||
string_view directive = meta->directive(); | ||
string_view arguments = meta->arguments(); | ||
|
||
if (directive.find("swift:") != 0) | ||
{ | ||
continue; | ||
} | ||
|
||
if (dynamic_pointer_cast<Module>(p) && directive == "swift:module" && !arguments.empty()) | ||
{ | ||
continue; | ||
} | ||
|
||
if (dynamic_pointer_cast<InterfaceDecl>(p) && directive == "swift:inherits" && !arguments.empty()) | ||
{ | ||
continue; | ||
} | ||
|
||
if ((dynamic_pointer_cast<ClassDecl>(p) || dynamic_pointer_cast<Struct>(p) || dynamic_pointer_cast<Enum>(p) || | ||
dynamic_pointer_cast<Exception>(p)) && | ||
directive == "swift:attribute" && !arguments.empty()) | ||
{ | ||
continue; | ||
} | ||
|
||
ostringstream msg; | ||
msg << "ignoring invalid metadata '" << *meta << "'"; | ||
p->unit()->warning(meta->file(), meta->line(), InvalidMetadata, msg.str()); | ||
newMetadata.remove(meta); | ||
continue; | ||
} | ||
return newMetadata; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should drop swift:inherits.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After this is merged I'll have a follow up PR to drop
swift:inherits
and loosen theswift:module
check.I think that should be all the issues around Swift metadata.