bump product version to 7.2.5.1
[LibreOffice.git] / idlc / source / astinterface.cxx
blob50e24d1fd667f3c42a8225523540c9d228c2e11d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
23 #include <idlc.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,
32 AstScope* pScope)
33 : AstType(NT_interface, name, pScope)
34 , AstScope(NT_interface)
35 , m_mandatoryInterfaces(0)
36 , m_bIsDefined(false)
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);
55 return doubleDecls;
58 void AstInterface::addInheritedInterface(
59 AstType const * ifc, bool optional, OUString const & documentation)
61 m_inheritedInterfaces.emplace_back(ifc, optional, documentation);
62 if (!optional) {
63 ++m_mandatoryInterfaces;
65 AstInterface const * resolved = resolveInterfaceTypedefs(ifc);
66 addVisibleInterface(resolved, true, optional);
67 if (optional) {
68 addOptionalVisibleMembers(resolved);
72 AstInterface::DoubleMemberDeclarations AstInterface::checkMemberClashes(
73 AstDeclaration const * member) const
75 DoubleMemberDeclarations doubleMembers;
76 checkMemberClashes(doubleMembers, member, true);
77 return doubleMembers;
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;
94 m_bIsDefined = true;
97 bool AstInterface::dump(RegistryKey& rKey)
99 if ( !isDefined() )
100 return true;
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());
108 return false;
111 if (m_mandatoryInterfaces > SAL_MAX_UINT16
112 || m_inheritedInterfaces.size() - m_mandatoryInterfaces
113 > SAL_MAX_UINT16)
115 fprintf(
116 stderr, "%s: interface %s has too many direct base interfaces\n",
117 idlc()->getOptions()->getProgramName().getStr(),
118 getScopedName().getStr());
119 return false;
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();
130 ++i)
132 switch ((*i)->getNodeType()) {
133 case NT_attribute:
135 if (!increment(&nAttributes, "attributes")) {
136 return false;
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) {
144 fprintf(
145 stderr,
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());
151 return false;
153 if (getCount > 0) {
154 version = TYPEREG_VERSION_1;
155 if (!increment(&nMethods, "attributes")) {
156 return false;
159 DeclList::size_type setCount = attr->getSetExceptionCount();
160 if (setCount > SAL_MAX_UINT16) {
161 fprintf(
162 stderr,
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());
168 return false;
170 if (setCount > 0) {
171 version = TYPEREG_VERSION_1;
172 if (!increment(&nMethods, "attributes")) {
173 return false;
176 break;
179 case NT_operation:
180 if (!increment(&nMethods, "methods")) {
181 return false;
183 break;
185 default:
186 OSL_ASSERT(false);
187 break;
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,
204 OStringToOUString(
205 elem.getInterface()->getRelativName(),
206 RTL_TEXTENCODING_UTF8));
207 } else {
208 aBlob.setSuperTypeName(
209 superTypeIndex++,
210 OStringToOUString(
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();
219 ++i)
221 switch ((*i)->getNodeType()) {
222 case NT_attribute:
223 static_cast<AstAttribute *>(*i)->dumpBlob(
224 aBlob, attributeIndex++, &methodIndex);
225 break;
227 case NT_operation:
228 static_cast<AstOperation *>(*i)->dumpBlob(aBlob, methodIndex++);
229 break;
231 default:
232 OSL_ASSERT(false);
233 break;
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());
245 return false;
248 return true;
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))
258 return;
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);
267 return;
269 break;
271 case INTERFACE_DIRECT_OPTIONAL:
272 if (direct || !mainOptional) {
273 doubleDeclarations.interfaces.push_back(ifc);
275 return;
277 case INTERFACE_INDIRECT_MANDATORY:
278 if (direct) {
279 doubleDeclarations.interfaces.push_back(ifc);
281 return;
283 case INTERFACE_DIRECT_MANDATORY:
284 if (direct || (!optional && !mainOptional)) {
285 doubleDeclarations.interfaces.push_back(ifc);
287 return;
290 if (!direct && optional)
291 return;
293 for (DeclList::const_iterator i(ifc->getIteratorBegin());
294 i != ifc->getIteratorEnd(); ++i)
296 checkMemberClashes(
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())
314 return;
316 if (i->second.mandatory != nullptr) {
317 if (i->second.mandatory->getScopedName() != member->getScopedName())
319 DoubleMemberDeclaration d;
320 d.first = i->second.mandatory;
321 d.second = member;
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;
330 d.second = member;
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)
351 return;
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) {
389 fprintf(
390 stderr, "%s: interface %s has too many direct %s\n",
391 idlc()->getOptions()->getProgramName().getStr(),
392 getScopedName().getStr(), sort);
393 return false;
395 ++*counter;
396 return true;
399 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */