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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <astinterface.hxx>
21 #include <astattribute.hxx>
22 #include <astoperation.hxx>
25 #include <registry/version.h>
26 #include <registry/writer.hxx>
28 #include <osl/diagnose.h>
30 AstInterface::AstInterface(const OString
& name
,
31 AstInterface
const * pInherits
,
33 : AstType(NT_interface
, name
, pScope
)
34 , AstScope(NT_interface
)
35 , m_mandatoryInterfaces(0)
37 , m_bSingleInheritance(pInherits
!= nullptr)
39 if (pInherits
!= nullptr) {
40 addInheritedInterface(pInherits
, false, OUString());
44 AstInterface::~AstInterface()
48 AstInterface::DoubleDeclarations
AstInterface::checkInheritedInterfaceClashes(
49 AstInterface
const * ifc
, bool optional
) const
51 DoubleDeclarations doubleDecls
;
52 std::set
< OString
> seen
;
53 checkInheritedInterfaceClashes(
54 doubleDecls
, seen
, ifc
, true, optional
, optional
);
58 void AstInterface::addInheritedInterface(
59 AstType
const * ifc
, bool optional
, OUString
const & documentation
)
61 m_inheritedInterfaces
.emplace_back(ifc
, optional
, documentation
);
63 ++m_mandatoryInterfaces
;
65 AstInterface
const * resolved
= resolveInterfaceTypedefs(ifc
);
66 addVisibleInterface(resolved
, true, optional
);
68 addOptionalVisibleMembers(resolved
);
72 AstInterface::DoubleMemberDeclarations
AstInterface::checkMemberClashes(
73 AstDeclaration
const * member
) const
75 DoubleMemberDeclarations doubleMembers
;
76 checkMemberClashes(doubleMembers
, member
, true);
80 void AstInterface::addMember(AstDeclaration
/*TODO: const*/ * member
) {
81 addDeclaration(member
);
82 m_visibleMembers
.emplace(member
->getLocalName(), VisibleMember(member
));
85 void AstInterface::forwardDefined(AstInterface
const & def
)
87 setImported(def
.isImported());
88 setInMainfile(def
.isInMainfile());
89 setLineNumber(def
.getLineNumber());
90 setFileName(def
.getFileName());
91 setDocumentation(def
.getDocumentation());
92 m_inheritedInterfaces
= def
.m_inheritedInterfaces
;
93 m_mandatoryInterfaces
= def
.m_mandatoryInterfaces
;
97 bool AstInterface::dump(RegistryKey
& rKey
)
102 RegistryKey localKey
;
103 if (rKey
.createKey( OStringToOUString(getFullName(), RTL_TEXTENCODING_UTF8
), localKey
) != RegError::NO_ERROR
)
105 fprintf(stderr
, "%s: warning, could not create key '%s' in '%s'\n",
106 idlc()->getOptions()->getProgramName().getStr(),
107 getFullName().getStr(), OUStringToOString(rKey
.getRegistryName(), RTL_TEXTENCODING_UTF8
).getStr());
111 if (m_mandatoryInterfaces
> SAL_MAX_UINT16
112 || m_inheritedInterfaces
.size() - m_mandatoryInterfaces
116 stderr
, "%s: interface %s has too many direct base interfaces\n",
117 idlc()->getOptions()->getProgramName().getStr(),
118 getScopedName().getStr());
121 sal_uInt16 nBaseTypes
= static_cast< sal_uInt16
>(m_mandatoryInterfaces
);
122 sal_uInt16 nAttributes
= 0;
123 sal_uInt16 nMethods
= 0;
124 sal_uInt16 nReferences
= static_cast< sal_uInt16
>(
125 m_inheritedInterfaces
.size() - m_mandatoryInterfaces
);
126 typereg_Version version
127 = (nBaseTypes
<= 1 && nReferences
== 0 && !m_bPublished
128 ? TYPEREG_VERSION_0
: TYPEREG_VERSION_1
);
129 for (DeclList::const_iterator
i(getIteratorBegin()); i
!= getIteratorEnd();
132 switch ((*i
)->getNodeType()) {
135 if (!increment(&nAttributes
, "attributes")) {
138 AstAttribute
* attr
= static_cast<AstAttribute
*>(*i
);
139 if (attr
->isBound()) {
140 version
= TYPEREG_VERSION_1
;
142 DeclList::size_type getCount
= attr
->getGetExceptionCount();
143 if (getCount
> SAL_MAX_UINT16
) {
146 ("%s: raises clause of getter for attribute %s of"
147 " interface %s is too long\n"),
148 idlc()->getOptions()->getProgramName().getStr(),
149 (*i
)->getLocalName().getStr(),
150 getScopedName().getStr());
154 version
= TYPEREG_VERSION_1
;
155 if (!increment(&nMethods
, "attributes")) {
159 DeclList::size_type setCount
= attr
->getSetExceptionCount();
160 if (setCount
> SAL_MAX_UINT16
) {
163 ("%s: raises clause of setter for attribute %s of"
164 " interface %s is too long\n"),
165 idlc()->getOptions()->getProgramName().getStr(),
166 (*i
)->getLocalName().getStr(),
167 getScopedName().getStr());
171 version
= TYPEREG_VERSION_1
;
172 if (!increment(&nMethods
, "attributes")) {
180 if (!increment(&nMethods
, "methods")) {
191 typereg::Writer
aBlob(
192 version
, getDocumentation(), "", RT_TYPE_INTERFACE
, m_bPublished
,
193 OStringToOUString(getRelativName(), RTL_TEXTENCODING_UTF8
), nBaseTypes
,
194 nAttributes
, nMethods
, nReferences
);
196 sal_uInt16 superTypeIndex
= 0;
197 sal_uInt16 referenceIndex
= 0;
198 for (auto const& elem
: m_inheritedInterfaces
)
200 if (elem
.isOptional()) {
201 aBlob
.setReferenceData(
202 referenceIndex
++, elem
.getDocumentation(), RTReferenceType::SUPPORTS
,
203 RTFieldAccess::OPTIONAL
,
205 elem
.getInterface()->getRelativName(),
206 RTL_TEXTENCODING_UTF8
));
208 aBlob
.setSuperTypeName(
211 elem
.getInterface()->getRelativName(),
212 RTL_TEXTENCODING_UTF8
));
216 sal_uInt16 attributeIndex
= 0;
217 sal_uInt16 methodIndex
= 0;
218 for (DeclList::const_iterator
i(getIteratorBegin()); i
!= getIteratorEnd();
221 switch ((*i
)->getNodeType()) {
223 static_cast<AstAttribute
*>(*i
)->dumpBlob(
224 aBlob
, attributeIndex
++, &methodIndex
);
228 static_cast<AstOperation
*>(*i
)->dumpBlob(aBlob
, methodIndex
++);
237 sal_uInt32 aBlobSize
;
238 void const * pBlob
= aBlob
.getBlob(&aBlobSize
);
240 if (localKey
.setValue("", RegValueType::BINARY
, const_cast<RegValue
>(pBlob
), aBlobSize
) != RegError::NO_ERROR
)
242 fprintf(stderr
, "%s: warning, could not set value of key \"%s\" in %s\n",
243 idlc()->getOptions()->getProgramName().getStr(),
244 getFullName().getStr(), OUStringToOString(localKey
.getRegistryName(), RTL_TEXTENCODING_UTF8
).getStr());
251 void AstInterface::checkInheritedInterfaceClashes(
252 DoubleDeclarations
& doubleDeclarations
,
253 std::set
< OString
> & seenInterfaces
, AstInterface
const * ifc
,
254 bool direct
, bool optional
, bool mainOptional
) const
256 if (!(direct
|| optional
257 || seenInterfaces
.insert(ifc
->getScopedName()).second
))
260 VisibleInterfaces::const_iterator
visible(
261 m_visibleInterfaces
.find(ifc
->getScopedName()));
262 if (visible
!= m_visibleInterfaces
.end()) {
263 switch (visible
->second
) {
264 case INTERFACE_INDIRECT_OPTIONAL
:
265 if (direct
&& optional
) {
266 doubleDeclarations
.interfaces
.push_back(ifc
);
271 case INTERFACE_DIRECT_OPTIONAL
:
272 if (direct
|| !mainOptional
) {
273 doubleDeclarations
.interfaces
.push_back(ifc
);
277 case INTERFACE_INDIRECT_MANDATORY
:
279 doubleDeclarations
.interfaces
.push_back(ifc
);
283 case INTERFACE_DIRECT_MANDATORY
:
284 if (direct
|| (!optional
&& !mainOptional
)) {
285 doubleDeclarations
.interfaces
.push_back(ifc
);
290 if (!direct
&& optional
)
293 for (DeclList::const_iterator
i(ifc
->getIteratorBegin());
294 i
!= ifc
->getIteratorEnd(); ++i
)
297 doubleDeclarations
.members
, *i
, !mainOptional
);
299 for (auto const& elem
: ifc
->m_inheritedInterfaces
)
301 checkInheritedInterfaceClashes(
302 doubleDeclarations
, seenInterfaces
, elem
.getResolved(),
303 false, elem
.isOptional(), mainOptional
);
307 void AstInterface::checkMemberClashes(
308 DoubleMemberDeclarations
& doubleMembers
, AstDeclaration
const * member
,
309 bool checkOptional
) const
311 VisibleMembers::const_iterator
i(
312 m_visibleMembers
.find(member
->getLocalName()));
313 if (i
== m_visibleMembers
.end())
316 if (i
->second
.mandatory
!= nullptr) {
317 if (i
->second
.mandatory
->getScopedName() != member
->getScopedName())
319 DoubleMemberDeclaration d
;
320 d
.first
= i
->second
.mandatory
;
322 doubleMembers
.push_back(d
);
324 } else if (checkOptional
) {
325 for (auto const& elem
: i
->second
.optionals
)
327 if (elem
.second
->getScopedName() != member
->getScopedName()) {
328 DoubleMemberDeclaration d
;
329 d
.first
= elem
.second
;
331 doubleMembers
.push_back(d
);
337 void AstInterface::addVisibleInterface(
338 AstInterface
const * ifc
, bool direct
, bool optional
)
340 InterfaceKind kind
= optional
341 ? direct
? INTERFACE_DIRECT_OPTIONAL
: INTERFACE_INDIRECT_OPTIONAL
342 : direct
? INTERFACE_DIRECT_MANDATORY
: INTERFACE_INDIRECT_MANDATORY
;
343 std::pair
< VisibleInterfaces::iterator
, bool > result(
344 m_visibleInterfaces
.emplace(ifc
->getScopedName(), kind
));
345 bool seen
= !result
.second
346 && result
.first
->second
>= INTERFACE_INDIRECT_MANDATORY
;
347 if (!result
.second
&& kind
> result
.first
->second
) {
348 result
.first
->second
= kind
;
350 if (optional
|| seen
)
353 for (DeclList::const_iterator
i(ifc
->getIteratorBegin());
354 i
!= ifc
->getIteratorEnd(); ++i
)
356 m_visibleMembers
.emplace(
357 (*i
)->getLocalName(), VisibleMember(*i
));
359 for (auto const& elem
: ifc
->m_inheritedInterfaces
)
361 addVisibleInterface(elem
.getResolved(), false, elem
.isOptional());
365 void AstInterface::addOptionalVisibleMembers(AstInterface
const * ifc
) {
366 for (DeclList::const_iterator
i(ifc
->getIteratorBegin());
367 i
!= ifc
->getIteratorEnd(); ++i
)
369 VisibleMembers::iterator
visible(
370 m_visibleMembers
.find((*i
)->getLocalName()));
371 if (visible
== m_visibleMembers
.end()) {
372 visible
= m_visibleMembers
.emplace(
373 (*i
)->getLocalName(), VisibleMember()).first
;
375 if (visible
->second
.mandatory
== nullptr) {
376 visible
->second
.optionals
.emplace(ifc
->getScopedName(), *i
);
379 for (auto const& elem
: ifc
->m_inheritedInterfaces
)
381 if (!elem
.isOptional()) {
382 addOptionalVisibleMembers(elem
.getResolved());
387 bool AstInterface::increment(sal_uInt16
* counter
, char const * sort
) const {
388 if (*counter
== SAL_MAX_UINT16
) {
390 stderr
, "%s: interface %s has too many direct %s\n",
391 idlc()->getOptions()->getProgramName().getStr(),
392 getScopedName().getStr(), sort
);
399 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */