Kaydet (Commit) 454f3f72 authored tarafından Stephan Bergmann's avatar Stephan Bergmann

Fix unoidl sourceprovider interface base and member checks

...and enable tests shared with idlc

Change-Id: I422b16c9b2636835d276cc2085cb640073894c97
üst e00562d9
......@@ -113,3 +113,65 @@ interface Derived {
[optional] interface Base1;
[optional] interface Base2;
};
EXPECT FAILURE "methodoverload.tests 10":
interface I {
[attribute] long a;
[attribute] short a;
};
EXPECT FAILURE "methodoverload.tests 11":
interface I1 {
[attribute] long a;
};
interface I2 {
[attribute] short a;
interface I1;
};
EXPECT FAILURE "methodoverload.tests 12":
interface I {
[attribute] long a;
void a();
};
EXPECT FAILURE "methodoverload.tests 13":
interface I1 {
[attribute] long a;
}
interface I2 {
void a();
interface I1;
};
EXPECT FAILURE "methodoverload.tests 14":
interface I1 {
void a();
}
interface I2 {
[attribute] long a;
interface I1;
};
EXPECT SUCCESS "methodoverload.tests 15":
interface I {
[attribute] long a;
void geta();
void seta();
};
EXPECT SUCCESS "methodoverload.tests 16":
interface I1 {
[attribute] long a;
};
interface I2: I1 {
void geta();
void seta();
};
# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
#
# This file is part of the LibreOffice project.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
$(eval $(call gb_CustomTarget_CustomTarget,unoidl/unoidl-write_test))
# this target is phony to run it every time
.PHONY : $(call gb_CustomTarget_get_target,unoidl/unoidl-write_test)
$(call gb_CustomTarget_get_target,unoidl/unoidl-write_test) : \
$(call gb_Executable_get_runtime_dependencies,unoidl-write) \
$(SRCDIR)/solenv/bin/exectest.pl \
$(SRCDIR)/idlc/test/parser/attribute.tests \
$(SRCDIR)/idlc/test/parser/constant.tests \
$(SRCDIR)/idlc/test/parser/constructor.tests \
$(SRCDIR)/idlc/test/parser/interfaceinheritance.tests \
$(SRCDIR)/idlc/test/parser/methodoverload.tests \
$(SRCDIR)/idlc/test/parser/polystruct.tests \
$(SRCDIR)/idlc/test/parser/published.tests \
$(SRCDIR)/idlc/test/parser/struct.tests \
$(SRCDIR)/idlc/test/parser/typedef.tests \
| $(call gb_CustomTarget_get_workdir,unoidl/unoidl-write_test)/.dir
$(call gb_Helper_abbreviate_dirs,( \
$(PERL) $(SRCDIR)/solenv/bin/exectest.pl \
$(SRCDIR)/idlc/test/parser/attribute.tests \
$(call gb_CustomTarget_get_workdir,unoidl/unoidl-write_test)/in.idl \
1 $(call gb_Executable_get_command,unoidl-write) $(SRCDIR)/udkapi \
{} \
$(call gb_CustomTarget_get_workdir,unoidl/unoidl-write_test)/out.rdb \
&& $(PERL) $(SRCDIR)/solenv/bin/exectest.pl \
$(SRCDIR)/idlc/test/parser/constant.tests \
$(call gb_CustomTarget_get_workdir,unoidl/unoidl-write_test)/in.idl \
1 $(call gb_Executable_get_command,unoidl-write) $(SRCDIR)/udkapi \
{} \
$(call gb_CustomTarget_get_workdir,unoidl/unoidl-write_test)/out.rdb \
&& $(PERL) $(SRCDIR)/solenv/bin/exectest.pl \
$(SRCDIR)/idlc/test/parser/constructor.tests \
$(call gb_CustomTarget_get_workdir,unoidl/unoidl-write_test)/in.idl \
1 $(call gb_Executable_get_command,unoidl-write) $(SRCDIR)/udkapi \
{} \
$(call gb_CustomTarget_get_workdir,unoidl/unoidl-write_test)/out.rdb \
&& $(PERL) $(SRCDIR)/solenv/bin/exectest.pl \
$(SRCDIR)/idlc/test/parser/interfaceinheritance.tests \
$(call gb_CustomTarget_get_workdir,unoidl/unoidl-write_test)/in.idl \
1 $(call gb_Executable_get_command,unoidl-write) $(SRCDIR)/udkapi \
{} \
$(call gb_CustomTarget_get_workdir,unoidl/unoidl-write_test)/out.rdb \
&& $(PERL) $(SRCDIR)/solenv/bin/exectest.pl \
$(SRCDIR)/idlc/test/parser/methodoverload.tests \
$(call gb_CustomTarget_get_workdir,unoidl/unoidl-write_test)/in.idl \
1 $(call gb_Executable_get_command,unoidl-write) $(SRCDIR)/udkapi \
{} \
$(call gb_CustomTarget_get_workdir,unoidl/unoidl-write_test)/out.rdb \
&& $(PERL) $(SRCDIR)/solenv/bin/exectest.pl \
$(SRCDIR)/idlc/test/parser/oldstyle.tests \
$(call gb_CustomTarget_get_workdir,unoidl/unoidl-write_test)/in.idl \
1 $(call gb_Executable_get_command,unoidl-write) $(SRCDIR)/udkapi \
{} \
$(call gb_CustomTarget_get_workdir,unoidl/unoidl-write_test)/out.rdb \
&& $(PERL) $(SRCDIR)/solenv/bin/exectest.pl \
$(SRCDIR)/idlc/test/parser/polystruct.tests \
$(call gb_CustomTarget_get_workdir,unoidl/unoidl-write_test)/in.idl \
1 $(call gb_Executable_get_command,unoidl-write) $(SRCDIR)/udkapi \
{} \
$(call gb_CustomTarget_get_workdir,unoidl/unoidl-write_test)/out.rdb \
&& $(PERL) $(SRCDIR)/solenv/bin/exectest.pl \
$(SRCDIR)/idlc/test/parser/published.tests \
$(call gb_CustomTarget_get_workdir,unoidl/unoidl-write_test)/in.idl \
1 $(call gb_Executable_get_command,unoidl-write) $(SRCDIR)/udkapi \
{} \
$(call gb_CustomTarget_get_workdir,unoidl/unoidl-write_test)/out.rdb \
&& $(PERL) $(SRCDIR)/solenv/bin/exectest.pl \
$(SRCDIR)/idlc/test/parser/struct.tests \
$(call gb_CustomTarget_get_workdir,unoidl/unoidl-write_test)/in.idl \
1 $(call gb_Executable_get_command,unoidl-write) $(SRCDIR)/udkapi \
{} \
$(call gb_CustomTarget_get_workdir,unoidl/unoidl-write_test)/out.rdb \
&& $(PERL) $(SRCDIR)/solenv/bin/exectest.pl \
$(SRCDIR)/idlc/test/parser/typedef.tests \
$(call gb_CustomTarget_get_workdir,unoidl/unoidl-write_test)/in.idl \
1 $(call gb_Executable_get_command,unoidl-write) $(SRCDIR)/udkapi \
{} \
$(call gb_CustomTarget_get_workdir,unoidl/unoidl-write_test)/out.rdb) \
> $@.log 2>&1 || (cat $@.log && false))
# vim: set noet sw=4 ts=4:
......@@ -16,6 +16,7 @@ $(eval $(call gb_Module_add_targets,unoidl, \
))
$(eval $(call gb_Module_add_targets_for_build,unoidl, \
CustomTarget_unoidl-write_test \
Executable_unoidl-check \
Executable_unoidl-write \
))
......
......@@ -316,7 +316,7 @@ Found findEntity(
YYLTYPE location, yyscan_t yyscanner,
unoidl::detail::SourceProviderScannerData * data,
bool resolveInterfaceDefinitions, OUString * name,
unoidl::detail::SourceProviderEntity const ** entity,
unoidl::detail::SourceProviderEntity const ** entity, bool * typedefed,
unoidl::detail::SourceProviderType * typedefedType)
{
//TODO: avoid recursion
......@@ -339,6 +339,9 @@ Found findEntity(
// fall through
case unoidl::detail::SourceProviderEntity::KIND_EXTERNAL:
if (e->entity->getSort() == unoidl::Entity::SORT_TYPEDEF) {
if (typedefed != 0) {
*typedefed = true;
}
if (data->publishedContext
&& !static_cast<unoidl::TypedefEntity *>(
e->entity.get())->isPublished())
......@@ -413,7 +416,7 @@ Found findEntity(
switch (
findEntity(
location, yyscanner, data, false,
&argName, &argEnt, &argType))
&argName, &argEnt, 0, &argType))
{
case FOUND_ERROR:
return FOUND_ERROR;
......@@ -1088,7 +1091,7 @@ plainStructDefn:
if ($5 != 0) {
baseName = convertName($5);
unoidl::detail::SourceProviderEntity const * p;
if (findEntity(@5, yyscanner, data, false, &baseName, &p, 0)
if (findEntity(@5, yyscanner, data, false, &baseName, &p, 0, 0)
== FOUND_ERROR)
{
YYERROR;
......@@ -1219,7 +1222,7 @@ exceptionDefn:
if ($5 != 0) {
baseName = convertName($5);
unoidl::detail::SourceProviderEntity const * p;
if (findEntity(@5, yyscanner, data, false, &baseName, &p, 0)
if (findEntity(@5, yyscanner, data, false, &baseName, &p, 0, 0)
== FOUND_ERROR)
{
YYERROR;
......@@ -1371,7 +1374,8 @@ structMember:
break;
}
unoidl::detail::SourceProviderEntity const * p;
if (findEntity(@2, yyscanner, data, false, &baseName, &p, 0)
if (findEntity(
@2, yyscanner, data, false, &baseName, &p, 0, 0)
== FOUND_ERROR)
{
YYERROR;
......@@ -1471,7 +1475,7 @@ structMember:
}
unoidl::detail::SourceProviderEntity const * p;
if (findEntity(
@2, yyscanner, data, false, &baseName, &p, 0)
@2, yyscanner, data, false, &baseName, &p, 0, 0)
== FOUND_ERROR)
{
YYERROR;
......@@ -1511,7 +1515,7 @@ interfaceDefn:
if ($5 != 0) {
baseName = convertName($5);
unoidl::detail::SourceProviderEntity const * p;
if (findEntity(@5, yyscanner, data, true, &baseName, &p, 0)
if (findEntity(@5, yyscanner, data, true, &baseName, &p, 0, 0)
== FOUND_ERROR)
{
YYERROR;
......@@ -1558,25 +1562,35 @@ interfaceDefn:
break;
}
}
data->entities[data->currentName] = unoidl::detail::SourceProviderEntity(
rtl::Reference<unoidl::detail::SourceProviderInterfaceTypeEntityPad> pad(
new unoidl::detail::SourceProviderInterfaceTypeEntityPad(
$2, baseName, baseEnt));
$2, baseEnt.is()));
if (baseEnt.is()
&& !pad->addDirectBase(
@4, yyscanner, data,
unoidl::detail::SourceProviderInterfaceTypeEntityPad::DirectBase(
baseName, baseEnt, std::vector<OUString>()),
false))
{
YYERROR;
}
data->entities[data->currentName] = unoidl::detail::SourceProviderEntity(
pad.get());
}
'{' interfaceMembers '}' ';'
{
//TODO: check direct member uniqueness
unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
unoidl::detail::SourceProviderEntity * ent = getCurrentEntity(data);
unoidl::detail::SourceProviderInterfaceTypeEntityPad * pad =
dynamic_cast<unoidl::detail::SourceProviderInterfaceTypeEntityPad *>(
ent->pad.get());
assert(pad != 0);
if (pad->mandatoryBases.empty()
if (pad->directMandatoryBases.empty()
&& data->currentName != "com.sun.star.uno.XInterface")
{
OUString base(".com.sun.star.uno.XInterface");
unoidl::detail::SourceProviderEntity const * p;
if (findEntity(@4, yyscanner, data, true, &base, &p, 0)
if (findEntity(@4, yyscanner, data, true, &base, &p, 0, 0)
== FOUND_ERROR)
{
YYERROR;
......@@ -1591,29 +1605,35 @@ interfaceDefn:
+ " does not resolve to an existing interface type"));
YYERROR;
}
pad->mandatoryBases.push_back(
unoidl::detail::SourceProviderInterfaceTypeEntityPad::Base(
if (!pad->addDirectBase(
@3, yyscanner, data,
unoidl::detail::SourceProviderInterfaceTypeEntityPad::DirectBase(
base,
static_cast<unoidl::InterfaceTypeEntity *>(p->entity.get()),
std::vector<OUString>()));
static_cast<unoidl::InterfaceTypeEntity *>(
p->entity.get()),
std::vector<OUString>()),
false))
{
YYERROR;
}
}
std::vector<unoidl::AnnotatedReference> mbases;
for (std::vector<unoidl::detail::SourceProviderInterfaceTypeEntityPad::Base>::const_iterator
i(pad->mandatoryBases.begin());
i != pad->mandatoryBases.end(); ++i)
for (std::vector<unoidl::detail::SourceProviderInterfaceTypeEntityPad::DirectBase>::const_iterator
i(pad->directMandatoryBases.begin());
i != pad->directMandatoryBases.end(); ++i)
{
mbases.push_back(unoidl::AnnotatedReference(i->name, i->annotations));
}
std::vector<unoidl::AnnotatedReference> obases;
for (std::vector<unoidl::detail::SourceProviderInterfaceTypeEntityPad::Base>::const_iterator
i(pad->optionalBases.begin());
i != pad->optionalBases.end(); ++i)
for (std::vector<unoidl::detail::SourceProviderInterfaceTypeEntityPad::DirectBase>::const_iterator
i(pad->directOptionalBases.begin());
i != pad->directOptionalBases.end(); ++i)
{
obases.push_back(unoidl::AnnotatedReference(i->name, i->annotations));
}
ent->entity = new unoidl::InterfaceTypeEntity(
pad->isPublished(), mbases, obases, pad->attributes, pad->methods,
annotations($1));
pad->isPublished(), mbases, obases, pad->directAttributes,
pad->directMethods, annotations($1));
ent->pad.clear();
clearCurrentState(data);
}
......@@ -1651,8 +1671,12 @@ interfaceBase:
YYERROR;
}
bool opt = ($2 & unoidl::detail::FLAG_OPTIONAL) != 0;
OUString orgName(name);
unoidl::detail::SourceProviderEntity const * p;
if (findEntity(@4, yyscanner, data, true, &name, &p, 0) == FOUND_ERROR) {
bool typedefed = false;
if (findEntity(@4, yyscanner, data, true, &name, &p, &typedefed, 0)
== FOUND_ERROR)
{
YYERROR;
}
if (p == 0 || !p->entity.is()
......@@ -1664,22 +1688,30 @@ interfaceBase:
+ " does not resolve to an existing interface type"));
YYERROR;
}
if (data->publishedContext
&& !(static_cast<unoidl::InterfaceTypeEntity *>(p->entity.get())
->isPublished()))
{
if (typedefed) {
error(
@4, yyscanner,
("interface type " + data->currentName + " direct base " + orgName
+ " is a typedef"));
YYERROR;
}
rtl::Reference<unoidl::InterfaceTypeEntity> ent(
static_cast<unoidl::InterfaceTypeEntity *>(p->entity.get()));
if (data->publishedContext && !ent->isPublished()) {
error(
@4, yyscanner,
("published interface type " + data->currentName + " direct base "
+ name + " is unpublished"));
YYERROR;
}
//TODO: check uniqueness (incl. that opt base != XInterface)
(opt ? pad->optionalBases : pad->mandatoryBases).push_back(
unoidl::detail::SourceProviderInterfaceTypeEntityPad::Base(
name,
static_cast<unoidl::InterfaceTypeEntity *>(p->entity.get()),
annotations($1)));
if (!pad->addDirectBase(
@4, yyscanner, data,
unoidl::detail::SourceProviderInterfaceTypeEntityPad::DirectBase(
name, ent, annotations($1)),
opt))
{
YYERROR;
}
}
;
......@@ -1722,7 +1754,10 @@ interfaceAttribute:
rtl::Reference<unoidl::detail::SourceProviderInterfaceTypeEntityPad> pad(
getCurrentPad<unoidl::detail::SourceProviderInterfaceTypeEntityPad>(
data));
pad->attributes.push_back(
if (!pad->addDirectMember(@4, yyscanner, data, id)) {
YYERROR;
}
pad->directAttributes.push_back(
unoidl::InterfaceTypeEntity::Attribute(
id, t.getName(), ($2 & unoidl::detail::FLAG_BOUND) != 0,
($2 & unoidl::detail::FLAG_READONLY) != 0,
......@@ -1757,8 +1792,8 @@ attributeAccessDecl:
rtl::Reference<unoidl::detail::SourceProviderInterfaceTypeEntityPad>
pad(getCurrentPad<unoidl::detail::SourceProviderInterfaceTypeEntityPad>(
data));
assert(!pad->attributes.empty());
pad->attributes.back().getExceptions = *$2;
assert(!pad->directAttributes.empty());
pad->directAttributes.back().getExceptions = *$2;
delete $2;
$$ = unoidl::detail::ACCESS_DECL_GET;
}
......@@ -1768,14 +1803,15 @@ attributeAccessDecl:
rtl::Reference<unoidl::detail::SourceProviderInterfaceTypeEntityPad>
pad(getCurrentPad<unoidl::detail::SourceProviderInterfaceTypeEntityPad>(
data));
assert(!pad->attributes.empty());
pad->attributes.back().setExceptions = *$2;
assert(!pad->directAttributes.empty());
pad->directAttributes.back().setExceptions = *$2;
delete $2;
if (pad->attributes.back().readOnly) {
if (pad->directAttributes.back().readOnly) {
error(
@1, yyscanner,
("interface type " + data->currentName
+ " direct read-only attribute " + pad->attributes.back().name
+ " direct read-only attribute "
+ pad->directAttributes.back().name
+ " cannot have set access declaration"));
YYERROR;
}
......@@ -1800,7 +1836,10 @@ interfaceMethod:
rtl::Reference<unoidl::detail::SourceProviderInterfaceTypeEntityPad> pad(
getCurrentPad<unoidl::detail::SourceProviderInterfaceTypeEntityPad>(
data));
pad->methods.push_back(
if (!pad->addDirectMember(@3, yyscanner, data, id)) {
YYERROR;
}
pad->directMethods.push_back(
unoidl::InterfaceTypeEntity::Method(
id, t.getName(),
std::vector<unoidl::InterfaceTypeEntity::Method::Parameter>(),
......@@ -1814,8 +1853,8 @@ interfaceMethod:
rtl::Reference<unoidl::detail::SourceProviderInterfaceTypeEntityPad>
pad(getCurrentPad<unoidl::detail::SourceProviderInterfaceTypeEntityPad>(
data));
assert(!pad->methods.empty());
pad->methods.back().exceptions = *$8;
assert(!pad->directMethods.empty());
pad->directMethods.back().exceptions = *$8;
delete $8;
}
}
......@@ -1841,34 +1880,34 @@ methodParam:
rtl::Reference<unoidl::detail::SourceProviderInterfaceTypeEntityPad>
pad(getCurrentPad<unoidl::detail::SourceProviderInterfaceTypeEntityPad>(
data));
assert(!pad->methods.empty());
assert(!pad->directMethods.empty());
switch (t.type) {
case unoidl::detail::SourceProviderType::TYPE_VOID:
case unoidl::detail::SourceProviderType::TYPE_EXCEPTION:
error(
@4, yyscanner,
("illegal interface type " + data->currentName
+ " direct method " + pad->methods.back().name + " parameter "
+ id + " type"));
+ " direct method " + pad->directMethods.back().name
+ " parameter " + id + " type"));
YYERROR;
break;
default:
break;
}
for (std::vector<unoidl::InterfaceTypeEntity::Method::Parameter>::iterator
i(pad->methods.back().parameters.begin());
i != pad->methods.back().parameters.end(); ++i)
i(pad->directMethods.back().parameters.begin());
i != pad->directMethods.back().parameters.end(); ++i)
{
if (id == i->name) {
error(
@5, yyscanner,
("interface type " + data->currentName + " direct method "
+ pad->methods.back().name + " parameter " + id
+ pad->directMethods.back().name + " parameter " + id
+ " has same identifier as another parameter"));
YYERROR;
}
}
pad->methods.back().parameters.push_back(
pad->directMethods.back().parameters.push_back(
unoidl::InterfaceTypeEntity::Method::Parameter(id, t.getName(), $2));
}
;
......@@ -2280,7 +2319,9 @@ singleInterfaceBasedServiceDefn:
convertToCurrentName(data, $4);
OUString base(convertName($5));
unoidl::detail::SourceProviderEntity const * p;
if (findEntity(@5, yyscanner, data, false, &base, &p, 0) == FOUND_ERROR) {
if (findEntity(@5, yyscanner, data, false, &base, &p, 0, 0)
== FOUND_ERROR)
{
YYERROR;
}
bool ifcBase = false;
......@@ -2607,7 +2648,9 @@ serviceBase:
}
bool opt = ($2 & unoidl::detail::FLAG_OPTIONAL) != 0;
unoidl::detail::SourceProviderEntity const * p;
if (findEntity(@4, yyscanner, data, false, &name, &p, 0) == FOUND_ERROR) {
if (findEntity(@4, yyscanner, data, false, &name, &p, 0, 0)
== FOUND_ERROR)
{
YYERROR;
}
if (p == 0 || !p->entity.is()
......@@ -2653,7 +2696,9 @@ serviceInterfaceBase:
}
bool opt = ($2 & unoidl::detail::FLAG_OPTIONAL) != 0;
unoidl::detail::SourceProviderEntity const * p;
if (findEntity(@4, yyscanner, data, false, &name, &p, 0) == FOUND_ERROR) {
if (findEntity(@4, yyscanner, data, false, &name, &p, 0, 0)
== FOUND_ERROR)
{
YYERROR;
}
bool ifcBase = false;
......@@ -2794,7 +2839,9 @@ interfaceBasedSingletonDefn:
OUString name(convertToFullName(data, $4));
OUString base(convertName($5));
unoidl::detail::SourceProviderEntity const * p;
if (findEntity(@5, yyscanner, data, false, &base, &p, 0) == FOUND_ERROR) {
if (findEntity(@5, yyscanner, data, false, &base, &p, 0, 0)
== FOUND_ERROR)
{
YYERROR;
}
bool ifcBase = false;
......@@ -2860,7 +2907,9 @@ serviceBasedSingletonDefn:
OUString name(convertToFullName(data, $4));
OUString base(convertName($7));
unoidl::detail::SourceProviderEntity const * p;
if (findEntity(@7, yyscanner, data, false, &base, &p, 0) == FOUND_ERROR) {
if (findEntity(@7, yyscanner, data, false, &base, &p, 0, 0)
== FOUND_ERROR)
{
YYERROR;
}
if (p == 0
......@@ -2922,7 +2971,9 @@ exceptions:
unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
OUString name(convertName($3));
unoidl::detail::SourceProviderEntity const * p;
if (findEntity(@3, yyscanner, data, false, &name, &p, 0) == FOUND_ERROR) {
if (findEntity(@3, yyscanner, data, false, &name, &p, 0, 0)
== FOUND_ERROR)
{
delete $1; /* see commented-out %destructor above */
YYERROR;
}
......@@ -2960,7 +3011,9 @@ exceptions:
unoidl::detail::SourceProviderScannerData * data = yyget_extra(yyscanner);
OUString name(convertName($1));
unoidl::detail::SourceProviderEntity const * p;
if (findEntity(@1, yyscanner, data, false, &name, &p, 0) == FOUND_ERROR) {
if (findEntity(@1, yyscanner, data, false, &name, &p, 0, 0)
== FOUND_ERROR)
{
YYERROR;
}
if (p == 0
......@@ -3479,7 +3532,7 @@ primaryExpr:
} else {
OUString scope(name.copy(0, i));
unoidl::detail::SourceProviderEntity const * ent;
if (findEntity(@1, yyscanner, data, false, &scope, &ent, 0)
if (findEntity(@1, yyscanner, data, false, &scope, &ent, 0, 0)
== FOUND_ERROR)
{
YYERROR;
......@@ -3720,7 +3773,7 @@ type:
if (!done) {
unoidl::detail::SourceProviderEntity const * ent;
unoidl::detail::SourceProviderType t;
switch (findEntity(@1, yyscanner, data, false, &name, &ent, &t)) {
switch (findEntity(@1, yyscanner, data, false, &name, &ent, 0, &t)) {
case FOUND_ERROR:
YYERROR;
break;
......@@ -3874,7 +3927,8 @@ type:
std::vector<unoidl::detail::SourceProviderType> args(*$3);
delete $3;
unoidl::detail::SourceProviderEntity const * ent;
if (findEntity(@1, yyscanner, data, false, &name, &ent, 0) == FOUND_ERROR)
if (findEntity(@1, yyscanner, data, false, &name, &ent, 0, 0)
== FOUND_ERROR)
{
YYERROR;
}
......@@ -4041,6 +4095,377 @@ bool SourceProviderType::equals(SourceProviderType const & other) const {
return true;
}
bool SourceProviderInterfaceTypeEntityPad::addDirectBase(
YYLTYPE location, yyscan_t yyscanner, SourceProviderScannerData * data,
DirectBase const & base, bool optional)
{
std::set<OUString> seen;
if (!(checkBaseClashes(
location, yyscanner, data, base.name, base.entity, true, optional,
optional, &seen)
&& addBase(
location, yyscanner, data, base.name, base.name, base.entity,
true, optional)))
{
return false;
}
if (optional) {
addOptionalBaseMembers(
location, yyscanner, data, base.name, base.entity);
}
//TODO: check that opt base != XInterface
(optional ? directOptionalBases : directMandatoryBases).push_back(base);
return true;
}
bool SourceProviderInterfaceTypeEntityPad::addDirectMember(
YYLTYPE location, yyscan_t yyscanner, SourceProviderScannerData * data,
OUString const & name)
{
assert(data != 0);
if (!checkMemberClashes(location, yyscanner, data, "", name, true)) {
return false;
}
allMembers.insert(
std::map<OUString, Member>::value_type(
name, Member(data->currentName)));
return true;
}
bool SourceProviderInterfaceTypeEntityPad::checkBaseClashes(
YYLTYPE location, yyscan_t yyscanner, SourceProviderScannerData * data,
OUString const & name,
rtl::Reference<unoidl::InterfaceTypeEntity> const & entity, bool direct,
bool optional, bool outerOptional, std::set<OUString> * seen) const
{
assert(data != 0);
assert(entity.is());
assert(seen != 0);
if (direct || optional || seen->insert(name).second) {
std::map<OUString, BaseKind>::const_iterator i(allBases.find(name));
if (i != allBases.end()) {
switch (i->second) {
case BASE_INDIRECT_OPTIONAL:
if (direct && optional) {
error(
location, yyscanner,
("interface type " + data->currentName
+ " duplicate base " + name));
return false;
}
break;
case BASE_DIRECT_OPTIONAL:
if (direct || !outerOptional) {
error(
location, yyscanner,
("interface type " + data->currentName
+ " duplicate base " + name));
return false;
}
return true;
case BASE_INDIRECT_MANDATORY:
if (direct) {
error(
location, yyscanner,
("interface type " + data->currentName
+ " duplicate base " + name));
return false;
}
return true;
case BASE_DIRECT_MANDATORY:
if (direct || (!optional && !outerOptional)) {
error(
location, yyscanner,
("interface type " + data->currentName
+ " duplicate base " + name));
return false;
}
return true;
}
}
if (direct || !optional) {
for (std::vector<unoidl::AnnotatedReference>::const_iterator j(
entity->getDirectMandatoryBases().begin());
j != entity->getDirectMandatoryBases().end(); ++j)
{
OUString n("." + j->name);
unoidl::detail::SourceProviderEntity const * p;
if (findEntity(location, yyscanner, data, true, &n, &p, 0, 0)
== FOUND_ERROR)
{
return false;
}
if (p == 0 || !p->entity.is()
|| (p->entity->getSort()
!= unoidl::Entity::SORT_INTERFACE_TYPE))
{
error(
location, yyscanner,
("inconsistent type manager: interface type "
+ data->currentName + " base " + n
+ " does not resolve to an existing interface type"));
return false;
}
if (!checkBaseClashes(
location, yyscanner, data, n,
static_cast<unoidl::InterfaceTypeEntity *>(
p->entity.get()),
false, false, outerOptional, seen))
{
return false;
}
}
for (std::vector<unoidl::AnnotatedReference>::const_iterator j(
entity->getDirectOptionalBases().begin());
j != entity->getDirectOptionalBases().end(); ++j)
{
OUString n("." + j->name);
unoidl::detail::SourceProviderEntity const * p;
if (findEntity(location, yyscanner, data, true, &n, &p, 0, 0)
== FOUND_ERROR)
{
return false;
}
if (p == 0 || !p->entity.is()
|| (p->entity->getSort()
!= unoidl::Entity::SORT_INTERFACE_TYPE))
{
error(
location, yyscanner,
("inconsistent type manager: interface type "
+ data->currentName + " base " + n
+ " does not resolve to an existing interface type"));
return false;
}
if (!checkBaseClashes(
location, yyscanner, data, n,
static_cast<unoidl::InterfaceTypeEntity *>(
p->entity.get()),
false, true, outerOptional, seen))
{
return false;
}
}
for (std::vector<unoidl::InterfaceTypeEntity::Attribute>::const_iterator
j(entity->getDirectAttributes().begin());
j != entity->getDirectAttributes().end(); ++j)
{
if (!checkMemberClashes(
location, yyscanner, data, name, j->name,
!outerOptional))
{
return false;
}
}
for (std::vector<unoidl::InterfaceTypeEntity::Method>::const_iterator
j(entity->getDirectMethods().begin());
j != entity->getDirectMethods().end(); ++j)
{
if (!checkMemberClashes(
location, yyscanner, data, name, j->name,
!outerOptional))
{
return false;
}
}
}
}
return true;
}
bool SourceProviderInterfaceTypeEntityPad::checkMemberClashes(
YYLTYPE location, yyscan_t yyscanner, SourceProviderScannerData * data,
OUString const & interfaceName, OUString const & memberName,
bool checkOptional) const
{
std::map<OUString, Member>::const_iterator i(allMembers.find(memberName));
if (i != allMembers.end()) {
if (!i->second.mandatory.isEmpty()) {
// For a direct member, interfaceName will be empty, so this will
// catch two direct members with the same name:
if (i->second.mandatory != interfaceName) {
error(
location, yyscanner,
("interface type " + data->currentName
+ " duplicate member " + memberName));
return false;
}
} else if (checkOptional) {
for (std::set<OUString>::const_iterator j(
i->second.optional.begin());
j != i->second.optional.end(); ++j)
{
if (*j != interfaceName) {
error(
location, yyscanner,
("interface type " + data->currentName
+ " duplicate member " + memberName));
return false;
}
}
}
}
return true;
}
bool SourceProviderInterfaceTypeEntityPad::addBase(
YYLTYPE location, yyscan_t yyscanner, SourceProviderScannerData * data,
OUString const & directBaseName, OUString const & name,
rtl::Reference<unoidl::InterfaceTypeEntity> const & entity, bool direct,
bool optional)
{
assert(data != 0);
assert(entity.is());
BaseKind kind = optional
? direct ? BASE_DIRECT_OPTIONAL : BASE_INDIRECT_OPTIONAL
: direct ? BASE_DIRECT_MANDATORY : BASE_INDIRECT_MANDATORY;
std::pair<std::map<OUString, BaseKind>::iterator, bool> p(
allBases.insert(
std::map<OUString, BaseKind>::value_type(name, kind)));
bool seen = !p.second && p.first->second >= BASE_INDIRECT_MANDATORY;
if (!p.second && kind > p.first->second) {
p.first->second = kind;
}
if (!optional && !seen) {
for (std::vector<unoidl::AnnotatedReference>::const_iterator i(
entity->getDirectMandatoryBases().begin());
i != entity->getDirectMandatoryBases().end(); ++i)
{
OUString n("." + i->name);
unoidl::detail::SourceProviderEntity const * q;
if (findEntity(location, yyscanner, data, true, &n, &q, 0, 0)
== FOUND_ERROR)
{
return false;
}
if (q == 0 || !q->entity.is()
|| q->entity->getSort() != unoidl::Entity::SORT_INTERFACE_TYPE)
{
error(
location, yyscanner,
("inconsistent type manager: interface type "
+ data->currentName + " base " + n
+ " does not resolve to an existing interface type"));
return false;
}
if (!addBase(
location, yyscanner, data, directBaseName, n,
static_cast<unoidl::InterfaceTypeEntity *>(q->entity.get()),
false, false))
{
return false;
}
}
for (std::vector<unoidl::AnnotatedReference>::const_iterator i(
entity->getDirectOptionalBases().begin());
i != entity->getDirectOptionalBases().end(); ++i)
{
OUString n("." + i->name);
unoidl::detail::SourceProviderEntity const * q;
if (findEntity(location, yyscanner, data, true, &n, &q, 0, 0)
== FOUND_ERROR)
{
return false;
}
if (q == 0 || !q->entity.is()
|| q->entity->getSort() != unoidl::Entity::SORT_INTERFACE_TYPE)
{
error(
location, yyscanner,
("inconsistent type manager: interface type "
+ data->currentName + " base " + n
+ " does not resolve to an existing interface type"));
return false;
}
if (!addBase(
location, yyscanner, data, directBaseName, n,
static_cast<unoidl::InterfaceTypeEntity *>(q->entity.get()),
false, true))
{
return false;
}
}
for (std::vector<unoidl::InterfaceTypeEntity::Attribute>::const_iterator
i(entity->getDirectAttributes().begin());
i != entity->getDirectAttributes().end(); ++i)
{
allMembers.insert(
std::map<OUString, Member>::value_type(i->name, Member(name)));
}
for (std::vector<unoidl::InterfaceTypeEntity::Method>::const_iterator i(
entity->getDirectMethods().begin());
i != entity->getDirectMethods().end(); ++i)
{
allMembers.insert(
std::map<OUString, Member>::value_type(i->name, Member(name)));
}
}
return true;
}
bool SourceProviderInterfaceTypeEntityPad::addOptionalBaseMembers(
YYLTYPE location, yyscan_t yyscanner, SourceProviderScannerData * data,
OUString const & name,
rtl::Reference<unoidl::InterfaceTypeEntity> const & entity)
{
assert(entity.is());
for (std::vector<unoidl::AnnotatedReference>::const_iterator i(
entity->getDirectMandatoryBases().begin());
i != entity->getDirectMandatoryBases().end(); ++i)
{
OUString n("." + i->name);
unoidl::detail::SourceProviderEntity const * p;
if (findEntity(location, yyscanner, data, true, &n, &p, 0, 0)
== FOUND_ERROR)
{
return false;
}
if (p == 0 || !p->entity.is()
|| p->entity->getSort() != unoidl::Entity::SORT_INTERFACE_TYPE)
{
error(
location, yyscanner,
("inconsistent type manager: interface type "
+ data->currentName + " base " + n
+ " does not resolve to an existing interface type"));
return false;
}
if (!addOptionalBaseMembers(
location, yyscanner, data, n,
static_cast<unoidl::InterfaceTypeEntity *>(p->entity.get())))
{
return false;
}
}
for (std::vector<unoidl::InterfaceTypeEntity::Attribute>::const_iterator i(
entity->getDirectAttributes().begin());
i != entity->getDirectAttributes().end(); ++i)
{
Member & m(
allMembers.insert(
std::map<OUString, Member>::value_type(
i->name, Member("")))
.first->second);
if (m.mandatory.isEmpty()) {
m.optional.insert(name);
}
}
for (std::vector<unoidl::InterfaceTypeEntity::Method>::const_iterator i(
entity->getDirectMethods().begin());
i != entity->getDirectMethods().end(); ++i)
{
Member & m(
allMembers.insert(
std::map<OUString, Member>::value_type(
i->name, Member("")))
.first->second);
if (m.mandatory.isEmpty()) {
m.optional.insert(name);
}
}
return true;
}
bool parse(OUString const & uri, SourceProviderScannerData * data) {
assert(data != 0);
oslFileHandle handle;
......
......@@ -14,6 +14,7 @@
#include <cassert>
#include <map>
#include <set>
#include <vector>
#include "rtl/ref.hxx"
......@@ -27,6 +28,8 @@
namespace unoidl { namespace detail {
struct SourceProviderScannerData;
class SourceProviderEntityPad: public salhelper::SimpleReferenceObject {
public:
bool isPublished() const { return published_; }
......@@ -103,41 +106,76 @@ private:
class SourceProviderInterfaceTypeEntityPad: public SourceProviderEntityPad {
public:
struct Base {
Base(
struct DirectBase {
DirectBase(
OUString const & theName,
rtl::Reference<unoidl::InterfaceTypeEntity> const & theEntity,
std::vector<OUString> const & theAnnotations):
name(theName), entity(theEntity), annotations(theAnnotations)
{}
{ assert(theEntity.is()); }
OUString name;
rtl::Reference<unoidl::InterfaceTypeEntity> entity;
std::vector<OUString> annotations;
};
SourceProviderInterfaceTypeEntityPad(
bool published, OUString singleBaseName,
rtl::Reference<unoidl::InterfaceTypeEntity> const & singleBaseEntity):
SourceProviderEntityPad(published),
singleBase(!singleBaseName.isEmpty())
{
assert(singleBaseName.isEmpty() != (bool) singleBaseEntity.is());
if (singleBase) {
mandatoryBases.push_back(
Base(
singleBaseName, singleBaseEntity, std::vector<OUString>()));
}
}
enum BaseKind {
BASE_INDIRECT_OPTIONAL, BASE_DIRECT_OPTIONAL, BASE_INDIRECT_MANDATORY,
BASE_DIRECT_MANDATORY
};
struct Member {
OUString mandatory;
std::set<OUString> optional;
explicit Member(OUString theMandatory): mandatory(theMandatory) {}
};
SourceProviderInterfaceTypeEntityPad(bool published, bool theSingleBase):
SourceProviderEntityPad(published), singleBase(theSingleBase)
{}
bool addDirectBase(
YYLTYPE location, yyscan_t yyscanner, SourceProviderScannerData * data,
DirectBase const & base, bool optional);
bool addDirectMember(
YYLTYPE location, yyscan_t yyscanner, SourceProviderScannerData * data,
OUString const & name);
bool singleBase;
std::vector<Base> mandatoryBases;
std::vector<Base> optionalBases;
std::vector<unoidl::InterfaceTypeEntity::Attribute> attributes;
std::vector<unoidl::InterfaceTypeEntity::Method> methods;
std::vector<DirectBase> directMandatoryBases;
std::vector<DirectBase> directOptionalBases;
std::vector<unoidl::InterfaceTypeEntity::Attribute> directAttributes;
std::vector<unoidl::InterfaceTypeEntity::Method> directMethods;
std::map<OUString, BaseKind> allBases;
std::map<OUString, Member> allMembers;
private:
virtual ~SourceProviderInterfaceTypeEntityPad() throw () {}
bool checkBaseClashes(
YYLTYPE location, yyscan_t yyscanner, SourceProviderScannerData * data,
OUString const & name,
rtl::Reference<unoidl::InterfaceTypeEntity> const & entity,
bool direct, bool optional, bool outerOptional,
std::set<OUString> * seen) const;
bool checkMemberClashes(
YYLTYPE location, yyscan_t yyscanner, SourceProviderScannerData * data,
OUString const & interfaceName, OUString const & memberName,
bool checkOptional) const;
bool addBase(
YYLTYPE location, yyscan_t yyscanner, SourceProviderScannerData * data,
OUString const & directBaseName, OUString const & name,
rtl::Reference<unoidl::InterfaceTypeEntity> const & entity, bool direct,
bool optional);
bool addOptionalBaseMembers(
YYLTYPE location, yyscan_t yyscanner, SourceProviderScannerData * data,
OUString const & name,
rtl::Reference<unoidl::InterfaceTypeEntity> const & entity);
};
class SourceProviderConstantGroupEntityPad: public SourceProviderEntityPad {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment