1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include <sal/config.h>
18 #include <osl/file.hxx>
19 #include <osl/process.h>
20 #include <rtl/character.hxx>
21 #include <rtl/process.h>
22 #include <rtl/ref.hxx>
23 #include <rtl/ustring.hxx>
25 #include <sal/types.h>
26 #include <unoidl/unoidl.hxx>
30 static bool operator ==(ConstantValue
const & lhs
, ConstantValue
const & rhs
) {
31 if (lhs
.type
== rhs
.type
) {
33 case ConstantValue::TYPE_BOOLEAN
:
34 return lhs
.booleanValue
== rhs
.booleanValue
;
35 case ConstantValue::TYPE_BYTE
:
36 return lhs
.byteValue
== rhs
.byteValue
;
37 case ConstantValue::TYPE_SHORT
:
38 return lhs
.shortValue
== rhs
.shortValue
;
39 case ConstantValue::TYPE_UNSIGNED_SHORT
:
40 return lhs
.unsignedShortValue
== rhs
.unsignedShortValue
;
41 case ConstantValue::TYPE_LONG
:
42 return lhs
.longValue
== rhs
.longValue
;
43 case ConstantValue::TYPE_UNSIGNED_LONG
:
44 return lhs
.unsignedLongValue
== rhs
.unsignedLongValue
;
45 case ConstantValue::TYPE_HYPER
:
46 return lhs
.hyperValue
== rhs
.hyperValue
;
47 case ConstantValue::TYPE_UNSIGNED_HYPER
:
48 return lhs
.unsignedHyperValue
== rhs
.unsignedHyperValue
;
49 case ConstantValue::TYPE_FLOAT
:
50 return lhs
.floatValue
== rhs
.floatValue
;
51 case ConstantValue::TYPE_DOUBLE
:
52 return lhs
.doubleValue
== rhs
.doubleValue
;
58 static bool operator !=(ConstantValue
const & lhs
, ConstantValue
const & rhs
) {
62 static bool operator ==(
63 SingleInterfaceBasedServiceEntity::Constructor::Parameter
const & lhs
,
64 SingleInterfaceBasedServiceEntity::Constructor::Parameter
const & rhs
)
66 return lhs
.name
== rhs
.name
&& lhs
.type
== rhs
.type
&& lhs
.rest
== rhs
.rest
;
75 << "Usage:" << std::endl
<< std::endl
76 << (" unoidl-check [--ignore-unpublished] [<extra registries A>]"
78 << std::endl
<< " [<extra registries B>] <registry B>" << std::endl
80 << ("where each <registry> is either a new- or legacy-format .rdb file,"
83 << ("file, or a root directory of an .idl file tree. Check that each"
86 << "<registry A> is also present in <registry B> in a compatible form."
88 std::exit(EXIT_FAILURE
);
92 sal_uInt32 argument
, bool * ignoreUnpublished
, bool * delimiter
,
95 assert(ignoreUnpublished
!= nullptr);
96 assert(uri
!= nullptr);
98 rtl_getAppCommandArg(argument
, &arg
.pData
);
99 if (argument
== 0 && arg
== "--ignore-unpublished") {
100 *ignoreUnpublished
= true;
104 if (delimiter
== nullptr) {
111 osl::FileBase::RC e1
= osl::FileBase::getFileURLFromSystemPath(arg
, url
);
112 if (e1
!= osl::FileBase::E_None
) {
114 << "Cannot convert \"" << arg
<< "\" to file URL, error code "
116 std::exit(EXIT_FAILURE
);
119 oslProcessError e2
= osl_getProcessWorkingDir(&cwd
.pData
);
120 if (e2
!= osl_Process_E_None
) {
122 << "Cannot obtain working directory, error code " << +e2
124 std::exit(EXIT_FAILURE
);
126 e1
= osl::FileBase::getAbsoluteFileURL(cwd
, url
, *uri
);
127 if (e1
!= osl::FileBase::E_None
) {
129 << "Cannot make \"" << url
130 << "\" into an absolute file URL, error code " << +e1
<< std::endl
;
131 std::exit(EXIT_FAILURE
);
136 OUString
showDirection(
137 unoidl::InterfaceTypeEntity::Method::Parameter::Direction direction
)
140 case unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN
:
141 return OUString("[in]");
142 case unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_OUT
:
143 return OUString("[out]");
144 case unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN_OUT
:
145 return OUString("[inout]");
147 assert(false && "this cannot happen"); for (;;) { std::abort(); }
151 struct EqualsAnnotation
{
152 explicit EqualsAnnotation(OUString
const & name
): name_(name
) {}
154 bool operator ()(unoidl::AnnotatedReference
const & ref
)
155 { return ref
.name
== name_
; }
158 OUString
const name_
;
162 rtl::Reference
<unoidl::Provider
> const & providerB
, OUString
const & prefix
,
163 rtl::Reference
<unoidl::MapCursor
> const & cursor
, bool ignoreUnpublished
)
165 assert(providerB
.is());
169 rtl::Reference
<unoidl::Entity
> entA(cursor
->getNext(&id
));
173 OUString
name(prefix
+ id
);
174 if (entA
->getSort() == unoidl::Entity::SORT_MODULE
) {
176 providerB
, name
+ ".",
177 (static_cast<unoidl::ModuleEntity
*>(entA
.get())
181 bool pubA
= dynamic_cast<unoidl::PublishableEntity
&>(*entA
).isPublished();
182 if (!pubA
&& ignoreUnpublished
) {
185 rtl::Reference
<unoidl::Entity
> entB(providerB
->findEntity(name
));
188 << "A entity " << name
<< " is not present in B"
190 std::exit(EXIT_FAILURE
);
192 if (entA
->getSort() != entB
->getSort()) {
194 << "A entity " << name
<< " is of different sort in B"
196 std::exit(EXIT_FAILURE
);
198 if (pubA
&& (!dynamic_cast<unoidl::PublishableEntity
&>(*entB
).isPublished()))
201 << "A published entity " << name
<< " is not published in B"
203 std::exit(EXIT_FAILURE
);
205 switch (entA
->getSort()) {
206 case unoidl::Entity::SORT_ENUM_TYPE
:
208 rtl::Reference
<unoidl::EnumTypeEntity
> ent2A(
209 static_cast<unoidl::EnumTypeEntity
*>(entA
.get()));
210 rtl::Reference
<unoidl::EnumTypeEntity
> ent2B(
211 static_cast<unoidl::EnumTypeEntity
*>(entB
.get()));
212 if (ent2A
->getMembers().size()
213 != ent2B
->getMembers().size())
216 << "enum type " << name
217 << " number of members changed from "
218 << ent2A
->getMembers().size() << " to "
219 << ent2B
->getMembers().size() << std::endl
;
220 std::exit(EXIT_FAILURE
);
223 i(ent2A
->getMembers().begin()),
224 j(ent2B
->getMembers().begin());
225 i
!= ent2A
->getMembers().end(); ++i
, ++j
)
227 if (i
->name
!= j
->name
|| i
->value
!= j
->value
) {
229 << "enum type " << name
<< " member #"
230 << i
- ent2A
->getMembers().begin() + 1
231 << " changed from " << i
->name
<< " = "
232 << i
->value
<< " to " << j
->name
<< " = "
233 << j
->value
<< std::endl
;
234 std::exit(EXIT_FAILURE
);
239 case unoidl::Entity::SORT_PLAIN_STRUCT_TYPE
:
241 rtl::Reference
<unoidl::PlainStructTypeEntity
> ent2A(
242 static_cast<unoidl::PlainStructTypeEntity
*>(
244 rtl::Reference
<unoidl::PlainStructTypeEntity
> ent2B(
245 static_cast<unoidl::PlainStructTypeEntity
*>(
247 if (ent2A
->getDirectBase() != ent2B
->getDirectBase()) {
249 << "plain struct type " << name
250 << " direct base changed from "
251 << (ent2A
->getDirectBase().isEmpty()
252 ? OUString("none") : ent2A
->getDirectBase())
254 << (ent2B
->getDirectBase().isEmpty()
255 ? OUString("none") : ent2B
->getDirectBase())
257 std::exit(EXIT_FAILURE
);
259 if (ent2A
->getDirectMembers().size()
260 != ent2B
->getDirectMembers().size())
263 << "plain struct type " << name
264 << " number of direct members changed from "
265 << ent2A
->getDirectMembers().size() << " to "
266 << ent2B
->getDirectMembers().size() << std::endl
;
267 std::exit(EXIT_FAILURE
);
270 i(ent2A
->getDirectMembers().begin()),
271 j(ent2B
->getDirectMembers().begin());
272 i
!= ent2A
->getDirectMembers().end(); ++i
, ++j
)
274 if (i
->name
!= j
->name
|| i
->type
!= j
->type
) {
276 << "plain struct type " << name
277 << " direct member #"
278 << i
- ent2A
->getDirectMembers().begin() + 1
279 << " changed from " << i
->type
<< " " << i
->name
280 << " to " << j
->type
<< " " << j
->name
282 std::exit(EXIT_FAILURE
);
287 case unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE
:
289 rtl::Reference
<unoidl::PolymorphicStructTypeTemplateEntity
>
291 static_cast<unoidl::PolymorphicStructTypeTemplateEntity
*>(
293 rtl::Reference
<unoidl::PolymorphicStructTypeTemplateEntity
>
295 static_cast<unoidl::PolymorphicStructTypeTemplateEntity
*>(
297 if (ent2A
->getTypeParameters().size()
298 != ent2B
->getTypeParameters().size())
301 << "polymorphic struct type template " << name
302 << " number of type parameters changed from "
303 << ent2A
->getTypeParameters().size() << " to "
304 << ent2B
->getTypeParameters().size() << std::endl
;
305 std::exit(EXIT_FAILURE
);
308 i(ent2A
->getTypeParameters().begin()),
309 j(ent2B
->getTypeParameters().begin());
310 i
!= ent2A
->getTypeParameters().end(); ++i
, ++j
)
314 << "polymorphic struct type template " << name
315 << " type parameter #"
316 << i
- ent2A
->getTypeParameters().begin() + 1
317 << " changed from " << *i
<< " to " << *j
319 std::exit(EXIT_FAILURE
);
322 if (ent2A
->getMembers().size()
323 != ent2B
->getMembers().size())
326 << "polymorphic struct type template " << name
327 << " number of members changed from "
328 << ent2A
->getMembers().size() << " to "
329 << ent2B
->getMembers().size() << std::endl
;
330 std::exit(EXIT_FAILURE
);
333 i(ent2A
->getMembers().begin()),
334 j(ent2B
->getMembers().begin());
335 i
!= ent2A
->getMembers().end(); ++i
, ++j
)
337 if (i
->name
!= j
->name
|| i
->type
!= j
->type
338 || i
->parameterized
!= j
->parameterized
)
341 << "polymorphic struct type template " << name
343 << i
- ent2A
->getMembers().begin() + 1
346 ? OUString("parameterized ") : OUString())
347 << i
->type
<< " " << i
->name
350 ? OUString("parameterized ") : OUString())
351 << j
->type
<< " " << j
->name
353 std::exit(EXIT_FAILURE
);
358 case unoidl::Entity::SORT_EXCEPTION_TYPE
:
360 rtl::Reference
<unoidl::ExceptionTypeEntity
> ent2A(
361 static_cast<unoidl::ExceptionTypeEntity
*>(entA
.get()));
362 rtl::Reference
<unoidl::ExceptionTypeEntity
> ent2B(
363 static_cast<unoidl::ExceptionTypeEntity
*>(entB
.get()));
364 if (ent2A
->getDirectBase() != ent2B
->getDirectBase()) {
366 << "exception type " << name
367 << " direct base changed from "
368 << (ent2A
->getDirectBase().isEmpty()
369 ? OUString("none") : ent2A
->getDirectBase())
371 << (ent2B
->getDirectBase().isEmpty()
372 ? OUString("none") : ent2B
->getDirectBase())
374 std::exit(EXIT_FAILURE
);
376 if (ent2A
->getDirectMembers().size()
377 != ent2B
->getDirectMembers().size())
380 << "exception type " << name
381 << " number of direct members changed from "
382 << ent2A
->getDirectMembers().size() << " to "
383 << ent2B
->getDirectMembers().size() << std::endl
;
384 std::exit(EXIT_FAILURE
);
387 i(ent2A
->getDirectMembers().begin()),
388 j(ent2B
->getDirectMembers().begin());
389 i
!= ent2A
->getDirectMembers().end(); ++i
, ++j
)
391 if (i
->name
!= j
->name
|| i
->type
!= j
->type
) {
393 << "exception type " << name
394 << " direct member #"
395 << i
- ent2A
->getDirectMembers().begin() + 1
396 << " changed from " << i
->type
<< " " << i
->name
397 << " to " << j
->type
<< " " << j
->name
399 std::exit(EXIT_FAILURE
);
404 case unoidl::Entity::SORT_INTERFACE_TYPE
:
406 rtl::Reference
<unoidl::InterfaceTypeEntity
> ent2A(
407 static_cast<unoidl::InterfaceTypeEntity
*>(entA
.get()));
408 rtl::Reference
<unoidl::InterfaceTypeEntity
> ent2B(
409 static_cast<unoidl::InterfaceTypeEntity
*>(entB
.get()));
410 if (ent2A
->getDirectMandatoryBases().size()
411 != ent2B
->getDirectMandatoryBases().size())
414 << "interface type " << name
415 << " number of direct mandatory bases changed from "
416 << ent2A
->getDirectMandatoryBases().size() << " to "
417 << ent2B
->getDirectMandatoryBases().size()
419 std::exit(EXIT_FAILURE
);
422 i(ent2A
->getDirectMandatoryBases().begin()),
423 j(ent2B
->getDirectMandatoryBases().begin());
424 i
!= ent2A
->getDirectMandatoryBases().end(); ++i
, ++j
)
426 if (i
->name
!= j
->name
) {
428 << "interface type " << name
429 << " direct mandatory base #"
430 << (i
- ent2A
->getDirectMandatoryBases().begin()
432 << " changed from " << i
->name
<< " to "
433 << j
->name
<< std::endl
;
434 std::exit(EXIT_FAILURE
);
437 if (ent2A
->getDirectOptionalBases().size()
438 != ent2B
->getDirectOptionalBases().size())
441 << "interface type " << name
442 << " number of direct optional bases changed from "
443 << ent2A
->getDirectOptionalBases().size() << " to "
444 << ent2B
->getDirectOptionalBases().size()
446 std::exit(EXIT_FAILURE
);
449 i(ent2A
->getDirectOptionalBases().begin()),
450 j(ent2B
->getDirectOptionalBases().begin());
451 i
!= ent2A
->getDirectOptionalBases().end(); ++i
, ++j
)
453 if (i
->name
!= j
->name
) {
455 << "interface type " << name
456 << " direct optional base #"
457 << (i
- ent2A
->getDirectOptionalBases().begin()
459 << " changed from " << i
->name
<< " to "
460 << j
->name
<< std::endl
;
461 std::exit(EXIT_FAILURE
);
464 if (ent2A
->getDirectAttributes().size()
465 != ent2B
->getDirectAttributes().size())
468 << "interface type " << name
469 << " number of direct attributes changed from "
470 << ent2A
->getDirectAttributes().size() << " to "
471 << ent2B
->getDirectAttributes().size() << std::endl
;
472 std::exit(EXIT_FAILURE
);
475 i(ent2A
->getDirectAttributes().begin()),
476 j(ent2B
->getDirectAttributes().begin());
477 i
!= ent2A
->getDirectAttributes().end(); ++i
, ++j
)
479 if (i
->name
!= j
->name
|| i
->type
!= j
->type
480 || i
->bound
!= j
->bound
481 || i
->readOnly
!= j
->readOnly
482 || i
->getExceptions
!= j
->getExceptions
483 || i
->setExceptions
!= j
->setExceptions
)
486 << "interface type " << name
487 << " direct attribute #"
488 << i
- ent2A
->getDirectAttributes().begin() + 1
490 << (i
->bound
? OUString("bound ") : OUString())
492 ? OUString("read-only ") : OUString())
493 << i
->type
<< " " << i
->name
//TODO: exceptions
495 << (j
->bound
? OUString("bound ") : OUString())
497 ? OUString("read-only ") : OUString())
498 << j
->type
<< " " << j
->name
//TODO: exceptions
500 std::exit(EXIT_FAILURE
);
503 if (ent2A
->getDirectMethods().size()
504 != ent2B
->getDirectMethods().size())
507 << "interface type " << name
508 << " number of direct methods changed from "
509 << ent2A
->getDirectMethods().size() << " to "
510 << ent2B
->getDirectMethods().size() << std::endl
;
511 std::exit(EXIT_FAILURE
);
514 i(ent2A
->getDirectMethods().begin()),
515 j(ent2B
->getDirectMethods().begin());
516 i
!= ent2A
->getDirectMethods().end(); ++i
, ++j
)
518 if (i
->name
!= j
->name
|| i
->returnType
!= j
->returnType
519 || i
->exceptions
!= j
->exceptions
)
522 << "interface type " << name
523 << " direct method #"
524 << i
- ent2A
->getDirectMethods().begin() + 1
526 << i
->returnType
<< " " << i
->name
//TODO: exceptions
527 << " to " << j
->returnType
<< " " << j
->name
//TODO: exceptions
529 std::exit(EXIT_FAILURE
);
531 if (i
->parameters
.size() != j
->parameters
.size()) {
533 << "interface type " << name
534 << " direct method " << i
->name
535 << " number of parameters changed from "
536 << i
->parameters
.size() << " to "
537 << j
->parameters
.size() << std::endl
;
538 std::exit(EXIT_FAILURE
);
541 k(i
->parameters
.begin()),
542 l(j
->parameters
.begin());
543 k
!= i
->parameters
.end(); ++k
, ++l
)
545 if (k
->type
!= l
->type
|| k
->direction
!= l
->direction
)
548 << "interface type " << name
549 << " direct method " << i
->name
551 << k
- i
->parameters
.begin() + 1
553 << showDirection(k
->direction
) << " "
555 << showDirection(l
->direction
) << " "
556 << l
->type
<< std::endl
;
557 std::exit(EXIT_FAILURE
);
559 if (k
->name
!= l
->name
) {
561 << "interface type " << name
562 << " direct method " << i
->name
564 << k
- i
->parameters
.begin() + 1
565 << " changed name from " << k
->name
566 << " to " << l
->name
<< std::endl
;
567 std::exit(EXIT_FAILURE
);
573 case unoidl::Entity::SORT_TYPEDEF
:
575 rtl::Reference
<unoidl::TypedefEntity
> ent2A(
576 static_cast<unoidl::TypedefEntity
*>(entA
.get()));
577 rtl::Reference
<unoidl::TypedefEntity
> ent2B(
578 static_cast<unoidl::TypedefEntity
*>(entB
.get()));
579 if (ent2A
->getType() != ent2B
->getType()) {
581 << "typedef " << name
<< " type changed from "
582 << ent2A
->getType() << " to " << ent2B
->getType()
584 std::exit(EXIT_FAILURE
);
588 case unoidl::Entity::SORT_CONSTANT_GROUP
:
590 rtl::Reference
<unoidl::ConstantGroupEntity
> ent2A(
591 static_cast<unoidl::ConstantGroupEntity
*>(entA
.get()));
592 rtl::Reference
<unoidl::ConstantGroupEntity
> ent2B(
593 static_cast<unoidl::ConstantGroupEntity
*>(entB
.get()));
594 for (auto & i
: ent2A
->getMembers()) {
596 for (auto & j
: ent2B
->getMembers()) {
597 if (i
.name
== j
.name
) {
598 if (i
.value
!= j
.value
) {
600 << "constant group " << name
601 << " member " << i
.name
602 << " changed value" << std::endl
;
603 std::exit(EXIT_FAILURE
);
611 << "A constant group " << name
<< " member "
612 << i
.name
<< " is not present in B"
614 std::exit(EXIT_FAILURE
);
619 case unoidl::Entity::SORT_SINGLE_INTERFACE_BASED_SERVICE
:
621 rtl::Reference
<unoidl::SingleInterfaceBasedServiceEntity
>
623 static_cast<unoidl::SingleInterfaceBasedServiceEntity
*>(
625 rtl::Reference
<unoidl::SingleInterfaceBasedServiceEntity
>
627 static_cast<unoidl::SingleInterfaceBasedServiceEntity
*>(
629 if (ent2A
->getBase() != ent2B
->getBase()) {
631 << "single-interface--based service " << name
632 << " base changed from " << ent2A
->getBase()
633 << " to " << ent2B
->getBase()
635 std::exit(EXIT_FAILURE
);
637 if (ent2A
->getConstructors().size()
638 != ent2B
->getConstructors().size())
641 << "single-interface--based service " << name
642 << " number of constructors changed from "
643 << ent2A
->getConstructors().size() << " to "
644 << ent2B
->getConstructors().size() << std::endl
;
645 std::exit(EXIT_FAILURE
);
648 i(ent2A
->getConstructors().begin()),
649 j(ent2B
->getConstructors().begin());
650 i
!= ent2A
->getConstructors().end(); ++i
, ++j
)
652 if (i
->name
!= j
->name
|| i
->parameters
!= j
->parameters
653 || i
->exceptions
!= j
->exceptions
654 || i
->defaultConstructor
!= j
->defaultConstructor
)
657 << "single-interface--based service " << name
659 << i
- ent2A
->getConstructors().begin() + 1
661 << (i
->defaultConstructor
662 ? OUString("default ") : i
->name
) //TODO: parameters, exceptions
664 << (j
->defaultConstructor
665 ? OUString("default ") : j
->name
) //TODO: parameters, exceptions
667 std::exit(EXIT_FAILURE
);
672 case unoidl::Entity::SORT_ACCUMULATION_BASED_SERVICE
:
674 rtl::Reference
<unoidl::AccumulationBasedServiceEntity
>
676 static_cast<unoidl::AccumulationBasedServiceEntity
*>(
678 rtl::Reference
<unoidl::AccumulationBasedServiceEntity
>
680 static_cast<unoidl::AccumulationBasedServiceEntity
*>(
682 if (ent2A
->getDirectMandatoryBaseServices().size()
683 != ent2B
->getDirectMandatoryBaseServices().size())
686 << "accumulation-based service " << name
687 << (" number of direct mandatory base services"
689 << ent2A
->getDirectMandatoryBaseServices().size()
691 << ent2B
->getDirectMandatoryBaseServices().size()
693 std::exit(EXIT_FAILURE
);
696 i(ent2A
->getDirectMandatoryBaseServices().begin()),
697 j(ent2B
->getDirectMandatoryBaseServices().begin());
698 i
!= ent2A
->getDirectMandatoryBaseServices().end();
701 if (i
->name
!= j
->name
) {
703 << "accumulation-based service " << name
704 << " direct mandatory base service #"
706 - (ent2A
->getDirectMandatoryBaseServices()
709 << " changed from " << i
->name
<< " to "
710 << j
->name
<< std::endl
;
711 std::exit(EXIT_FAILURE
);
714 if (ent2A
->getDirectOptionalBaseServices().size()
715 > ent2B
->getDirectOptionalBaseServices().size())
718 << "accumulation-based service " << name
719 << (" number of direct optional base services"
721 << ent2A
->getDirectOptionalBaseServices().size()
723 << ent2B
->getDirectOptionalBaseServices().size()
725 std::exit(EXIT_FAILURE
);
727 for (auto & i
: ent2A
->getDirectOptionalBaseServices()) {
729 ent2B
->getDirectOptionalBaseServices().begin(),
730 ent2B
->getDirectOptionalBaseServices().end(),
731 EqualsAnnotation(i
.name
)))
734 << "accumulation-based service " << name
735 << " direct optional base service " << i
.name
736 << " was removed" << std::endl
;
737 std::exit(EXIT_FAILURE
);
740 if (ent2A
->getDirectMandatoryBaseInterfaces().size()
741 != ent2B
->getDirectMandatoryBaseInterfaces().size())
744 << "accumulation-based service " << name
745 << (" number of direct mandatory base interfaces"
747 << ent2A
->getDirectMandatoryBaseInterfaces().size()
749 << ent2B
->getDirectMandatoryBaseInterfaces().size()
751 std::exit(EXIT_FAILURE
);
754 i(ent2A
->getDirectMandatoryBaseInterfaces()
756 j(ent2B
->getDirectMandatoryBaseInterfaces()
758 i
!= ent2A
->getDirectMandatoryBaseInterfaces().end();
761 if (i
->name
!= j
->name
) {
763 << "accumulation-based service " << name
764 << " direct mandatory base interface #"
766 - (ent2A
->getDirectMandatoryBaseInterfaces()
769 << " changed from " << i
->name
<< " to "
770 << j
->name
<< std::endl
;
771 std::exit(EXIT_FAILURE
);
774 if (ent2A
->getDirectOptionalBaseInterfaces().size()
775 > ent2B
->getDirectOptionalBaseInterfaces().size())
778 << "accumulation-based service " << name
779 << (" number of direct optional base interfaces"
781 << ent2A
->getDirectOptionalBaseInterfaces().size()
783 << ent2B
->getDirectOptionalBaseInterfaces().size()
785 std::exit(EXIT_FAILURE
);
787 for (auto & i
: ent2A
->getDirectOptionalBaseInterfaces()) {
789 (ent2B
->getDirectOptionalBaseInterfaces()
791 ent2B
->getDirectOptionalBaseInterfaces().end(),
792 EqualsAnnotation(i
.name
)))
795 << "accumulation-based service " << name
796 << " direct optional base interface " << i
.name
797 << " was removed" << std::endl
;
798 std::exit(EXIT_FAILURE
);
801 if (ent2A
->getDirectProperties().size()
802 > ent2B
->getDirectProperties().size())
805 << "accumulation-based service " << name
806 << " number of direct properties changed from "
807 << ent2A
->getDirectProperties().size() << " to "
808 << ent2B
->getDirectProperties().size() << std::endl
;
809 std::exit(EXIT_FAILURE
);
812 i(ent2A
->getDirectProperties().begin()),
813 j(ent2B
->getDirectProperties().begin());
814 i
!= ent2A
->getDirectProperties().end(); ++i
, ++j
)
816 if (i
->name
!= j
->name
|| i
->type
!= j
->type
817 || i
->attributes
!= j
->attributes
)
820 << "accumulation-based service " << name
821 << " direct property #"
822 << i
- ent2A
->getDirectProperties().begin() + 1
824 << i
->type
<< " " << i
->name
//TODO: attributes
826 << j
->type
<< " " << j
->name
//TODO: attributes
828 std::exit(EXIT_FAILURE
);
832 i(ent2B
->getDirectProperties().begin()
833 + ent2A
->getDirectProperties().size());
834 i
!= ent2B
->getDirectProperties().end(); ++i
)
836 if ((i
->attributes
& unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_OPTIONAL
) == 0)
839 << "B accumulation-based service " << name
840 << " additional direct property " << i
->name
841 << " is not optional" << std::endl
;
842 std::exit(EXIT_FAILURE
);
847 case unoidl::Entity::SORT_INTERFACE_BASED_SINGLETON
:
849 rtl::Reference
<unoidl::InterfaceBasedSingletonEntity
> ent2A(
850 static_cast<unoidl::InterfaceBasedSingletonEntity
*>(
852 rtl::Reference
<unoidl::InterfaceBasedSingletonEntity
> ent2B(
853 static_cast<unoidl::InterfaceBasedSingletonEntity
*>(
855 if (ent2A
->getBase() != ent2B
->getBase()) {
857 << "interface-based singleton " << name
858 << " base changed from " << ent2A
->getBase()
859 << " to " << ent2B
->getBase() << std::endl
;
860 std::exit(EXIT_FAILURE
);
864 case unoidl::Entity::SORT_SERVICE_BASED_SINGLETON
:
866 rtl::Reference
<unoidl::ServiceBasedSingletonEntity
> ent2A(
867 static_cast<unoidl::ServiceBasedSingletonEntity
*>(
869 rtl::Reference
<unoidl::ServiceBasedSingletonEntity
> ent2B(
870 static_cast<unoidl::ServiceBasedSingletonEntity
*>(
872 if (ent2A
->getBase() != ent2B
->getBase()) {
874 << "service-based singleton " << name
875 << " base changed from " << ent2A
->getBase()
876 << " to " << ent2B
->getBase() << std::endl
;
877 std::exit(EXIT_FAILURE
);
881 case unoidl::Entity::SORT_MODULE
:
882 assert(false && "this cannot happen");
888 bool valid(OUString
const & identifier
) {
889 for (sal_Int32 i
= 0;; ++i
) {
890 i
= identifier
.indexOf('_', i
);
894 if (!rtl::isAsciiUpperCase(identifier
[0]) || identifier
[i
- 1] == '_') {
901 rtl::Reference
<unoidl::Provider
> const & providerA
, OUString
const & prefix
,
902 rtl::Reference
<unoidl::MapCursor
> const & cursor
)
907 rtl::Reference
<unoidl::Entity
> entB(cursor
->getNext(&id
));
911 OUString
name(prefix
+ id
);
912 rtl::Reference
<unoidl::Entity
> entA(providerA
->findEntity(name
));
913 if (!(entA
.is() || valid(id
))) {
915 << "entity name " << name
<< " uses an invalid identifier"
917 std::exit(EXIT_FAILURE
);
919 switch (entB
->getSort()) {
920 case unoidl::Entity::SORT_MODULE
:
922 providerA
, name
+ ".",
923 (static_cast<unoidl::ModuleEntity
*>(entB
.get())
926 case unoidl::Entity::SORT_ENUM_TYPE
:
928 rtl::Reference
<unoidl::EnumTypeEntity
> ent2B(
929 static_cast<unoidl::EnumTypeEntity
*>(entB
.get()));
930 for (auto & i
: ent2B
->getMembers()) {
931 if (!valid(i
.name
)) {
933 << "enum type " << name
<< " member " << i
.name
934 << " uses an invalid identifier" << std::endl
;
935 std::exit(EXIT_FAILURE
);
940 case unoidl::Entity::SORT_PLAIN_STRUCT_TYPE
:
942 rtl::Reference
<unoidl::PlainStructTypeEntity
> ent2B(
943 static_cast<unoidl::PlainStructTypeEntity
*>(
945 for (auto & i
: ent2B
->getDirectMembers()) {
946 if (!valid(i
.name
)) {
948 << "plain struct type " << name
<< " direct member "
949 << i
.name
<< " uses an invalid identifier"
951 std::exit(EXIT_FAILURE
);
956 case unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE
:
958 rtl::Reference
<unoidl::PolymorphicStructTypeTemplateEntity
>
961 unoidl::PolymorphicStructTypeTemplateEntity
*>(
963 for (auto & i
: ent2B
->getTypeParameters()) {
966 << "polymorphic struct type template " << name
967 << " type parameter " << i
968 << " uses an invalid identifier" << std::endl
;
969 std::exit(EXIT_FAILURE
);
972 for (auto & i
: ent2B
->getMembers()) {
973 if (!valid(i
.name
)) {
975 << "polymorphic struct type template " << name
976 << " member " << i
.name
977 << " uses an invalid identifier" << std::endl
;
978 std::exit(EXIT_FAILURE
);
983 case unoidl::Entity::SORT_EXCEPTION_TYPE
:
985 rtl::Reference
<unoidl::ExceptionTypeEntity
> ent2B(
986 static_cast<unoidl::ExceptionTypeEntity
*>(entB
.get()));
987 for (auto & i
: ent2B
->getDirectMembers()) {
988 if (!valid(i
.name
)) {
990 << "exception type " << name
<< " direct member "
991 << i
.name
<< " uses an invalid identifier"
993 std::exit(EXIT_FAILURE
);
998 case unoidl::Entity::SORT_INTERFACE_TYPE
:
1000 rtl::Reference
<unoidl::InterfaceTypeEntity
> ent2B(
1001 static_cast<unoidl::InterfaceTypeEntity
*>(entB
.get()));
1002 for (auto & i
: ent2B
->getDirectAttributes()) {
1003 if (!valid(i
.name
)) {
1005 << "interface type " << name
<< " direct attribute "
1006 << i
.name
<< " uses an invalid identifier"
1008 std::exit(EXIT_FAILURE
);
1011 for (auto & i
: ent2B
->getDirectMethods()) {
1012 if (!valid(i
.name
)) {
1014 << "interface type " << name
<< " direct method "
1015 << i
.name
<< " uses an invalid identifier"
1017 std::exit(EXIT_FAILURE
);
1019 for (auto & j
: i
.parameters
) {
1020 if (!valid(j
.name
)) {
1022 << "interface type " << name
1023 << " direct method " << i
.name
<< " parameter "
1024 << j
.name
<< " uses an invalid identifier"
1026 std::exit(EXIT_FAILURE
);
1032 case unoidl::Entity::SORT_TYPEDEF
:
1033 case unoidl::Entity::SORT_INTERFACE_BASED_SINGLETON
:
1034 case unoidl::Entity::SORT_SERVICE_BASED_SINGLETON
:
1036 case unoidl::Entity::SORT_CONSTANT_GROUP
:
1038 rtl::Reference
<unoidl::ConstantGroupEntity
> ent2B(
1039 static_cast<unoidl::ConstantGroupEntity
*>(entB
.get()));
1040 for (auto & i
: ent2B
->getMembers()) {
1043 rtl::Reference
<unoidl::ConstantGroupEntity
> ent2A(
1044 static_cast<unoidl::ConstantGroupEntity
*>(
1046 for (auto & j
: ent2A
->getMembers()) {
1047 if (i
.name
== j
.name
) {
1053 if (!(found
|| valid(i
.name
))) {
1055 << "Constant group " << name
<< " member "
1056 << i
.name
<< " uses an invalid identifier"
1058 std::exit(EXIT_FAILURE
);
1063 case unoidl::Entity::SORT_SINGLE_INTERFACE_BASED_SERVICE
:
1065 rtl::Reference
<unoidl::SingleInterfaceBasedServiceEntity
>
1067 static_cast<unoidl::SingleInterfaceBasedServiceEntity
*>(
1069 for (auto & i
: ent2B
->getConstructors()) {
1070 if (!valid(i
.name
)) {
1072 << "single-interface--based service " << name
1073 << " constructor " << i
.name
1074 << " uses an invalid identifier" << std::endl
;
1075 std::exit(EXIT_FAILURE
);
1077 for (auto & j
: i
.parameters
) {
1078 if (!valid(j
.name
)) {
1080 << "single-interface--based service " << name
1081 << " constructor " << i
.name
<< " parameter "
1082 << j
.name
<< " uses an invalid identifier"
1084 std::exit(EXIT_FAILURE
);
1090 case unoidl::Entity::SORT_ACCUMULATION_BASED_SERVICE
:
1092 rtl::Reference
<unoidl::AccumulationBasedServiceEntity
> ent2B(
1093 static_cast<unoidl::AccumulationBasedServiceEntity
*>(
1095 std::vector
<unoidl::AccumulationBasedServiceEntity::Property
>::size_type
1097 ? (static_cast<unoidl::AccumulationBasedServiceEntity
*>(
1099 ->getDirectProperties().size())
1101 assert(n
<= ent2B
->getDirectProperties().size());
1102 for (auto i(ent2B
->getDirectProperties().begin() +n
);
1103 i
!= ent2B
->getDirectProperties().end(); ++i
)
1105 if (!valid(i
->name
)) {
1107 << "accumulation-based service " << name
1108 << " direct property " << i
->name
1109 << " uses an invalid identifier" << std::endl
;
1110 std::exit(EXIT_FAILURE
);
1121 SAL_IMPLEMENT_MAIN() {
1123 sal_uInt32 args
= rtl_getAppCommandArgCount();
1124 rtl::Reference
<unoidl::Manager
> mgr
[2];
1125 mgr
[0] = new unoidl::Manager
;
1126 mgr
[1] = new unoidl::Manager
;
1127 rtl::Reference
<unoidl::Provider
> prov
[2];
1129 bool ignoreUnpublished
= false;
1130 for (sal_uInt32 i
= 0; i
!= args
; ++i
) {
1131 bool delimiter
= false;
1134 i
, &ignoreUnpublished
, side
== 0 ? &delimiter
: nullptr,
1138 prov
[side
] = mgr
[side
]->addProvider(uri
);
1139 } catch (unoidl::NoSuchFileException
&) {
1141 << "Input <" << uri
<< "> does not exist" << std::endl
;
1142 std::exit(EXIT_FAILURE
);
1144 } else if (delimiter
) {
1148 if (side
== 0 || !(prov
[0].is() && prov
[1].is())) {
1151 checkMap(prov
[1], "", prov
[0]->createRootCursor(), ignoreUnpublished
);
1152 checkIds(prov
[0], "", prov
[1]->createRootCursor());
1153 return EXIT_SUCCESS
;
1154 } catch (unoidl::FileFormatException
& e1
) {
1156 << "Bad input <" << e1
.getUri() << ">: " << e1
.getDetail()
1158 std::exit(EXIT_FAILURE
);
1159 } catch (std::exception
& e1
) {
1160 std::cerr
<< "Failure: " << e1
.what() << std::endl
;
1161 std::exit(EXIT_FAILURE
);
1165 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */