1 /**************************************************************************** 2 ** 3 ** Copyright (C) 2016 The Qt Company Ltd. 4 ** Contact: https://www.qt.io/licensing/ 5 ** 6 ** This file is part of Qt Creator. 7 ** 8 ** Commercial License Usage 9 ** Licensees holding valid commercial Qt licenses may use this file in 10 ** accordance with the commercial license agreement provided with the 11 ** Software or, alternatively, in accordance with the terms contained in 12 ** a written agreement between you and The Qt Company. For licensing terms 13 ** and conditions see https://www.qt.io/terms-conditions. For further 14 ** information use the contact form at https://www.qt.io/contact-us. 15 ** 16 ** GNU General Public License Usage 17 ** Alternatively, this file may be used under the terms of the GNU 18 ** General Public License version 3 as published by the Free Software 19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT 20 ** included in the packaging of this file. Please review the following 21 ** information to ensure the GNU General Public License requirements will 22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html. 23 ** 24 ****************************************************************************/ 25 26 #pragma once 27 28 #include "CppDocument.h" 29 #include "LookupItem.h" 30 #include "AlreadyConsideredClassContainer.h" 31 32 #include <cplusplus/FullySpecifiedType.h> 33 #include <cplusplus/Type.h> 34 #include <cplusplus/SymbolVisitor.h> 35 #include <cplusplus/Control.h> 36 #include <cplusplus/Name.h> 37 38 #include <QSet> 39 #include <QMap> 40 41 #include <functional> 42 #include <map> 43 #include <unordered_map> 44 45 namespace CPlusPlus { 46 47 namespace Internal { 48 struct FullyQualifiedName 49 { 50 QList<const Name *> fqn; 51 FullyQualifiedNameFullyQualifiedName52 FullyQualifiedName(const QList<const Name *> &fqn) 53 : fqn(fqn) 54 {} 55 }; 56 } // namespace Internal; 57 58 class CreateBindings; 59 60 class CPLUSPLUS_EXPORT ClassOrNamespace 61 { 62 Q_DISABLE_COPY(ClassOrNamespace) 63 64 ClassOrNamespace(CreateBindings *factory, ClassOrNamespace *parent); 65 66 public: 67 ~ClassOrNamespace(); 68 69 const TemplateNameId *templateId() const; 70 ClassOrNamespace *instantiationOrigin() const; 71 72 ClassOrNamespace *parent() const; 73 QList<ClassOrNamespace *> usings() const; 74 QList<Enum *> unscopedEnums() const; 75 QList<Symbol *> symbols() const; 76 77 ClassOrNamespace *globalNamespace() const; 78 79 QList<LookupItem> lookup(const Name *name); 80 QList<LookupItem> find(const Name *name); 81 82 ClassOrNamespace *lookupType(const Name *name); 83 ClassOrNamespace *lookupType(const Name *name, Block *block); 84 ClassOrNamespace *findType(const Name *name); 85 ClassOrNamespace *findBlock(Block *block); 86 ClassOrNamespace *getNested(const Name *name); 87 88 Symbol *lookupInScope(const QList<const Name *> &fullName); 89 90 /// The class this ClassOrNamespace is based on. rootClass()91 Class *rootClass() const { return _rootClass; } 92 93 private: 94 typedef std::unordered_map<const Name *, ClassOrNamespace *, Name::Hash, Name::Equals> Table; 95 typedef std::unordered_map<const TemplateNameId *, ClassOrNamespace *, TemplateNameId::Hash, TemplateNameId::Equals> TemplateNameIdTable; 96 typedef QHash<const AnonymousNameId *, ClassOrNamespace *> Anonymouses; 97 98 /// \internal 99 void flush(); 100 101 /// \internal 102 ClassOrNamespace *findOrCreateType(const Name *name, ClassOrNamespace *origin = nullptr, 103 Class *clazz = nullptr); 104 105 ClassOrNamespace *findOrCreateNestedAnonymousType(const AnonymousNameId *anonymousNameId); 106 107 void addTodo(Symbol *symbol); 108 void addSymbol(Symbol *symbol); 109 void addUnscopedEnum(Enum *e); 110 void addUsing(ClassOrNamespace *u); 111 void addNestedType(const Name *alias, ClassOrNamespace *e); 112 113 QList<LookupItem> lookup_helper(const Name *name, bool searchInEnclosingScope); 114 115 void lookup_helper(const Name *name, ClassOrNamespace *binding, 116 QList<LookupItem> *result, 117 QSet<ClassOrNamespace *> *processed, 118 const TemplateNameId *templateId); 119 120 ClassOrNamespace *lookupType_helper(const Name *name, QSet<ClassOrNamespace *> *processed, 121 bool searchInEnclosingScope, ClassOrNamespace *origin); 122 123 ClassOrNamespace *findBlock_helper(Block *block, QSet<ClassOrNamespace *> *processed, 124 bool searchInEnclosingScope); 125 126 ClassOrNamespace *nestedType(const Name *name, QSet<ClassOrNamespace *> *processed, 127 ClassOrNamespace *origin); 128 129 void instantiateNestedClasses(ClassOrNamespace *enclosingTemplateClass, 130 Clone &cloner, 131 Subst &subst, 132 ClassOrNamespace *enclosingTemplateClassInstantiation); 133 ClassOrNamespace *findSpecialization(const TemplateNameId *templId, 134 const TemplateNameIdTable &specializations); 135 136 CreateBindings *_factory; 137 ClassOrNamespace *_parent; 138 QList<Symbol *> _symbols; 139 QList<ClassOrNamespace *> _usings; 140 Table _classOrNamespaces; 141 QHash<Block *, ClassOrNamespace *> _blocks; 142 QList<Enum *> _enums; 143 QList<Symbol *> _todo; 144 QSharedPointer<Control> _control; 145 TemplateNameIdTable _specializations; 146 QMap<const TemplateNameId *, ClassOrNamespace *> _instantiations; 147 Anonymouses _anonymouses; 148 QSet<const AnonymousNameId *> _declaredOrTypedefedAnonymouses; 149 150 QHash<Internal::FullyQualifiedName, Symbol *> *_scopeLookupCache; 151 152 // it's an instantiation. 153 const TemplateNameId *_templateId; 154 ClassOrNamespace *_instantiationOrigin; 155 156 AlreadyConsideredClassContainer<Class> _alreadyConsideredClasses; 157 AlreadyConsideredClassContainer<TemplateNameId> _alreadyConsideredTemplates; 158 159 Class *_rootClass; 160 161 class NestedClassInstantiator 162 { 163 public: NestedClassInstantiator(CreateBindings * factory,Clone & cloner,Subst & subst)164 NestedClassInstantiator(CreateBindings *factory, Clone &cloner, Subst &subst) 165 : _factory(factory) 166 , _cloner(cloner) 167 , _subst(subst) 168 {} 169 void instantiate(ClassOrNamespace *enclosingTemplateClass, 170 ClassOrNamespace *enclosingTemplateClassInstantiation); 171 private: 172 bool isInstantiateNestedClassNeeded(const QList<Symbol *> &symbols) const; 173 bool containsTemplateType(Declaration *declaration) const; 174 bool containsTemplateType(Function *function) const; 175 NamedType *findNamedType(Type *memberType) const; 176 177 QSet<ClassOrNamespace *> _alreadyConsideredNestedClassInstantiations; 178 CreateBindings *_factory; 179 Clone &_cloner; 180 Subst &_subst; 181 }; 182 183 public: 184 const Name *_name; // For debug 185 186 friend class CreateBindings; 187 }; 188 189 class CPLUSPLUS_EXPORT CreateBindings: protected SymbolVisitor 190 { 191 Q_DISABLE_COPY(CreateBindings) 192 193 public: 194 CreateBindings(Document::Ptr thisDocument, const Snapshot &snapshot); 195 virtual ~CreateBindings(); 196 197 /// Returns the binding for the global namespace. 198 ClassOrNamespace *globalNamespace() const; 199 200 /// Finds the binding associated to the given symbol. 201 ClassOrNamespace *lookupType(Symbol *symbol, ClassOrNamespace *enclosingBinding = nullptr); 202 ClassOrNamespace *lookupType(const QList<const Name *> &path, 203 ClassOrNamespace *enclosingBinding = nullptr); 204 205 /// Returns the Control that must be used to create temporary symbols. 206 /// \internal control()207 QSharedPointer<Control> control() const 208 { return _control; } 209 expandTemplates()210 bool expandTemplates() const 211 { return _expandTemplates; } setExpandTemplates(bool expandTemplates)212 void setExpandTemplates(bool expandTemplates) 213 { _expandTemplates = expandTemplates; } 214 215 /// Searches in \a scope for symbols with the given \a name. 216 /// Store the result in \a results. 217 /// \internal 218 void lookupInScope(const Name *name, Scope *scope, QList<LookupItem> *result, 219 const TemplateNameId *templateId, ClassOrNamespace *binding); 220 221 /// Create bindings for the symbols reachable from \a rootSymbol. 222 /// \internal 223 void process(Symbol *rootSymbol, ClassOrNamespace *classOrNamespace); 224 225 /// Create an empty ClassOrNamespace binding with the given \a parent. 226 /// \internal 227 ClassOrNamespace *allocClassOrNamespace(ClassOrNamespace *parent); 228 229 protected: 230 using SymbolVisitor::visit; 231 232 /// Change the current ClassOrNamespace binding. 233 ClassOrNamespace *switchCurrentClassOrNamespace(ClassOrNamespace *classOrNamespace); 234 235 /// Enters the ClassOrNamespace binding associated with the given \a symbol. 236 ClassOrNamespace *enterClassOrNamespaceBinding(Symbol *symbol); 237 238 /// Enters a ClassOrNamespace binding for the given \a symbol in the global 239 /// namespace binding. 240 ClassOrNamespace *enterGlobalClassOrNamespace(Symbol *symbol); 241 242 /// Creates bindings for the given \a document. 243 void process(Document::Ptr document); 244 245 /// Creates bindings for the symbols reachable from the \a root symbol. 246 void process(Symbol *root); 247 248 bool visit(Template *templ) override; 249 bool visit(Namespace *ns) override; 250 bool visit(Class *klass) override; 251 bool visit(ForwardClassDeclaration *klass) override; 252 bool visit(Enum *e) override; 253 bool visit(Declaration *decl) override; 254 bool visit(Function *function) override; 255 bool visit(Block *block) override; 256 257 bool visit(BaseClass *b) override; 258 bool visit(UsingNamespaceDirective *u) override; 259 bool visit(UsingDeclaration *u) override; 260 bool visit(NamespaceAlias *a) override; 261 262 bool visit(ObjCClass *klass) override; 263 bool visit(ObjCBaseClass *b) override; 264 bool visit(ObjCForwardClassDeclaration *klass) override; 265 bool visit(ObjCProtocol *proto) override; 266 bool visit(ObjCBaseProtocol *b) override; 267 bool visit(ObjCForwardProtocolDeclaration *proto) override; 268 bool visit(ObjCMethod *) override; 269 270 private: 271 Symbol *instantiateTemplateFunction(const Name *instantiationName, 272 Template *specialization) const; 273 274 Snapshot _snapshot; 275 QSharedPointer<Control> _control; 276 QSet<Namespace *> _processed; 277 QList<ClassOrNamespace *> _entities; 278 ClassOrNamespace *_globalNamespace; 279 ClassOrNamespace *_currentClassOrNamespace; 280 bool _expandTemplates; 281 }; 282 283 class CPLUSPLUS_EXPORT LookupContext 284 { 285 public: 286 LookupContext(); 287 288 LookupContext(Document::Ptr thisDocument, 289 const Snapshot &snapshot); 290 291 LookupContext(Document::Ptr expressionDocument, 292 Document::Ptr thisDocument, 293 const Snapshot &snapshot, 294 QSharedPointer<CreateBindings> bindings = QSharedPointer<CreateBindings>()); 295 296 LookupContext(const LookupContext &other); 297 LookupContext &operator = (const LookupContext &other); 298 299 Document::Ptr expressionDocument() const; 300 Document::Ptr thisDocument() const; 301 Document::Ptr document(const QString &fileName) const; 302 Snapshot snapshot() const; 303 304 ClassOrNamespace *globalNamespace() const; 305 306 QList<LookupItem> lookup(const Name *name, Scope *scope) const; 307 ClassOrNamespace *lookupType(const Name *name, Scope *scope, 308 ClassOrNamespace *enclosingBinding = nullptr, 309 QSet<const Declaration *> typedefsBeingResolved 310 = QSet<const Declaration *>()) const; 311 ClassOrNamespace *lookupType(Symbol *symbol, 312 ClassOrNamespace *enclosingBinding = nullptr) const; 313 ClassOrNamespace *lookupParent(Symbol *symbol) const; 314 315 /// \internal bindings()316 QSharedPointer<CreateBindings> bindings() const 317 { return _bindings; } 318 319 enum InlineNamespacePolicy { ShowInlineNamespaces, HideInlineNamespaces }; 320 static QList<const Name *> fullyQualifiedName( 321 Symbol *symbol, InlineNamespacePolicy policy = ShowInlineNamespaces); 322 static QList<const Name *> path(Symbol *symbol, 323 InlineNamespacePolicy policy = ShowInlineNamespaces); 324 325 static const Name *minimalName(Symbol *symbol, ClassOrNamespace *target, Control *control); 326 setExpandTemplates(bool expandTemplates)327 void setExpandTemplates(bool expandTemplates) 328 { 329 if (_bindings) 330 _bindings->setExpandTemplates(expandTemplates); 331 m_expandTemplates = expandTemplates; 332 } 333 334 private: 335 QList<LookupItem> lookupByUsing(const Name *name, ClassOrNamespace *bindingScope) const; 336 337 // The current expression. 338 Document::Ptr _expressionDocument; 339 340 // The current document. 341 Document::Ptr _thisDocument; 342 343 // All documents. 344 Snapshot _snapshot; 345 346 // Bindings 347 QSharedPointer<CreateBindings> _bindings; 348 349 bool m_expandTemplates; 350 }; 351 352 bool CPLUSPLUS_EXPORT compareFullyQualifiedName(const QList<const Name *> &path, 353 const QList<const Name *> &other); 354 355 356 } // namespace CPlusPlus 357