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>
16 #include <string_view>
20 #include <osl/file.hxx>
21 #include <osl/process.h>
22 #include <rtl/character.hxx>
23 #include <rtl/process.h>
24 #include <rtl/ref.hxx>
25 #include <rtl/ustring.hxx>
27 #include <sal/types.h>
28 #include <unoidl/unoidl.hxx>
32 static bool operator ==(ConstantValue
const & lhs
, ConstantValue
const & rhs
) {
33 if (lhs
.type
== rhs
.type
) {
35 case ConstantValue::TYPE_BOOLEAN
:
36 return lhs
.booleanValue
== rhs
.booleanValue
;
37 case ConstantValue::TYPE_BYTE
:
38 return lhs
.byteValue
== rhs
.byteValue
;
39 case ConstantValue::TYPE_SHORT
:
40 return lhs
.shortValue
== rhs
.shortValue
;
41 case ConstantValue::TYPE_UNSIGNED_SHORT
:
42 return lhs
.unsignedShortValue
== rhs
.unsignedShortValue
;
43 case ConstantValue::TYPE_LONG
:
44 return lhs
.longValue
== rhs
.longValue
;
45 case ConstantValue::TYPE_UNSIGNED_LONG
:
46 return lhs
.unsignedLongValue
== rhs
.unsignedLongValue
;
47 case ConstantValue::TYPE_HYPER
:
48 return lhs
.hyperValue
== rhs
.hyperValue
;
49 case ConstantValue::TYPE_UNSIGNED_HYPER
:
50 return lhs
.unsignedHyperValue
== rhs
.unsignedHyperValue
;
51 case ConstantValue::TYPE_FLOAT
:
52 return lhs
.floatValue
== rhs
.floatValue
;
53 case ConstantValue::TYPE_DOUBLE
:
54 return lhs
.doubleValue
== rhs
.doubleValue
;
60 static bool operator !=(ConstantValue
const & lhs
, ConstantValue
const & rhs
) {
64 static bool operator ==(
65 SingleInterfaceBasedServiceEntity::Constructor::Parameter
const & lhs
,
66 SingleInterfaceBasedServiceEntity::Constructor::Parameter
const & rhs
)
68 return lhs
.name
== rhs
.name
&& lhs
.type
== rhs
.type
&& lhs
.rest
== rhs
.rest
;
77 << "Usage:" << std::endl
<< std::endl
78 << (" unoidl-check [--ignore-unpublished] [<extra registries A>]"
80 << std::endl
<< " [<extra registries B>] <registry B>" << std::endl
82 << ("where each <registry> is either a new- or legacy-format .rdb file,"
85 << ("file, or a root directory of an .idl file tree. Check that each"
88 << "<registry A> is also present in <registry B> in a compatible form."
90 std::exit(EXIT_FAILURE
);
94 sal_uInt32 argument
, bool * ignoreUnpublished
, bool * delimiter
,
97 assert(ignoreUnpublished
!= nullptr);
98 assert(uri
!= nullptr);
100 rtl_getAppCommandArg(argument
, &arg
.pData
);
101 if (argument
== 0 && arg
== "--ignore-unpublished") {
102 *ignoreUnpublished
= true;
106 if (delimiter
== nullptr) {
113 osl::FileBase::RC e1
= osl::FileBase::getFileURLFromSystemPath(arg
, url
);
114 if (e1
!= osl::FileBase::E_None
) {
116 << "Cannot convert \"" << arg
<< "\" to file URL, error code "
118 std::exit(EXIT_FAILURE
);
121 oslProcessError e2
= osl_getProcessWorkingDir(&cwd
.pData
);
122 if (e2
!= osl_Process_E_None
) {
124 << "Cannot obtain working directory, error code " << +e2
126 std::exit(EXIT_FAILURE
);
128 e1
= osl::FileBase::getAbsoluteFileURL(cwd
, url
, *uri
);
129 if (e1
!= osl::FileBase::E_None
) {
131 << "Cannot make \"" << url
132 << "\" into an absolute file URL, error code " << +e1
<< std::endl
;
133 std::exit(EXIT_FAILURE
);
138 OUString
showDirection(
139 unoidl::InterfaceTypeEntity::Method::Parameter::Direction direction
)
142 case unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN
:
144 case unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_OUT
:
146 case unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN_OUT
:
149 assert(false && "this cannot happen"); for (;;) { std::abort(); }
153 struct EqualsAnnotation
{
154 explicit EqualsAnnotation(OUString name
): name_(std::move(name
)) {}
156 bool operator ()(unoidl::AnnotatedReference
const & ref
)
157 { return ref
.name
== name_
; }
164 rtl::Reference
<unoidl::Provider
> const & providerB
, std::u16string_view prefix
,
165 rtl::Reference
<unoidl::MapCursor
> const & cursor
, bool ignoreUnpublished
)
167 assert(providerB
.is());
171 rtl::Reference
<unoidl::Entity
> entA(cursor
->getNext(&id
));
175 OUString
name(prefix
+ id
);
176 if (entA
->getSort() == unoidl::Entity::SORT_MODULE
) {
178 providerB
, Concat2View(name
+ "."),
179 (static_cast<unoidl::ModuleEntity
*>(entA
.get())
183 bool pubA
= dynamic_cast<unoidl::PublishableEntity
&>(*entA
).isPublished();
184 if (!pubA
&& ignoreUnpublished
) {
187 rtl::Reference
<unoidl::Entity
> entB(providerB
->findEntity(name
));
190 << "A entity " << name
<< " is not present in B"
192 std::exit(EXIT_FAILURE
);
194 if (entA
->getSort() != entB
->getSort()) {
196 << "A entity " << name
<< " is of different sort in B"
198 std::exit(EXIT_FAILURE
);
200 if (pubA
&& (!dynamic_cast<unoidl::PublishableEntity
&>(*entB
).isPublished()))
203 << "A published entity " << name
<< " is not published in B"
205 std::exit(EXIT_FAILURE
);
207 switch (entA
->getSort()) {
208 case unoidl::Entity::SORT_ENUM_TYPE
:
210 rtl::Reference
<unoidl::EnumTypeEntity
> ent2A(
211 static_cast<unoidl::EnumTypeEntity
*>(entA
.get()));
212 rtl::Reference
<unoidl::EnumTypeEntity
> ent2B(
213 static_cast<unoidl::EnumTypeEntity
*>(entB
.get()));
214 if (ent2A
->getMembers().size()
215 != ent2B
->getMembers().size())
218 << "enum type " << name
219 << " number of members changed from "
220 << ent2A
->getMembers().size() << " to "
221 << ent2B
->getMembers().size() << std::endl
;
222 std::exit(EXIT_FAILURE
);
225 i(ent2A
->getMembers().begin()),
226 j(ent2B
->getMembers().begin());
227 i
!= ent2A
->getMembers().end(); ++i
, ++j
)
229 if (i
->name
!= j
->name
|| i
->value
!= j
->value
) {
231 << "enum type " << name
<< " member #"
232 << i
- ent2A
->getMembers().begin() + 1
233 << " changed from " << i
->name
<< " = "
234 << i
->value
<< " to " << j
->name
<< " = "
235 << j
->value
<< std::endl
;
236 std::exit(EXIT_FAILURE
);
241 case unoidl::Entity::SORT_PLAIN_STRUCT_TYPE
:
243 rtl::Reference
<unoidl::PlainStructTypeEntity
> ent2A(
244 static_cast<unoidl::PlainStructTypeEntity
*>(
246 rtl::Reference
<unoidl::PlainStructTypeEntity
> ent2B(
247 static_cast<unoidl::PlainStructTypeEntity
*>(
249 if (ent2A
->getDirectBase() != ent2B
->getDirectBase()) {
251 << "plain struct type " << name
252 << " direct base changed from "
253 << (ent2A
->getDirectBase().isEmpty()
254 ? OUString("none") : ent2A
->getDirectBase())
256 << (ent2B
->getDirectBase().isEmpty()
257 ? OUString("none") : ent2B
->getDirectBase())
259 std::exit(EXIT_FAILURE
);
261 if (ent2A
->getDirectMembers().size()
262 != ent2B
->getDirectMembers().size())
265 << "plain struct type " << name
266 << " number of direct members changed from "
267 << ent2A
->getDirectMembers().size() << " to "
268 << ent2B
->getDirectMembers().size() << std::endl
;
269 std::exit(EXIT_FAILURE
);
272 i(ent2A
->getDirectMembers().begin()),
273 j(ent2B
->getDirectMembers().begin());
274 i
!= ent2A
->getDirectMembers().end(); ++i
, ++j
)
276 if (i
->name
!= j
->name
|| i
->type
!= j
->type
) {
278 << "plain struct type " << name
279 << " direct member #"
280 << i
- ent2A
->getDirectMembers().begin() + 1
281 << " changed from " << i
->type
<< " " << i
->name
282 << " to " << j
->type
<< " " << j
->name
284 std::exit(EXIT_FAILURE
);
289 case unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE
:
291 rtl::Reference
<unoidl::PolymorphicStructTypeTemplateEntity
>
293 static_cast<unoidl::PolymorphicStructTypeTemplateEntity
*>(
295 rtl::Reference
<unoidl::PolymorphicStructTypeTemplateEntity
>
297 static_cast<unoidl::PolymorphicStructTypeTemplateEntity
*>(
299 if (ent2A
->getTypeParameters().size()
300 != ent2B
->getTypeParameters().size())
303 << "polymorphic struct type template " << name
304 << " number of type parameters changed from "
305 << ent2A
->getTypeParameters().size() << " to "
306 << ent2B
->getTypeParameters().size() << std::endl
;
307 std::exit(EXIT_FAILURE
);
310 i(ent2A
->getTypeParameters().begin()),
311 j(ent2B
->getTypeParameters().begin());
312 i
!= ent2A
->getTypeParameters().end(); ++i
, ++j
)
316 << "polymorphic struct type template " << name
317 << " type parameter #"
318 << i
- ent2A
->getTypeParameters().begin() + 1
319 << " changed from " << *i
<< " to " << *j
321 std::exit(EXIT_FAILURE
);
324 if (ent2A
->getMembers().size()
325 != ent2B
->getMembers().size())
328 << "polymorphic struct type template " << name
329 << " number of members changed from "
330 << ent2A
->getMembers().size() << " to "
331 << ent2B
->getMembers().size() << std::endl
;
332 std::exit(EXIT_FAILURE
);
335 i(ent2A
->getMembers().begin()),
336 j(ent2B
->getMembers().begin());
337 i
!= ent2A
->getMembers().end(); ++i
, ++j
)
339 if (i
->name
!= j
->name
|| i
->type
!= j
->type
340 || i
->parameterized
!= j
->parameterized
)
343 << "polymorphic struct type template " << name
345 << i
- ent2A
->getMembers().begin() + 1
348 ? OUString("parameterized ") : OUString())
349 << i
->type
<< " " << i
->name
352 ? OUString("parameterized ") : OUString())
353 << j
->type
<< " " << j
->name
355 std::exit(EXIT_FAILURE
);
360 case unoidl::Entity::SORT_EXCEPTION_TYPE
:
362 rtl::Reference
<unoidl::ExceptionTypeEntity
> ent2A(
363 static_cast<unoidl::ExceptionTypeEntity
*>(entA
.get()));
364 rtl::Reference
<unoidl::ExceptionTypeEntity
> ent2B(
365 static_cast<unoidl::ExceptionTypeEntity
*>(entB
.get()));
366 if (ent2A
->getDirectBase() != ent2B
->getDirectBase()) {
368 << "exception type " << name
369 << " direct base changed from "
370 << (ent2A
->getDirectBase().isEmpty()
371 ? OUString("none") : ent2A
->getDirectBase())
373 << (ent2B
->getDirectBase().isEmpty()
374 ? OUString("none") : ent2B
->getDirectBase())
376 std::exit(EXIT_FAILURE
);
378 if (ent2A
->getDirectMembers().size()
379 != ent2B
->getDirectMembers().size())
382 << "exception type " << name
383 << " number of direct members changed from "
384 << ent2A
->getDirectMembers().size() << " to "
385 << ent2B
->getDirectMembers().size() << std::endl
;
386 std::exit(EXIT_FAILURE
);
389 i(ent2A
->getDirectMembers().begin()),
390 j(ent2B
->getDirectMembers().begin());
391 i
!= ent2A
->getDirectMembers().end(); ++i
, ++j
)
393 if (i
->name
!= j
->name
|| i
->type
!= j
->type
) {
395 << "exception type " << name
396 << " direct member #"
397 << i
- ent2A
->getDirectMembers().begin() + 1
398 << " changed from " << i
->type
<< " " << i
->name
399 << " to " << j
->type
<< " " << j
->name
401 std::exit(EXIT_FAILURE
);
406 case unoidl::Entity::SORT_INTERFACE_TYPE
:
408 rtl::Reference
<unoidl::InterfaceTypeEntity
> ent2A(
409 static_cast<unoidl::InterfaceTypeEntity
*>(entA
.get()));
410 rtl::Reference
<unoidl::InterfaceTypeEntity
> ent2B(
411 static_cast<unoidl::InterfaceTypeEntity
*>(entB
.get()));
412 if (ent2A
->getDirectMandatoryBases().size()
413 != ent2B
->getDirectMandatoryBases().size())
416 << "interface type " << name
417 << " number of direct mandatory bases changed from "
418 << ent2A
->getDirectMandatoryBases().size() << " to "
419 << ent2B
->getDirectMandatoryBases().size()
421 std::exit(EXIT_FAILURE
);
424 i(ent2A
->getDirectMandatoryBases().begin()),
425 j(ent2B
->getDirectMandatoryBases().begin());
426 i
!= ent2A
->getDirectMandatoryBases().end(); ++i
, ++j
)
428 if (i
->name
!= j
->name
) {
430 << "interface type " << name
431 << " direct mandatory base #"
432 << (i
- ent2A
->getDirectMandatoryBases().begin()
434 << " changed from " << i
->name
<< " to "
435 << j
->name
<< std::endl
;
436 std::exit(EXIT_FAILURE
);
439 if (ent2A
->getDirectOptionalBases().size()
440 != ent2B
->getDirectOptionalBases().size())
443 << "interface type " << name
444 << " number of direct optional bases changed from "
445 << ent2A
->getDirectOptionalBases().size() << " to "
446 << ent2B
->getDirectOptionalBases().size()
448 std::exit(EXIT_FAILURE
);
451 i(ent2A
->getDirectOptionalBases().begin()),
452 j(ent2B
->getDirectOptionalBases().begin());
453 i
!= ent2A
->getDirectOptionalBases().end(); ++i
, ++j
)
455 if (i
->name
!= j
->name
) {
457 << "interface type " << name
458 << " direct optional base #"
459 << (i
- ent2A
->getDirectOptionalBases().begin()
461 << " changed from " << i
->name
<< " to "
462 << j
->name
<< std::endl
;
463 std::exit(EXIT_FAILURE
);
466 if (ent2A
->getDirectAttributes().size()
467 != ent2B
->getDirectAttributes().size())
470 << "interface type " << name
471 << " number of direct attributes changed from "
472 << ent2A
->getDirectAttributes().size() << " to "
473 << ent2B
->getDirectAttributes().size() << std::endl
;
474 std::exit(EXIT_FAILURE
);
477 i(ent2A
->getDirectAttributes().begin()),
478 j(ent2B
->getDirectAttributes().begin());
479 i
!= ent2A
->getDirectAttributes().end(); ++i
, ++j
)
481 if (i
->name
!= j
->name
|| i
->type
!= j
->type
482 || i
->bound
!= j
->bound
483 || i
->readOnly
!= j
->readOnly
484 || i
->getExceptions
!= j
->getExceptions
485 || i
->setExceptions
!= j
->setExceptions
)
488 << "interface type " << name
489 << " direct attribute #"
490 << i
- ent2A
->getDirectAttributes().begin() + 1
492 << (i
->bound
? OUString("bound ") : OUString())
494 ? OUString("read-only ") : OUString())
495 << i
->type
<< " " << i
->name
//TODO: exceptions
497 << (j
->bound
? OUString("bound ") : OUString())
499 ? OUString("read-only ") : OUString())
500 << j
->type
<< " " << j
->name
//TODO: exceptions
502 std::exit(EXIT_FAILURE
);
505 if (ent2A
->getDirectMethods().size()
506 != ent2B
->getDirectMethods().size())
509 << "interface type " << name
510 << " number of direct methods changed from "
511 << ent2A
->getDirectMethods().size() << " to "
512 << ent2B
->getDirectMethods().size() << std::endl
;
513 std::exit(EXIT_FAILURE
);
516 i(ent2A
->getDirectMethods().begin()),
517 j(ent2B
->getDirectMethods().begin());
518 i
!= ent2A
->getDirectMethods().end(); ++i
, ++j
)
520 if (i
->name
!= j
->name
|| i
->returnType
!= j
->returnType
521 || i
->exceptions
!= j
->exceptions
)
524 << "interface type " << name
525 << " direct method #"
526 << i
- ent2A
->getDirectMethods().begin() + 1
528 << i
->returnType
<< " " << i
->name
//TODO: exceptions
529 << " to " << j
->returnType
<< " " << j
->name
//TODO: exceptions
531 std::exit(EXIT_FAILURE
);
533 if (i
->parameters
.size() != j
->parameters
.size()) {
535 << "interface type " << name
536 << " direct method " << i
->name
537 << " number of parameters changed from "
538 << i
->parameters
.size() << " to "
539 << j
->parameters
.size() << std::endl
;
540 std::exit(EXIT_FAILURE
);
543 k(i
->parameters
.begin()),
544 l(j
->parameters
.begin());
545 k
!= i
->parameters
.end(); ++k
, ++l
)
547 if (k
->type
!= l
->type
|| k
->direction
!= l
->direction
)
550 << "interface type " << name
551 << " direct method " << i
->name
553 << k
- i
->parameters
.begin() + 1
555 << showDirection(k
->direction
) << " "
557 << showDirection(l
->direction
) << " "
558 << l
->type
<< std::endl
;
559 std::exit(EXIT_FAILURE
);
561 if (k
->name
!= l
->name
) {
563 << "interface type " << name
564 << " direct method " << i
->name
566 << k
- i
->parameters
.begin() + 1
567 << " changed name from " << k
->name
568 << " to " << l
->name
<< std::endl
;
569 std::exit(EXIT_FAILURE
);
575 case unoidl::Entity::SORT_TYPEDEF
:
577 rtl::Reference
<unoidl::TypedefEntity
> ent2A(
578 static_cast<unoidl::TypedefEntity
*>(entA
.get()));
579 rtl::Reference
<unoidl::TypedefEntity
> ent2B(
580 static_cast<unoidl::TypedefEntity
*>(entB
.get()));
581 if (ent2A
->getType() != ent2B
->getType()) {
583 << "typedef " << name
<< " type changed from "
584 << ent2A
->getType() << " to " << ent2B
->getType()
586 std::exit(EXIT_FAILURE
);
590 case unoidl::Entity::SORT_CONSTANT_GROUP
:
592 rtl::Reference
<unoidl::ConstantGroupEntity
> ent2A(
593 static_cast<unoidl::ConstantGroupEntity
*>(entA
.get()));
594 rtl::Reference
<unoidl::ConstantGroupEntity
> ent2B(
595 static_cast<unoidl::ConstantGroupEntity
*>(entB
.get()));
596 for (auto & i
: ent2A
->getMembers()) {
598 for (auto & j
: ent2B
->getMembers()) {
599 if (i
.name
== j
.name
) {
600 if (i
.value
!= j
.value
) {
602 << "constant group " << name
603 << " member " << i
.name
604 << " changed value" << std::endl
;
605 std::exit(EXIT_FAILURE
);
613 << "A constant group " << name
<< " member "
614 << i
.name
<< " is not present in B"
616 std::exit(EXIT_FAILURE
);
621 case unoidl::Entity::SORT_SINGLE_INTERFACE_BASED_SERVICE
:
623 rtl::Reference
<unoidl::SingleInterfaceBasedServiceEntity
>
625 static_cast<unoidl::SingleInterfaceBasedServiceEntity
*>(
627 rtl::Reference
<unoidl::SingleInterfaceBasedServiceEntity
>
629 static_cast<unoidl::SingleInterfaceBasedServiceEntity
*>(
631 if (ent2A
->getBase() != ent2B
->getBase()) {
633 << "single-interface--based service " << name
634 << " base changed from " << ent2A
->getBase()
635 << " to " << ent2B
->getBase()
637 std::exit(EXIT_FAILURE
);
639 if (ent2A
->getConstructors().size()
640 != ent2B
->getConstructors().size())
643 << "single-interface--based service " << name
644 << " number of constructors changed from "
645 << ent2A
->getConstructors().size() << " to "
646 << ent2B
->getConstructors().size() << std::endl
;
647 std::exit(EXIT_FAILURE
);
650 i(ent2A
->getConstructors().begin()),
651 j(ent2B
->getConstructors().begin());
652 i
!= ent2A
->getConstructors().end(); ++i
, ++j
)
654 if (i
->name
!= j
->name
|| i
->parameters
!= j
->parameters
655 || i
->exceptions
!= j
->exceptions
656 || i
->defaultConstructor
!= j
->defaultConstructor
)
659 << "single-interface--based service " << name
661 << i
- ent2A
->getConstructors().begin() + 1
663 << (i
->defaultConstructor
664 ? OUString("default ") : i
->name
) //TODO: parameters, exceptions
666 << (j
->defaultConstructor
667 ? OUString("default ") : j
->name
) //TODO: parameters, exceptions
669 std::exit(EXIT_FAILURE
);
674 case unoidl::Entity::SORT_ACCUMULATION_BASED_SERVICE
:
676 rtl::Reference
<unoidl::AccumulationBasedServiceEntity
>
678 static_cast<unoidl::AccumulationBasedServiceEntity
*>(
680 rtl::Reference
<unoidl::AccumulationBasedServiceEntity
>
682 static_cast<unoidl::AccumulationBasedServiceEntity
*>(
684 if (ent2A
->getDirectMandatoryBaseServices().size()
685 != ent2B
->getDirectMandatoryBaseServices().size())
688 << "accumulation-based service " << name
689 << (" number of direct mandatory base services"
691 << ent2A
->getDirectMandatoryBaseServices().size()
693 << ent2B
->getDirectMandatoryBaseServices().size()
695 std::exit(EXIT_FAILURE
);
698 i(ent2A
->getDirectMandatoryBaseServices().begin()),
699 j(ent2B
->getDirectMandatoryBaseServices().begin());
700 i
!= ent2A
->getDirectMandatoryBaseServices().end();
703 if (i
->name
!= j
->name
) {
705 << "accumulation-based service " << name
706 << " direct mandatory base service #"
708 - (ent2A
->getDirectMandatoryBaseServices()
711 << " changed from " << i
->name
<< " to "
712 << j
->name
<< std::endl
;
713 std::exit(EXIT_FAILURE
);
716 if (ent2A
->getDirectOptionalBaseServices().size()
717 > ent2B
->getDirectOptionalBaseServices().size())
720 << "accumulation-based service " << name
721 << (" number of direct optional base services"
723 << ent2A
->getDirectOptionalBaseServices().size()
725 << ent2B
->getDirectOptionalBaseServices().size()
727 std::exit(EXIT_FAILURE
);
729 for (auto & i
: ent2A
->getDirectOptionalBaseServices()) {
731 ent2B
->getDirectOptionalBaseServices().begin(),
732 ent2B
->getDirectOptionalBaseServices().end(),
733 EqualsAnnotation(i
.name
)))
736 << "accumulation-based service " << name
737 << " direct optional base service " << i
.name
738 << " was removed" << std::endl
;
739 std::exit(EXIT_FAILURE
);
742 if (ent2A
->getDirectMandatoryBaseInterfaces().size()
743 != ent2B
->getDirectMandatoryBaseInterfaces().size())
746 << "accumulation-based service " << name
747 << (" number of direct mandatory base interfaces"
749 << ent2A
->getDirectMandatoryBaseInterfaces().size()
751 << ent2B
->getDirectMandatoryBaseInterfaces().size()
753 std::exit(EXIT_FAILURE
);
756 i(ent2A
->getDirectMandatoryBaseInterfaces()
758 j(ent2B
->getDirectMandatoryBaseInterfaces()
760 i
!= ent2A
->getDirectMandatoryBaseInterfaces().end();
763 if (i
->name
!= j
->name
) {
765 << "accumulation-based service " << name
766 << " direct mandatory base interface #"
768 - (ent2A
->getDirectMandatoryBaseInterfaces()
771 << " changed from " << i
->name
<< " to "
772 << j
->name
<< std::endl
;
773 std::exit(EXIT_FAILURE
);
776 if (ent2A
->getDirectOptionalBaseInterfaces().size()
777 > ent2B
->getDirectOptionalBaseInterfaces().size())
780 << "accumulation-based service " << name
781 << (" number of direct optional base interfaces"
783 << ent2A
->getDirectOptionalBaseInterfaces().size()
785 << ent2B
->getDirectOptionalBaseInterfaces().size()
787 std::exit(EXIT_FAILURE
);
789 for (auto & i
: ent2A
->getDirectOptionalBaseInterfaces()) {
791 (ent2B
->getDirectOptionalBaseInterfaces()
793 ent2B
->getDirectOptionalBaseInterfaces().end(),
794 EqualsAnnotation(i
.name
)))
797 << "accumulation-based service " << name
798 << " direct optional base interface " << i
.name
799 << " was removed" << std::endl
;
800 std::exit(EXIT_FAILURE
);
803 if (ent2A
->getDirectProperties().size()
804 > ent2B
->getDirectProperties().size())
807 << "accumulation-based service " << name
808 << " number of direct properties changed from "
809 << ent2A
->getDirectProperties().size() << " to "
810 << ent2B
->getDirectProperties().size() << std::endl
;
811 std::exit(EXIT_FAILURE
);
814 i(ent2A
->getDirectProperties().begin()),
815 j(ent2B
->getDirectProperties().begin());
816 i
!= ent2A
->getDirectProperties().end(); ++i
, ++j
)
818 if (i
->name
!= j
->name
|| i
->type
!= j
->type
819 || i
->attributes
!= j
->attributes
)
822 << "accumulation-based service " << name
823 << " direct property #"
824 << i
- ent2A
->getDirectProperties().begin() + 1
826 << i
->type
<< " " << i
->name
//TODO: attributes
828 << j
->type
<< " " << j
->name
//TODO: attributes
830 std::exit(EXIT_FAILURE
);
834 i(ent2B
->getDirectProperties().begin()
835 + ent2A
->getDirectProperties().size());
836 i
!= ent2B
->getDirectProperties().end(); ++i
)
838 if ((i
->attributes
& unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_OPTIONAL
) == 0)
841 << "B accumulation-based service " << name
842 << " additional direct property " << i
->name
843 << " is not optional" << std::endl
;
844 std::exit(EXIT_FAILURE
);
849 case unoidl::Entity::SORT_INTERFACE_BASED_SINGLETON
:
851 rtl::Reference
<unoidl::InterfaceBasedSingletonEntity
> ent2A(
852 static_cast<unoidl::InterfaceBasedSingletonEntity
*>(
854 rtl::Reference
<unoidl::InterfaceBasedSingletonEntity
> ent2B(
855 static_cast<unoidl::InterfaceBasedSingletonEntity
*>(
857 if (ent2A
->getBase() != ent2B
->getBase()) {
859 << "interface-based singleton " << name
860 << " base changed from " << ent2A
->getBase()
861 << " to " << ent2B
->getBase() << std::endl
;
862 std::exit(EXIT_FAILURE
);
866 case unoidl::Entity::SORT_SERVICE_BASED_SINGLETON
:
868 rtl::Reference
<unoidl::ServiceBasedSingletonEntity
> ent2A(
869 static_cast<unoidl::ServiceBasedSingletonEntity
*>(
871 rtl::Reference
<unoidl::ServiceBasedSingletonEntity
> ent2B(
872 static_cast<unoidl::ServiceBasedSingletonEntity
*>(
874 if (ent2A
->getBase() != ent2B
->getBase()) {
876 << "service-based singleton " << name
877 << " base changed from " << ent2A
->getBase()
878 << " to " << ent2B
->getBase() << std::endl
;
879 std::exit(EXIT_FAILURE
);
883 case unoidl::Entity::SORT_MODULE
:
884 assert(false && "this cannot happen");
890 bool valid(std::u16string_view identifier
) {
891 for (size_t i
= 0;; ++i
) {
892 i
= identifier
.find('_', i
);
893 if (i
== std::u16string_view::npos
) {
896 if (!rtl::isAsciiUpperCase(identifier
[0]) || identifier
[i
- 1] == '_') {
903 rtl::Reference
<unoidl::Provider
> const & providerA
, std::u16string_view prefix
,
904 rtl::Reference
<unoidl::MapCursor
> const & cursor
)
909 rtl::Reference
<unoidl::Entity
> entB(cursor
->getNext(&id
));
913 OUString
name(prefix
+ id
);
914 rtl::Reference
<unoidl::Entity
> entA(providerA
->findEntity(name
));
915 if (!(entA
.is() || valid(id
))) {
917 << "entity name " << name
<< " uses an invalid identifier"
919 std::exit(EXIT_FAILURE
);
921 switch (entB
->getSort()) {
922 case unoidl::Entity::SORT_MODULE
:
924 providerA
, Concat2View(name
+ "."),
925 (static_cast<unoidl::ModuleEntity
*>(entB
.get())
928 case unoidl::Entity::SORT_ENUM_TYPE
:
930 rtl::Reference
<unoidl::EnumTypeEntity
> ent2B(
931 static_cast<unoidl::EnumTypeEntity
*>(entB
.get()));
932 for (auto & i
: ent2B
->getMembers()) {
933 if (!valid(i
.name
)) {
935 << "enum type " << name
<< " member " << i
.name
936 << " uses an invalid identifier" << std::endl
;
937 std::exit(EXIT_FAILURE
);
942 case unoidl::Entity::SORT_PLAIN_STRUCT_TYPE
:
944 rtl::Reference
<unoidl::PlainStructTypeEntity
> ent2B(
945 static_cast<unoidl::PlainStructTypeEntity
*>(
947 for (auto & i
: ent2B
->getDirectMembers()) {
948 if (!valid(i
.name
)) {
950 << "plain struct type " << name
<< " direct member "
951 << i
.name
<< " uses an invalid identifier"
953 std::exit(EXIT_FAILURE
);
958 case unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE
:
960 rtl::Reference
<unoidl::PolymorphicStructTypeTemplateEntity
>
963 unoidl::PolymorphicStructTypeTemplateEntity
*>(
965 for (auto & i
: ent2B
->getTypeParameters()) {
968 << "polymorphic struct type template " << name
969 << " type parameter " << i
970 << " uses an invalid identifier" << std::endl
;
971 std::exit(EXIT_FAILURE
);
974 for (auto & i
: ent2B
->getMembers()) {
975 if (!valid(i
.name
)) {
977 << "polymorphic struct type template " << name
978 << " member " << i
.name
979 << " uses an invalid identifier" << std::endl
;
980 std::exit(EXIT_FAILURE
);
985 case unoidl::Entity::SORT_EXCEPTION_TYPE
:
987 rtl::Reference
<unoidl::ExceptionTypeEntity
> ent2B(
988 static_cast<unoidl::ExceptionTypeEntity
*>(entB
.get()));
989 for (auto & i
: ent2B
->getDirectMembers()) {
990 if (!valid(i
.name
)) {
992 << "exception type " << name
<< " direct member "
993 << i
.name
<< " uses an invalid identifier"
995 std::exit(EXIT_FAILURE
);
1000 case unoidl::Entity::SORT_INTERFACE_TYPE
:
1002 rtl::Reference
<unoidl::InterfaceTypeEntity
> ent2B(
1003 static_cast<unoidl::InterfaceTypeEntity
*>(entB
.get()));
1004 for (auto & i
: ent2B
->getDirectAttributes()) {
1005 if (!valid(i
.name
)) {
1007 << "interface type " << name
<< " direct attribute "
1008 << i
.name
<< " uses an invalid identifier"
1010 std::exit(EXIT_FAILURE
);
1013 for (auto & i
: ent2B
->getDirectMethods()) {
1014 if (!valid(i
.name
)) {
1016 << "interface type " << name
<< " direct method "
1017 << i
.name
<< " uses an invalid identifier"
1019 std::exit(EXIT_FAILURE
);
1021 for (auto & j
: i
.parameters
) {
1022 if (!valid(j
.name
)) {
1024 << "interface type " << name
1025 << " direct method " << i
.name
<< " parameter "
1026 << j
.name
<< " uses an invalid identifier"
1028 std::exit(EXIT_FAILURE
);
1034 case unoidl::Entity::SORT_TYPEDEF
:
1035 case unoidl::Entity::SORT_INTERFACE_BASED_SINGLETON
:
1036 case unoidl::Entity::SORT_SERVICE_BASED_SINGLETON
:
1038 case unoidl::Entity::SORT_CONSTANT_GROUP
:
1040 rtl::Reference
<unoidl::ConstantGroupEntity
> ent2B(
1041 static_cast<unoidl::ConstantGroupEntity
*>(entB
.get()));
1042 for (auto & i
: ent2B
->getMembers()) {
1045 rtl::Reference
<unoidl::ConstantGroupEntity
> ent2A(
1046 static_cast<unoidl::ConstantGroupEntity
*>(
1048 for (auto & j
: ent2A
->getMembers()) {
1049 if (i
.name
== j
.name
) {
1055 if (!(found
|| valid(i
.name
))) {
1057 << "Constant group " << name
<< " member "
1058 << i
.name
<< " uses an invalid identifier"
1060 std::exit(EXIT_FAILURE
);
1065 case unoidl::Entity::SORT_SINGLE_INTERFACE_BASED_SERVICE
:
1067 rtl::Reference
<unoidl::SingleInterfaceBasedServiceEntity
>
1069 static_cast<unoidl::SingleInterfaceBasedServiceEntity
*>(
1071 for (auto & i
: ent2B
->getConstructors()) {
1072 if (!valid(i
.name
)) {
1074 << "single-interface--based service " << name
1075 << " constructor " << i
.name
1076 << " uses an invalid identifier" << std::endl
;
1077 std::exit(EXIT_FAILURE
);
1079 for (auto & j
: i
.parameters
) {
1080 if (!valid(j
.name
)) {
1082 << "single-interface--based service " << name
1083 << " constructor " << i
.name
<< " parameter "
1084 << j
.name
<< " uses an invalid identifier"
1086 std::exit(EXIT_FAILURE
);
1092 case unoidl::Entity::SORT_ACCUMULATION_BASED_SERVICE
:
1094 rtl::Reference
<unoidl::AccumulationBasedServiceEntity
> ent2B(
1095 static_cast<unoidl::AccumulationBasedServiceEntity
*>(
1097 std::vector
<unoidl::AccumulationBasedServiceEntity::Property
>::size_type
1099 ? (static_cast<unoidl::AccumulationBasedServiceEntity
*>(
1101 ->getDirectProperties().size())
1103 assert(n
<= ent2B
->getDirectProperties().size());
1104 for (auto i(ent2B
->getDirectProperties().begin() +n
);
1105 i
!= ent2B
->getDirectProperties().end(); ++i
)
1107 if (!valid(i
->name
)) {
1109 << "accumulation-based service " << name
1110 << " direct property " << i
->name
1111 << " uses an invalid identifier" << std::endl
;
1112 std::exit(EXIT_FAILURE
);
1123 SAL_IMPLEMENT_MAIN() {
1125 sal_uInt32 args
= rtl_getAppCommandArgCount();
1126 rtl::Reference
<unoidl::Manager
> mgr
[2];
1127 mgr
[0] = new unoidl::Manager
;
1128 mgr
[1] = new unoidl::Manager
;
1129 rtl::Reference
<unoidl::Provider
> prov
[2];
1131 bool ignoreUnpublished
= false;
1132 for (sal_uInt32 i
= 0; i
!= args
; ++i
) {
1133 bool delimiter
= false;
1136 i
, &ignoreUnpublished
, side
== 0 ? &delimiter
: nullptr,
1140 prov
[side
] = mgr
[side
]->addProvider(uri
);
1141 } catch (unoidl::NoSuchFileException
&) {
1143 << "Input <" << uri
<< "> does not exist" << std::endl
;
1144 std::exit(EXIT_FAILURE
);
1146 } else if (delimiter
) {
1150 if (side
== 0 || !(prov
[0].is() && prov
[1].is())) {
1153 checkMap(prov
[1], u
"", prov
[0]->createRootCursor(), ignoreUnpublished
);
1154 checkIds(prov
[0], u
"", prov
[1]->createRootCursor());
1155 return EXIT_SUCCESS
;
1156 } catch (unoidl::FileFormatException
& e1
) {
1158 << "Bad input <" << e1
.getUri() << ">: " << e1
.getDetail()
1160 std::exit(EXIT_FAILURE
);
1161 } catch (std::exception
& e1
) {
1162 std::cerr
<< "Failure: " << e1
.what() << std::endl
;
1163 std::exit(EXIT_FAILURE
);
1167 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */