| 
							- /*
 -   ==============================================================================
 - 
 -    This file is part of the JUCE library.
 -    Copyright (c) 2017 - ROLI Ltd.
 - 
 -    JUCE is an open source library subject to commercial or open-source
 -    licensing.
 - 
 -    By using JUCE, you agree to the terms of both the JUCE 5 End-User License
 -    Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
 -    27th April 2017).
 - 
 -    End User License Agreement: www.juce.com/juce-5-licence
 -    Privacy Policy: www.juce.com/juce-5-privacy-policy
 - 
 -    Or: You may also use this code under the terms of the GPL v3 (see
 -    www.gnu.org/licenses).
 - 
 -    JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
 -    EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
 -    DISCLAIMED.
 - 
 -   ==============================================================================
 - */
 - 
 - #pragma once
 - 
 - 
 - //==============================================================================
 - struct ClassDatabase
 - {
 -     //==============================================================================
 -     struct MemberInfo
 -     {
 -         enum CodeLocationType
 -         {
 -             declaration = 0,
 -             addedToParent,
 -             setBoundsParamX,
 -             setBoundsParamY,
 -             setBoundsParamW,
 -             setBoundsParamH,
 - 
 -             // WARNING! When you change any of these, also update the copy that lives in the live editing code
 - 
 -             numCodeLocationTypes
 -         };
 - 
 -         MemberInfo() {}
 - 
 -         MemberInfo (const MemberInfo& other)
 -             : name (other.name), type (other.type)
 -         {
 -             for (int i = 0; i < numCodeLocationTypes; ++i)
 -                 locations[i] = other.locations[i];
 -         }
 - 
 -         MemberInfo (const String& nm, const String& ty)
 -             : name (nm), type (ty)
 -         {
 -         }
 - 
 -         MemberInfo (const ValueTree& v)
 -             : name (v [Ids::name].toString()),
 -               type (v [Ids::class_].toString())
 -         {
 -             for (int i = 0; i < numCodeLocationTypes; ++i)
 -                 locations[i] = v [getIdentifierForCodeLocationType (i)].toString();
 -         }
 - 
 -         const String& getName() const   { return name; }
 -         const String& getType() const   { return type; }
 - 
 -         const SourceCodeRange& getLocation (CodeLocationType t) const
 -         {
 -             return locations[t];
 -         }
 - 
 -         void setLocation (CodeLocationType t, const SourceCodeRange& range)
 -         {
 -             locations[t] = range;
 -         }
 - 
 -         void mergeWith (const MemberInfo& other)
 -         {
 -             jassert (name == other.name);
 -             if (other.type.isNotEmpty())
 -                 type = other.type;
 - 
 -             for (int i = 0; i < numCodeLocationTypes; ++i)
 -                 if (other.locations[i].isValid())
 -                     locations[i] = other.locations[i];
 -         }
 - 
 -         void nudgeAllCodeRanges (const String& file, const int insertPoint, const int delta)
 -         {
 -             for (int i = 0; i < numCodeLocationTypes; ++i)
 -                 locations[i].nudge (file, insertPoint, delta);
 -         }
 - 
 -         void fileContentChanged (const String& file)
 -         {
 -             for (int i = 0; i < numCodeLocationTypes; ++i)
 -                 locations[i].fileContentChanged (file);
 -         }
 - 
 -         ValueTree toValueTree() const
 -         {
 -             ValueTree m (Ids::MEMBER);
 -             m.setProperty (Ids::name, name, nullptr);
 -             m.setProperty (Ids::class_, type, nullptr);
 - 
 -             for (int i = 0; i < numCodeLocationTypes; ++i)
 -                 locations[i].writeToValueTree (m, getIdentifierForCodeLocationType (i));
 - 
 -             return m;
 -         }
 - 
 -     private:
 -         String name, type;
 -         SourceCodeRange locations [numCodeLocationTypes];
 - 
 -         static Identifier getIdentifierForCodeLocationType (int typeIndex)
 -         {
 -             // (These need to remain in order)
 -             static_assert (setBoundsParamX + 1 == setBoundsParamY && setBoundsParamY + 1 == setBoundsParamW
 -                             && setBoundsParamW + 1 == setBoundsParamH, "");
 - 
 -             static const Identifier ids[] =
 -             {
 -                 "declaration",
 -                 "addedToParent",
 -                 "setBoundsParamX",
 -                 "setBoundsParamY",
 -                 "setBoundsParamW",
 -                 "setBoundsParamH"
 -             };
 - 
 -             return ids [typeIndex];
 -         }
 -     };
 - 
 -     //==============================================================================
 -     struct MethodInfo
 -     {
 -         MethodInfo() {}
 - 
 -         MethodInfo (const MethodInfo& other)
 -             : name (other.name), returnType (other.returnType),
 -               declaration (other.declaration), definition (other.definition),
 -               numArgs (other.numArgs), flags (other.flags)
 -         {
 -         }
 - 
 -         String name, returnType;
 -         SourceCodeRange declaration, definition;
 -         int numArgs, flags;
 - 
 -         enum
 -         {
 -             isConstructor = 1,
 -             isDefaultConstructor = 2,
 -             isTemplated = 4,
 -             isPublic = 8
 -         };
 - 
 -         MethodInfo (const ValueTree& v)
 -             : name (v[Ids::name].toString()),
 -               returnType (v[Ids::returnType].toString()),
 -               declaration (v[Ids::declaration].toString()),
 -               definition (v[Ids::definition].toString()),
 -               numArgs (v[Ids::numArgs]),
 -               flags (v[Ids::flags])
 -         {
 -         }
 - 
 -         ValueTree toValueTree() const
 -         {
 -             ValueTree m (Ids::METHOD);
 -             m.setProperty (Ids::name, name, nullptr);
 -             m.setProperty (Ids::returnType, returnType, nullptr);
 -             m.setProperty (Ids::numArgs, numArgs, nullptr);
 -             m.setProperty (Ids::flags, flags, nullptr);
 -             declaration.writeToValueTree (m, Ids::declaration);
 -             definition.writeToValueTree (m, Ids::definition);
 -             return m;
 -         }
 - 
 -         void nudgeAllCodeRanges (const String& file, const int insertPoint, const int delta)
 -         {
 -             declaration.nudge (file, insertPoint, delta);
 -             definition.nudge (file, insertPoint, delta);
 -         }
 - 
 -         void fileContentChanged (const String& file)
 -         {
 -             declaration.fileContentChanged (file);
 -             definition.fileContentChanged (file);
 -         }
 -     };
 - 
 -     //==============================================================================
 -     struct InstantiationFlags
 -     {
 -         InstantiationFlags()
 -             : isAbstract (false),
 -               inAnonymousNamespace (false),
 -               noDefaultConstructor (false)
 -         {}
 - 
 -         InstantiationFlags (const InstantiationFlags& other)
 -             : isAbstract (other.isAbstract),
 -               inAnonymousNamespace (other.inAnonymousNamespace),
 -               noDefaultConstructor (other.noDefaultConstructor)
 -         {}
 - 
 -         bool canBeInstantiated() const noexcept
 -         {
 -             return ! (isAbstract || inAnonymousNamespace || noDefaultConstructor);
 -         }
 - 
 -         String getReasonForUnavailability() const
 -         {
 -             if (isAbstract)             return "This class is abstract";
 -             if (noDefaultConstructor)   return "This class has no default constructor";
 -             if (inAnonymousNamespace)   return "This class is declared inside an anonymous namespace";
 -             return String();
 -         }
 - 
 -         bool isDisallowed (const InstantiationFlags& disallowedFlags) const
 -         {
 -             return ! ((disallowedFlags.isAbstract && isAbstract)
 -                       || (disallowedFlags.inAnonymousNamespace && inAnonymousNamespace)
 -                       || (disallowedFlags.noDefaultConstructor && noDefaultConstructor));
 -         }
 - 
 -         bool isAbstract;
 -         bool inAnonymousNamespace;
 -         bool noDefaultConstructor;
 -     };
 - 
 -     //==============================================================================
 -     struct Class
 -     {
 -         Class() {}
 -         ~Class() {}
 - 
 -         Class (const Class& other)
 -             : className (other.className), members (other.members),
 -               methods (other.methods), classDeclaration (other.classDeclaration),
 -               instantiationFlags (other.instantiationFlags)
 -         {
 -         }
 - 
 -         Class (const String& name, const InstantiationFlags& flags,
 -                const Array<MemberInfo>& m,
 -                const Array<MethodInfo>& meth,
 -                const SourceCodeRange& classDeclarationRange)
 -             : className (name),
 -               members (m), methods (meth),
 -               classDeclaration (classDeclarationRange),
 -               instantiationFlags (flags)
 -         {
 -         }
 - 
 -         Class& operator= (const Class& other)
 -         {
 -             className = other.className;
 -             members = other.members;
 -             methods = other.methods;
 -             classDeclaration = other.classDeclaration;
 -             instantiationFlags = other.instantiationFlags;
 -             return *this;
 -         }
 - 
 -         const String& getName() const noexcept          { return className; }
 - 
 -         const InstantiationFlags& getInstantiationFlags() const
 -         {
 -             return instantiationFlags;
 -         }
 - 
 -         void setInstantiationFlags (const InstantiationFlags& newFlags)
 -         {
 -             instantiationFlags = newFlags;
 -         }
 - 
 -         const SourceCodeRange& getClassDeclarationRange() const
 -         {
 -             return classDeclaration;
 -         }
 - 
 -         const MemberInfo* findMember (const String& memberName) const
 -         {
 -             for (auto& m : members)
 -                 if (m.getName() == memberName)
 -                     return &m;
 - 
 -             return nullptr;
 -         }
 - 
 -         MemberInfo* findMember (const String& memberName)
 -         {
 -             return const_cast<MemberInfo*> (static_cast<const Class&>(*this).findMember (memberName));
 -         }
 - 
 -         const MethodInfo* getDefaultConstructor() const
 -         {
 -             for (const MethodInfo& m : methods)
 -                 if ((m.flags & MethodInfo::isDefaultConstructor) != 0)
 -                     return &m;
 - 
 -             return nullptr;
 -         }
 - 
 -         const MethodInfo* getConstructor() const
 -         {
 -             if (const MethodInfo* m = getDefaultConstructor())
 -                 return m;
 - 
 -             for (const MethodInfo& m : methods)
 -                 if ((m.flags & MethodInfo::isConstructor) != 0)
 -                     return &m;
 - 
 -             return nullptr;
 -         }
 - 
 -         const MethodInfo* getResizedMethod() const
 -         {
 -             for (const MethodInfo& m : methods)
 -                 if (m.name == "resized" && m.numArgs == 0)
 -                     return &m;
 - 
 -             return nullptr;
 -         }
 - 
 -         File getMainSourceFile() const
 -         {
 -             if (const MethodInfo* m = getResizedMethod())
 -                 if (m->definition.isValid())
 -                     return m->definition.file;
 - 
 -             if (const MethodInfo* m = getConstructor())
 -                 if (m->definition.isValid())
 -                     return m->definition.file;
 - 
 -             for (auto& m : methods)
 -                 if (m.definition.isValid() && File (m.definition.file).hasFileExtension ("cpp;mm"))
 -                     return m.definition.file;
 - 
 -             for (auto& m : methods)
 -                 if ((m.flags & MethodInfo::isConstructor) != 0 && m.definition.isValid())
 -                     return m.definition.file;
 - 
 -             for (auto& m : methods)
 -                 if (m.definition.isValid() && File (m.definition.file).exists())
 -                     return m.definition.file;
 - 
 -             return {};
 -         }
 - 
 -         Array<File> getAllSourceFiles() const
 -         {
 -             Array<File> files;
 - 
 -             for (const MethodInfo& m : methods)
 -             {
 -                 files.addIfNotAlreadyThere (m.declaration.file);
 -                 files.addIfNotAlreadyThere (m.definition.file);
 -             }
 - 
 -             return files;
 -         }
 - 
 -         bool isDeclaredInFile (const File& file) const
 -         {
 -             return file == classDeclaration.file;
 -         }
 - 
 -         void mergeWith (const Class& other)
 -         {
 -             jassert (*this == other);
 - 
 -             if (other.classDeclaration.isValid())
 -                 classDeclaration = other.classDeclaration;
 - 
 -             for (auto& m : other.members)
 -             {
 -                 if (auto* existing = findMember (m.getName()))
 -                     existing->mergeWith (m);
 -                 else
 -                     members.add (m);
 -             }
 -         }
 - 
 -         void nudgeAllCodeRanges (const String& file, int index, int delta)
 -         {
 -             for (MemberInfo& m : members)   m.nudgeAllCodeRanges (file, index, delta);
 -             for (MethodInfo& m : methods)   m.nudgeAllCodeRanges (file, index, delta);
 - 
 -             classDeclaration.nudge (file, index, delta);
 -         }
 - 
 -         void fileContentChanged (const String& file)
 -         {
 -             for (MemberInfo& m : members)   m.fileContentChanged (file);
 -             for (MethodInfo& m : methods)   m.fileContentChanged (file);
 - 
 -             classDeclaration.fileContentChanged (file);
 -         }
 - 
 -         Class (const ValueTree& v)
 -         {
 -             className = v[Ids::name];
 -             instantiationFlags.isAbstract = v[Ids::abstract];
 -             instantiationFlags.inAnonymousNamespace = v[Ids::anonymous];
 -             instantiationFlags.noDefaultConstructor = v[Ids::noDefConstructor];
 - 
 -             classDeclaration = v [Ids::classDecl].toString();
 - 
 -             for (int i = 0; i < v.getNumChildren(); ++i)
 -                 members.add (MemberInfo (v.getChild(i)));
 -         }
 - 
 -         ValueTree toValueTree() const
 -         {
 -             ValueTree v (Ids::CLASS);
 -             v.setProperty (Ids::name, className, nullptr);
 -             v.setProperty (Ids::abstract, instantiationFlags.isAbstract, nullptr);
 -             v.setProperty (Ids::anonymous, instantiationFlags.inAnonymousNamespace, nullptr);
 -             v.setProperty (Ids::noDefConstructor, instantiationFlags.noDefaultConstructor, nullptr);
 -             classDeclaration.writeToValueTree (v, Ids::classDecl);
 - 
 -             for (const MemberInfo& m : members)
 -                 v.appendChild (m.toValueTree(), nullptr);
 - 
 -             return v;
 -         }
 - 
 -         bool operator== (const Class& other) const noexcept  { return className == other.className; }
 -         bool operator!= (const Class& other) const noexcept  { return ! operator== (other); }
 -         bool operator<  (const Class& other) const noexcept  { return className < other.className; }
 - 
 -         const Array<MemberInfo>& getMembers() const     { return members; }
 - 
 -     private:
 -         String className;
 -         Array<MemberInfo> members;
 -         Array<MethodInfo> methods;
 -         SourceCodeRange classDeclaration;
 -         InstantiationFlags instantiationFlags;
 - 
 -         JUCE_LEAK_DETECTOR (Class)
 -     };
 - 
 -     //==============================================================================
 -     struct Namespace
 -     {
 -         Namespace()  : name ("Global Namespace") {}
 -         Namespace (const String& n, const String& full)  : name (n), fullName (full) {}
 - 
 -         bool isEmpty() const noexcept
 -         {
 -             for (const auto& n : namespaces)
 -                 if (! n.isEmpty())
 -                     return false;
 - 
 -             return components.size() == 0;
 -         }
 - 
 -         int getTotalClassesAndNamespaces() const
 -         {
 -             int total = components.size();
 - 
 -             for (const auto& n : namespaces)
 -                 total += n.getTotalClassesAndNamespaces();
 - 
 -             return total;
 -         }
 - 
 -         void add (const Class& c, const String::CharPointerType& localName)
 -         {
 -             auto nextDoubleColon = CharacterFunctions::find (localName, CharPointer_ASCII ("::"));
 - 
 -             if (nextDoubleColon.isEmpty())
 -                 merge (c);
 -             else
 -                 getOrCreateNamespace (String (localName, nextDoubleColon))->add (c, nextDoubleColon + 2);
 -         }
 - 
 -         bool containsRecursively (const Class& c) const
 -         {
 -             if (components.contains (c))
 -                 return true;
 - 
 -             for (const auto& n : namespaces)
 -                 if (n.containsRecursively (c))
 -                     return true;
 - 
 -             return false;
 -         }
 - 
 -         const Class* findClass (const String& className) const
 -         {
 -             for (auto& c : components)
 -                 if (c.getName() == className)
 -                     return &c;
 - 
 -             for (auto& n : namespaces)
 -                 if (auto* c = n.findClass (className))
 -                     return c;
 - 
 -             return nullptr;
 -         }
 - 
 -         const MemberInfo* findClassMemberInfo (const String& className, const String& memberName) const
 -         {
 -             if (auto* classInfo = findClass (className))
 -                 return classInfo->findMember (memberName);
 - 
 -             return nullptr;
 -         }
 - 
 -         void findClassesDeclaredInFile (Array<Class*>& results, const File& file)
 -         {
 -             for (auto& c : components)
 -                 if (c.isDeclaredInFile (file))
 -                     results.add (&c);
 - 
 -             for (auto& n : namespaces)
 -                 n.findClassesDeclaredInFile (results, file);
 -         }
 - 
 -         void merge (const Namespace& other)
 -         {
 -             if (components.size() == 0)
 -             {
 -                 components = other.components;
 -             }
 -             else
 -             {
 -                 for (const auto& c : other.components)
 -                     merge (c);
 -             }
 - 
 -             for (const auto& n : other.namespaces)
 -                 getOrCreateNamespace (n.name)->merge (n);
 -         }
 - 
 -         void merge (const Class& c)
 -         {
 -             const int existing = components.indexOf (c);
 - 
 -             if (existing < 0)
 -                 components.add (c);
 -             else
 -                 components.getReference (existing).mergeWith (c);
 -         }
 - 
 -         Namespace* findNamespace (const String& targetName)
 -         {
 -             for (auto& n : namespaces)
 -                 if (n.name == targetName)
 -                     return &n;
 - 
 -             return nullptr;
 -         }
 - 
 -         Namespace* createNamespace (const String& newName)
 -         {
 -             namespaces.add (Namespace (newName, fullName + "::" + newName));
 -             return findNamespace (newName);
 -         }
 - 
 -         Namespace* getOrCreateNamespace (const String& newName)
 -         {
 -             if (Namespace* existing = findNamespace (newName))
 -                 return existing;
 - 
 -             return createNamespace (newName);
 -         }
 - 
 -         void addInstantiableClasses (SortedSet<Class>& classes) const
 -         {
 -             for (const auto& c : components)
 -                 if (c.getInstantiationFlags().canBeInstantiated())
 -                     classes.add (c);
 - 
 -             for (const auto& n : namespaces)
 -                 n.addInstantiableClasses (classes);
 -         }
 - 
 -         void swapWith (Namespace& other) noexcept
 -         {
 -             name.swapWith (other.name);
 -             components.swapWith (other.components);
 -             namespaces.swapWith (other.namespaces);
 -         }
 - 
 -         void nudgeAllCodeRanges (const String& file, int index, int delta)
 -         {
 -             for (auto& c : components)  c.nudgeAllCodeRanges (file, index, delta);
 -             for (auto& n : namespaces)  n.nudgeAllCodeRanges (file, index, delta);
 -         }
 - 
 -         void fileContentChanged (const String& file)
 -         {
 -             for (auto& c : components)  c.fileContentChanged (file);
 -             for (auto& n : namespaces)  n.fileContentChanged (file);
 -         }
 - 
 -         bool matches (const Namespace& other) const
 -         {
 -             if (name == other.name
 -                  && components == other.components
 -                  && namespaces.size() == other.namespaces.size())
 -             {
 -                 for (int i = namespaces.size(); --i >= 0;)
 -                     if (! namespaces.getReference (i).matches (other.namespaces.getReference(i)))
 -                         return false;
 - 
 -                 return true;
 -             }
 - 
 -             return false;
 -         }
 - 
 -         void getAllClassNames (StringArray& results, const InstantiationFlags& disallowedFlags) const
 -         {
 -             for (const auto& c : components)
 -                 if (c.getInstantiationFlags().isDisallowed (disallowedFlags))
 -                     results.add (c.getName());
 - 
 -             for (const auto& n : namespaces)
 -                 n.getAllClassNames (results, disallowedFlags);
 -         }
 - 
 -         ValueTree toValueTree() const
 -         {
 -             ValueTree v (Ids::CLASSLIST);
 - 
 -             v.setProperty (Ids::name, name, nullptr);
 - 
 -             for (const auto& c : components)    v.appendChild (c.toValueTree(), nullptr);
 -             for (const auto& n : namespaces)    v.appendChild (n.toValueTree(), nullptr);
 - 
 -             return v;
 -         }
 - 
 -         void loadFromValueTree (const ValueTree& v)
 -         {
 -             name = v[Ids::name];
 - 
 -             for (int i = 0; i < v.getNumChildren(); ++i)
 -             {
 -                 const ValueTree c (v.getChild(i));
 - 
 -                 if (c.hasType (Ids::CLASS))
 -                     components.add (Class (c));
 -                 else if (c.hasType (Ids::CLASSLIST))
 -                     createNamespace (c[Ids::name])->loadFromValueTree (c);
 -             }
 -         }
 - 
 -         bool operator== (const Namespace& other) const noexcept  { return name == other.name; }
 -         bool operator!= (const Namespace& other) const noexcept  { return ! operator== (other); }
 -         bool operator<  (const Namespace& other) const noexcept  { return name < other.name; }
 - 
 -         String name, fullName;
 -         SortedSet<Class> components;
 -         SortedSet<Namespace> namespaces;
 - 
 -         JUCE_LEAK_DETECTOR (Namespace)
 -     };
 - 
 -     struct ClassList
 -     {
 -         ClassList() {}
 - 
 -         void clear()
 -         {
 -             Namespace newNamespace;
 -             globalNamespace.swapWith (newNamespace);
 -         }
 - 
 -         void registerComp (const Class& comp)
 -         {
 -             globalNamespace.add (comp, comp.getName().getCharPointer());
 -         }
 - 
 -         void merge (const ClassList& other)
 -         {
 -             globalNamespace.merge (other.globalNamespace);
 -         }
 - 
 -         void swapWith (ClassList& other) noexcept
 -         {
 -             globalNamespace.swapWith (other.globalNamespace);
 -         }
 - 
 -         //==============================================================================
 -         ValueTree toValueTree() const
 -         {
 -             return globalNamespace.toValueTree();
 -         }
 - 
 -         static ClassList fromValueTree (const ValueTree& v)
 -         {
 -             ClassList l;
 -             l.globalNamespace.loadFromValueTree (v);
 -             return l;
 -         }
 - 
 -         Namespace globalNamespace;
 - 
 -         bool operator== (const ClassList& other) const noexcept  { return globalNamespace.matches (other.globalNamespace); }
 -         bool operator!= (const ClassList& other) const noexcept  { return ! operator== (other); }
 - 
 -     private:
 -         JUCE_LEAK_DETECTOR (ClassList)
 -     };
 - };
 
 
  |