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 <idlc/astinterface.hxx>
21 #include <idlc/astattribute.hxx>
22 #include <idlc/astoperation.hxx>
23 #include "idlc/idlc.hxx"
25 #include <registry/version.h>
26 #include <registry/writer.hxx>
28 using namespace ::rtl
;
30 AstInterface::AstInterface(const OString
& name
,
31 AstInterface
const * pInherits
,
33 : AstType(NT_interface
, name
, pScope
)
34 , AstScope(NT_interface
)
35 , m_mandatoryInterfaces(0)
38 , m_bForwardedInSameFile(false)
39 , m_bSingleInheritance(pInherits
!= 0)
42 addInheritedInterface(pInherits
, false, OUString());
46 AstInterface::~AstInterface()
50 AstInterface::DoubleDeclarations
AstInterface::checkInheritedInterfaceClashes(
51 AstInterface
const * ifc
, bool optional
) const
53 DoubleDeclarations doubleDecls
;
54 std::set
< OString
> seen
;
55 checkInheritedInterfaceClashes(
56 doubleDecls
, seen
, ifc
, true, optional
, optional
);
60 void AstInterface::addInheritedInterface(
61 AstType
const * ifc
, bool optional
, OUString
const & documentation
)
63 m_inheritedInterfaces
.push_back(
64 InheritedInterface(ifc
, optional
, documentation
));
66 ++m_mandatoryInterfaces
;
68 AstInterface
const * resolved
= resolveInterfaceTypedefs(ifc
);
69 addVisibleInterface(resolved
, true, optional
);
71 addOptionalVisibleMembers(resolved
);
75 AstInterface::DoubleMemberDeclarations
AstInterface::checkMemberClashes(
76 AstDeclaration
const * member
) const
78 DoubleMemberDeclarations doubleMembers
;
79 checkMemberClashes(doubleMembers
, member
, true);
83 void AstInterface::addMember(AstDeclaration
/*TODO: const*/ * member
) {
84 addDeclaration(member
);
85 m_visibleMembers
.insert(
86 VisibleMembers::value_type(
87 member
->getLocalName(), VisibleMember(member
)));
90 void AstInterface::forwardDefined(AstInterface
const & def
)
92 setImported(def
.isImported());
93 setInMainfile(def
.isInMainfile());
94 setLineNumber(def
.getLineNumber());
95 setFileName(def
.getFileName());
96 setDocumentation(def
.getDocumentation());
97 m_inheritedInterfaces
= def
.m_inheritedInterfaces
;
98 m_mandatoryInterfaces
= def
.m_mandatoryInterfaces
;
102 bool AstInterface::dump(RegistryKey
& rKey
)
107 RegistryKey localKey
;
108 if (rKey
.createKey( OStringToOUString(getFullName(), RTL_TEXTENCODING_UTF8
), localKey
))
110 fprintf(stderr
, "%s: warning, could not create key '%s' in '%s'\n",
111 idlc()->getOptions()->getProgramName().getStr(),
112 getFullName().getStr(), OUStringToOString(rKey
.getRegistryName(), RTL_TEXTENCODING_UTF8
).getStr());
116 if (m_mandatoryInterfaces
> SAL_MAX_UINT16
117 || m_inheritedInterfaces
.size() - m_mandatoryInterfaces
121 stderr
, "%s: interface %s has too many direct base interfaces\n",
122 idlc()->getOptions()->getProgramName().getStr(),
123 getScopedName().getStr());
126 sal_uInt16 nBaseTypes
= static_cast< sal_uInt16
>(m_mandatoryInterfaces
);
127 sal_uInt16 nAttributes
= 0;
128 sal_uInt16 nMethods
= 0;
129 sal_uInt16 nReferences
= static_cast< sal_uInt16
>(
130 m_inheritedInterfaces
.size() - m_mandatoryInterfaces
);
131 typereg_Version version
132 = (nBaseTypes
<= 1 && nReferences
== 0 && !m_bPublished
133 ? TYPEREG_VERSION_0
: TYPEREG_VERSION_1
);
134 for (DeclList::const_iterator
i(getIteratorBegin()); i
!= getIteratorEnd();
137 switch ((*i
)->getNodeType()) {
140 if (!increment(&nAttributes
, "attributes")) {
143 AstAttribute
* attr
= (AstAttribute
*)(*i
);
144 if (attr
->isBound()) {
145 version
= TYPEREG_VERSION_1
;
147 DeclList::size_type getCount
= attr
->getGetExceptionCount();
148 if (getCount
> SAL_MAX_UINT16
) {
151 ("%s: raises clause of getter for attribute %s of"
152 " interface %s is too long\n"),
153 idlc()->getOptions()->getProgramName().getStr(),
154 (*i
)->getLocalName().getStr(),
155 getScopedName().getStr());
159 version
= TYPEREG_VERSION_1
;
160 if (!increment(&nMethods
, "attributes")) {
164 DeclList::size_type setCount
= attr
->getSetExceptionCount();
165 if (setCount
> SAL_MAX_UINT16
) {
168 ("%s: raises clause of setter for attribute %s of"
169 " interface %s is too long\n"),
170 idlc()->getOptions()->getProgramName().getStr(),
171 (*i
)->getLocalName().getStr(),
172 getScopedName().getStr());
176 version
= TYPEREG_VERSION_1
;
177 if (!increment(&nMethods
, "attributes")) {
185 if (!increment(&nMethods
, "methods")) {
197 typereg::Writer
aBlob(
198 version
, getDocumentation(), emptyStr
, RT_TYPE_INTERFACE
, m_bPublished
,
199 OStringToOUString(getRelativName(), RTL_TEXTENCODING_UTF8
), nBaseTypes
,
200 nAttributes
, nMethods
, nReferences
);
202 sal_uInt16 superTypeIndex
= 0;
203 sal_uInt16 referenceIndex
= 0;
204 for (InheritedInterfaces::iterator i
= m_inheritedInterfaces
.begin();
205 i
!= m_inheritedInterfaces
.end(); ++i
)
207 if (i
->isOptional()) {
208 aBlob
.setReferenceData(
209 referenceIndex
++, i
->getDocumentation(), RT_REF_SUPPORTS
,
212 i
->getInterface()->getRelativName(),
213 RTL_TEXTENCODING_UTF8
));
215 aBlob
.setSuperTypeName(
218 i
->getInterface()->getRelativName(),
219 RTL_TEXTENCODING_UTF8
));
223 sal_uInt16 attributeIndex
= 0;
224 sal_uInt16 methodIndex
= 0;
225 for (DeclList::const_iterator
i(getIteratorBegin()); i
!= getIteratorEnd();
228 switch ((*i
)->getNodeType()) {
231 ((AstAttribute
*)(*i
))->dumpBlob(
232 aBlob
, attributeIndex
++, &methodIndex
);
236 ((AstOperation
*)(*i
))->dumpBlob(aBlob
, methodIndex
++);
245 sal_uInt32 aBlobSize
;
246 void const * pBlob
= aBlob
.getBlob(&aBlobSize
);
248 if (localKey
.setValue(emptyStr
, RG_VALUETYPE_BINARY
, (RegValue
)pBlob
, aBlobSize
))
250 fprintf(stderr
, "%s: warning, could not set value of key \"%s\" in %s\n",
251 idlc()->getOptions()->getProgramName().getStr(),
252 getFullName().getStr(), OUStringToOString(localKey
.getRegistryName(), RTL_TEXTENCODING_UTF8
).getStr());
259 void AstInterface::checkInheritedInterfaceClashes(
260 DoubleDeclarations
& doubleDeclarations
,
261 std::set
< OString
> & seenInterfaces
, AstInterface
const * ifc
,
262 bool direct
, bool optional
, bool mainOptional
) const
264 if (direct
|| optional
265 || seenInterfaces
.insert(ifc
->getScopedName()).second
)
267 VisibleInterfaces::const_iterator
visible(
268 m_visibleInterfaces
.find(ifc
->getScopedName()));
269 if (visible
!= m_visibleInterfaces
.end()) {
270 switch (visible
->second
) {
271 case INTERFACE_INDIRECT_OPTIONAL
:
272 if (direct
&& optional
) {
273 doubleDeclarations
.interfaces
.push_back(ifc
);
278 case INTERFACE_DIRECT_OPTIONAL
:
279 if (direct
|| !mainOptional
) {
280 doubleDeclarations
.interfaces
.push_back(ifc
);
284 case INTERFACE_INDIRECT_MANDATORY
:
286 doubleDeclarations
.interfaces
.push_back(ifc
);
290 case INTERFACE_DIRECT_MANDATORY
:
291 if (direct
|| (!optional
&& !mainOptional
)) {
292 doubleDeclarations
.interfaces
.push_back(ifc
);
297 if (direct
|| !optional
) {
298 for (DeclList::const_iterator
i(ifc
->getIteratorBegin());
299 i
!= ifc
->getIteratorEnd(); ++i
)
302 doubleDeclarations
.members
, *i
, !mainOptional
);
304 for (InheritedInterfaces::const_iterator
i(
305 ifc
->m_inheritedInterfaces
.begin());
306 i
!= ifc
->m_inheritedInterfaces
.end(); ++i
)
308 checkInheritedInterfaceClashes(
309 doubleDeclarations
, seenInterfaces
, i
->getResolved(),
310 false, i
->isOptional(), mainOptional
);
316 void AstInterface::checkMemberClashes(
317 DoubleMemberDeclarations
& doubleMembers
, AstDeclaration
const * member
,
318 bool checkOptional
) const
320 VisibleMembers::const_iterator
i(
321 m_visibleMembers
.find(member
->getLocalName()));
322 if (i
!= m_visibleMembers
.end()) {
323 if (i
->second
.mandatory
!= 0) {
324 if (i
->second
.mandatory
->getScopedName() != member
->getScopedName())
326 DoubleMemberDeclaration d
;
327 d
.first
= i
->second
.mandatory
;
329 doubleMembers
.push_back(d
);
331 } else if (checkOptional
) {
332 for (VisibleMember::Optionals::const_iterator
j(
333 i
->second
.optionals
.begin());
334 j
!= i
->second
.optionals
.end(); ++j
)
336 if (j
->second
->getScopedName() != member
->getScopedName()) {
337 DoubleMemberDeclaration d
;
340 doubleMembers
.push_back(d
);
347 void AstInterface::addVisibleInterface(
348 AstInterface
const * ifc
, bool direct
, bool optional
)
350 InterfaceKind kind
= optional
351 ? direct
? INTERFACE_DIRECT_OPTIONAL
: INTERFACE_INDIRECT_OPTIONAL
352 : direct
? INTERFACE_DIRECT_MANDATORY
: INTERFACE_INDIRECT_MANDATORY
;
353 std::pair
< VisibleInterfaces::iterator
, bool > result(
354 m_visibleInterfaces
.insert(
355 VisibleInterfaces::value_type(ifc
->getScopedName(), kind
)));
356 bool seen
= !result
.second
357 && result
.first
->second
>= INTERFACE_INDIRECT_MANDATORY
;
358 if (!result
.second
&& kind
> result
.first
->second
) {
359 result
.first
->second
= kind
;
361 if (!optional
&& !seen
) {
362 for (DeclList::const_iterator
i(ifc
->getIteratorBegin());
363 i
!= ifc
->getIteratorEnd(); ++i
)
365 m_visibleMembers
.insert(
366 VisibleMembers::value_type(
367 (*i
)->getLocalName(), VisibleMember(*i
)));
369 for (InheritedInterfaces::const_iterator
i(
370 ifc
->m_inheritedInterfaces
.begin());
371 i
!= ifc
->m_inheritedInterfaces
.end(); ++i
)
373 addVisibleInterface(i
->getResolved(), false, i
->isOptional());
378 void AstInterface::addOptionalVisibleMembers(AstInterface
const * ifc
) {
379 for (DeclList::const_iterator
i(ifc
->getIteratorBegin());
380 i
!= ifc
->getIteratorEnd(); ++i
)
382 VisibleMembers::iterator
visible(
383 m_visibleMembers
.find((*i
)->getLocalName()));
384 if (visible
== m_visibleMembers
.end()) {
385 visible
= m_visibleMembers
.insert(
386 VisibleMembers::value_type(
387 (*i
)->getLocalName(), VisibleMember())).first
;
389 if (visible
->second
.mandatory
== 0) {
390 visible
->second
.optionals
.insert(
391 VisibleMember::Optionals::value_type(ifc
->getScopedName(), *i
));
394 for (InheritedInterfaces::const_iterator
i(
395 ifc
->m_inheritedInterfaces
.begin());
396 i
!= ifc
->m_inheritedInterfaces
.end(); ++i
)
398 if (!i
->isOptional()) {
399 addOptionalVisibleMembers(i
->getResolved());
404 bool AstInterface::increment(sal_uInt16
* counter
, char const * sort
) const {
405 if (*counter
== SAL_MAX_UINT16
) {
407 stderr
, "%s: interface %s has too many direct %s\n",
408 idlc()->getOptions()->getProgramName().getStr(),
409 getScopedName().getStr(), sort
);
416 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */