bump product version to 6.4.0.3
[LibreOffice.git] / idlc / source / astinterface.cxx
blob991759384869224408dfdf5071638073cae3f540
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)
259 VisibleInterfaces::const_iterator visible(
260 m_visibleInterfaces.find(ifc->getScopedName()));
261 if (visible != m_visibleInterfaces.end()) {
262 switch (visible->second) {
263 case INTERFACE_INDIRECT_OPTIONAL:
264 if (direct && optional) {
265 doubleDeclarations.interfaces.push_back(ifc);
266 return;
268 break;
270 case INTERFACE_DIRECT_OPTIONAL:
271 if (direct || !mainOptional) {
272 doubleDeclarations.interfaces.push_back(ifc);
274 return;
276 case INTERFACE_INDIRECT_MANDATORY:
277 if (direct) {
278 doubleDeclarations.interfaces.push_back(ifc);
280 return;
282 case INTERFACE_DIRECT_MANDATORY:
283 if (direct || (!optional && !mainOptional)) {
284 doubleDeclarations.interfaces.push_back(ifc);
286 return;
289 if (direct || !optional) {
290 for (DeclList::const_iterator i(ifc->getIteratorBegin());
291 i != ifc->getIteratorEnd(); ++i)
293 checkMemberClashes(
294 doubleDeclarations.members, *i, !mainOptional);
296 for (auto const& elem : ifc->m_inheritedInterfaces)
298 checkInheritedInterfaceClashes(
299 doubleDeclarations, seenInterfaces, elem.getResolved(),
300 false, elem.isOptional(), mainOptional);
306 void AstInterface::checkMemberClashes(
307 DoubleMemberDeclarations & doubleMembers, AstDeclaration const * member,
308 bool checkOptional) const
310 VisibleMembers::const_iterator i(
311 m_visibleMembers.find(member->getLocalName()));
312 if (i != m_visibleMembers.end()) {
313 if (i->second.mandatory != nullptr) {
314 if (i->second.mandatory->getScopedName() != member->getScopedName())
316 DoubleMemberDeclaration d;
317 d.first = i->second.mandatory;
318 d.second = member;
319 doubleMembers.push_back(d);
321 } else if (checkOptional) {
322 for (auto const& elem : i->second.optionals)
324 if (elem.second->getScopedName() != member->getScopedName()) {
325 DoubleMemberDeclaration d;
326 d.first = elem.second;
327 d.second = member;
328 doubleMembers.push_back(d);
335 void AstInterface::addVisibleInterface(
336 AstInterface const * ifc, bool direct, bool optional)
338 InterfaceKind kind = optional
339 ? direct ? INTERFACE_DIRECT_OPTIONAL : INTERFACE_INDIRECT_OPTIONAL
340 : direct ? INTERFACE_DIRECT_MANDATORY : INTERFACE_INDIRECT_MANDATORY;
341 std::pair< VisibleInterfaces::iterator, bool > result(
342 m_visibleInterfaces.emplace(ifc->getScopedName(), kind));
343 bool seen = !result.second
344 && result.first->second >= INTERFACE_INDIRECT_MANDATORY;
345 if (!result.second && kind > result.first->second) {
346 result.first->second = kind;
348 if (!optional && !seen) {
349 for (DeclList::const_iterator i(ifc->getIteratorBegin());
350 i != ifc->getIteratorEnd(); ++i)
352 m_visibleMembers.emplace(
353 (*i)->getLocalName(), VisibleMember(*i));
355 for (auto const& elem : ifc->m_inheritedInterfaces)
357 addVisibleInterface(elem.getResolved(), false, elem.isOptional());
362 void AstInterface::addOptionalVisibleMembers(AstInterface const * ifc) {
363 for (DeclList::const_iterator i(ifc->getIteratorBegin());
364 i != ifc->getIteratorEnd(); ++i)
366 VisibleMembers::iterator visible(
367 m_visibleMembers.find((*i)->getLocalName()));
368 if (visible == m_visibleMembers.end()) {
369 visible = m_visibleMembers.emplace(
370 (*i)->getLocalName(), VisibleMember()).first;
372 if (visible->second.mandatory == nullptr) {
373 visible->second.optionals.emplace(ifc->getScopedName(), *i);
376 for (auto const& elem : ifc->m_inheritedInterfaces)
378 if (!elem.isOptional()) {
379 addOptionalVisibleMembers(elem.getResolved());
384 bool AstInterface::increment(sal_uInt16 * counter, char const * sort) const {
385 if (*counter == SAL_MAX_UINT16) {
386 fprintf(
387 stderr, "%s: interface %s has too many direct %s\n",
388 idlc()->getOptions()->getProgramName().getStr(),
389 getScopedName().getStr(), sort);
390 return false;
392 ++*counter;
393 return true;
396 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */