LibreOffice Module unoidl (master) 1
unoidl-check.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 */
9
10#include <sal/config.h>
11
12#include <algorithm>
13#include <cassert>
14#include <cstdlib>
15#include <iostream>
16#include <string_view>
17#include <utility>
18#include <vector>
19
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>
26#include <sal/main.h>
27#include <sal/types.h>
28#include <unoidl/unoidl.hxx>
29
30namespace unoidl {
31
32static bool operator ==(ConstantValue const & lhs, ConstantValue const & rhs) {
33 if (lhs.type == rhs.type) {
34 switch (lhs.type) {
36 return lhs.booleanValue == rhs.booleanValue;
38 return lhs.byteValue == rhs.byteValue;
40 return lhs.shortValue == rhs.shortValue;
42 return lhs.unsignedShortValue == rhs.unsignedShortValue;
44 return lhs.longValue == rhs.longValue;
46 return lhs.unsignedLongValue == rhs.unsignedLongValue;
48 return lhs.hyperValue == rhs.hyperValue;
50 return lhs.unsignedHyperValue == rhs.unsignedHyperValue;
52 return lhs.floatValue == rhs.floatValue;
54 return lhs.doubleValue == rhs.doubleValue;
55 }
56 }
57 return false;
58}
59
60static bool operator !=(ConstantValue const & lhs, ConstantValue const & rhs) {
61 return !(lhs == rhs);
62}
63
64static bool operator ==(
67{
68 return lhs.name == rhs.name && lhs.type == rhs.type && lhs.rest == rhs.rest;
69}
70
71}
72
73namespace {
74
75void badUsage() {
76 std::cerr
77 << "Usage:" << std::endl << std::endl
78 << (" unoidl-check [--ignore-unpublished] [<extra registries A>]"
79 " <registry A> --")
80 << std::endl << " [<extra registries B>] <registry B>" << std::endl
81 << std::endl
82 << ("where each <registry> is either a new- or legacy-format .rdb file,"
83 " a single .idl")
84 << std::endl
85 << ("file, or a root directory of an .idl file tree. Check that each"
86 " entity from")
87 << std::endl
88 << "<registry A> is also present in <registry B> in a compatible form."
89 << std::endl;
90 std::exit(EXIT_FAILURE);
91}
92
93bool getArgument(
94 sal_uInt32 argument, bool * ignoreUnpublished, bool * delimiter,
95 OUString * uri)
96{
97 assert(ignoreUnpublished != nullptr);
98 assert(uri != nullptr);
99 OUString arg;
100 rtl_getAppCommandArg(argument, &arg.pData);
101 if (argument == 0 && arg == "--ignore-unpublished") {
102 *ignoreUnpublished = true;
103 return false;
104 }
105 if (arg == "--") {
106 if (delimiter == nullptr) {
107 badUsage();
108 }
109 *delimiter = true;
110 return false;
111 }
112 OUString url;
113 osl::FileBase::RC e1 = osl::FileBase::getFileURLFromSystemPath(arg, url);
114 if (e1 != osl::FileBase::E_None) {
115 std::cerr
116 << "Cannot convert \"" << arg << "\" to file URL, error code "
117 << +e1 << std::endl;
118 std::exit(EXIT_FAILURE);
119 }
120 OUString cwd;
121 oslProcessError e2 = osl_getProcessWorkingDir(&cwd.pData);
122 if (e2 != osl_Process_E_None) {
123 std::cerr
124 << "Cannot obtain working directory, error code " << +e2
125 << std::endl;
126 std::exit(EXIT_FAILURE);
127 }
128 e1 = osl::FileBase::getAbsoluteFileURL(cwd, url, *uri);
129 if (e1 != osl::FileBase::E_None) {
130 std::cerr
131 << "Cannot make \"" << url
132 << "\" into an absolute file URL, error code " << +e1 << std::endl;
133 std::exit(EXIT_FAILURE);
134 }
135 return true;
136}
137
138OUString showDirection(
140{
141 switch (direction) {
143 return "[in]";
145 return "[out]";
147 return "[inout]";
148 default:
149 assert(false && "this cannot happen"); for (;;) { std::abort(); }
150 }
151}
152
153struct EqualsAnnotation {
154 explicit EqualsAnnotation(OUString name): name_(std::move(name)) {}
155
156 bool operator ()(unoidl::AnnotatedReference const & ref)
157 { return ref.name == name_; }
158
159private:
160 OUString name_;
161};
162
163void checkMap(
164 rtl::Reference<unoidl::Provider> const & providerB, std::u16string_view prefix,
165 rtl::Reference<unoidl::MapCursor> const & cursor, bool ignoreUnpublished)
166{
167 assert(providerB.is());
168 assert(cursor.is());
169 for (;;) {
170 OUString id;
171 rtl::Reference<unoidl::Entity> entA(cursor->getNext(&id));
172 if (!entA.is()) {
173 break;
174 }
175 OUString name(prefix + id);
176 if (entA->getSort() == unoidl::Entity::SORT_MODULE) {
177 checkMap(
178 providerB, Concat2View(name + "."),
179 (static_cast<unoidl::ModuleEntity *>(entA.get())
180 ->createCursor()),
181 ignoreUnpublished);
182 } else {
183 bool pubA = dynamic_cast<unoidl::PublishableEntity&>(*entA).isPublished();
184 if (!pubA && ignoreUnpublished) {
185 continue;
186 }
187 rtl::Reference<unoidl::Entity> entB(providerB->findEntity(name));
188 if (!entB.is()) {
189 std::cerr
190 << "A entity " << name << " is not present in B"
191 << std::endl;
192 std::exit(EXIT_FAILURE);
193 }
194 if (entA->getSort() != entB->getSort()) {
195 std::cerr
196 << "A entity " << name << " is of different sort in B"
197 << std::endl;
198 std::exit(EXIT_FAILURE);
199 }
200 if (pubA && (!dynamic_cast<unoidl::PublishableEntity&>(*entB).isPublished()))
201 {
202 std::cerr
203 << "A published entity " << name << " is not published in B"
204 << std::endl;
205 std::exit(EXIT_FAILURE);
206 }
207 switch (entA->getSort()) {
209 {
211 static_cast<unoidl::EnumTypeEntity *>(entA.get()));
213 static_cast<unoidl::EnumTypeEntity *>(entB.get()));
214 if (ent2A->getMembers().size()
215 != ent2B->getMembers().size())
216 {
217 std::cerr
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);
223 }
224 for (auto
225 i(ent2A->getMembers().begin()),
226 j(ent2B->getMembers().begin());
227 i != ent2A->getMembers().end(); ++i, ++j)
228 {
229 if (i->name != j->name || i->value != j->value) {
230 std::cerr
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);
237 }
238 }
239 break;
240 }
242 {
244 static_cast<unoidl::PlainStructTypeEntity *>(
245 entA.get()));
247 static_cast<unoidl::PlainStructTypeEntity *>(
248 entB.get()));
249 if (ent2A->getDirectBase() != ent2B->getDirectBase()) {
250 std::cerr
251 << "plain struct type " << name
252 << " direct base changed from "
253 << (ent2A->getDirectBase().isEmpty()
254 ? OUString("none") : ent2A->getDirectBase())
255 << " to "
256 << (ent2B->getDirectBase().isEmpty()
257 ? OUString("none") : ent2B->getDirectBase())
258 << std::endl;
259 std::exit(EXIT_FAILURE);
260 }
261 if (ent2A->getDirectMembers().size()
262 != ent2B->getDirectMembers().size())
263 {
264 std::cerr
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);
270 }
271 for (auto
272 i(ent2A->getDirectMembers().begin()),
273 j(ent2B->getDirectMembers().begin());
274 i != ent2A->getDirectMembers().end(); ++i, ++j)
275 {
276 if (i->name != j->name || i->type != j->type) {
277 std::cerr
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
283 << std::endl;
284 std::exit(EXIT_FAILURE);
285 }
286 }
287 break;
288 }
290 {
292 ent2A(
294 entA.get()));
296 ent2B(
298 entB.get()));
299 if (ent2A->getTypeParameters().size()
300 != ent2B->getTypeParameters().size())
301 {
302 std::cerr
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);
308 }
309 for (auto
310 i(ent2A->getTypeParameters().begin()),
311 j(ent2B->getTypeParameters().begin());
312 i != ent2A->getTypeParameters().end(); ++i, ++j)
313 {
314 if (*i != *j) {
315 std::cerr
316 << "polymorphic struct type template " << name
317 << " type parameter #"
318 << i - ent2A->getTypeParameters().begin() + 1
319 << " changed from " << *i << " to " << *j
320 << std::endl;
321 std::exit(EXIT_FAILURE);
322 }
323 }
324 if (ent2A->getMembers().size()
325 != ent2B->getMembers().size())
326 {
327 std::cerr
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);
333 }
334 for (auto
335 i(ent2A->getMembers().begin()),
336 j(ent2B->getMembers().begin());
337 i != ent2A->getMembers().end(); ++i, ++j)
338 {
339 if (i->name != j->name || i->type != j->type
340 || i->parameterized != j->parameterized)
341 {
342 std::cerr
343 << "polymorphic struct type template " << name
344 << " member #"
345 << i - ent2A->getMembers().begin() + 1
346 << " changed from "
347 << (i->parameterized
348 ? OUString("parameterized ") : OUString())
349 << i->type << " " << i->name
350 << " to "
351 << (j->parameterized
352 ? OUString("parameterized ") : OUString())
353 << j->type << " " << j->name
354 << std::endl;
355 std::exit(EXIT_FAILURE);
356 }
357 }
358 break;
359 }
361 {
363 static_cast<unoidl::ExceptionTypeEntity *>(entA.get()));
365 static_cast<unoidl::ExceptionTypeEntity *>(entB.get()));
366 if (ent2A->getDirectBase() != ent2B->getDirectBase()) {
367 std::cerr
368 << "exception type " << name
369 << " direct base changed from "
370 << (ent2A->getDirectBase().isEmpty()
371 ? OUString("none") : ent2A->getDirectBase())
372 << " to "
373 << (ent2B->getDirectBase().isEmpty()
374 ? OUString("none") : ent2B->getDirectBase())
375 << std::endl;
376 std::exit(EXIT_FAILURE);
377 }
378 if (ent2A->getDirectMembers().size()
379 != ent2B->getDirectMembers().size())
380 {
381 std::cerr
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);
387 }
388 for (auto
389 i(ent2A->getDirectMembers().begin()),
390 j(ent2B->getDirectMembers().begin());
391 i != ent2A->getDirectMembers().end(); ++i, ++j)
392 {
393 if (i->name != j->name || i->type != j->type) {
394 std::cerr
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
400 << std::endl;
401 std::exit(EXIT_FAILURE);
402 }
403 }
404 break;
405 }
407 {
409 static_cast<unoidl::InterfaceTypeEntity *>(entA.get()));
411 static_cast<unoidl::InterfaceTypeEntity *>(entB.get()));
412 if (ent2A->getDirectMandatoryBases().size()
413 != ent2B->getDirectMandatoryBases().size())
414 {
415 std::cerr
416 << "interface type " << name
417 << " number of direct mandatory bases changed from "
418 << ent2A->getDirectMandatoryBases().size() << " to "
419 << ent2B->getDirectMandatoryBases().size()
420 << std::endl;
421 std::exit(EXIT_FAILURE);
422 }
423 for (auto
424 i(ent2A->getDirectMandatoryBases().begin()),
425 j(ent2B->getDirectMandatoryBases().begin());
426 i != ent2A->getDirectMandatoryBases().end(); ++i, ++j)
427 {
428 if (i->name != j->name) {
429 std::cerr
430 << "interface type " << name
431 << " direct mandatory base #"
432 << (i - ent2A->getDirectMandatoryBases().begin()
433 + 1)
434 << " changed from " << i->name << " to "
435 << j->name << std::endl;
436 std::exit(EXIT_FAILURE);
437 }
438 }
439 if (ent2A->getDirectOptionalBases().size()
440 != ent2B->getDirectOptionalBases().size())
441 {
442 std::cerr
443 << "interface type " << name
444 << " number of direct optional bases changed from "
445 << ent2A->getDirectOptionalBases().size() << " to "
446 << ent2B->getDirectOptionalBases().size()
447 << std::endl;
448 std::exit(EXIT_FAILURE);
449 }
450 for (auto
451 i(ent2A->getDirectOptionalBases().begin()),
452 j(ent2B->getDirectOptionalBases().begin());
453 i != ent2A->getDirectOptionalBases().end(); ++i, ++j)
454 {
455 if (i->name != j->name) {
456 std::cerr
457 << "interface type " << name
458 << " direct optional base #"
459 << (i - ent2A->getDirectOptionalBases().begin()
460 + 1)
461 << " changed from " << i->name << " to "
462 << j->name << std::endl;
463 std::exit(EXIT_FAILURE);
464 }
465 }
466 if (ent2A->getDirectAttributes().size()
467 != ent2B->getDirectAttributes().size())
468 {
469 std::cerr
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);
475 }
476 for (auto
477 i(ent2A->getDirectAttributes().begin()),
478 j(ent2B->getDirectAttributes().begin());
479 i != ent2A->getDirectAttributes().end(); ++i, ++j)
480 {
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)
486 {
487 std::cerr
488 << "interface type " << name
489 << " direct attribute #"
490 << i - ent2A->getDirectAttributes().begin() + 1
491 << " changed from "
492 << (i->bound ? OUString("bound ") : OUString())
493 << (i->readOnly
494 ? OUString("read-only ") : OUString())
495 << i->type << " " << i->name //TODO: exceptions
496 << " to "
497 << (j->bound ? OUString("bound ") : OUString())
498 << (j->readOnly
499 ? OUString("read-only ") : OUString())
500 << j->type << " " << j->name //TODO: exceptions
501 << std::endl;
502 std::exit(EXIT_FAILURE);
503 }
504 }
505 if (ent2A->getDirectMethods().size()
506 != ent2B->getDirectMethods().size())
507 {
508 std::cerr
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);
514 }
515 for (auto
516 i(ent2A->getDirectMethods().begin()),
517 j(ent2B->getDirectMethods().begin());
518 i != ent2A->getDirectMethods().end(); ++i, ++j)
519 {
520 if (i->name != j->name || i->returnType != j->returnType
521 || i->exceptions != j->exceptions)
522 {
523 std::cerr
524 << "interface type " << name
525 << " direct method #"
526 << i - ent2A->getDirectMethods().begin() + 1
527 << " changed from "
528 << i->returnType << " " << i->name //TODO: exceptions
529 << " to " << j->returnType << " " << j->name //TODO: exceptions
530 << std::endl;
531 std::exit(EXIT_FAILURE);
532 }
533 if (i->parameters.size() != j->parameters.size()) {
534 std::cerr
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);
541 }
542 for (auto
543 k(i->parameters.begin()),
544 l(j->parameters.begin());
545 k != i->parameters.end(); ++k, ++l)
546 {
547 if (k->type != l->type || k->direction != l->direction)
548 {
549 std::cerr
550 << "interface type " << name
551 << " direct method " << i->name
552 << " parameter #"
553 << k - i->parameters.begin() + 1
554 << " changed from "
555 << showDirection(k->direction) << " "
556 << k->type << " to "
557 << showDirection(l->direction) << " "
558 << l->type << std::endl;
559 std::exit(EXIT_FAILURE);
560 }
561 if (k->name != l->name) {
562 std::cerr
563 << "interface type " << name
564 << " direct method " << i->name
565 << " parameter #"
566 << k - i->parameters.begin() + 1
567 << " changed name from " << k->name
568 << " to " << l->name << std::endl;
569 std::exit(EXIT_FAILURE);
570 }
571 }
572 }
573 break;
574 }
576 {
578 static_cast<unoidl::TypedefEntity *>(entA.get()));
580 static_cast<unoidl::TypedefEntity *>(entB.get()));
581 if (ent2A->getType() != ent2B->getType()) {
582 std::cerr
583 << "typedef " << name << " type changed from "
584 << ent2A->getType() << " to " << ent2B->getType()
585 << std::endl;
586 std::exit(EXIT_FAILURE);
587 }
588 break;
589 }
591 {
593 static_cast<unoidl::ConstantGroupEntity *>(entA.get()));
595 static_cast<unoidl::ConstantGroupEntity *>(entB.get()));
596 for (auto & i: ent2A->getMembers()) {
597 bool found = false;
598 for (auto & j: ent2B->getMembers()) {
599 if (i.name == j.name) {
600 if (i.value != j.value) {
601 std::cerr
602 << "constant group " << name
603 << " member " << i.name
604 << " changed value" << std::endl;
605 std::exit(EXIT_FAILURE);
606 }
607 found = true;
608 break;
609 }
610 }
611 if (!found) {
612 std::cerr
613 << "A constant group " << name << " member "
614 << i.name << " is not present in B"
615 << std::endl;
616 std::exit(EXIT_FAILURE);
617 }
618 }
619 break;
620 }
622 {
624 ent2A(
626 entA.get()));
628 ent2B(
630 entB.get()));
631 if (ent2A->getBase() != ent2B->getBase()) {
632 std::cerr
633 << "single-interface--based service " << name
634 << " base changed from " << ent2A->getBase()
635 << " to " << ent2B->getBase()
636 << std::endl;
637 std::exit(EXIT_FAILURE);
638 }
639 if (ent2A->getConstructors().size()
640 != ent2B->getConstructors().size())
641 {
642 std::cerr
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);
648 }
649 for (auto
650 i(ent2A->getConstructors().begin()),
651 j(ent2B->getConstructors().begin());
652 i != ent2A->getConstructors().end(); ++i, ++j)
653 {
654 if (i->name != j->name || i->parameters != j->parameters
655 || i->exceptions != j->exceptions
656 || i->defaultConstructor != j->defaultConstructor)
657 {
658 std::cerr
659 << "single-interface--based service " << name
660 << " constructor #"
661 << i - ent2A->getConstructors().begin() + 1
662 << " changed from "
663 << (i->defaultConstructor
664 ? OUString("default ") : i->name) //TODO: parameters, exceptions
665 << " to "
666 << (j->defaultConstructor
667 ? OUString("default ") : j->name) //TODO: parameters, exceptions
668 << std::endl;
669 std::exit(EXIT_FAILURE);
670 }
671 }
672 break;
673 }
675 {
677 ent2A(
679 entA.get()));
681 ent2B(
683 entB.get()));
684 if (ent2A->getDirectMandatoryBaseServices().size()
685 != ent2B->getDirectMandatoryBaseServices().size())
686 {
687 std::cerr
688 << "accumulation-based service " << name
689 << (" number of direct mandatory base services"
690 " changed from ")
691 << ent2A->getDirectMandatoryBaseServices().size()
692 << " to "
693 << ent2B->getDirectMandatoryBaseServices().size()
694 << std::endl;
695 std::exit(EXIT_FAILURE);
696 }
697 for (auto
698 i(ent2A->getDirectMandatoryBaseServices().begin()),
699 j(ent2B->getDirectMandatoryBaseServices().begin());
700 i != ent2A->getDirectMandatoryBaseServices().end();
701 ++i, ++j)
702 {
703 if (i->name != j->name) {
704 std::cerr
705 << "accumulation-based service " << name
706 << " direct mandatory base service #"
707 << (i
708 - (ent2A->getDirectMandatoryBaseServices()
709 .begin())
710 + 1)
711 << " changed from " << i->name << " to "
712 << j->name << std::endl;
713 std::exit(EXIT_FAILURE);
714 }
715 }
716 if (ent2A->getDirectOptionalBaseServices().size()
717 > ent2B->getDirectOptionalBaseServices().size())
718 {
719 std::cerr
720 << "accumulation-based service " << name
721 << (" number of direct optional base services"
722 " shrank from ")
723 << ent2A->getDirectOptionalBaseServices().size()
724 << " to "
725 << ent2B->getDirectOptionalBaseServices().size()
726 << std::endl;
727 std::exit(EXIT_FAILURE);
728 }
729 for (auto & i: ent2A->getDirectOptionalBaseServices()) {
730 if (std::none_of(
731 ent2B->getDirectOptionalBaseServices().begin(),
732 ent2B->getDirectOptionalBaseServices().end(),
733 EqualsAnnotation(i.name)))
734 {
735 std::cerr
736 << "accumulation-based service " << name
737 << " direct optional base service " << i.name
738 << " was removed" << std::endl;
739 std::exit(EXIT_FAILURE);
740 }
741 }
742 if (ent2A->getDirectMandatoryBaseInterfaces().size()
743 != ent2B->getDirectMandatoryBaseInterfaces().size())
744 {
745 std::cerr
746 << "accumulation-based service " << name
747 << (" number of direct mandatory base interfaces"
748 " changed from ")
749 << ent2A->getDirectMandatoryBaseInterfaces().size()
750 << " to "
751 << ent2B->getDirectMandatoryBaseInterfaces().size()
752 << std::endl;
753 std::exit(EXIT_FAILURE);
754 }
755 for (auto
756 i(ent2A->getDirectMandatoryBaseInterfaces()
757 .begin()),
758 j(ent2B->getDirectMandatoryBaseInterfaces()
759 .begin());
760 i != ent2A->getDirectMandatoryBaseInterfaces().end();
761 ++i, ++j)
762 {
763 if (i->name != j->name) {
764 std::cerr
765 << "accumulation-based service " << name
766 << " direct mandatory base interface #"
767 << (i
768 - (ent2A->getDirectMandatoryBaseInterfaces()
769 .begin())
770 + 1)
771 << " changed from " << i->name << " to "
772 << j->name << std::endl;
773 std::exit(EXIT_FAILURE);
774 }
775 }
776 if (ent2A->getDirectOptionalBaseInterfaces().size()
777 > ent2B->getDirectOptionalBaseInterfaces().size())
778 {
779 std::cerr
780 << "accumulation-based service " << name
781 << (" number of direct optional base interfaces"
782 " shrank from ")
783 << ent2A->getDirectOptionalBaseInterfaces().size()
784 << " to "
785 << ent2B->getDirectOptionalBaseInterfaces().size()
786 << std::endl;
787 std::exit(EXIT_FAILURE);
788 }
789 for (auto & i: ent2A->getDirectOptionalBaseInterfaces()) {
790 if (std::none_of(
791 (ent2B->getDirectOptionalBaseInterfaces()
792 .begin()),
793 ent2B->getDirectOptionalBaseInterfaces().end(),
794 EqualsAnnotation(i.name)))
795 {
796 std::cerr
797 << "accumulation-based service " << name
798 << " direct optional base interface " << i.name
799 << " was removed" << std::endl;
800 std::exit(EXIT_FAILURE);
801 }
802 }
803 if (ent2A->getDirectProperties().size()
804 > ent2B->getDirectProperties().size())
805 {
806 std::cerr
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);
812 }
813 for (auto
814 i(ent2A->getDirectProperties().begin()),
815 j(ent2B->getDirectProperties().begin());
816 i != ent2A->getDirectProperties().end(); ++i, ++j)
817 {
818 if (i->name != j->name || i->type != j->type
819 || i->attributes != j->attributes)
820 {
821 std::cerr
822 << "accumulation-based service " << name
823 << " direct property #"
824 << i - ent2A->getDirectProperties().begin() + 1
825 << " changed from "
826 << i->type << " " << i->name //TODO: attributes
827 << " to "
828 << j->type << " " << j->name //TODO: attributes
829 << std::endl;
830 std::exit(EXIT_FAILURE);
831 }
832 }
833 for (auto
834 i(ent2B->getDirectProperties().begin()
835 + ent2A->getDirectProperties().size());
836 i != ent2B->getDirectProperties().end(); ++i)
837 {
839 {
840 std::cerr
841 << "B accumulation-based service " << name
842 << " additional direct property " << i->name
843 << " is not optional" << std::endl;
844 std::exit(EXIT_FAILURE);
845 }
846 }
847 break;
848 }
850 {
853 entA.get()));
856 entB.get()));
857 if (ent2A->getBase() != ent2B->getBase()) {
858 std::cerr
859 << "interface-based singleton " << name
860 << " base changed from " << ent2A->getBase()
861 << " to " << ent2B->getBase() << std::endl;
862 std::exit(EXIT_FAILURE);
863 }
864 break;
865 }
867 {
870 entA.get()));
873 entB.get()));
874 if (ent2A->getBase() != ent2B->getBase()) {
875 std::cerr
876 << "service-based singleton " << name
877 << " base changed from " << ent2A->getBase()
878 << " to " << ent2B->getBase() << std::endl;
879 std::exit(EXIT_FAILURE);
880 }
881 break;
882 }
884 assert(false && "this cannot happen");
885 }
886 }
887 }
888}
889
890bool valid(std::u16string_view identifier) {
891 for (size_t i = 0;; ++i) {
892 i = identifier.find('_', i);
893 if (i == std::u16string_view::npos) {
894 return true;
895 }
896 if (!rtl::isAsciiUpperCase(identifier[0]) || identifier[i - 1] == '_') {
897 return false;
898 }
899 }
900}
901
902void checkIds(
903 rtl::Reference<unoidl::Provider> const & providerA, std::u16string_view prefix,
905{
906 assert(cursor.is());
907 for (;;) {
908 OUString id;
909 rtl::Reference<unoidl::Entity> entB(cursor->getNext(&id));
910 if (!entB.is()) {
911 break;
912 }
913 OUString name(prefix + id);
914 rtl::Reference<unoidl::Entity> entA(providerA->findEntity(name));
915 if (!(entA.is() || valid(id))) {
916 std::cerr
917 << "entity name " << name << " uses an invalid identifier"
918 << std::endl;
919 std::exit(EXIT_FAILURE);
920 }
921 switch (entB->getSort()) {
923 checkIds(
924 providerA, Concat2View(name + "."),
925 (static_cast<unoidl::ModuleEntity *>(entB.get())
926 ->createCursor()));
927 break;
929 if (!entA.is()) {
931 static_cast<unoidl::EnumTypeEntity *>(entB.get()));
932 for (auto & i: ent2B->getMembers()) {
933 if (!valid(i.name)) {
934 std::cerr
935 << "enum type " << name << " member " << i.name
936 << " uses an invalid identifier" << std::endl;
937 std::exit(EXIT_FAILURE);
938 }
939 }
940 }
941 break;
943 if (!entA.is()) {
945 static_cast<unoidl::PlainStructTypeEntity *>(
946 entB.get()));
947 for (auto & i: ent2B->getDirectMembers()) {
948 if (!valid(i.name)) {
949 std::cerr
950 << "plain struct type " << name << " direct member "
951 << i.name << " uses an invalid identifier"
952 << std::endl;
953 std::exit(EXIT_FAILURE);
954 }
955 }
956 }
957 break;
959 if (!entA.is()) {
961 ent2B(
962 static_cast<
964 entB.get()));
965 for (auto & i: ent2B->getTypeParameters()) {
966 if (!valid(i)) {
967 std::cerr
968 << "polymorphic struct type template " << name
969 << " type parameter " << i
970 << " uses an invalid identifier" << std::endl;
971 std::exit(EXIT_FAILURE);
972 }
973 }
974 for (auto & i: ent2B->getMembers()) {
975 if (!valid(i.name)) {
976 std::cerr
977 << "polymorphic struct type template " << name
978 << " member " << i.name
979 << " uses an invalid identifier" << std::endl;
980 std::exit(EXIT_FAILURE);
981 }
982 }
983 }
984 break;
986 if (!entA.is()) {
988 static_cast<unoidl::ExceptionTypeEntity *>(entB.get()));
989 for (auto & i: ent2B->getDirectMembers()) {
990 if (!valid(i.name)) {
991 std::cerr
992 << "exception type " << name << " direct member "
993 << i.name << " uses an invalid identifier"
994 << std::endl;
995 std::exit(EXIT_FAILURE);
996 }
997 }
998 }
999 break;
1001 if (!entA.is()) {
1003 static_cast<unoidl::InterfaceTypeEntity *>(entB.get()));
1004 for (auto & i: ent2B->getDirectAttributes()) {
1005 if (!valid(i.name)) {
1006 std::cerr
1007 << "interface type " << name << " direct attribute "
1008 << i.name << " uses an invalid identifier"
1009 << std::endl;
1010 std::exit(EXIT_FAILURE);
1011 }
1012 }
1013 for (auto & i: ent2B->getDirectMethods()) {
1014 if (!valid(i.name)) {
1015 std::cerr
1016 << "interface type " << name << " direct method "
1017 << i.name << " uses an invalid identifier"
1018 << std::endl;
1019 std::exit(EXIT_FAILURE);
1020 }
1021 for (auto & j: i.parameters) {
1022 if (!valid(j.name)) {
1023 std::cerr
1024 << "interface type " << name
1025 << " direct method " << i.name << " parameter "
1026 << j.name << " uses an invalid identifier"
1027 << std::endl;
1028 std::exit(EXIT_FAILURE);
1029 }
1030 }
1031 }
1032 }
1033 break;
1037 break;
1039 {
1041 static_cast<unoidl::ConstantGroupEntity *>(entB.get()));
1042 for (auto & i: ent2B->getMembers()) {
1043 bool found = false;
1044 if (entA.is()) {
1046 static_cast<unoidl::ConstantGroupEntity *>(
1047 entA.get()));
1048 for (auto & j: ent2A->getMembers()) {
1049 if (i.name == j.name) {
1050 found = true;
1051 break;
1052 }
1053 }
1054 }
1055 if (!(found || valid(i.name))) {
1056 std::cerr
1057 << "Constant group " << name << " member "
1058 << i.name << " uses an invalid identifier"
1059 << std::endl;
1060 std::exit(EXIT_FAILURE);
1061 }
1062 }
1063 break;
1064 }
1066 if (!entA.is()) {
1068 ent2B(
1070 entB.get()));
1071 for (auto & i: ent2B->getConstructors()) {
1072 if (!valid(i.name)) {
1073 std::cerr
1074 << "single-interface--based service " << name
1075 << " constructor " << i.name
1076 << " uses an invalid identifier" << std::endl;
1077 std::exit(EXIT_FAILURE);
1078 }
1079 for (auto & j: i.parameters) {
1080 if (!valid(j.name)) {
1081 std::cerr
1082 << "single-interface--based service " << name
1083 << " constructor " << i.name << " parameter "
1084 << j.name << " uses an invalid identifier"
1085 << std::endl;
1086 std::exit(EXIT_FAILURE);
1087 }
1088 }
1089 }
1090 }
1091 break;
1093 {
1096 entB.get()));
1097 std::vector<unoidl::AccumulationBasedServiceEntity::Property>::size_type
1098 n(entA.is()
1100 entA.get())
1101 ->getDirectProperties().size())
1102 : 0);
1103 assert(n <= ent2B->getDirectProperties().size());
1104 for (auto i(ent2B->getDirectProperties().begin() +n);
1105 i != ent2B->getDirectProperties().end(); ++i)
1106 {
1107 if (!valid(i->name)) {
1108 std::cerr
1109 << "accumulation-based service " << name
1110 << " direct property " << i->name
1111 << " uses an invalid identifier" << std::endl;
1112 std::exit(EXIT_FAILURE);
1113 }
1114 }
1115 break;
1116 }
1117 }
1118 }
1119}
1120
1121}
1122
1124 try {
1125 sal_uInt32 args = rtl_getAppCommandArgCount();
1127 mgr[0] = new unoidl::Manager;
1128 mgr[1] = new unoidl::Manager;
1130 int side = 0;
1131 bool ignoreUnpublished = false;
1132 for (sal_uInt32 i = 0; i != args; ++i) {
1133 bool delimiter = false;
1134 OUString uri;
1135 if (getArgument(
1136 i, &ignoreUnpublished, side == 0 ? &delimiter : nullptr,
1137 &uri))
1138 {
1139 try {
1140 prov[side] = mgr[side]->addProvider(uri);
1141 } catch (unoidl::NoSuchFileException &) {
1142 std::cerr
1143 << "Input <" << uri << "> does not exist" << std::endl;
1144 std::exit(EXIT_FAILURE);
1145 }
1146 } else if (delimiter) {
1147 side = 1;
1148 }
1149 }
1150 if (side == 0 || !(prov[0].is() && prov[1].is())) {
1151 badUsage();
1152 }
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) {
1157 std::cerr
1158 << "Bad input <" << e1.getUri() << ">: " << e1.getDetail()
1159 << std::endl;
1160 std::exit(EXIT_FAILURE);
1161 } catch (std::exception & e1) {
1162 std::cerr << "Failure: " << e1.what() << std::endl;
1163 std::exit(EXIT_FAILURE);
1164 }
1165}
1166
1167/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
std::vector< Property > const & getDirectProperties() const
Definition: unoidl.hxx:622
@ SORT_PLAIN_STRUCT_TYPE
Definition: unoidl.hxx:84
@ SORT_ACCUMULATION_BASED_SERVICE
Definition: unoidl.hxx:87
@ SORT_SINGLE_INTERFACE_BASED_SERVICE
Definition: unoidl.hxx:87
@ SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE
Definition: unoidl.hxx:85
@ SORT_INTERFACE_TYPE
Definition: unoidl.hxx:86
@ SORT_CONSTANT_GROUP
Definition: unoidl.hxx:86
@ SORT_EXCEPTION_TYPE
Definition: unoidl.hxx:85
@ SORT_INTERFACE_BASED_SINGLETON
Definition: unoidl.hxx:88
@ SORT_SERVICE_BASED_SINGLETON
Definition: unoidl.hxx:88
const OUString & getDetail() const
Definition: unoidl.hxx:60
const OUString & getUri() const
Definition: unoidl.hxx:58
virtual rtl::Reference< MapCursor > createCursor() const =0
bool isPublished() const
Definition: unoidl.hxx:129
float u
const char * name
sal_Int64 n
size
int i
args
bool getArgument(std::u16string_view name, OUString *value)
static bool operator==(ConstantValue const &lhs, ConstantValue const &rhs)
static bool operator!=(ConstantValue const &lhs, ConstantValue const &rhs)
::boost::spirit::classic::rule< ScannerT > identifier
TOOLS_DLLPUBLIC SvStream & endl(SvStream &rStr)
sal_Int16 shortValue
Definition: unoidl.hxx:448
sal_Int32 longValue
Definition: unoidl.hxx:450
sal_uInt16 unsignedShortValue
Definition: unoidl.hxx:449
sal_uInt64 unsignedHyperValue
Definition: unoidl.hxx:453
sal_uInt32 unsignedLongValue
Definition: unoidl.hxx:451
sal_Int64 hyperValue
Definition: unoidl.hxx:452
ResultType type
SAL_IMPLEMENT_MAIN()
OUString name_
Definition: unoidl.cxx:49