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>
19 #include <osl/file.hxx>
20 #include <osl/process.h>
21 #include <rtl/character.hxx>
22 #include <rtl/process.h>
23 #include <rtl/ref.hxx>
24 #include <rtl/ustring.hxx>
26 #include <sal/types.h>
27 #include <unoidl/unoidl.hxx>
31 static bool operator ==(ConstantValue
const & lhs
, ConstantValue
const & rhs
) {
32 if (lhs
.type
== rhs
.type
) {
34 case ConstantValue::TYPE_BOOLEAN
:
35 return lhs
.booleanValue
== rhs
.booleanValue
;
36 case ConstantValue::TYPE_BYTE
:
37 return lhs
.byteValue
== rhs
.byteValue
;
38 case ConstantValue::TYPE_SHORT
:
39 return lhs
.shortValue
== rhs
.shortValue
;
40 case ConstantValue::TYPE_UNSIGNED_SHORT
:
41 return lhs
.unsignedShortValue
== rhs
.unsignedShortValue
;
42 case ConstantValue::TYPE_LONG
:
43 return lhs
.longValue
== rhs
.longValue
;
44 case ConstantValue::TYPE_UNSIGNED_LONG
:
45 return lhs
.unsignedLongValue
== rhs
.unsignedLongValue
;
46 case ConstantValue::TYPE_HYPER
:
47 return lhs
.hyperValue
== rhs
.hyperValue
;
48 case ConstantValue::TYPE_UNSIGNED_HYPER
:
49 return lhs
.unsignedHyperValue
== rhs
.unsignedHyperValue
;
50 case ConstantValue::TYPE_FLOAT
:
51 return lhs
.floatValue
== rhs
.floatValue
;
52 case ConstantValue::TYPE_DOUBLE
:
53 return lhs
.doubleValue
== rhs
.doubleValue
;
59 static bool operator !=(ConstantValue
const & lhs
, ConstantValue
const & rhs
) {
63 static bool operator ==(
64 SingleInterfaceBasedServiceEntity::Constructor::Parameter
const & lhs
,
65 SingleInterfaceBasedServiceEntity::Constructor::Parameter
const & rhs
)
67 return lhs
.name
== rhs
.name
&& lhs
.type
== rhs
.type
&& lhs
.rest
== rhs
.rest
;
76 << "Usage:" << std::endl
<< std::endl
77 << (" unoidl-check [--ignore-unpublished] [<extra registries A>]"
79 << std::endl
<< " [<extra registries B>] <registry B>" << std::endl
81 << ("where each <registry> is either a new- or legacy-format .rdb file,"
84 << ("file, or a root directory of an .idl file tree. Check that each"
87 << "<registry A> is also present in <registry B> in a compatible form."
89 std::exit(EXIT_FAILURE
);
93 sal_uInt32 argument
, bool * ignoreUnpublished
, bool * delimiter
,
96 assert(ignoreUnpublished
!= nullptr);
97 assert(uri
!= nullptr);
99 rtl_getAppCommandArg(argument
, &arg
.pData
);
100 if (argument
== 0 && arg
== "--ignore-unpublished") {
101 *ignoreUnpublished
= true;
105 if (delimiter
== nullptr) {
112 osl::FileBase::RC e1
= osl::FileBase::getFileURLFromSystemPath(arg
, url
);
113 if (e1
!= osl::FileBase::E_None
) {
115 << "Cannot convert \"" << arg
<< "\" to file URL, error code "
117 std::exit(EXIT_FAILURE
);
120 oslProcessError e2
= osl_getProcessWorkingDir(&cwd
.pData
);
121 if (e2
!= osl_Process_E_None
) {
123 << "Cannot obtain working directory, error code " << +e2
125 std::exit(EXIT_FAILURE
);
127 e1
= osl::FileBase::getAbsoluteFileURL(cwd
, url
, *uri
);
128 if (e1
!= osl::FileBase::E_None
) {
130 << "Cannot make \"" << url
131 << "\" into an absolute file URL, error code " << +e1
<< std::endl
;
132 std::exit(EXIT_FAILURE
);
137 OUString
showDirection(
138 unoidl::InterfaceTypeEntity::Method::Parameter::Direction direction
)
141 case unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN
:
143 case unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_OUT
:
145 case unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN_OUT
:
148 assert(false && "this cannot happen"); for (;;) { std::abort(); }
152 struct EqualsAnnotation
{
153 explicit EqualsAnnotation(OUString
const & name
): name_(name
) {}
155 bool operator ()(unoidl::AnnotatedReference
const & ref
)
156 { return ref
.name
== name_
; }
163 rtl::Reference
<unoidl::Provider
> const & providerB
, std::u16string_view prefix
,
164 rtl::Reference
<unoidl::MapCursor
> const & cursor
, bool ignoreUnpublished
)
166 assert(providerB
.is());
170 rtl::Reference
<unoidl::Entity
> entA(cursor
->getNext(&id
));
174 OUString
name(prefix
+ id
);
175 if (entA
->getSort() == unoidl::Entity::SORT_MODULE
) {
177 providerB
, OUString(name
+ "."),
178 (static_cast<unoidl::ModuleEntity
*>(entA
.get())
182 bool pubA
= dynamic_cast<unoidl::PublishableEntity
&>(*entA
).isPublished();
183 if (!pubA
&& ignoreUnpublished
) {
186 rtl::Reference
<unoidl::Entity
> entB(providerB
->findEntity(name
));
189 << "A entity " << name
<< " is not present in B"
191 std::exit(EXIT_FAILURE
);
193 if (entA
->getSort() != entB
->getSort()) {
195 << "A entity " << name
<< " is of different sort in B"
197 std::exit(EXIT_FAILURE
);
199 if (pubA
&& (!dynamic_cast<unoidl::PublishableEntity
&>(*entB
).isPublished()))
202 << "A published entity " << name
<< " is not published in B"
204 std::exit(EXIT_FAILURE
);
206 switch (entA
->getSort()) {
207 case unoidl::Entity::SORT_ENUM_TYPE
:
209 rtl::Reference
<unoidl::EnumTypeEntity
> ent2A(
210 static_cast<unoidl::EnumTypeEntity
*>(entA
.get()));
211 rtl::Reference
<unoidl::EnumTypeEntity
> ent2B(
212 static_cast<unoidl::EnumTypeEntity
*>(entB
.get()));
213 if (ent2A
->getMembers().size()
214 != ent2B
->getMembers().size())
217 << "enum type " << name
218 << " number of members changed from "
219 << ent2A
->getMembers().size() << " to "
220 << ent2B
->getMembers().size() << std::endl
;
221 std::exit(EXIT_FAILURE
);
224 i(ent2A
->getMembers().begin()),
225 j(ent2B
->getMembers().begin());
226 i
!= ent2A
->getMembers().end(); ++i
, ++j
)
228 if (i
->name
!= j
->name
|| i
->value
!= j
->value
) {
230 << "enum type " << name
<< " member #"
231 << i
- ent2A
->getMembers().begin() + 1
232 << " changed from " << i
->name
<< " = "
233 << i
->value
<< " to " << j
->name
<< " = "
234 << j
->value
<< std::endl
;
235 std::exit(EXIT_FAILURE
);
240 case unoidl::Entity::SORT_PLAIN_STRUCT_TYPE
:
242 rtl::Reference
<unoidl::PlainStructTypeEntity
> ent2A(
243 static_cast<unoidl::PlainStructTypeEntity
*>(
245 rtl::Reference
<unoidl::PlainStructTypeEntity
> ent2B(
246 static_cast<unoidl::PlainStructTypeEntity
*>(
248 if (ent2A
->getDirectBase() != ent2B
->getDirectBase()) {
250 << "plain struct type " << name
251 << " direct base changed from "
252 << (ent2A
->getDirectBase().isEmpty()
253 ? OUString("none") : ent2A
->getDirectBase())
255 << (ent2B
->getDirectBase().isEmpty()
256 ? OUString("none") : ent2B
->getDirectBase())
258 std::exit(EXIT_FAILURE
);
260 if (ent2A
->getDirectMembers().size()
261 != ent2B
->getDirectMembers().size())
264 << "plain struct type " << name
265 << " number of direct members changed from "
266 << ent2A
->getDirectMembers().size() << " to "
267 << ent2B
->getDirectMembers().size() << std::endl
;
268 std::exit(EXIT_FAILURE
);
271 i(ent2A
->getDirectMembers().begin()),
272 j(ent2B
->getDirectMembers().begin());
273 i
!= ent2A
->getDirectMembers().end(); ++i
, ++j
)
275 if (i
->name
!= j
->name
|| i
->type
!= j
->type
) {
277 << "plain struct type " << name
278 << " direct member #"
279 << i
- ent2A
->getDirectMembers().begin() + 1
280 << " changed from " << i
->type
<< " " << i
->name
281 << " to " << j
->type
<< " " << j
->name
283 std::exit(EXIT_FAILURE
);
288 case unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE
:
290 rtl::Reference
<unoidl::PolymorphicStructTypeTemplateEntity
>
292 static_cast<unoidl::PolymorphicStructTypeTemplateEntity
*>(
294 rtl::Reference
<unoidl::PolymorphicStructTypeTemplateEntity
>
296 static_cast<unoidl::PolymorphicStructTypeTemplateEntity
*>(
298 if (ent2A
->getTypeParameters().size()
299 != ent2B
->getTypeParameters().size())
302 << "polymorphic struct type template " << name
303 << " number of type parameters changed from "
304 << ent2A
->getTypeParameters().size() << " to "
305 << ent2B
->getTypeParameters().size() << std::endl
;
306 std::exit(EXIT_FAILURE
);
309 i(ent2A
->getTypeParameters().begin()),
310 j(ent2B
->getTypeParameters().begin());
311 i
!= ent2A
->getTypeParameters().end(); ++i
, ++j
)
315 << "polymorphic struct type template " << name
316 << " type parameter #"
317 << i
- ent2A
->getTypeParameters().begin() + 1
318 << " changed from " << *i
<< " to " << *j
320 std::exit(EXIT_FAILURE
);
323 if (ent2A
->getMembers().size()
324 != ent2B
->getMembers().size())
327 << "polymorphic struct type template " << name
328 << " number of members changed from "
329 << ent2A
->getMembers().size() << " to "
330 << ent2B
->getMembers().size() << std::endl
;
331 std::exit(EXIT_FAILURE
);
334 i(ent2A
->getMembers().begin()),
335 j(ent2B
->getMembers().begin());
336 i
!= ent2A
->getMembers().end(); ++i
, ++j
)
338 if (i
->name
!= j
->name
|| i
->type
!= j
->type
339 || i
->parameterized
!= j
->parameterized
)
342 << "polymorphic struct type template " << name
344 << i
- ent2A
->getMembers().begin() + 1
347 ? OUString("parameterized ") : OUString())
348 << i
->type
<< " " << i
->name
351 ? OUString("parameterized ") : OUString())
352 << j
->type
<< " " << j
->name
354 std::exit(EXIT_FAILURE
);
359 case unoidl::Entity::SORT_EXCEPTION_TYPE
:
361 rtl::Reference
<unoidl::ExceptionTypeEntity
> ent2A(
362 static_cast<unoidl::ExceptionTypeEntity
*>(entA
.get()));
363 rtl::Reference
<unoidl::ExceptionTypeEntity
> ent2B(
364 static_cast<unoidl::ExceptionTypeEntity
*>(entB
.get()));
365 if (ent2A
->getDirectBase() != ent2B
->getDirectBase()) {
367 << "exception type " << name
368 << " direct base changed from "
369 << (ent2A
->getDirectBase().isEmpty()
370 ? OUString("none") : ent2A
->getDirectBase())
372 << (ent2B
->getDirectBase().isEmpty()
373 ? OUString("none") : ent2B
->getDirectBase())
375 std::exit(EXIT_FAILURE
);
377 if (ent2A
->getDirectMembers().size()
378 != ent2B
->getDirectMembers().size())
381 << "exception type " << name
382 << " number of direct members changed from "
383 << ent2A
->getDirectMembers().size() << " to "
384 << ent2B
->getDirectMembers().size() << std::endl
;
385 std::exit(EXIT_FAILURE
);
388 i(ent2A
->getDirectMembers().begin()),
389 j(ent2B
->getDirectMembers().begin());
390 i
!= ent2A
->getDirectMembers().end(); ++i
, ++j
)
392 if (i
->name
!= j
->name
|| i
->type
!= j
->type
) {
394 << "exception type " << name
395 << " direct member #"
396 << i
- ent2A
->getDirectMembers().begin() + 1
397 << " changed from " << i
->type
<< " " << i
->name
398 << " to " << j
->type
<< " " << j
->name
400 std::exit(EXIT_FAILURE
);
405 case unoidl::Entity::SORT_INTERFACE_TYPE
:
407 rtl::Reference
<unoidl::InterfaceTypeEntity
> ent2A(
408 static_cast<unoidl::InterfaceTypeEntity
*>(entA
.get()));
409 rtl::Reference
<unoidl::InterfaceTypeEntity
> ent2B(
410 static_cast<unoidl::InterfaceTypeEntity
*>(entB
.get()));
411 if (ent2A
->getDirectMandatoryBases().size()
412 != ent2B
->getDirectMandatoryBases().size())
415 << "interface type " << name
416 << " number of direct mandatory bases changed from "
417 << ent2A
->getDirectMandatoryBases().size() << " to "
418 << ent2B
->getDirectMandatoryBases().size()
420 std::exit(EXIT_FAILURE
);
423 i(ent2A
->getDirectMandatoryBases().begin()),
424 j(ent2B
->getDirectMandatoryBases().begin());
425 i
!= ent2A
->getDirectMandatoryBases().end(); ++i
, ++j
)
427 if (i
->name
!= j
->name
) {
429 << "interface type " << name
430 << " direct mandatory base #"
431 << (i
- ent2A
->getDirectMandatoryBases().begin()
433 << " changed from " << i
->name
<< " to "
434 << j
->name
<< std::endl
;
435 std::exit(EXIT_FAILURE
);
438 if (ent2A
->getDirectOptionalBases().size()
439 != ent2B
->getDirectOptionalBases().size())
442 << "interface type " << name
443 << " number of direct optional bases changed from "
444 << ent2A
->getDirectOptionalBases().size() << " to "
445 << ent2B
->getDirectOptionalBases().size()
447 std::exit(EXIT_FAILURE
);
450 i(ent2A
->getDirectOptionalBases().begin()),
451 j(ent2B
->getDirectOptionalBases().begin());
452 i
!= ent2A
->getDirectOptionalBases().end(); ++i
, ++j
)
454 if (i
->name
!= j
->name
) {
456 << "interface type " << name
457 << " direct optional base #"
458 << (i
- ent2A
->getDirectOptionalBases().begin()
460 << " changed from " << i
->name
<< " to "
461 << j
->name
<< std::endl
;
462 std::exit(EXIT_FAILURE
);
465 if (ent2A
->getDirectAttributes().size()
466 != ent2B
->getDirectAttributes().size())
469 << "interface type " << name
470 << " number of direct attributes changed from "
471 << ent2A
->getDirectAttributes().size() << " to "
472 << ent2B
->getDirectAttributes().size() << std::endl
;
473 std::exit(EXIT_FAILURE
);
476 i(ent2A
->getDirectAttributes().begin()),
477 j(ent2B
->getDirectAttributes().begin());
478 i
!= ent2A
->getDirectAttributes().end(); ++i
, ++j
)
480 if (i
->name
!= j
->name
|| i
->type
!= j
->type
481 || i
->bound
!= j
->bound
482 || i
->readOnly
!= j
->readOnly
483 || i
->getExceptions
!= j
->getExceptions
484 || i
->setExceptions
!= j
->setExceptions
)
487 << "interface type " << name
488 << " direct attribute #"
489 << i
- ent2A
->getDirectAttributes().begin() + 1
491 << (i
->bound
? OUString("bound ") : OUString())
493 ? OUString("read-only ") : OUString())
494 << i
->type
<< " " << i
->name
//TODO: exceptions
496 << (j
->bound
? OUString("bound ") : OUString())
498 ? OUString("read-only ") : OUString())
499 << j
->type
<< " " << j
->name
//TODO: exceptions
501 std::exit(EXIT_FAILURE
);
504 if (ent2A
->getDirectMethods().size()
505 != ent2B
->getDirectMethods().size())
508 << "interface type " << name
509 << " number of direct methods changed from "
510 << ent2A
->getDirectMethods().size() << " to "
511 << ent2B
->getDirectMethods().size() << std::endl
;
512 std::exit(EXIT_FAILURE
);
515 i(ent2A
->getDirectMethods().begin()),
516 j(ent2B
->getDirectMethods().begin());
517 i
!= ent2A
->getDirectMethods().end(); ++i
, ++j
)
519 if (i
->name
!= j
->name
|| i
->returnType
!= j
->returnType
520 || i
->exceptions
!= j
->exceptions
)
523 << "interface type " << name
524 << " direct method #"
525 << i
- ent2A
->getDirectMethods().begin() + 1
527 << i
->returnType
<< " " << i
->name
//TODO: exceptions
528 << " to " << j
->returnType
<< " " << j
->name
//TODO: exceptions
530 std::exit(EXIT_FAILURE
);
532 if (i
->parameters
.size() != j
->parameters
.size()) {
534 << "interface type " << name
535 << " direct method " << i
->name
536 << " number of parameters changed from "
537 << i
->parameters
.size() << " to "
538 << j
->parameters
.size() << std::endl
;
539 std::exit(EXIT_FAILURE
);
542 k(i
->parameters
.begin()),
543 l(j
->parameters
.begin());
544 k
!= i
->parameters
.end(); ++k
, ++l
)
546 if (k
->type
!= l
->type
|| k
->direction
!= l
->direction
)
549 << "interface type " << name
550 << " direct method " << i
->name
552 << k
- i
->parameters
.begin() + 1
554 << showDirection(k
->direction
) << " "
556 << showDirection(l
->direction
) << " "
557 << l
->type
<< std::endl
;
558 std::exit(EXIT_FAILURE
);
560 if (k
->name
!= l
->name
) {
562 << "interface type " << name
563 << " direct method " << i
->name
565 << k
- i
->parameters
.begin() + 1
566 << " changed name from " << k
->name
567 << " to " << l
->name
<< std::endl
;
568 std::exit(EXIT_FAILURE
);
574 case unoidl::Entity::SORT_TYPEDEF
:
576 rtl::Reference
<unoidl::TypedefEntity
> ent2A(
577 static_cast<unoidl::TypedefEntity
*>(entA
.get()));
578 rtl::Reference
<unoidl::TypedefEntity
> ent2B(
579 static_cast<unoidl::TypedefEntity
*>(entB
.get()));
580 if (ent2A
->getType() != ent2B
->getType()) {
582 << "typedef " << name
<< " type changed from "
583 << ent2A
->getType() << " to " << ent2B
->getType()
585 std::exit(EXIT_FAILURE
);
589 case unoidl::Entity::SORT_CONSTANT_GROUP
:
591 rtl::Reference
<unoidl::ConstantGroupEntity
> ent2A(
592 static_cast<unoidl::ConstantGroupEntity
*>(entA
.get()));
593 rtl::Reference
<unoidl::ConstantGroupEntity
> ent2B(
594 static_cast<unoidl::ConstantGroupEntity
*>(entB
.get()));
595 for (auto & i
: ent2A
->getMembers()) {
597 for (auto & j
: ent2B
->getMembers()) {
598 if (i
.name
== j
.name
) {
599 if (i
.value
!= j
.value
) {
601 << "constant group " << name
602 << " member " << i
.name
603 << " changed value" << std::endl
;
604 std::exit(EXIT_FAILURE
);
612 << "A constant group " << name
<< " member "
613 << i
.name
<< " is not present in B"
615 std::exit(EXIT_FAILURE
);
620 case unoidl::Entity::SORT_SINGLE_INTERFACE_BASED_SERVICE
:
622 rtl::Reference
<unoidl::SingleInterfaceBasedServiceEntity
>
624 static_cast<unoidl::SingleInterfaceBasedServiceEntity
*>(
626 rtl::Reference
<unoidl::SingleInterfaceBasedServiceEntity
>
628 static_cast<unoidl::SingleInterfaceBasedServiceEntity
*>(
630 if (ent2A
->getBase() != ent2B
->getBase()) {
632 << "single-interface--based service " << name
633 << " base changed from " << ent2A
->getBase()
634 << " to " << ent2B
->getBase()
636 std::exit(EXIT_FAILURE
);
638 if (ent2A
->getConstructors().size()
639 != ent2B
->getConstructors().size())
642 << "single-interface--based service " << name
643 << " number of constructors changed from "
644 << ent2A
->getConstructors().size() << " to "
645 << ent2B
->getConstructors().size() << std::endl
;
646 std::exit(EXIT_FAILURE
);
649 i(ent2A
->getConstructors().begin()),
650 j(ent2B
->getConstructors().begin());
651 i
!= ent2A
->getConstructors().end(); ++i
, ++j
)
653 if (i
->name
!= j
->name
|| i
->parameters
!= j
->parameters
654 || i
->exceptions
!= j
->exceptions
655 || i
->defaultConstructor
!= j
->defaultConstructor
)
658 << "single-interface--based service " << name
660 << i
- ent2A
->getConstructors().begin() + 1
662 << (i
->defaultConstructor
663 ? OUString("default ") : i
->name
) //TODO: parameters, exceptions
665 << (j
->defaultConstructor
666 ? OUString("default ") : j
->name
) //TODO: parameters, exceptions
668 std::exit(EXIT_FAILURE
);
673 case unoidl::Entity::SORT_ACCUMULATION_BASED_SERVICE
:
675 rtl::Reference
<unoidl::AccumulationBasedServiceEntity
>
677 static_cast<unoidl::AccumulationBasedServiceEntity
*>(
679 rtl::Reference
<unoidl::AccumulationBasedServiceEntity
>
681 static_cast<unoidl::AccumulationBasedServiceEntity
*>(
683 if (ent2A
->getDirectMandatoryBaseServices().size()
684 != ent2B
->getDirectMandatoryBaseServices().size())
687 << "accumulation-based service " << name
688 << (" number of direct mandatory base services"
690 << ent2A
->getDirectMandatoryBaseServices().size()
692 << ent2B
->getDirectMandatoryBaseServices().size()
694 std::exit(EXIT_FAILURE
);
697 i(ent2A
->getDirectMandatoryBaseServices().begin()),
698 j(ent2B
->getDirectMandatoryBaseServices().begin());
699 i
!= ent2A
->getDirectMandatoryBaseServices().end();
702 if (i
->name
!= j
->name
) {
704 << "accumulation-based service " << name
705 << " direct mandatory base service #"
707 - (ent2A
->getDirectMandatoryBaseServices()
710 << " changed from " << i
->name
<< " to "
711 << j
->name
<< std::endl
;
712 std::exit(EXIT_FAILURE
);
715 if (ent2A
->getDirectOptionalBaseServices().size()
716 > ent2B
->getDirectOptionalBaseServices().size())
719 << "accumulation-based service " << name
720 << (" number of direct optional base services"
722 << ent2A
->getDirectOptionalBaseServices().size()
724 << ent2B
->getDirectOptionalBaseServices().size()
726 std::exit(EXIT_FAILURE
);
728 for (auto & i
: ent2A
->getDirectOptionalBaseServices()) {
730 ent2B
->getDirectOptionalBaseServices().begin(),
731 ent2B
->getDirectOptionalBaseServices().end(),
732 EqualsAnnotation(i
.name
)))
735 << "accumulation-based service " << name
736 << " direct optional base service " << i
.name
737 << " was removed" << std::endl
;
738 std::exit(EXIT_FAILURE
);
741 if (ent2A
->getDirectMandatoryBaseInterfaces().size()
742 != ent2B
->getDirectMandatoryBaseInterfaces().size())
745 << "accumulation-based service " << name
746 << (" number of direct mandatory base interfaces"
748 << ent2A
->getDirectMandatoryBaseInterfaces().size()
750 << ent2B
->getDirectMandatoryBaseInterfaces().size()
752 std::exit(EXIT_FAILURE
);
755 i(ent2A
->getDirectMandatoryBaseInterfaces()
757 j(ent2B
->getDirectMandatoryBaseInterfaces()
759 i
!= ent2A
->getDirectMandatoryBaseInterfaces().end();
762 if (i
->name
!= j
->name
) {
764 << "accumulation-based service " << name
765 << " direct mandatory base interface #"
767 - (ent2A
->getDirectMandatoryBaseInterfaces()
770 << " changed from " << i
->name
<< " to "
771 << j
->name
<< std::endl
;
772 std::exit(EXIT_FAILURE
);
775 if (ent2A
->getDirectOptionalBaseInterfaces().size()
776 > ent2B
->getDirectOptionalBaseInterfaces().size())
779 << "accumulation-based service " << name
780 << (" number of direct optional base interfaces"
782 << ent2A
->getDirectOptionalBaseInterfaces().size()
784 << ent2B
->getDirectOptionalBaseInterfaces().size()
786 std::exit(EXIT_FAILURE
);
788 for (auto & i
: ent2A
->getDirectOptionalBaseInterfaces()) {
790 (ent2B
->getDirectOptionalBaseInterfaces()
792 ent2B
->getDirectOptionalBaseInterfaces().end(),
793 EqualsAnnotation(i
.name
)))
796 << "accumulation-based service " << name
797 << " direct optional base interface " << i
.name
798 << " was removed" << std::endl
;
799 std::exit(EXIT_FAILURE
);
802 if (ent2A
->getDirectProperties().size()
803 > ent2B
->getDirectProperties().size())
806 << "accumulation-based service " << name
807 << " number of direct properties changed from "
808 << ent2A
->getDirectProperties().size() << " to "
809 << ent2B
->getDirectProperties().size() << std::endl
;
810 std::exit(EXIT_FAILURE
);
813 i(ent2A
->getDirectProperties().begin()),
814 j(ent2B
->getDirectProperties().begin());
815 i
!= ent2A
->getDirectProperties().end(); ++i
, ++j
)
817 if (i
->name
!= j
->name
|| i
->type
!= j
->type
818 || i
->attributes
!= j
->attributes
)
821 << "accumulation-based service " << name
822 << " direct property #"
823 << i
- ent2A
->getDirectProperties().begin() + 1
825 << i
->type
<< " " << i
->name
//TODO: attributes
827 << j
->type
<< " " << j
->name
//TODO: attributes
829 std::exit(EXIT_FAILURE
);
833 i(ent2B
->getDirectProperties().begin()
834 + ent2A
->getDirectProperties().size());
835 i
!= ent2B
->getDirectProperties().end(); ++i
)
837 if ((i
->attributes
& unoidl::AccumulationBasedServiceEntity::Property::ATTRIBUTE_OPTIONAL
) == 0)
840 << "B accumulation-based service " << name
841 << " additional direct property " << i
->name
842 << " is not optional" << std::endl
;
843 std::exit(EXIT_FAILURE
);
848 case unoidl::Entity::SORT_INTERFACE_BASED_SINGLETON
:
850 rtl::Reference
<unoidl::InterfaceBasedSingletonEntity
> ent2A(
851 static_cast<unoidl::InterfaceBasedSingletonEntity
*>(
853 rtl::Reference
<unoidl::InterfaceBasedSingletonEntity
> ent2B(
854 static_cast<unoidl::InterfaceBasedSingletonEntity
*>(
856 if (ent2A
->getBase() != ent2B
->getBase()) {
858 << "interface-based singleton " << name
859 << " base changed from " << ent2A
->getBase()
860 << " to " << ent2B
->getBase() << std::endl
;
861 std::exit(EXIT_FAILURE
);
865 case unoidl::Entity::SORT_SERVICE_BASED_SINGLETON
:
867 rtl::Reference
<unoidl::ServiceBasedSingletonEntity
> ent2A(
868 static_cast<unoidl::ServiceBasedSingletonEntity
*>(
870 rtl::Reference
<unoidl::ServiceBasedSingletonEntity
> ent2B(
871 static_cast<unoidl::ServiceBasedSingletonEntity
*>(
873 if (ent2A
->getBase() != ent2B
->getBase()) {
875 << "service-based singleton " << name
876 << " base changed from " << ent2A
->getBase()
877 << " to " << ent2B
->getBase() << std::endl
;
878 std::exit(EXIT_FAILURE
);
882 case unoidl::Entity::SORT_MODULE
:
883 assert(false && "this cannot happen");
889 bool valid(OUString
const & identifier
) {
890 for (sal_Int32 i
= 0;; ++i
) {
891 i
= identifier
.indexOf('_', i
);
895 if (!rtl::isAsciiUpperCase(identifier
[0]) || identifier
[i
- 1] == '_') {
902 rtl::Reference
<unoidl::Provider
> const & providerA
, std::u16string_view prefix
,
903 rtl::Reference
<unoidl::MapCursor
> const & cursor
)
908 rtl::Reference
<unoidl::Entity
> entB(cursor
->getNext(&id
));
912 OUString
name(prefix
+ id
);
913 rtl::Reference
<unoidl::Entity
> entA(providerA
->findEntity(name
));
914 if (!(entA
.is() || valid(id
))) {
916 << "entity name " << name
<< " uses an invalid identifier"
918 std::exit(EXIT_FAILURE
);
920 switch (entB
->getSort()) {
921 case unoidl::Entity::SORT_MODULE
:
923 providerA
, OUString(name
+ "."),
924 (static_cast<unoidl::ModuleEntity
*>(entB
.get())
927 case unoidl::Entity::SORT_ENUM_TYPE
:
929 rtl::Reference
<unoidl::EnumTypeEntity
> ent2B(
930 static_cast<unoidl::EnumTypeEntity
*>(entB
.get()));
931 for (auto & i
: ent2B
->getMembers()) {
932 if (!valid(i
.name
)) {
934 << "enum type " << name
<< " member " << i
.name
935 << " uses an invalid identifier" << std::endl
;
936 std::exit(EXIT_FAILURE
);
941 case unoidl::Entity::SORT_PLAIN_STRUCT_TYPE
:
943 rtl::Reference
<unoidl::PlainStructTypeEntity
> ent2B(
944 static_cast<unoidl::PlainStructTypeEntity
*>(
946 for (auto & i
: ent2B
->getDirectMembers()) {
947 if (!valid(i
.name
)) {
949 << "plain struct type " << name
<< " direct member "
950 << i
.name
<< " uses an invalid identifier"
952 std::exit(EXIT_FAILURE
);
957 case unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE
:
959 rtl::Reference
<unoidl::PolymorphicStructTypeTemplateEntity
>
962 unoidl::PolymorphicStructTypeTemplateEntity
*>(
964 for (auto & i
: ent2B
->getTypeParameters()) {
967 << "polymorphic struct type template " << name
968 << " type parameter " << i
969 << " uses an invalid identifier" << std::endl
;
970 std::exit(EXIT_FAILURE
);
973 for (auto & i
: ent2B
->getMembers()) {
974 if (!valid(i
.name
)) {
976 << "polymorphic struct type template " << name
977 << " member " << i
.name
978 << " uses an invalid identifier" << std::endl
;
979 std::exit(EXIT_FAILURE
);
984 case unoidl::Entity::SORT_EXCEPTION_TYPE
:
986 rtl::Reference
<unoidl::ExceptionTypeEntity
> ent2B(
987 static_cast<unoidl::ExceptionTypeEntity
*>(entB
.get()));
988 for (auto & i
: ent2B
->getDirectMembers()) {
989 if (!valid(i
.name
)) {
991 << "exception type " << name
<< " direct member "
992 << i
.name
<< " uses an invalid identifier"
994 std::exit(EXIT_FAILURE
);
999 case unoidl::Entity::SORT_INTERFACE_TYPE
:
1001 rtl::Reference
<unoidl::InterfaceTypeEntity
> ent2B(
1002 static_cast<unoidl::InterfaceTypeEntity
*>(entB
.get()));
1003 for (auto & i
: ent2B
->getDirectAttributes()) {
1004 if (!valid(i
.name
)) {
1006 << "interface type " << name
<< " direct attribute "
1007 << i
.name
<< " uses an invalid identifier"
1009 std::exit(EXIT_FAILURE
);
1012 for (auto & i
: ent2B
->getDirectMethods()) {
1013 if (!valid(i
.name
)) {
1015 << "interface type " << name
<< " direct method "
1016 << i
.name
<< " uses an invalid identifier"
1018 std::exit(EXIT_FAILURE
);
1020 for (auto & j
: i
.parameters
) {
1021 if (!valid(j
.name
)) {
1023 << "interface type " << name
1024 << " direct method " << i
.name
<< " parameter "
1025 << j
.name
<< " uses an invalid identifier"
1027 std::exit(EXIT_FAILURE
);
1033 case unoidl::Entity::SORT_TYPEDEF
:
1034 case unoidl::Entity::SORT_INTERFACE_BASED_SINGLETON
:
1035 case unoidl::Entity::SORT_SERVICE_BASED_SINGLETON
:
1037 case unoidl::Entity::SORT_CONSTANT_GROUP
:
1039 rtl::Reference
<unoidl::ConstantGroupEntity
> ent2B(
1040 static_cast<unoidl::ConstantGroupEntity
*>(entB
.get()));
1041 for (auto & i
: ent2B
->getMembers()) {
1044 rtl::Reference
<unoidl::ConstantGroupEntity
> ent2A(
1045 static_cast<unoidl::ConstantGroupEntity
*>(
1047 for (auto & j
: ent2A
->getMembers()) {
1048 if (i
.name
== j
.name
) {
1054 if (!(found
|| valid(i
.name
))) {
1056 << "Constant group " << name
<< " member "
1057 << i
.name
<< " uses an invalid identifier"
1059 std::exit(EXIT_FAILURE
);
1064 case unoidl::Entity::SORT_SINGLE_INTERFACE_BASED_SERVICE
:
1066 rtl::Reference
<unoidl::SingleInterfaceBasedServiceEntity
>
1068 static_cast<unoidl::SingleInterfaceBasedServiceEntity
*>(
1070 for (auto & i
: ent2B
->getConstructors()) {
1071 if (!valid(i
.name
)) {
1073 << "single-interface--based service " << name
1074 << " constructor " << i
.name
1075 << " uses an invalid identifier" << std::endl
;
1076 std::exit(EXIT_FAILURE
);
1078 for (auto & j
: i
.parameters
) {
1079 if (!valid(j
.name
)) {
1081 << "single-interface--based service " << name
1082 << " constructor " << i
.name
<< " parameter "
1083 << j
.name
<< " uses an invalid identifier"
1085 std::exit(EXIT_FAILURE
);
1091 case unoidl::Entity::SORT_ACCUMULATION_BASED_SERVICE
:
1093 rtl::Reference
<unoidl::AccumulationBasedServiceEntity
> ent2B(
1094 static_cast<unoidl::AccumulationBasedServiceEntity
*>(
1096 std::vector
<unoidl::AccumulationBasedServiceEntity::Property
>::size_type
1098 ? (static_cast<unoidl::AccumulationBasedServiceEntity
*>(
1100 ->getDirectProperties().size())
1102 assert(n
<= ent2B
->getDirectProperties().size());
1103 for (auto i(ent2B
->getDirectProperties().begin() +n
);
1104 i
!= ent2B
->getDirectProperties().end(); ++i
)
1106 if (!valid(i
->name
)) {
1108 << "accumulation-based service " << name
1109 << " direct property " << i
->name
1110 << " uses an invalid identifier" << std::endl
;
1111 std::exit(EXIT_FAILURE
);
1122 SAL_IMPLEMENT_MAIN() {
1124 sal_uInt32 args
= rtl_getAppCommandArgCount();
1125 rtl::Reference
<unoidl::Manager
> mgr
[2];
1126 mgr
[0] = new unoidl::Manager
;
1127 mgr
[1] = new unoidl::Manager
;
1128 rtl::Reference
<unoidl::Provider
> prov
[2];
1130 bool ignoreUnpublished
= false;
1131 for (sal_uInt32 i
= 0; i
!= args
; ++i
) {
1132 bool delimiter
= false;
1135 i
, &ignoreUnpublished
, side
== 0 ? &delimiter
: nullptr,
1139 prov
[side
] = mgr
[side
]->addProvider(uri
);
1140 } catch (unoidl::NoSuchFileException
&) {
1142 << "Input <" << uri
<< "> does not exist" << std::endl
;
1143 std::exit(EXIT_FAILURE
);
1145 } else if (delimiter
) {
1149 if (side
== 0 || !(prov
[0].is() && prov
[1].is())) {
1152 checkMap(prov
[1], u
"", prov
[0]->createRootCursor(), ignoreUnpublished
);
1153 checkIds(prov
[0], u
"", prov
[1]->createRootCursor());
1154 return EXIT_SUCCESS
;
1155 } catch (unoidl::FileFormatException
& e1
) {
1157 << "Bad input <" << e1
.getUri() << ">: " << e1
.getDetail()
1159 std::exit(EXIT_FAILURE
);
1160 } catch (std::exception
& e1
) {
1161 std::cerr
<< "Failure: " << e1
.what() << std::endl
;
1162 std::exit(EXIT_FAILURE
);
1166 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */