Bump version to 6.4-15
[LibreOffice.git] / idlc / source / astscope.cxx
blob9af691501a8a47af422f9180b02ff5626ccfc84f
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 <astscope.hxx>
21 #include <astbasetype.hxx>
22 #include <astinterface.hxx>
23 #include <errorhandler.hxx>
24 #include <osl/diagnose.h>
27 static bool isGlobal(const OString& scopedName)
29 return scopedName.isEmpty() || scopedName.startsWith(":");
32 AstScope::AstScope(NodeType nodeType)
33 : m_nodeType(nodeType)
38 AstScope::~AstScope()
43 AstDeclaration* AstScope::addDeclaration(AstDeclaration* pDecl)
45 AstDeclaration* pDeclaration = nullptr;
47 if ((pDeclaration = lookupForAdd(pDecl)) != nullptr)
49 if ( pDecl->hasAncestor(pDeclaration) )
51 ErrorHandler::error2(ErrorCode::RedefScope, pDecl, pDeclaration);
52 return nullptr;
54 if ( (pDecl->getNodeType() == pDeclaration->getNodeType()) &&
55 (pDecl->getNodeType() == NT_sequence
56 || pDecl->getNodeType() == NT_instantiated_struct) )
58 return pDeclaration;
60 if ( (pDeclaration->getNodeType() == NT_interface)
61 && (pDecl->getNodeType() == NT_interface)
62 && !(static_cast<AstInterface*>(pDeclaration)->isDefined()) )
64 m_declarations.push_back(pDecl);
65 return pDecl;
67 if ( (NT_service == m_nodeType) &&
68 ( ((pDecl->getNodeType() == NT_interface_member)
69 && (pDeclaration->getNodeType() == NT_interface)) ||
70 ((pDecl->getNodeType() == NT_service_member)
71 && (pDeclaration->getNodeType() == NT_service)) )
74 m_declarations.push_back(pDecl);
75 return pDecl;
78 ErrorHandler::error2(ErrorCode::RedefScope, scopeAsDecl(this), pDecl);
79 return nullptr;
82 m_declarations.push_back(pDecl);
83 return pDecl;
86 sal_uInt16 AstScope::getNodeCount(NodeType nodeType) const
88 return static_cast<sal_uInt16>(std::count_if(getIteratorBegin(), getIteratorEnd(),
89 [&nodeType](const AstDeclaration* pDecl) { return pDecl->getNodeType() == nodeType; }));
92 AstDeclaration* AstScope::lookupByName(const OString& scopedName)
94 AstDeclaration* pDecl = nullptr;
95 AstScope* pScope = nullptr;
96 if (scopedName.isEmpty())
97 return nullptr;
99 // If name starts with "::" start look up in global scope
100 if ( isGlobal(scopedName) )
102 pDecl = scopeAsDecl(this);
103 if ( !pDecl )
104 return nullptr;
106 pScope = pDecl->getScope();
107 // If this is the global scope ...
108 if ( !pScope )
110 // look up the scopedName part after "::"
111 OString subName = scopedName.copy(2);
112 pDecl = lookupByName(subName);
113 return pDecl;
114 //return pScope->lookupByName();
116 // OK, not global scope yet, so simply iterate with parent scope
117 pDecl = pScope->lookupByName(scopedName);
118 return pDecl;
121 // The name does not start with "::"
122 // Look up in the local scope and start with the first scope
123 sal_Int32 nIndex = scopedName.indexOf(':');
124 OString firstScope = nIndex > 0 ? scopedName.copy(0, nIndex) : scopedName;
125 bool bFindFirstScope = true;
126 pDecl = lookupByNameLocal(firstScope);
127 if ( !pDecl )
129 bFindFirstScope = false;
131 // OK, not found. Go down parent scope chain
132 pDecl = scopeAsDecl(this);
133 if ( pDecl )
135 pScope = pDecl->getScope();
136 if ( pScope )
137 pDecl = pScope->lookupByName(scopedName);
138 else
139 pDecl = nullptr;
141 // Special case for scope which is an interface. We
142 // have to look in the inherited interfaces as well.
143 if ( !pDecl && m_nodeType == NT_interface )
144 pDecl = lookupInInherited(scopedName);
148 if ( bFindFirstScope && (firstScope != scopedName) )
150 sal_Int32 i = 0;
151 sal_Int32 nOffset = 2;
154 pScope = declAsScope(pDecl);
155 if( pScope )
157 pDecl = pScope->lookupByNameLocal(scopedName.getToken(nOffset, ':', i ));
158 nOffset = 1;
160 if( !pDecl )
161 break;
162 } while( i != -1 );
164 if ( !pDecl )
166 // last try if is not the global scope and the scopeName isn't specify global too
167 pDecl = scopeAsDecl(this);
168 if ( pDecl && !pDecl->getLocalName().isEmpty() )
170 pScope = pDecl->getScope();
171 if ( pScope )
172 pDecl = pScope->lookupByName(scopedName);
173 } else
175 pDecl = nullptr;
181 return pDecl;
184 AstDeclaration* AstScope::lookupByNameLocal(const OString& name) const
186 for (auto const& declaration : m_declarations)
188 if ( declaration->getLocalName() == name )
189 return declaration;
191 return nullptr;
194 AstDeclaration* AstScope::lookupInInherited(const OString& scopedName) const
196 const AstInterface* pInterface = dynamic_cast<const AstInterface*>(this);
198 if ( !pInterface )
199 return nullptr;
201 // Can't look in an interface which was not yet defined
202 if ( !pInterface->getScope() )
204 ErrorHandler::forwardLookupError(pInterface, scopedName);
207 // OK, loop through inherited interfaces. Stop when you find it
208 for (auto const& elem : pInterface->getAllInheritedInterfaces())
210 AstInterface const * resolved = elem.getResolved();
211 AstDeclaration* pDecl = resolved->lookupByNameLocal(scopedName);
212 if ( pDecl )
213 return pDecl;
214 pDecl = resolved->lookupInInherited(scopedName);
215 if ( pDecl )
216 return pDecl;
218 // Not found
219 return nullptr;
222 AstDeclaration* AstScope::lookupPrimitiveType(ExprType type)
224 AstDeclaration* pDecl = nullptr;
225 AstScope* pScope = nullptr;
226 OString typeName;
227 pDecl = scopeAsDecl(this);
228 if ( !pDecl )
229 return nullptr;
230 pScope = pDecl->getScope();
231 if ( pScope)
232 return pScope->lookupPrimitiveType(type);
234 switch (type)
236 case ET_none:
237 OSL_ASSERT(false);
238 break;
239 case ET_short:
240 typeName = OString("short");
241 break;
242 case ET_ushort:
243 typeName = OString("unsigned short");
244 break;
245 case ET_long:
246 typeName = OString("long");
247 break;
248 case ET_ulong:
249 typeName = OString("unsigned long");
250 break;
251 case ET_hyper:
252 typeName = OString("hyper");
253 break;
254 case ET_uhyper:
255 typeName = OString("unsigned hyper");
256 break;
257 case ET_float:
258 typeName = OString("float");
259 break;
260 case ET_double:
261 typeName = OString("double");
262 break;
263 case ET_char:
264 typeName = OString("char");
265 break;
266 case ET_byte:
267 typeName = OString("byte");
268 break;
269 case ET_boolean:
270 typeName = OString("boolean");
271 break;
272 case ET_any:
273 typeName = OString("any");
274 break;
275 case ET_void:
276 typeName = OString("void");
277 break;
278 case ET_type:
279 typeName = OString("type");
280 break;
281 case ET_string:
282 typeName = OString("string");
283 break;
286 pDecl = lookupByNameLocal(typeName);
288 if ( pDecl && (pDecl->getNodeType() == NT_predefined) )
290 AstBaseType* pBaseType = static_cast<AstBaseType*>(pDecl);
292 if ( pBaseType->getExprType() == type )
293 return pDecl;
296 return nullptr;
299 AstDeclaration* AstScope::lookupForAdd(AstDeclaration const * pDecl) const
301 if ( !pDecl )
302 return nullptr;
304 AstDeclaration* pRetDecl = lookupByNameLocal(pDecl->getLocalName());
306 return pRetDecl;
309 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */