LibreOffice Module unodevtools (master) 1
skeletoncommon.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 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
22#include <codemaker/global.hxx>
23#include <unoidl/unoidl.hxx>
24
25#include "skeletoncommon.hxx"
26
27#include <algorithm>
28#include <cassert>
29#include <iostream>
30#include <string_view>
31
32using namespace ::codemaker::cpp;
33
34namespace skeletonmaker {
35
36void printLicenseHeader(std::ostream& o)
37{
38 o << "/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n"
39 "/*\n"
40 " * This file is part of the LibreOffice project.\n"
41 " *\n"
42 " * This Source Code Form is subject to the terms of the Mozilla Public\n"
43 " * License, v. 2.0. If a copy of the MPL was not distributed with this\n"
44 " * file, You can obtain one at http://mozilla.org/MPL/2.0/.\n"
45 " */\n\n";
46}
47
48bool getOutputStream(ProgramOptions const & options,
49 OString const & extension,
50 std::ostream** ppOutputStream,
51 OString & targetSourceFileName,
52 OString & tmpSourceFileName)
53{
54 bool bStandardout = false;
55 if ( options.outputpath == "stdout" )
56 {
57 bStandardout = true;
58 *ppOutputStream = &std::cout;
59 return bStandardout;
60 }
61
62 targetSourceFileName = createFileNameFromType(
63 options.outputpath, options.implname.replace('.','/'), extension);
64
65 OString tmpDir = getTempDir(targetSourceFileName);
66 FileStream file;
67 file.createTempFile(tmpDir);
68
69 if( !file.isValid() )
70 {
72 "cannot open " + b2u(targetSourceFileName) + " for writing");
73 }
74 tmpSourceFileName = file.getName();
75 file.close();
76 *ppOutputStream = new std::ofstream(tmpSourceFileName.getStr(),
77 std::ios_base::binary);
78
79 return bStandardout;
80}
81
82static bool containsAttribute(AttributeInfo& attributes, OUString const & attrname)
83{
84 return std::any_of(attributes.begin(), attributes.end(),
85 [&attrname](const unoidl::AccumulationBasedServiceEntity::Property& rAttr) {
86 return rAttr.name == attrname; });
87}
88
89// collect attributes including inherited attributes
91 OUString const & name,
92 AttributeInfo& attributes,
93 std::set< OUString >& propinterfaces)
94{
95 if ( name == "com.sun.star.beans.XPropertySet" ||
96 name == "com.sun.star.beans.XFastPropertySet" ||
97 name == "com.sun.star.beans.XPropertyAccess" )
98 {
99 propinterfaces.insert(name);
100 }
102 switch (manager->getSort(name, &ent)) {
104 {
106 dynamic_cast< unoidl::InterfaceTypeEntity * >(ent.get()));
107 assert(ent2.is());
108 for (const auto& rBase : ent2->getDirectMandatoryBases())
109 {
110 checkAttributes(manager, rBase.name, attributes, propinterfaces);
111 }
112 for (const auto& rAttr : ent2->getDirectAttributes())
113 {
114 if (!containsAttribute(attributes, rAttr.name)) {
115 attributes.emplace_back(
116 rAttr.name, rAttr.type,
118 Attributes(
119 ((rAttr.bound
121 : 0)
122 | (rAttr.readOnly
124 : 0)))),
125 std::vector< OUString >());
126 }
127 }
128 break;
129 }
131 {
134 ent.get()));
135 assert(ent2.is());
136 for (const auto& rService : ent2->getDirectMandatoryBaseServices())
137 {
138 checkAttributes(manager, rService.name, attributes, propinterfaces);
139 }
140 for (const auto& rIface : ent2->getDirectMandatoryBaseInterfaces())
141 {
142 checkAttributes(manager, rIface.name, attributes, propinterfaces);
143 }
144 for (const auto& rProp : ent2->getDirectProperties())
145 {
146 if (!containsAttribute(attributes, rProp.name)) {
147 attributes.push_back(rProp);
148 }
149 }
150 break;
151 }
152 default:
154 "unexpected entity \"" + name
155 + "\" in call to skeletonmaker::checkAttributes");
156 }
157}
158
160 OUString const & name,
161 std::set< OUString >& interfaceTypes,
162 std::set< OUString >& serviceTypes,
164{
166 switch (manager->getSort(name, &ent)) {
168 // com.sun.star.lang.XComponent should be also not in the list
169 // but it will be used for checking the impl helper and will be
170 // removed later if necessary.
171 if ( name == "com.sun.star.lang.XTypeProvider" ||
172 name == "com.sun.star.uno.XWeak" )
173 return;
174 interfaceTypes.insert(name);
175 break;
177 if (serviceTypes.insert(name).second) {
180 ent.get()));
181 assert(ent2.is());
182 if (interfaceTypes.insert(ent2->getBase()).second) {
183 // check if constructors are specified, if yes automatically
184 // support of XInitialization. We will take care of the default
185 // constructor because in this case XInitialization is not
186 // called.
187 if (ent2->getConstructors().size() > 1 ||
188 (ent2->getConstructors().size() == 1 &&
189 !ent2->getConstructors()[0].defaultConstructor))
190 {
191 interfaceTypes.insert(OUString("com.sun.star.lang.XInitialization"));
192 }
193 }
194 }
195 break;
197 if ( serviceTypes.insert(name).second ) {
200 ent.get()));
201 assert(ent2.is());
202 for (const auto& rService : ent2->getDirectMandatoryBaseServices())
203 {
204 checkType(
205 manager, rService.name, interfaceTypes, serviceTypes, properties);
206 }
207 for (const auto& rIface : ent2->getDirectMandatoryBaseInterfaces())
208 {
209 checkType(
210 manager, rIface.name, interfaceTypes, serviceTypes, properties);
211 }
212 for (const auto& rProp : ent2->getDirectProperties())
213 {
214 properties.push_back(rProp);
215 }
216 }
217 break;
218 default:
220 "unexpected entity \"" + name
221 + "\" in call to skeletonmaker::checkType");
222 }
223}
224
226 std::set< OUString >& interfaces,
227 const std::set< OUString >& services,
228 std::u16string_view propertyhelper)
229{
230 if ( services.empty() ) {
231 interfaces.erase("com.sun.star.lang.XServiceInfo");
232 } else {
233 interfaces.insert("com.sun.star.lang.XServiceInfo");
234 }
235
236 if ( propertyhelper == u"_" ) {
237 interfaces.erase("com.sun.star.beans.XPropertySet");
238 interfaces.erase("com.sun.star.beans.XFastPropertySet");
239 interfaces.erase("com.sun.star.beans.XPropertyAccess");
240 }
241}
242
244 OUString const & name)
245{
247 if (manager->getSort(name, &ent)
249 {
252 ent.get()));
253 assert(ent2.is());
254 if (!ent2->getDirectProperties().empty()) {
255 return true;
256 }
257 return std::any_of(ent2->getDirectMandatoryBaseServices().begin(),
258 ent2->getDirectMandatoryBaseServices().end(),
259 [&manager](const unoidl::AnnotatedReference& rService) {
260 return checkServiceProperties(manager, rService.name); });
261 }
262 return false;
263}
264
265
267 ProgramOptions const & options,
268 rtl::Reference< TypeManager > const & manager,
269 const std::set< OUString >& services,
270 const std::set< OUString >& interfaces,
271 AttributeInfo& attributes,
272 std::set< OUString >& propinterfaces)
273{
274 std::set< OUString >::const_iterator iter;
275 std::set< OUString >::const_iterator end;
276
277 if ( !services.empty() ) {
278 iter = services.begin();
279 end = services.end();
280 } else {
281 iter = interfaces.begin();
282 end = interfaces.end();
283 }
284
285 bool oldStyleWithProperties = false;
286 while ( iter != end ) {
288 codemaker::UnoType::Sort sort = manager->getSort(*iter, &ent);
289 if ( !services.empty() ) {
290 if (options.supportpropertysetmixin
291 && (sort
293 {
295 ent2(
296 dynamic_cast<
298 ent.get()));
299 assert(ent2.is());
301 manager, ent2->getBase(), attributes, propinterfaces);
302 if (!(attributes.empty() || propinterfaces.empty())) {
303 return ent2->getBase();
304 }
305 } else {
306 oldStyleWithProperties = checkServiceProperties(manager, *iter);
307 }
308 } else {
309 checkAttributes(manager, *iter, attributes, propinterfaces);
310 if (!(attributes.empty() || propinterfaces.empty())) {
311 return *iter;
312 }
313 }
314 ++iter;
315 }
316
317 return oldStyleWithProperties ? OUString("_") : OUString();
318}
319
321 rtl::Reference< TypeManager > const & manager, OUString const & name)
322{
323 assert(manager.is());
324 if (name == "com.sun.star.lang.XComponent") {
325 return true;
326 }
328 codemaker::UnoType::Sort sort = manager->getSort(name, &ent);
331 "unexpected entity \"" + name
332 + "\" in call to skeletonmaker::checkXComponentSupport");
333 }
335 dynamic_cast< unoidl::InterfaceTypeEntity * >(ent.get()));
336 assert(ent2.is());
337 return std::any_of(ent2->getDirectMandatoryBases().begin(), ent2->getDirectMandatoryBases().end(),
338 [&manager](const unoidl::AnnotatedReference& rBase) { return checkXComponentSupport(manager, rBase.name); });
339}
340
341
342// if XComponent is directly specified, return true and remove it from the
343// supported interfaces list
345 std::set< OUString >& interfaces)
346{
347 if ( interfaces.empty() )
348 return false;
349
350 for ( const auto& rIface : interfaces ) {
351 if ( rIface == "com.sun.star.lang.XComponent" ) {
352 interfaces.erase("com.sun.star.lang.XComponent");
353 return true;
354 }
355 if ( checkXComponentSupport(manager, rIface) )
356 return true;
357 }
358
359 return false;
360}
361
365{
366 int flags = 0;
367 bool getterSupportsUnknown = false;
368 for (const auto& rException : attribute.getExceptions)
369 {
370 if (rException == "com.sun.star.beans.UnknownPropertyException") {
371 getterSupportsUnknown = true;
372 }
373 }
374 for (const auto& rException : attribute.setExceptions)
375 {
376 if (rException == "com.sun.star.beans.PropertyVetoException") {
379 } else if (getterSupportsUnknown
380 && rException == "com.sun.star.beans.UnknownPropertyException")
381 {
384 }
385 }
387}
388
389// This function checks if the specified types for parameters and return
390// types are allowed add-in types, for more info see the com.sun.star.sheet.AddIn
391// service description
393 std::u16string_view type, bool & bLastAny,
394 bool & bHasXPropertySet, bool bIsReturn)
395{
396 assert(manager.is());
397 sal_Int32 rank;
398 codemaker::UnoType::Sort sort = manager->decompose(
399 type, true, nullptr, &rank, nullptr, nullptr);
400
401 if ( sort == codemaker::UnoType::Sort::Long ||
404 {
405 if ( rank == 0 || rank ==2 )
406 return true;
407 }
408 if ( sort == codemaker::UnoType::Sort::Any )
409 {
410 if ( rank <= 2 ) {
411 if ( rank ==1 ) {
412 if ( bIsReturn )
413 return false;
414 bLastAny = true;
415 }
416
417 return true;
418 }
419 }
421 {
422 if ( bIsReturn && type == u"com.sun.star.sheet.XVolatileResult" )
423 return true;
424 if ( !bIsReturn && type == u"com.sun.star.table.XCellRange" )
425 return true;
426 if ( !bIsReturn && type == u"com.sun.star.beans.XPropertySet" )
427 {
428 if ( bHasXPropertySet ) {
429 return false;
430 } else {
431 bHasXPropertySet = true;
432 return true;
433 }
434 }
435 }
436 return false;
437}
438
439static void checkAddInTypes(
440 rtl::Reference< TypeManager > const & manager, std::u16string_view name,
442{
443 assert(entity.is());
444 bool bLastAny = false;
445 bool bHasXPropertySet = false;
446 for (const auto& rMethod : entity->getDirectMethods())
447 {
448 if ( !checkAddinType(
449 manager, rMethod.returnType, bLastAny, bHasXPropertySet, true) )
450 {
452 OUString::Concat("the return type of the calc add-in function '") + name
453 + ":" + rMethod.name
454 + "' is invalid. Please check your IDL definition.");
455 }
456
457 bHasXPropertySet = false;
458 for (const auto& rParam : rMethod.parameters)
459 {
460 bLastAny = false;
461 if ( !checkAddinType(manager, rParam.type,
462 bLastAny, bHasXPropertySet, false) ||
463 bLastAny )
464 {
466 "the type of the " + rParam.name
467 + " parameter of the calc add-in function '" + name
468 + ":" + rMethod.name + "' is invalid."
469 + (bLastAny
470 ? OUString(
471 " The type 'sequence<any>' is allowed as last"
472 " parameter only.")
473 : OUString())
474 + (bHasXPropertySet
475 ? OUString(
476 " The type 'XPropertySet' is allowed only once.")
477 : OUString())
478 + " Please check your IDL definition.");
479 }
480 }
481 }
482}
483
484static void generateFunctionParameterMap(std::ostream& o,
485 ProgramOptions const & options,
486 rtl::Reference< TypeManager > const & manager,
487 OUString const & name,
489 bool& bFirst)
490{
491 if ( name == "com.sun.star.uno.XInterface" ||
492 name == "com.sun.star.lang.XLocalizable" ||
493 name == "com.sun.star.lang.XServiceInfo" ||
494 // the next three checks becomes obsolete when configuration is used
495 name == "com.sun.star.sheet.XAddIn" ||
496 name == "com.sun.star.sheet.XCompatibilityNames" ||
497 name == "com.sun.star.lang.XServiceName" )
498 {
499 return;
500 }
501
503 codemaker::UnoType::Sort sort = manager->getSort(name, &ent);
506 "unexpected entity \"" + name
507 + "\" in call to skeletonmaker::generateFunctionParameterMap");
508 }
510 dynamic_cast< unoidl::InterfaceTypeEntity * >(ent.get()));
511 assert(ent2.is());
512
513 // check if the specified add-in functions supports valid types
515
516 for (const auto& rBase : ent2->getDirectMandatoryBases())
517 {
519 o, options, manager, rBase.name, generated, bFirst);
520 }
521
522 if ( generated.contains(u2b(name)) )
523 return;
524 else
525 generated.add(u2b(name));
526
527 for (const auto& rMethod : ent2->getDirectMethods())
528 {
529 if ( bFirst ) {
530 if (options.language == 2) {
531 o << " ParamMap fpm;\n";
532 }
533 else {
534 o << " java.util.Hashtable< Integer, String > fpm = "
535 "new java.util.Hashtable< Integer, String >();\n";
536 }
537 bFirst = false;
538 } else
539 if ( options.language == 2 ) {
540 o << " fpm = ParamMap();\n";
541 }
542 else {
543 o << " fpm = new java.util.Hashtable< "
544 "Integer, String >();\n";
545 }
546
547 std::vector< unoidl::InterfaceTypeEntity::Method::Parameter >::size_type
548 n = 0;
549 for (const auto& rParam : rMethod.parameters)
550 {
551 if ( options.language == 2 ) {
552 o << " fpm[" << n
553 << "] = OUString(\""
554 << rParam.name
555 << "\");\n";
556 }
557 else {
558 o << " fpm.put(" << n << ", \""
559 << rParam.name
560 << "\");\n";
561 }
562 ++n;
563 }
564
565 if ( options.language == 2 ) {
566 o << " m_functionMap[OUString(\""
567 << rMethod.name << "\")] = fpm;\n\n";
568 }
569 else {
570 o << " m_functionMap.put(\"" << rMethod.name << "\", fpm);\n\n";
571 }
572 }
573}
574
575void generateFunctionParameterMap(std::ostream& o,
576 ProgramOptions const & options,
577 rtl::Reference< TypeManager > const & manager,
578 const std::set< OUString >& interfaces)
579{
581 bool bFirst = true;
582 for ( const auto& rIface : interfaces ) {
583 generateFunctionParameterMap(o, options, manager, rIface, generated, bFirst);
584 }
585}
586
587}
588
589/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void createTempFile(const ::rtl::OString &sPath)
const ::rtl::OString & getName() const
bool isValid() const
void close()
bool contains(OString const &type) const
void add(OString const &type)
rtl::Reference< ParseManager > manager
float u
OString getTempDir(const OString &sFileName)
OString createFileNameFromType(const OString &destination, const OString &typeName, const OString &postfix)
const char * name
sal_Int64 n
end
OUString checkPropertyHelper(ProgramOptions const &options, rtl::Reference< TypeManager > const &manager, const std::set< OUString > &services, const std::set< OUString > &interfaces, AttributeInfo &attributes, std::set< OUString > &propinterfaces)
bool getOutputStream(ProgramOptions const &options, OString const &extension, std::ostream **ppOutputStream, OString &targetSourceFileName, OString &tmpSourceFileName)
create dependent on the output path, the implementation name and the extension a new output file.
::std::vector< unoidl::AccumulationBasedServiceEntity::Property > AttributeInfo
static bool checkAddinType(rtl::Reference< TypeManager > const &manager, std::u16string_view type, bool &bLastAny, bool &bHasXPropertySet, bool bIsReturn)
static bool containsAttribute(AttributeInfo &attributes, OUString const &attrname)
void checkDefaultInterfaces(std::set< OUString > &interfaces, const std::set< OUString > &services, std::u16string_view propertyhelper)
static bool checkXComponentSupport(rtl::Reference< TypeManager > const &manager, OUString const &name)
static bool checkServiceProperties(rtl::Reference< TypeManager > const &manager, OUString const &name)
static void checkAttributes(rtl::Reference< TypeManager > const &manager, OUString const &name, AttributeInfo &attributes, std::set< OUString > &propinterfaces)
static void checkAddInTypes(rtl::Reference< TypeManager > const &manager, std::u16string_view name, rtl::Reference< unoidl::InterfaceTypeEntity > const &entity)
unoidl::AccumulationBasedServiceEntity::Property::Attributes checkAdditionalPropertyFlags(unoidl::InterfaceTypeEntity::Attribute const &attribute)
void checkType(rtl::Reference< TypeManager > const &manager, OUString const &name, std::set< OUString > &interfaceTypes, std::set< OUString > &serviceTypes, AttributeInfo &properties)
void printLicenseHeader(std::ostream &o)
print the standard OpenOffice.org license header
static void generateFunctionParameterMap(std::ostream &o, ProgramOptions const &options, rtl::Reference< TypeManager > const &manager, OUString const &name, ::codemaker::GeneratedTypeSet &generated, bool &bFirst)
sal_Int32 attribute
OUString b2u(std::string_view s)
OString u2b(std::u16string_view s)
ResultType type