1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20 #include <astscope.hxx>
21 #include <astbasetype.hxx>
22 #include <astinterface.hxx>
23 #include <errorhandler.hxx>
24 #include <osl/diagnose.h>
25
26
isGlobal(const OString & scopedName)27 static bool isGlobal(const OString& scopedName)
28 {
29 return scopedName.isEmpty() || scopedName.startsWith(":");
30 }
31
AstScope(NodeType nodeType)32 AstScope::AstScope(NodeType nodeType)
33 : m_nodeType(nodeType)
34 {
35
36 }
37
~AstScope()38 AstScope::~AstScope()
39 {
40
41 }
42
addDeclaration(AstDeclaration * pDecl)43 AstDeclaration* AstScope::addDeclaration(AstDeclaration* pDecl)
44 {
45 AstDeclaration* pDeclaration = nullptr;
46
47 if ((pDeclaration = lookupForAdd(pDecl)) != nullptr)
48 {
49 if ( pDecl->hasAncestor(pDeclaration) )
50 {
51 ErrorHandler::error2(ErrorCode::RedefScope, pDecl, pDeclaration);
52 return nullptr;
53 }
54 if ( (pDecl->getNodeType() == pDeclaration->getNodeType()) &&
55 (pDecl->getNodeType() == NT_sequence
56 || pDecl->getNodeType() == NT_instantiated_struct) )
57 {
58 return pDeclaration;
59 }
60 if ( (pDeclaration->getNodeType() == NT_interface)
61 && (pDecl->getNodeType() == NT_interface)
62 && !(static_cast<AstInterface*>(pDeclaration)->isDefined()) )
63 {
64 m_declarations.push_back(pDecl);
65 return pDecl;
66 }
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)) )
72 )
73 {
74 m_declarations.push_back(pDecl);
75 return pDecl;
76 }
77
78 ErrorHandler::error2(ErrorCode::RedefScope, scopeAsDecl(this), pDecl);
79 return nullptr;
80 }
81
82 m_declarations.push_back(pDecl);
83 return pDecl;
84 }
85
getNodeCount(NodeType nodeType) const86 sal_uInt16 AstScope::getNodeCount(NodeType nodeType) const
87 {
88 return static_cast<sal_uInt16>(std::count_if(getIteratorBegin(), getIteratorEnd(),
89 [&nodeType](const AstDeclaration* pDecl) { return pDecl->getNodeType() == nodeType; }));
90 }
91
lookupByName(const OString & scopedName)92 AstDeclaration* AstScope::lookupByName(const OString& scopedName)
93 {
94 AstDeclaration* pDecl = nullptr;
95 AstScope* pScope = nullptr;
96 if (scopedName.isEmpty())
97 return nullptr;
98
99 // If name starts with "::" start look up in global scope
100 if ( isGlobal(scopedName) )
101 {
102 pDecl = scopeAsDecl(this);
103 if ( !pDecl )
104 return nullptr;
105
106 pScope = pDecl->getScope();
107 // If this is the global scope ...
108 if ( !pScope )
109 {
110 // look up the scopedName part after "::"
111 OString subName = scopedName.copy(2);
112 pDecl = lookupByName(subName);
113 return pDecl;
114 //return pScope->lookupByName();
115 }
116 // OK, not global scope yet, so simply iterate with parent scope
117 pDecl = pScope->lookupByName(scopedName);
118 return pDecl;
119 }
120
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 )
128 {
129 bFindFirstScope = false;
130
131 // OK, not found. Go down parent scope chain
132 pDecl = scopeAsDecl(this);
133 if ( pDecl )
134 {
135 pScope = pDecl->getScope();
136 if ( pScope )
137 pDecl = pScope->lookupByName(scopedName);
138 else
139 pDecl = nullptr;
140
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);
145 }
146 }
147
148 if ( bFindFirstScope && (firstScope != scopedName) )
149 {
150 sal_Int32 i = 0;
151 sal_Int32 nOffset = 2;
152 do
153 {
154 pScope = declAsScope(pDecl);
155 if( pScope )
156 {
157 pDecl = pScope->lookupByNameLocal(scopedName.getToken(nOffset, ':', i ));
158 nOffset = 1;
159 }
160 if( !pDecl )
161 break;
162 } while( i != -1 );
163
164 if ( !pDecl )
165 {
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() )
169 {
170 pScope = pDecl->getScope();
171 if ( pScope )
172 pDecl = pScope->lookupByName(scopedName);
173 } else
174 {
175 pDecl = nullptr;
176 }
177 }
178
179 }
180
181 return pDecl;
182 }
183
lookupByNameLocal(const OString & name) const184 AstDeclaration* AstScope::lookupByNameLocal(const OString& name) const
185 {
186 for (auto const& declaration : m_declarations)
187 {
188 if ( declaration->getLocalName() == name )
189 return declaration;
190 }
191 return nullptr;
192 }
193
lookupInInherited(const OString & scopedName) const194 AstDeclaration* AstScope::lookupInInherited(const OString& scopedName) const
195 {
196 const AstInterface* pInterface = dynamic_cast<const AstInterface*>(this);
197
198 if ( !pInterface )
199 return nullptr;
200
201 // Can't look in an interface which was not yet defined
202 if ( !pInterface->getScope() )
203 {
204 ErrorHandler::forwardLookupError(pInterface, scopedName);
205 }
206
207 // OK, loop through inherited interfaces. Stop when you find it
208 for (auto const& elem : pInterface->getAllInheritedInterfaces())
209 {
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;
217 }
218 // Not found
219 return nullptr;
220 }
221
lookupPrimitiveType(ExprType type)222 AstDeclaration* AstScope::lookupPrimitiveType(ExprType type)
223 {
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);
233
234 switch (type)
235 {
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;
284 }
285
286 pDecl = lookupByNameLocal(typeName);
287
288 if ( pDecl && (pDecl->getNodeType() == NT_predefined) )
289 {
290 AstBaseType* pBaseType = static_cast<AstBaseType*>(pDecl);
291
292 if ( pBaseType->getExprType() == type )
293 return pDecl;
294 }
295
296 return nullptr;
297 }
298
lookupForAdd(AstDeclaration const * pDecl) const299 AstDeclaration* AstScope::lookupForAdd(AstDeclaration const * pDecl) const
300 {
301 if ( !pDecl )
302 return nullptr;
303
304 AstDeclaration* pRetDecl = lookupByNameLocal(pDecl->getLocalName());
305
306 return pRetDecl;
307 }
308
309 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
310