From 60f8d808c2451fd37f02c1f86ed7fe60f4f58fa6 Mon Sep 17 00:00:00 2001 From: Stephan Bergmann Date: Fri, 20 Sep 2013 13:11:59 +0200 Subject: Reject "too similar" service constructors Change-Id: Ie81e9994084b5a2f44a436c764318ea6e5049faf --- unoidl/source/sourceprovider-parser-requires.hxx | 2 + unoidl/source/sourceprovider-parser.y | 95 ++++++++++++++++++++---- unoidl/source/sourceprovider-scanner.hxx | 33 +++++++- 3 files changed, 112 insertions(+), 18 deletions(-) diff --git a/unoidl/source/sourceprovider-parser-requires.hxx b/unoidl/source/sourceprovider-parser-requires.hxx index fc84c5d41e02..98657205ac7a 100644 --- a/unoidl/source/sourceprovider-parser-requires.hxx +++ b/unoidl/source/sourceprovider-parser-requires.hxx @@ -118,6 +118,8 @@ struct SourceProviderType { OUString getName() const; + bool equals(SourceProviderType const & other) const; + Type type; OUString name; // TYPE_ENUM ... TYPE_PARAMETER SourceProviderEntity const * entity; diff --git a/unoidl/source/sourceprovider-parser.y b/unoidl/source/sourceprovider-parser.y index e410f35f8d4c..6512e4a69d64 100644 --- a/unoidl/source/sourceprovider-parser.y +++ b/unoidl/source/sourceprovider-parser.y @@ -2205,13 +2205,32 @@ singleInterfaceBasedServiceDefn: dynamic_cast( ent->pad.get()); assert(pad != 0); - if (!$7) { + std::vector ctors; + if ($7) { + for (std::vector::iterator + i(pad->constructors.begin()); + i != pad->constructors.end(); ++i) + { + std::vector parms; + for (std::vector::iterator + j(i->parameters.begin()); + j != i->parameters.end(); ++j) + { + parms.push_back( + unoidl::SingleInterfaceBasedServiceEntity::Constructor::Parameter( + j->name, j->type.getName(), j->rest)); + } + ctors.push_back( + unoidl::SingleInterfaceBasedServiceEntity::Constructor( + i->name, parms, i->exceptions, i->annotations)); + } + } else { assert(pad->constructors.empty()); - pad->constructors.push_back( + ctors.push_back( unoidl::SingleInterfaceBasedServiceEntity::Constructor()); } ent->entity = new unoidl::SingleInterfaceBasedServiceEntity( - pad->isPublished(), pad->base, pad->constructors, annotations($1)); + pad->isPublished(), pad->base, ctors, annotations($1)); ent->pad.clear(); clearCurrentName(data); } @@ -2235,7 +2254,7 @@ ctor: rtl::Reference pad(getCurrentPad( data)); - for (std::vector::iterator + for (std::vector::iterator i(pad->constructors.begin()); i != pad->constructors.end(); ++i) { @@ -2249,22 +2268,49 @@ ctor: } } pad->constructors.push_back( - unoidl::SingleInterfaceBasedServiceEntity::Constructor( - id, std::vector(), - std::vector(), annotations($1))); + unoidl::detail::SourceProviderSingleInterfaceBasedServiceEntityPad::Constructor( + id, annotations($1))); } '(' ctorParams_opt ')' exceptionSpec_opt ';' { + unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner); + rtl::Reference + pad(getCurrentPad( + data)); + assert(!pad->constructors.empty()); if ($7 != 0) { - unoidl::detail::SourceProviderScannerData * data - = yyget_extra(yyscanner); - rtl::Reference - pad(getCurrentPad( - data)); - assert(!pad->constructors.empty()); pad->constructors.back().exceptions = *$7; delete $7; } + for (std::vector::iterator + i(pad->constructors.begin()); + i != pad->constructors.end() - 1; ++i) + { + if (i->parameters.size() + == pad->constructors.back().parameters.size()) + { + bool same = true; + for (std::vector::iterator + j(i->parameters.begin()), + k(pad->constructors.back().parameters.begin()); + j != i->parameters.end(); ++j, ++k) + { + if (!j->type.equals(k->type) || j->rest != k->rest) { + same = false; + break; + } + } + if (same) { + error( + @2, yyscanner, + ("single-interface--based service " + data->currentName + + " constructor " + pad->constructors.back().name + + " has similar paramete list to constructor " + + i->name)); + YYERROR; + } + } + } } ; @@ -2338,7 +2384,7 @@ ctorParam: + " rest parameter must be last parameter")); YYERROR; } - for (std::vector::iterator + for (std::vector::iterator i(pad->constructors.back().parameters.begin()); i != pad->constructors.back().parameters.end(); ++i) { @@ -2353,8 +2399,8 @@ ctorParam: } } pad->constructors.back().parameters.push_back( - unoidl::SingleInterfaceBasedServiceEntity::Constructor::Parameter( - id, t.getName(), $5)); + unoidl::detail::SourceProviderSingleInterfaceBasedServiceEntityPad::Constructor::Parameter( + id, t, $5)); } ; @@ -3682,6 +3728,23 @@ OUString SourceProviderType::getName() const { } } +bool SourceProviderType::equals(SourceProviderType const & other) const { + if (type != other.type || name != other.name + || subtypes.size() != other.subtypes.size()) + { + return false; + } + for (std::vector::const_iterator + i(subtypes.begin()), j(other.subtypes.begin()); + i != subtypes.end(); ++i, ++j) + { + if (!i->equals(*j)) { + return false; + } + } + return true; +} + bool parse(OUString const & uri, SourceProviderScannerData * data) { assert(data != 0); oslFileHandle handle; diff --git a/unoidl/source/sourceprovider-scanner.hxx b/unoidl/source/sourceprovider-scanner.hxx index 8a79d3172d6d..0c08a13208d0 100644 --- a/unoidl/source/sourceprovider-scanner.hxx +++ b/unoidl/source/sourceprovider-scanner.hxx @@ -156,14 +156,43 @@ class SourceProviderSingleInterfaceBasedServiceEntityPad: public SourceProviderEntityPad { public: + struct Constructor { + struct Parameter { + Parameter( + rtl::OUString const & theName, + SourceProviderType const & theType, bool theRest): + name(theName), type(theType), rest(theRest) + {} + + rtl::OUString name; + + SourceProviderType type; + + bool rest; + }; + + Constructor( + rtl::OUString const & theName, + std::vector< rtl::OUString > const & theAnnotations): + name(theName), annotations(theAnnotations) + {} + + rtl::OUString const name; + + std::vector< Parameter > parameters; + + std::vector< rtl::OUString > exceptions; + + std::vector< rtl::OUString > const annotations; + }; + explicit SourceProviderSingleInterfaceBasedServiceEntityPad( bool published, OUString const & theBase): SourceProviderEntityPad(published), base(theBase) {} OUString const base; - std::vector - constructors; + std::vector constructors; private: virtual ~SourceProviderSingleInterfaceBasedServiceEntityPad() throw () {} -- cgit