/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.netbeans.modules.php.editor.elements;

import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.netbeans.modules.parsing.spi.indexing.support.IndexResult;
import org.netbeans.modules.parsing.spi.indexing.support.QuerySupport;
import org.netbeans.modules.parsing.spi.indexing.support.QuerySupport.Kind;
import org.netbeans.modules.php.api.editor.PhpBaseElement;
import org.netbeans.modules.php.api.editor.PhpClass;
import org.netbeans.modules.php.api.editor.PhpType;
import org.netbeans.modules.php.api.editor.PhpVariable;
import org.netbeans.modules.php.editor.api.AbstractElementQuery;
import org.netbeans.modules.php.editor.api.AliasedName;
import org.netbeans.modules.php.editor.api.ElementQuery;
import org.netbeans.modules.php.editor.api.NameKind;
import org.netbeans.modules.php.editor.api.NameKind.Exact;
import org.netbeans.modules.php.editor.api.PhpElementKind;
import org.netbeans.modules.php.editor.api.QualifiedName;
import org.netbeans.modules.php.editor.api.elements.AliasedClass;
import org.netbeans.modules.php.editor.api.elements.AliasedConstant;
import org.netbeans.modules.php.editor.api.elements.AliasedElement;
import org.netbeans.modules.php.editor.api.elements.AliasedElement.Trait;
import org.netbeans.modules.php.editor.api.elements.AliasedFunction;
import org.netbeans.modules.php.editor.api.elements.AliasedInterface;
import org.netbeans.modules.php.editor.api.elements.AliasedNamespace;
import org.netbeans.modules.php.editor.api.elements.AliasedTrait;
import org.netbeans.modules.php.editor.api.elements.AliasedType;
import org.netbeans.modules.php.editor.api.elements.ClassElement;
import org.netbeans.modules.php.editor.api.elements.ConstantElement;
import org.netbeans.modules.php.editor.api.elements.ElementFilter;
import org.netbeans.modules.php.editor.api.elements.FieldElement;
import org.netbeans.modules.php.editor.api.elements.FunctionElement;
import org.netbeans.modules.php.editor.api.elements.InterfaceElement;
import org.netbeans.modules.php.editor.api.elements.MethodElement;
import org.netbeans.modules.php.editor.api.elements.NamespaceElement;
import org.netbeans.modules.php.editor.api.elements.PhpElement;
import org.netbeans.modules.php.editor.api.elements.TraitElement;
import org.netbeans.modules.php.editor.api.elements.TraitedElement;
import org.netbeans.modules.php.editor.api.elements.TreeElement;
import org.netbeans.modules.php.editor.api.elements.TypeConstantElement;
import org.netbeans.modules.php.editor.api.elements.TypeElement;
import org.netbeans.modules.php.editor.api.elements.TypeMemberElement;
import org.netbeans.modules.php.editor.api.elements.VariableElement;
import org.netbeans.modules.php.editor.index.PHPIndexer;
import org.netbeans.modules.php.editor.index.Signature;
import org.netbeans.modules.php.editor.model.Model;
import org.netbeans.modules.php.editor.model.ModelUtils;
import org.netbeans.modules.php.editor.model.NamespaceScope;
import org.netbeans.modules.php.editor.model.UseScope;
import org.netbeans.modules.php.editor.parser.PHPParseResult;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.filesystems.URLMapper;
import org.openide.util.Exceptions;
import org.openide.util.Utilities;

/**
 * @author Radek Matous
 */
public final class IndexQueryImpl implements ElementQuery.Index {

    public static final String FIELD_TOP_LEVEL = PHPIndexer.FIELD_TOP_LEVEL;
    private static final Logger LOG = Logger.getLogger(IndexQueryImpl.class.getName());
    private static Collection<NamespaceElement> namespacesCache = null;
    private final QuerySupport index;
    private final Set<AliasedName> aliases = new HashSet<>();
    private final AbstractElementQuery extendedQuery = new AbstractElementQuery(QueryScope.VIRTUAL_SCOPE);


    private IndexQueryImpl(QuerySupport index, final Model model) {
        this.index = index;
        if (model != null) {
            init(model);
        }
    }

    private void init(final Model model) {
        initExtendedQuery(model);
        initAliases(model);
    }

    /**
     * Intended to be used for fake additions of aliases that are returned
     * as if they were in index
     */
    private void initAliases(final Model model) {
        for (final NamespaceScope namespaceScope : model.getFileScope().getDeclaredNamespaces()) {
            if (namespaceScope != null) {
                for (UseScope useElement : namespaceScope.getAllDeclaredSingleUses()) {
                    AliasedName aliasedName = useElement.getAliasedName();
                    if (aliasedName != null) {
                        aliases.add(aliasedName);
                    }
                }
            }
        }
    }

    /**
     * Intended to be used for fake additions of frameworks that are returned
     * as if they were in index
     */
    private void initExtendedQuery(final Model model) {
        //TODO: the best approach would be the frameworks returned ElementQuery instance
        //and get rid of PhpBaseElement and its subclasses
        List<PhpBaseElement> extendedElements = model.getExtendedElements();
        for (PhpBaseElement phpBaseElement : extendedElements) {
            if (phpBaseElement instanceof PhpVariable) {
                PhpVariable variable = (PhpVariable) phpBaseElement;
                extendedQuery.addElement(VariableElementImpl.fromFrameworks(variable, extendedQuery));
                final PhpType type = variable.getType();
                if (type instanceof PhpClass) {
                    final ClassElement classElement = ClassElementImpl.fromFrameworks((PhpClass) type, extendedQuery);
                    extendedQuery.addElement(classElement);
                    for (final PhpType.Field field : type.getFields()) {
                        final FieldElement fieldElement = FieldElementImpl.fromFrameworks(classElement, field, extendedQuery);
                        extendedQuery.addElement(fieldElement);
                    }
                }
            }
        }
    }
    private IndexQueryImpl(QuerySupport index) {
        this(index, null);
    }

    public static Index create(final QuerySupport querySupport) {
        return new IndexQueryImpl(querySupport);
    }
    public static Index create(final QuerySupport querySupport, final Model model) {
        return new IndexQueryImpl(querySupport, model);
    }
    public static Index getModelInstance(final PHPParseResult parseResult) {
        return parseResult.getModel().getIndexScope().getIndex();
    }
    public static void clearNamespaceCache() {
        synchronized (IndexQueryImpl.class) {
            namespacesCache = null;
        }
    }

    private Set<ClassElement> getClassesImpl(final NameKind query) {
        final long start = (LOG.isLoggable(Level.FINE)) ? System.currentTimeMillis() : 0;
        final Set<ClassElement> classes = new HashSet<>();
        final Collection<? extends IndexResult> result = results(ClassElementImpl.IDX_FIELD, query);
        for (final IndexResult indexResult : result) {
            Set<ClassElement> allClasses = ClassElementImpl.fromSignature(query, this, indexResult);
            if (query.isPrefix() || query.isCaseInsensitivePrefix()) {
                classes.addAll(allClasses);
            } else {
                for (ClassElement classElement : allClasses) {
                    if (query.getQuery().getNamespaceName().equals(classElement.getNamespaceName().toString())) {
                        classes.add(classElement);
                    }
                }
            }
        }
        if (LOG.isLoggable(Level.FINE)) {
            logQueryTime("Set<ClassElement> getClasses", query, start); //NOI18N
        }
        return Collections.unmodifiableSet(classes);
    }



    private Set<InterfaceElement> getInterfacesImpl(final NameKind query) {
        final long start = (LOG.isLoggable(Level.FINE)) ? System.currentTimeMillis() : 0;
        final Set<InterfaceElement> ifaces = new HashSet<>();
        final Collection<? extends IndexResult> result = results(InterfaceElementImpl.IDX_FIELD, query);
        for (final IndexResult indexResult : result) {
            ifaces.addAll(InterfaceElementImpl.fromSignature(query, this, indexResult));
        }
        if (LOG.isLoggable(Level.FINE)) {
            logQueryTime("Set<InterfaceElement> getInterfaces", query, start); //NOI18N
        }
        return Collections.unmodifiableSet(ifaces);
    }

    private Set<TraitElement> getTraitsImpl(final NameKind query) {
        final long start = (LOG.isLoggable(Level.FINE)) ? System.currentTimeMillis() : 0;
        final Set<TraitElement> traits = new HashSet<>();
        final Collection<? extends IndexResult> result = results(TraitElementImpl.IDX_FIELD, query);
        for (final IndexResult indexResult : result) {
            traits.addAll(TraitElementImpl.fromSignature(query, this, indexResult));
        }
        if (LOG.isLoggable(Level.FINE)) {
            logQueryTime("Set<TraitElement> getTraits", query, start); //NOI18N
        }
        return Collections.unmodifiableSet(traits);
    }

    private static Set<NameKind> queriesForAlias(final NameKind query, final AliasedName aliasedName, final PhpElementKind elementKind) {
        final Set<NameKind> aliasQueries = new HashSet<>();
        final boolean fullyQualified = query.getQuery().getKind().isFullyQualified();
        final Kind queryKind = query.getQueryKind();
        final LinkedList<String> segments = query.getQuery().getSegments();
        for (int i = 0; i < segments.size(); i++) {
            final String nextSegment = segments.get(i);
            if (!nextSegment.isEmpty() && (i == 0 || (i == segments.size() - 1)) && (!nextSegment.isEmpty() || segments.size() == 1)
                    && NameKind.create(nextSegment, queryKind).matchesName(elementKind, aliasedName.getAliasName())) {
                final LinkedList<String> nSegments = new LinkedList<>();
                nSegments.addAll(segments.subList(0, i));
                nSegments.addAll(aliasedName.getRealName().getSegments());
                if (i + 1 < segments.size()) {
                    nSegments.addAll(segments.subList(i + 1, segments.size()));
                }
                aliasQueries.add(NameKind.create(QualifiedName.create(fullyQualified, nSegments), queryKind));
            }
        }
        return aliasQueries;
    }

    private Set<TypeElement> getTypesImpl(NameKind query) {
        final Set<TypeElement> types = new HashSet<>();
        types.addAll(getClassesImpl(query));
        types.addAll(getInterfacesImpl(query));
        types.addAll(getTraitsImpl(query));
        return types;
    }


    @Override
    public Set<MethodElement> getAccessibleMagicMethods(final TypeElement type) {
        return MethodElementImpl.getMagicMethods(type);
    }

    @Override
    public Set<TypeConstantElement> getAccessibleMagicConstants(TypeElement type) {
        return TypeConstantElementImpl.getMagicConstants(type);
    }

    private Set<FunctionElement> getFunctionsImpl(final NameKind query) {
        final long start = (LOG.isLoggable(Level.FINE)) ? System.currentTimeMillis() : 0;
        final Set<FunctionElement> functions = new HashSet<>();
        final Collection<? extends IndexResult> result = results(FunctionElementImpl.IDX_FIELD, query);
        for (final IndexResult indexResult : result) {
            functions.addAll(FunctionElementImpl.fromSignature(query, this, indexResult));
        }
        if (LOG.isLoggable(Level.FINE)) {
            logQueryTime("Set<FunctionElement> getFunctions", query, start); //NOI18N
        }
        return Collections.unmodifiableSet(functions);
    }

    private Set<NamespaceElement> getNamespacesImpl(final NameKind query) {
        final Set<NamespaceElement> retval = new HashSet<>();
        synchronized (IndexQueryImpl.class) {
            if (namespacesCache == null) {
                final Map<String, NamespaceElement> namespacesMap = new LinkedHashMap<>();
                for (final NamespaceElement namespace : namespacesImpl(NameKind.empty())) {
                    NamespaceElement original = null;
                    QualifiedName qn = namespace.getFullyQualifiedName();
                    while (original == null && !qn.isDefaultNamespace()) {
                        original = namespacesMap.put(
                                qn.toFullyQualified().toString().toLowerCase(),
                                new NamespaceElementImpl(
                                        qn,
                                        namespace.getOffset(),
                                        namespace.getFilenameUrl(),
                                        namespace.getElementQuery(),
                                        namespace.isDeprecated()));
                        qn = qn.toNamespaceName();
                    }
                }
                namespacesCache = namespacesMap.values();
            }
        }
        for (final NamespaceElement indexedNamespace : namespacesCache) {
            if (query.matchesName(indexedNamespace)) {
                retval.add(indexedNamespace);
            }
        }
        return retval;
    }

    private Set<NamespaceElement> namespacesImpl(NameKind query) {
        final long start = (LOG.isLoggable(Level.FINE)) ? System.currentTimeMillis() : 0;
        //TODO: not cached yet
        final Set<NamespaceElement> namespaces = new HashSet<>();
        final Collection<? extends IndexResult> result = results(NamespaceElementImpl.IDX_FIELD, query);
        for (final IndexResult indexResult : result) {
            namespaces.addAll(NamespaceElementImpl.fromSignature(query, this, indexResult));
        }
        if (LOG.isLoggable(Level.FINE)) {
            logQueryTime("Set<NamespaceElement> getNamespaces", query, start); //NOI18N
        }
        return Collections.unmodifiableSet(namespaces);
    }


    private Set<ConstantElement> getConstantsImpl(final NameKind query) {
        final long start = (LOG.isLoggable(Level.FINE)) ? System.currentTimeMillis() : 0;
        final Set<ConstantElement> constants = new HashSet<>();
        final Collection<? extends IndexResult> result = results(ConstantElementImpl.IDX_FIELD, query);
        for (final IndexResult indexResult : result) {
            constants.addAll(ConstantElementImpl.fromSignature(query, this, indexResult));
        }
        if (LOG.isLoggable(Level.FINE)) {
            logQueryTime("Set<ConstantElement> getConstants", query, start); //NOI18N
        }
        return Collections.unmodifiableSet(constants);
    }

    private Set<PhpElement> getTopLevelElementsImpl(NameKind query) {
        final boolean isVariable = query.getQueryName().startsWith(VariableElementImpl.DOLLAR_PREFIX);
        final String[] fieldsToLoad = isVariable
                ? new String[] {
                    PHPIndexer.FIELD_VAR
                }
                : new String[] {
                    PHPIndexer.FIELD_BASE,
                    PHPIndexer.FIELD_CONST,
                    PHPIndexer.FIELD_CLASS,
                    PHPIndexer.FIELD_IFACE,
                    PHPIndexer.FIELD_NAMESPACE,
                    PHPIndexer.FIELD_TRAIT
                };
        final long start = (LOG.isLoggable(Level.FINE)) ? System.currentTimeMillis() : 0;
        final Set<PhpElement> elements = new HashSet<>();
        final Collection<? extends IndexResult> result = results(FIELD_TOP_LEVEL, query, fieldsToLoad);
        for (final IndexResult indexResult : result) {
            if (isVariable) {
                elements.addAll(VariableElementImpl.fromSignature(query, this, indexResult));
            } else {
                elements.addAll(ClassElementImpl.fromSignature(query, this, indexResult));
                elements.addAll(InterfaceElementImpl.fromSignature(query, this, indexResult));
                elements.addAll(FunctionElementImpl.fromSignature(query, this, indexResult));
                elements.addAll(ConstantElementImpl.fromSignature(query, this, indexResult));
                elements.addAll(TraitElementImpl.fromSignature(query, this, indexResult));
            }
        }
        if (isVariable) {
            elements.addAll(extendedQuery.getTopLevelVariables(query));
        }
        if (LOG.isLoggable(Level.FINE)) {
            logQueryTime("Set<PhpElement> getTopLevelElements", query, start); //NOI18N
        }
        return Collections.unmodifiableSet(elements);
    }

    @Override
    public Set<VariableElement> getTopLevelVariables(final NameKind query) {
        final long start = (LOG.isLoggable(Level.FINE)) ? System.currentTimeMillis() : 0;
        final Set<VariableElement> vars = new HashSet<>();
        final Collection<? extends IndexResult> result = results(VariableElementImpl.IDX_FIELD, query);
        for (final IndexResult indexResult : result) {
            vars.addAll(VariableElementImpl.fromSignature(query, this, indexResult));
        }
        vars.addAll(extendedQuery.getTopLevelVariables(query));
        if (LOG.isLoggable(Level.FINE)) {
            logQueryTime("Set<VariableElement> getTopLevelVariables", query, start); //NOI18N
        }
        return Collections.unmodifiableSet(vars);
    }


    @Override
    public Set<MethodElement> getConstructors(final ClassElement classElement) {
        final long start = (LOG.isLoggable(Level.FINE)) ? System.currentTimeMillis() : 0;
        final Set<MethodElement> retval = getConstructorsImpl(classElement, classElement, new LinkedHashSet<ClassElement>());
        if (LOG.isLoggable(Level.FINE)) {
            logQueryTime("Set<MethodElement> getConstructors", NameKind.exact(classElement.getFullyQualifiedName()), start); //NOI18N
        }
        return retval.isEmpty() ? getDefaultConstructors(classElement) : retval;
    }

    private Set<MethodElement> getConstructorsImpl(NameKind typeQuery) {
        final Set<MethodElement> retval = new HashSet<>();
        final Set<ClassElement> classes = getClassesImpl(typeQuery);
        for (ClassElement classElement : classes) {
            retval.addAll(getConstructors(classElement));
        }
        return retval;
    }

    private Set<MethodElement> getConstructorsImpl(final ClassElement originalClass, final ClassElement inheritedClass, final Set<ClassElement> check) {
        final Set<MethodElement> methods = new HashSet<>();
        if (!check.contains(inheritedClass)) {
            check.add(inheritedClass);
            final Exact typeQuery = NameKind.exact(inheritedClass.getFullyQualifiedName());
            final Collection<? extends IndexResult> constructorResults = results(ClassElementImpl.IDX_FIELD, typeQuery,
                    new String[]{ClassElementImpl.IDX_FIELD, MethodElementImpl.IDX_CONSTRUCTOR_FIELD, MethodElementImpl.IDX_FIELD});
            final Set<MethodElement> methodsForResult = new HashSet<>();
            final ElementFilter forEqualTypes = ElementFilter.forEqualTypes(inheritedClass);
            for (final IndexResult indexResult : constructorResults) {
                Set<ClassElement> classes = ClassElementImpl.fromSignature(this, indexResult);
                for (ClassElement classElement : classes) {
                    if (forEqualTypes.isAccepted(classElement)) {
                        methodsForResult.addAll(MethodElementImpl.fromSignature(originalClass, this, indexResult));
                    }
                }
            }
            methods.addAll(ElementFilter.forConstructor().filter(methodsForResult));
            if (methods.isEmpty()) {
                for (TypeElement typeElement : getDirectInheritedTypes(inheritedClass, true, false)) {
                    if (typeElement instanceof ClassElement) {
                        methods.addAll(getConstructorsImpl(originalClass, (ClassElement) typeElement, check));
                        if (!methods.isEmpty()) {
                            break;
                        }
                    }
                }
            }
        }
        return Collections.unmodifiableSet(methods);
    }

    private Set<MethodElement> getDefaultConstructors(final ClassElement classElement) {
        Set<MethodElement> magicMethods = getAccessibleMagicMethods(classElement);
        for (MethodElement methodElement : magicMethods) {
            if (methodElement.isConstructor()) {
                return Collections.singleton(methodElement);
            }
        }
        throw new IllegalStateException();
    }


    @Override
    public Set<MethodElement> getMethods(final NameKind methodQuery) {
        final long start = (LOG.isLoggable(Level.FINE)) ? System.currentTimeMillis() : 0;
        final Set<MethodElement> methods = new HashSet<>();
        final Collection<? extends IndexResult> methResults = results(MethodElementImpl.IDX_FIELD, methodQuery,
                new String[]{ClassElementImpl.IDX_FIELD, InterfaceElementImpl.IDX_FIELD, TraitElementImpl.IDX_FIELD, MethodElementImpl.IDX_FIELD});
        for (final IndexResult indexResult : methResults) {
            final Set<TypeElement> types = new HashSet<>();
            types.addAll(ClassElementImpl.fromSignature(this, indexResult));
            types.addAll(InterfaceElementImpl.fromSignature(this, indexResult));
            types.addAll(TraitElementImpl.fromSignature(this, indexResult));
            for (final TypeElement typeElement : types) {
                methods.addAll(MethodElementImpl.fromSignature(typeElement, methodQuery, this, indexResult));
            }
        }
        if (LOG.isLoggable(Level.FINE)) {
            logQueryTime("Set<MethodElement> getMethods", methodQuery, start); //NOI18N
        }
        return Collections.unmodifiableSet(methods);
    }

    @Override
    public Set<TypeMemberElement> getDeclaredTypeMembers(TypeElement typeElement) {
        final long start = (LOG.isLoggable(Level.FINE)) ? System.currentTimeMillis() : 0;
        final QualifiedName fullyQualifiedName = typeElement.getFullyQualifiedName();
        final Set<TypeMemberElement> members = new HashSet<>();
        final NameKind.Exact typeQuery = NameKind.exact(fullyQualifiedName);
        final NameKind memberQuery = NameKind.empty();
        final FileObject typeFo = typeElement.getFileObject();

        switch (typeElement.getPhpElementKind()) {
            case CLASS:
                final Collection<? extends IndexResult> clzResults = results(ClassElementImpl.IDX_FIELD, typeQuery,
                        new String[]{
                            ClassElementImpl.IDX_FIELD,
                            FieldElementImpl.IDX_FIELD,
                            TypeConstantElementImpl.IDX_FIELD,
                            MethodElementImpl.IDX_FIELD
                        });
                for (final IndexResult indexResult : clzResults) {
                    for (final TypeElement clzElement : ClassElementImpl.fromSignature(typeQuery, this, indexResult)) {
                        if (fullyQualifiedName.getNamespaceName().equals(clzElement.getNamespaceName().toString())) {
                            members.addAll(MethodElementImpl.fromSignature(clzElement, memberQuery, this, indexResult));
                            members.addAll(FieldElementImpl.fromSignature(clzElement, memberQuery, this, indexResult));
                            members.addAll(TypeConstantElementImpl.fromSignature(clzElement, memberQuery, this, indexResult));
                        }
                    }
                }
                break;
            case IFACE:
                final Collection<? extends IndexResult> ifaceResults = results(InterfaceElementImpl.IDX_FIELD, typeQuery,
                        new String[]{
                            InterfaceElementImpl.IDX_FIELD,
                            TypeConstantElementImpl.IDX_FIELD,
                            MethodElementImpl.IDX_FIELD
                        });
                for (final IndexResult indexResult : ifaceResults) {
                    for (final TypeElement ifaceElement : InterfaceElementImpl.fromSignature(typeQuery, this, indexResult)) {
                        members.addAll(MethodElementImpl.fromSignature(ifaceElement, memberQuery, this, indexResult));
                        members.addAll(TypeConstantElementImpl.fromSignature(ifaceElement, memberQuery, this, indexResult));
                    }
                }
                break;
            case TRAIT:
                final Collection<? extends IndexResult> traitResults = results(TraitElementImpl.IDX_FIELD, typeQuery,
                        new String[]{
                            TraitElementImpl.IDX_FIELD,
                            FieldElementImpl.IDX_FIELD,
                            MethodElementImpl.IDX_FIELD
                        });
                for (final IndexResult indexResult : traitResults) {
                    for (final TypeElement traitElement : TraitElementImpl.fromSignature(typeQuery, this, indexResult)) {
                        members.addAll(MethodElementImpl.fromSignature(traitElement, memberQuery, this, indexResult));
                        members.addAll(FieldElementImpl.fromSignature(traitElement, memberQuery, this, indexResult));
                    }
                }
                break;
            default:
                assert false : typeElement.getPhpElementKind();
        }
        if (LOG.isLoggable(Level.FINE)) {
            logQueryTime("Set<PhpElement> getTypeMembers", typeQuery, memberQuery, start); //NOI18N
        }
        final Set<TypeMemberElement> retval = new HashSet<>();
        final Exact exactTypeName = NameKind.exact(typeElement.getFullyQualifiedName());
        retval.addAll(extendedQuery.getFields(exactTypeName, NameKind.empty()));
        retval.addAll(extendedQuery.getMethods(exactTypeName, NameKind.empty()));
        retval.addAll(extendedQuery.getTypeConstants(exactTypeName, NameKind.empty()));
        retval.addAll(ElementFilter.forFiles(typeFo).filter(members));
        return retval;
    }

    @Override
    public Set<MethodElement> getDeclaredConstructors(ClassElement typeElement) {
        return ElementFilter.forName(NameKind.exact(MethodElementImpl.CONSTRUCTOR_NAME)).
                filter(getDeclaredMethods(typeElement));
    }


    @Override
    public Set<MethodElement> getDeclaredMethods(final TypeElement typeElement) {
        final long start = (LOG.isLoggable(Level.FINE)) ? System.currentTimeMillis() : 0;
        final QualifiedName fullyQualifiedName = typeElement.getFullyQualifiedName();
        final Set<MethodElement> methods = new HashSet<>();
        final NameKind.Exact typeQuery = NameKind.exact(fullyQualifiedName);
        final NameKind methodQuery = NameKind.empty();
        final FileObject typeFo = typeElement.getFileObject();

        switch (typeElement.getPhpElementKind()) {
            case CLASS:
                final Collection<? extends IndexResult> clzResults = results(ClassElementImpl.IDX_FIELD, typeQuery,
                        new String[]{ClassElementImpl.IDX_FIELD, MethodElementImpl.IDX_FIELD});
                for (final IndexResult indexResult : clzResults) {
                    for (final TypeElement clzElement : ClassElementImpl.fromSignature(typeQuery, this, indexResult)) {
                        methods.addAll(MethodElementImpl.fromSignature(clzElement, methodQuery, this, indexResult));
                    }
                }
                break;
            case IFACE:
                final Collection<? extends IndexResult> ifaceResults = results(InterfaceElementImpl.IDX_FIELD, typeQuery,
                        new String[]{InterfaceElementImpl.IDX_FIELD, MethodElementImpl.IDX_FIELD});
                for (final IndexResult indexResult : ifaceResults) {
                    for (final TypeElement ifaceElement : InterfaceElementImpl.fromSignature(typeQuery, this, indexResult)) {
                        methods.addAll(MethodElementImpl.fromSignature(ifaceElement, methodQuery, this, indexResult));
                    }
                }
                break;
            case TRAIT:
                final Collection<? extends IndexResult> traitResults = results(TraitElementImpl.IDX_FIELD, typeQuery,
                        new String[]{TraitElementImpl.IDX_FIELD, MethodElementImpl.IDX_FIELD});
                for (final IndexResult indexResult : traitResults) {
                    for (final TypeElement traitElement : TraitElementImpl.fromSignature(typeQuery, this, indexResult)) {
                        methods.addAll(MethodElementImpl.fromSignature(traitElement, methodQuery, this, indexResult));
                    }
                }
                break;
            default:
                assert false : typeElement.getPhpElementKind();
        }
        if (LOG.isLoggable(Level.FINE)) {
            logQueryTime("Set<MethodElement> getMethods", typeQuery, methodQuery, start); //NOI18N
        }
        return ElementFilter.forFiles(typeFo).filter(methods);
    }

    @Override
    public Set<TypeMemberElement> getTypeMembers(final NameKind.Exact typeQuery, final NameKind memberQuery) {
        final long start = (LOG.isLoggable(Level.FINE)) ? System.currentTimeMillis() : 0;
        final Set<TypeMemberElement> members = new HashSet<>();
        //two queries: once for classes, second for ifaces
        final Collection<? extends IndexResult> clzResults = results(ClassElementImpl.IDX_FIELD, typeQuery,
                new String[]{
                    ClassElementImpl.IDX_FIELD,
                    MethodElementImpl.IDX_FIELD,
                    FieldElementImpl.IDX_FIELD,
                    TypeConstantElementImpl.IDX_FIELD
                });
        for (final IndexResult indexResult : clzResults) {
            for (final TypeElement typeElement : ClassElementImpl.fromSignature(typeQuery, this, indexResult)) {
                members.addAll(MethodElementImpl.fromSignature(typeElement, memberQuery, this, indexResult));
                members.addAll(FieldElementImpl.fromSignature(typeElement, memberQuery, this, indexResult));
                members.addAll(TypeConstantElementImpl.fromSignature(typeElement, memberQuery, this, indexResult));
            }
        }
        final Collection<? extends IndexResult> ifaceResults = results(InterfaceElementImpl.IDX_FIELD, typeQuery,
                new String[]{
                    InterfaceElementImpl.IDX_FIELD,
                    MethodElementImpl.IDX_FIELD,
                    TypeConstantElementImpl.IDX_FIELD
                });

        for (final IndexResult indexResult : ifaceResults) {
            for (final TypeElement typeElement : InterfaceElementImpl.fromSignature(typeQuery, this, indexResult)) {
                members.addAll(MethodElementImpl.fromSignature(typeElement, memberQuery, this, indexResult));
                members.addAll(TypeConstantElementImpl.fromSignature(typeElement, memberQuery, this, indexResult));
            }
        }
        final Collection<? extends IndexResult> traitResults = results(TraitElementImpl.IDX_FIELD, typeQuery,
                new String[] {
                    TraitElementImpl.IDX_FIELD,
                    MethodElementImpl.IDX_FIELD,
                    FieldElementImpl.IDX_FIELD
                });
        for (IndexResult indexResult : traitResults) {
            for (final TypeElement typeElement : TraitElementImpl.fromSignature(typeQuery, this, indexResult)) {
                members.addAll(MethodElementImpl.fromSignature(typeElement, memberQuery, this, indexResult));
                members.addAll(FieldElementImpl.fromSignature(typeElement, memberQuery, this, indexResult));
            }
        }
        if (LOG.isLoggable(Level.FINE)) {
            logQueryTime("Set<PhpElement> getTypeMembers", typeQuery, memberQuery, start); //NOI18N
        }
        return Collections.unmodifiableSet(members);
    }

    @Override
    public Set<MethodElement> getMethods(final NameKind.Exact typeQuery, final NameKind methodQuery) {
        return getMethodsImpl(typeQuery, methodQuery, EnumSet.of(PhpElementKind.CLASS, PhpElementKind.IFACE, PhpElementKind.TRAIT));
    }

    private Set<MethodElement> getMethodsImpl(final NameKind.Exact typeQuery, final NameKind methodQuery, EnumSet<PhpElementKind> typeKinds) {
        final long start = (LOG.isLoggable(Level.FINE)) ? System.currentTimeMillis() : 0;
        final Set<MethodElement> methods = new HashSet<>();
        //two queries: once for classes, second for ifaces
        if (typeKinds.contains(PhpElementKind.CLASS)) {
            final Collection<? extends IndexResult> clzResults = results(ClassElementImpl.IDX_FIELD, typeQuery,
                    new String[]{ClassElementImpl.IDX_FIELD, MethodElementImpl.IDX_FIELD});
            for (final IndexResult indexResult : clzResults) {
                for (final TypeElement typeElement : ClassElementImpl.fromSignature(typeQuery, this, indexResult)) {
                    methods.addAll(MethodElementImpl.fromSignature(typeElement, methodQuery, this, indexResult));
                }
            }
        }
        if (typeKinds.contains(PhpElementKind.IFACE)) {
            final Collection<? extends IndexResult> ifaceResults = results(InterfaceElementImpl.IDX_FIELD, typeQuery,
                    new String[]{InterfaceElementImpl.IDX_FIELD, MethodElementImpl.IDX_FIELD});
            for (final IndexResult indexResult : ifaceResults) {
                for (final TypeElement typeElement : InterfaceElementImpl.fromSignature(typeQuery, this, indexResult)) {
                    methods.addAll(MethodElementImpl.fromSignature(typeElement, methodQuery, this, indexResult));
                }
            }
        }
        if (typeKinds.contains(PhpElementKind.TRAIT)) {
            final Collection<? extends IndexResult> traitResults = results(TraitElementImpl.IDX_FIELD, typeQuery,
                    new String[]{TraitElementImpl.IDX_FIELD, MethodElementImpl.IDX_FIELD});
            for (final IndexResult indexResult : traitResults) {
                for (final TypeElement typeElement : TraitElementImpl.fromSignature(typeQuery, this, indexResult)) {
                    methods.addAll(MethodElementImpl.fromSignature(typeElement, methodQuery, this, indexResult));
                }
            }
        }
        if (LOG.isLoggable(Level.FINE)) {
            logQueryTime("Set<MethodElement> getMethods", typeQuery, methodQuery, start); //NOI18N
        }
        return Collections.unmodifiableSet(methods);
    }

    @Override
    public Set<FileObject> getLocationsForIdentifiers(String identifierName) {
        final Set<FileObject> result = new HashSet<>();

        Collection<? extends IndexResult> idIndexResult = search(
                PHPIndexer.FIELD_IDENTIFIER,
                identifierName.toLowerCase(),
                QuerySupport.Kind.PREFIX,
                PHPIndexer.FIELD_BASE,
                PHPIndexer.FIELD_IDENTIFIER);
        for (IndexResult indexResult : idIndexResult) {
            String[] values = indexResult.getValues(PHPIndexer.FIELD_IDENTIFIER);
            for (String val : values) {
                Signature sig = Signature.get(val);

                if (identifierName.equalsIgnoreCase(sig.string(0))) {
                    URL url = indexResult.getUrl();
                    FileObject fo = null;
                    try {
                        fo = "file".equals(url.getProtocol()) ? //NOI18N
                                FileUtil.toFileObject(Utilities.toFile(url.toURI())) : URLMapper.findFileObject(url);
                    } catch (URISyntaxException ex) {
                        Exceptions.printStackTrace(ex);
                    }
                    if (fo != null) {
                        result.add(fo);
                    }
                }
            }
        }
        return result;
    }

    @Override
    public Set<FieldElement> getDeclaredFields(TypeElement typeElement) {
        final Set<FieldElement> retval = new HashSet<>();
        final Exact typeNameQuery = NameKind.exact(typeElement.getFullyQualifiedName());
        retval.addAll(ElementFilter.forFiles(typeElement.getFileObject())
                .filter(getFields(typeNameQuery, NameKind.empty())));
        retval.addAll(extendedQuery.getFields(typeNameQuery, NameKind.empty()));
        return retval;
    }

    @Override
    public Set<FieldElement> getFields(final NameKind fieldQuery) {
        final long start = (LOG.isLoggable(Level.FINE)) ? System.currentTimeMillis() : 0;
        final Set<FieldElement> fields = new HashSet<>();
        final Collection<? extends IndexResult> classFieldResults = results(FieldElementImpl.IDX_FIELD, fieldQuery,
                new String[]{ClassElementImpl.IDX_FIELD, FieldElementImpl.IDX_FIELD});
        for (final IndexResult indexResult : classFieldResults) {
            for (final TypeElement typeElement : ClassElementImpl.fromSignature(this, indexResult)) {
                fields.addAll(FieldElementImpl.fromSignature(typeElement, fieldQuery, this, indexResult));
            }
        }
        final Collection<? extends IndexResult> traitFieldResults = results(FieldElementImpl.IDX_FIELD, fieldQuery,
                new String[]{TraitElementImpl.IDX_FIELD, FieldElementImpl.IDX_FIELD});
        for (final IndexResult indexResult : traitFieldResults) {
            for (final TypeElement typeElement : TraitElementImpl.fromSignature(this, indexResult)) {
                fields.addAll(FieldElementImpl.fromSignature(typeElement, fieldQuery, this, indexResult));
            }
        }
        fields.addAll(extendedQuery.getFields(fieldQuery));
        if (LOG.isLoggable(Level.FINE)) {
            logQueryTime("Set<FieldElement> getFields", fieldQuery, start); //NOI18N
        }
        return Collections.unmodifiableSet(fields);
    }

    @Override
    public Set<FieldElement> getFields(final NameKind.Exact classQuery, final NameKind fieldQuery) {
        final long start = (LOG.isLoggable(Level.FINE)) ? System.currentTimeMillis() : 0;
        final Set<FieldElement> fields = new HashSet<>();
        final Collection<? extends IndexResult> clzResults = results(ClassElementImpl.IDX_FIELD, classQuery,
                new String[]{ClassElementImpl.IDX_FIELD, FieldElementImpl.IDX_FIELD});
        for (final IndexResult indexResult : clzResults) {
            for (final TypeElement typeElement : ClassElementImpl.fromSignature(classQuery, this, indexResult)) {
                fields.addAll(FieldElementImpl.fromSignature(typeElement, fieldQuery, this, indexResult));
            }
        }
        final Collection<? extends IndexResult> traitResults = results(TraitElementImpl.IDX_FIELD, classQuery,
                new String[]{TraitElementImpl.IDX_FIELD, FieldElementImpl.IDX_FIELD});
        for (final IndexResult indexResult : traitResults) {
            for (final TypeElement typeElement : TraitElementImpl.fromSignature(classQuery, this, indexResult)) {
                fields.addAll(FieldElementImpl.fromSignature(typeElement, fieldQuery, this, indexResult));
            }
        }
        fields.addAll(extendedQuery.getFields(classQuery, fieldQuery));
        if (LOG.isLoggable(Level.FINE)) {
            logQueryTime("Set<FieldElement> getFields", classQuery, fieldQuery, start); //NOI18N
        }
        return Collections.unmodifiableSet(fields);
    }

    @Override
    public Set<TypeConstantElement> getDeclaredTypeConstants(TypeElement typeElement) {
        final long start = (LOG.isLoggable(Level.FINE)) ? System.currentTimeMillis() : 0;
        final QualifiedName fullyQualifiedName = typeElement.getFullyQualifiedName();
        final FileObject typeFo = typeElement.getFileObject();
        final Set<TypeConstantElement> constants = new HashSet<>();
        final NameKind.Exact typeQuery = NameKind.exact(fullyQualifiedName);
        final NameKind constantQuery = NameKind.empty();

        switch (typeElement.getPhpElementKind()) {
            case CLASS:
                final Collection<? extends IndexResult> clzResults = results(ClassElementImpl.IDX_FIELD, typeQuery,
                        new String[]{ClassElementImpl.IDX_FIELD, TypeConstantElementImpl.IDX_FIELD});
                for (final IndexResult indexResult : clzResults) {
                    for (final TypeElement classElement : ClassElementImpl.fromSignature(typeQuery, this, indexResult)) {
                        constants.addAll(TypeConstantElementImpl.fromSignature(classElement, constantQuery, this, indexResult));
                    }
                }
                break;
            case IFACE:
                final Collection<? extends IndexResult> ifaceResults = results(InterfaceElementImpl.IDX_FIELD, typeQuery,
                        new String[]{InterfaceElementImpl.IDX_FIELD, TypeConstantElementImpl.IDX_FIELD});
                for (final IndexResult indexResult : ifaceResults) {
                    for (final TypeElement ifaceElement : InterfaceElementImpl.fromSignature(typeQuery, this, indexResult)) {
                        constants.addAll(TypeConstantElementImpl.fromSignature(ifaceElement, constantQuery, this, indexResult));
                    }
                }
                break;
            default:
                //noop
        }
        if (LOG.isLoggable(Level.FINE)) {
            logQueryTime("Set<TypeConstantElement> getTypeConstants", typeQuery, constantQuery, start); //NOI18N
        }
        return Collections.unmodifiableSet(ElementFilter.forFiles(typeFo).filter(constants));
    }

    @Override
    public Set<TypeConstantElement> getTypeConstants(NameKind constantQuery) {
        final long start = (LOG.isLoggable(Level.FINE)) ? System.currentTimeMillis() : 0;
        final Set<TypeConstantElement> constants = new HashSet<>();
        final Collection<? extends IndexResult> constantResults = results(TypeConstantElementImpl.IDX_FIELD, constantQuery,
                new String[]{ClassElementImpl.IDX_FIELD, InterfaceElementImpl.IDX_FIELD, TypeConstantElementImpl.IDX_FIELD});
        for (final IndexResult indexResult : constantResults) {
            final Set<TypeElement> types = new HashSet<>();
            types.addAll(ClassElementImpl.fromSignature(this, indexResult));
            types.addAll(InterfaceElementImpl.fromSignature(this, indexResult));
            for (final TypeElement typeElement : types) {
                constants.addAll(TypeConstantElementImpl.fromSignature(typeElement, constantQuery, this, indexResult));
            }
        }
        if (LOG.isLoggable(Level.FINE)) {
            logQueryTime("Set<TypeConstantElement> getTypeConstants", constantQuery, start); //NOI18N
        }
        return Collections.unmodifiableSet(constants);
    }

    @Override
    public Set<TypeConstantElement> getTypeConstants(NameKind.Exact typeQuery, NameKind constantQuery) {
        return getTypeConstantsImpl(typeQuery, constantQuery, EnumSet.of(PhpElementKind.CLASS, PhpElementKind.IFACE));
    }

    private Set<TypeConstantElement> getTypeConstantsImpl(NameKind.Exact typeQuery, NameKind constantQuery, EnumSet<PhpElementKind> typeKinds) {
        final long start = (LOG.isLoggable(Level.FINE)) ? System.currentTimeMillis() : 0;
        final Set<TypeConstantElement> constants = new HashSet<>();
        //two queries: once for classes, second for ifaces
        if (typeKinds.contains(PhpElementKind.CLASS)) {
            final Collection<? extends IndexResult> clzResults = results(ClassElementImpl.IDX_FIELD, typeQuery,
                    new String[]{ClassElementImpl.IDX_FIELD, TypeConstantElementImpl.IDX_FIELD});
            for (final IndexResult indexResult : clzResults) {
                for (final TypeElement typeElement : ClassElementImpl.fromSignature(typeQuery, this, indexResult)) {
                    constants.addAll(TypeConstantElementImpl.fromSignature(typeElement, constantQuery, this, indexResult));
                }
            }
        }
        if (typeKinds.contains(PhpElementKind.IFACE)) {
            final Collection<? extends IndexResult> ifaceResults = results(InterfaceElementImpl.IDX_FIELD, typeQuery,
                    new String[]{InterfaceElementImpl.IDX_FIELD, TypeConstantElementImpl.IDX_FIELD});
            for (final IndexResult indexResult : ifaceResults) {
                for (final TypeElement typeElement : InterfaceElementImpl.fromSignature(typeQuery, this, indexResult)) {
                    constants.addAll(TypeConstantElementImpl.fromSignature(typeElement, constantQuery, this, indexResult));
                }
            }
        }
        if (LOG.isLoggable(Level.FINE)) {
            logQueryTime("Set<TypeConstantElement> getTypeConstants", typeQuery, constantQuery, start); //NOI18N
        }
        return Collections.unmodifiableSet(constants);
    }

    @Override
    public QueryScope getQueryScope() {
        return QueryScope.INDEX_SCOPE;
    }

    @Override
    public Set<MethodElement> getStaticInheritedMethods(TypeElement typeElement) {
        return ElementFilter.forStaticModifiers(true).filter(getInheritedMethods(typeElement));
    }


    /**
     * @param enclosingType null if not enclosed at all
     */
    private static ElementFilter forAccessibleTypeMembers(final TypeElement enclosingType, final Collection<TypeElement> inheritedTypes) {
        final ElementFilter publicOnly = ElementFilter.forPublicModifiers(true);
        final ElementFilter publicAndProtectedOnly = ElementFilter.forPrivateModifiers(false);
        final ElementFilter fromEnclosingType = ElementFilter.forMembersOfType(enclosingType);
        // #253290 check used traits except for them of the inherited class
        final Set<TypeElement> usedTraits = getAllUsedTraits(enclosingType);

        return new ElementFilter() {
            private ElementFilter[] subtypesFilters = null;
            @Override
            public boolean isAccepted(final PhpElement element) {
                if (element instanceof TypeMemberElement) {
                    if (enclosingType != null) {
                        return isFromEnclosingType(element) || isFromTraitOfEnclosingType(element)
                                ? true
                                : (isFromSubclassOfEnclosingType(element) ? publicAndProtectedOnly.isAccepted(element) : publicOnly.isAccepted(element));
                    }
                    return publicOnly.isAccepted(element);
                }
                return true;
            }

            private boolean isFromEnclosingType(final PhpElement element) {
                return fromEnclosingType.isAccepted(element);
            }

            private boolean isFromTraitOfEnclosingType(final PhpElement element) {
                if (!usedTraits.isEmpty()) {
                    for (TypeElement nextType : inheritedTypes) {
                        if (nextType.isTrait() && usedTraits.contains(nextType) && ElementFilter.forMembersOfType(nextType).isAccepted(element)) {
                            return true;
                        }
                    }
                }
                return false;
            }

            private boolean isFromSubclassOfEnclosingType(final PhpElement element) {
                for (TypeElement nextType : inheritedTypes) {
                    if (ElementFilter.forMembersOfType(nextType).isAccepted(element)) {
                        return true;
                    }
                }
                if (subtypesFilters == null) {
                    subtypesFilters = createSubtypeFilters();
                }
                return subtypesFilters.length == 0 ? false : ElementFilter.anyOf(subtypesFilters).isAccepted(element);
            }

            private ElementFilter[] createSubtypeFilters() {
                final List<ElementFilter> filters = new ArrayList<>();
                final ElementQuery elementQuery = enclosingType.getElementQuery();
                if (elementQuery.getQueryScope().isIndexScope()) {
                    final ElementQuery.Index elementQueryIndex = (ElementQuery.Index) elementQuery;
                    final Set<TypeElement> inheritedTypes = elementQueryIndex.getInheritedTypes(enclosingType);
                    for (final TypeElement nextType : inheritedTypes) {
                        filters.add(ElementFilter.forMembersOfType(nextType));
                    }
                }
                return filters.toArray(new ElementFilter[filters.size()]);
            }
        };
    }

    /**
     * Get all traits directly used from a class or trait recursively.
     *
     * @param typeElement the type element
     * @return Used traits
     */
    private static Set<TypeElement> getAllUsedTraits(TypeElement typeElement) {
        final Set<TypeElement> usedTraits = new HashSet<>();
        if (typeElement instanceof TraitedElement) {
            TraitedElement traitedElement = (TraitedElement) typeElement;
            Collection<QualifiedName> traits = traitedElement.getUsedTraits();
            if (!traits.isEmpty()) {
                addAllUsedTraits(usedTraits, traitedElement, traits);
            }
        }
        return usedTraits;
    }

    private static void addAllUsedTraits(final Set<TypeElement> traits, TraitedElement traitedElement, final Collection<QualifiedName> usedTraits) {
        ElementQuery elementQuery = traitedElement.getElementQuery();
        if (elementQuery.getQueryScope().isIndexScope()) {
            final ElementQuery.Index elementQueryIndex = (ElementQuery.Index) elementQuery;
            for (QualifiedName usedTrait : usedTraits) {
                Set<TraitElement> usedTraitElements = elementQueryIndex.getTraits(NameKind.exact(usedTrait));
                traits.addAll(usedTraitElements);
                for (TraitElement usedTraitElement : usedTraitElements) {
                    // add traits recursively
                    addAllUsedTraits(traits, usedTraitElement, usedTraitElement.getUsedTraits());
                }
            }
        }
    }

    @Override
    public Set<MethodElement> getAccessibleMethods(final TypeElement typeElement, final TypeElement calledFromEnclosingType) {
        final long start = (LOG.isLoggable(Level.FINE)) ? System.currentTimeMillis() : 0;
        final Set<MethodElement> allMethods = getAllMethods(typeElement);
        Collection<TypeElement> subTypes = Collections.emptySet();
        if (calledFromEnclosingType != null && ElementFilter.forEqualTypes(typeElement).isAccepted(calledFromEnclosingType)) {
            subTypes = toTypes(allMethods);
        }
        final ElementFilter filterForAccessible = forAccessibleTypeMembers(calledFromEnclosingType, subTypes);
        Set<MethodElement> retval  = filterForAccessible.filter(allMethods);
        if (LOG.isLoggable(Level.FINE)) {
            logQueryTime("Set<MethodElement> getAccessibleMethods", NameKind.exact(typeElement.getFullyQualifiedName()), start); //NOI18N
        }
        return Collections.unmodifiableSet(retval);
    }

    @Override
    public Set<FieldElement> getAccessibleFields(final TypeElement typeElement, final TypeElement calledFromEnclosingType) {
        final long start = (LOG.isLoggable(Level.FINE)) ? System.currentTimeMillis() : 0;
        final Set<FieldElement> allFields = getAlllFields(typeElement);
        Collection<TypeElement> subTypes = Collections.emptySet();
        if (calledFromEnclosingType != null && ElementFilter.forEqualTypes(typeElement).isAccepted(calledFromEnclosingType)) {
            subTypes = toTypes(allFields);
        }
        final ElementFilter filterForAccessible = forAccessibleTypeMembers(calledFromEnclosingType, subTypes);
        Set<FieldElement> retval  = filterForAccessible.filter(allFields);
        if (LOG.isLoggable(Level.FINE)) {
            logQueryTime("Set<FieldElement> getAccessibleFields", NameKind.exact(typeElement.getFullyQualifiedName()), start); //NOI18N
        }
        return Collections.unmodifiableSet(retval);
    }

    private Set<TypeMemberElement> getDirectInheritedTypeMembers(final TypeElement typeElement,
            EnumSet<PhpElementKind> typeKinds, EnumSet<PhpElementKind> memberKinds) {
        final Set<TypeMemberElement> directTypes = new LinkedHashSet<>();
        if (typeKinds.contains(PhpElementKind.CLASS) && (typeElement instanceof ClassElement)) {
            ClassElement classElement = (ClassElement) typeElement;
            QualifiedName superClassName;
            Collection<QualifiedName> possibleFQSuperClassNames = classElement.getPossibleFQSuperClassNames();
            if (possibleFQSuperClassNames.size() == 1) {
                superClassName = possibleFQSuperClassNames.iterator().next();
            } else {
                superClassName = classElement.getSuperClassName();
            }
            Set<TypeMemberElement> classTypes = getDirectInheritedClassTypes(superClassName, memberKinds, typeElement);
            directTypes.addAll(classTypes);
        }
        if (typeKinds.contains(PhpElementKind.IFACE)) {
            Collection<QualifiedName> interfaceNames;
            Collection<QualifiedName> fQSuperInterfaceNames = typeElement.getFQSuperInterfaceNames();
            if (!fQSuperInterfaceNames.isEmpty()) {
                interfaceNames = fQSuperInterfaceNames;
            } else {
                interfaceNames = typeElement.getSuperInterfaces();
            }
            for (QualifiedName iface : interfaceNames) {
                final Set<TypeMemberElement> ifaceTypes = new LinkedHashSet<>();
                ifaceTypes.addAll(extendedQuery.getFields(NameKind.exact(iface), NameKind.empty()));
                ifaceTypes.addAll(extendedQuery.getMethods(NameKind.exact(iface), NameKind.empty()));
                ifaceTypes.addAll(extendedQuery.getTypeConstants(NameKind.exact(iface), NameKind.empty()));
                if (memberKinds.size() != 1) {
                    ifaceTypes.addAll(ElementFilter.forFiles(typeElement.getFileObject()).prefer(getTypeMembers(NameKind.exact(iface), NameKind.empty())));
                } else {
                    switch(memberKinds.iterator().next()) {
                        case METHOD:
                            ifaceTypes.addAll(ElementFilter.forFiles(typeElement.getFileObject()).prefer(getMethodsImpl(NameKind.exact(iface), NameKind.empty(),
                                    EnumSet.of(PhpElementKind.IFACE))));
                            break;
                        case TYPE_CONSTANT:
                            ifaceTypes.addAll(ElementFilter.forFiles(typeElement.getFileObject()).prefer(getTypeConstantsImpl(NameKind.exact(iface), NameKind.empty(),
                                    EnumSet.of(PhpElementKind.IFACE))));
                            break;
                        default:
                            //no-op
                    }
                }
                if (ifaceTypes.isEmpty()) {
                    insertEmptyElement(ifaceTypes, getInterfaces(NameKind.exact(iface)));
                }
                directTypes.addAll(ifaceTypes);
            }
        }
        if (typeKinds.contains(PhpElementKind.TRAIT) && (typeElement instanceof TraitedElement)) {
            TraitedElement traitedElement = (TraitedElement) typeElement;
            Collection<QualifiedName> usedTraits = traitedElement.getUsedTraits();
            for (QualifiedName trait : usedTraits) {
                final Set<TypeMemberElement> traitTypes = new LinkedHashSet<>();
                if (memberKinds.size() != 1) {
                    traitTypes.addAll(ElementFilter.forFiles(typeElement.getFileObject()).prefer(getTypeMembers(NameKind.exact(trait), NameKind.empty())));
                } else {
                    switch(memberKinds.iterator().next()) {
                        case METHOD:
                            traitTypes.addAll(ElementFilter.forFiles(typeElement.getFileObject()).prefer(getMethodsImpl(NameKind.exact(trait), NameKind.empty(),
                                    EnumSet.of(PhpElementKind.TRAIT))));
                            break;
                        case FIELD:
                            traitTypes.addAll(ElementFilter.forFiles(typeElement.getFileObject()).prefer(getFields(NameKind.exact(trait), NameKind.empty())));
                            break;
                        default:
                            //no-op
                    }
                }
                if (traitTypes.isEmpty()) {
                    insertEmptyElement(traitTypes, getTraits(NameKind.exact(trait)));
                }
                directTypes.addAll(traitTypes);
            }
        }
        return directTypes;
    }

    private Set<TypeMemberElement> getDirectMixinTypeMembers(final TypeElement typeElement,
            EnumSet<PhpElementKind> typeKinds, EnumSet<PhpElementKind> memberKinds) {
        final Set<TypeMemberElement> directTypes = new LinkedHashSet<>();
        if (typeKinds.contains(PhpElementKind.CLASS) && (typeElement instanceof ClassElement)) {
            ClassElement classElement = (ClassElement) typeElement;
            Collection<QualifiedName> mixinNames = classElement.getFQMixinClassNames();
            mixinNames.stream()
                    .map(mixinName -> getDirectInheritedClassTypes(mixinName, memberKinds, typeElement))
                    .forEach(classTypes -> directTypes.addAll(classTypes));
        }
        return directTypes;
    }

    private Set<TypeMemberElement> getDirectInheritedClassTypes(QualifiedName superClassName, EnumSet<PhpElementKind> memberKinds, final TypeElement typeElement) {
        final Set<TypeMemberElement> classTypes = new LinkedHashSet<>();
        if (superClassName != null) {
            classTypes.addAll(extendedQuery.getFields(NameKind.exact(superClassName), NameKind.empty()));
            classTypes.addAll(extendedQuery.getMethods(NameKind.exact(superClassName), NameKind.empty()));
            classTypes.addAll(extendedQuery.getTypeConstants(NameKind.exact(superClassName), NameKind.empty()));
            if (memberKinds.size() != 1) {
                classTypes.addAll(ElementFilter.forFiles(typeElement.getFileObject()).prefer(getTypeMembers(NameKind.exact(superClassName), NameKind.empty())));
            } else {
                switch (memberKinds.iterator().next()) {
                    case METHOD:
                        classTypes.addAll(ElementFilter.forFiles(typeElement.getFileObject()).prefer(
                                getMethodsImpl(NameKind.exact(superClassName), NameKind.empty(), EnumSet.of(PhpElementKind.CLASS))));
                        break;
                    case FIELD:
                        classTypes.addAll(ElementFilter.forFiles(typeElement.getFileObject()).prefer(getFields(NameKind.exact(superClassName), NameKind.empty())));
                        break;
                    case TYPE_CONSTANT:
                        classTypes.addAll(ElementFilter.forFiles(typeElement.getFileObject()).prefer(
                                getTypeConstantsImpl(NameKind.exact(superClassName), NameKind.empty(), EnumSet.of(PhpElementKind.CLASS))));
                        break;
                    default:
                    //no-op
                }
            }
            if (classTypes.isEmpty()) {
                insertEmptyElement(classTypes, getClasses(NameKind.exact(superClassName)));
            }
        }
        return classTypes;
    }

    private void insertEmptyElement(final Set<TypeMemberElement> where, final Set<? extends TypeElement> exactTypeName) {
        TypeElement exactType = ModelUtils.getFirst(exactTypeName);
        if (exactType != null) {
            where.add(new EmptyElement(exactType));
        }
    }

    @Override
    public Set<MethodElement> getInheritedMethods(final TypeElement typeElement) {
        final long start = (LOG.isLoggable(Level.FINE)) ? System.currentTimeMillis() : 0;
        final Set<TypeMemberElement> typeMembers =
                getInheritedTypeMembers(typeElement, new LinkedHashSet<TypeElement>(),
                new LinkedHashSet<TypeMemberElement>(),
                EnumSet.of(PhpElementKind.CLASS, PhpElementKind.IFACE, PhpElementKind.TRAIT),
                EnumSet.of(PhpElementKind.METHOD));
        final Set<MethodElement> retval = new HashSet<>();
        for (TypeMemberElement member : typeMembers) {
            if (member instanceof MethodElement) {
                retval.add((MethodElement) member);
            }
        }
        if (LOG.isLoggable(Level.FINE)) {
            logQueryTime("Set<MethodElement> getInheritedMethods", NameKind.exact(typeElement.getFullyQualifiedName()), start); //NOI18N
        }
        return Collections.unmodifiableSet(retval);
    }

    @Override
    public Set<MethodElement> getAllMethods(TypeElement typeElement) {
        final long start = (LOG.isLoggable(Level.FINE)) ? System.currentTimeMillis() : 0;
        final Set<TypeMemberElement> typeMembers =
                getInheritedTypeMembers(typeElement, new LinkedHashSet<TypeElement>(),
                new LinkedHashSet<TypeMemberElement>(getDeclaredMethods(typeElement)),
                EnumSet.of(PhpElementKind.CLASS, PhpElementKind.IFACE, PhpElementKind.TRAIT),
                EnumSet.of(PhpElementKind.METHOD));
        final Set<MethodElement> retval = new HashSet<>();
        for (TypeMemberElement member : typeMembers) {
            if (member instanceof MethodElement) {
                retval.add((MethodElement) member);
            }
        }
        if (LOG.isLoggable(Level.FINE)) {
            logQueryTime("Set<MethodElement> getAllMethods", NameKind.exact(typeElement.getFullyQualifiedName()), start); //NOI18N
        }
        return Collections.unmodifiableSet(retval);
    }

    @Override
    public Set<FieldElement> getAlllFields(TypeElement typeElement) {
        final long start = (LOG.isLoggable(Level.FINE)) ? System.currentTimeMillis() : 0;
        final Set<TypeMemberElement> typeMembers =
                getInheritedTypeMembers(typeElement, new LinkedHashSet<TypeElement>(),
                new LinkedHashSet<TypeMemberElement>(getDeclaredFields(typeElement)),
                EnumSet.of(PhpElementKind.CLASS, PhpElementKind.TRAIT),
                EnumSet.of(PhpElementKind.FIELD));
        final Set<FieldElement> retval = new HashSet<>();
        for (TypeMemberElement member : typeMembers) {
            if (member instanceof FieldElement) {
                retval.add((FieldElement) member);
            }
        }
        if (LOG.isLoggable(Level.FINE)) {
            logQueryTime("Set<FieldElement> getAlllFields", NameKind.exact(typeElement.getFullyQualifiedName()), start); //NOI18N
        }
        return Collections.unmodifiableSet(retval);
    }

    @Override
    public Set<TypeConstantElement> getAllTypeConstants(TypeElement typeElement) {
        final long start = (LOG.isLoggable(Level.FINE)) ? System.currentTimeMillis() : 0;
        final Set<TypeMemberElement> typeMembers =
                getInheritedTypeMembers(typeElement, new LinkedHashSet<TypeElement>(),
                new LinkedHashSet<TypeMemberElement>(getDeclaredTypeConstants(typeElement)),
                EnumSet.of(PhpElementKind.CLASS, PhpElementKind.IFACE),
                EnumSet.of(PhpElementKind.TYPE_CONSTANT));
        final Set<TypeConstantElement> retval = new HashSet<>();
        for (TypeMemberElement member : typeMembers) {
            if (member instanceof TypeConstantElement) {
                retval.add((TypeConstantElement) member);
            }
        }
        if (LOG.isLoggable(Level.FINE)) {
            logQueryTime("Set<TypeConstantElement> getAllTypeConstants", NameKind.exact(typeElement.getFullyQualifiedName()), start); //NOI18N
        }
        return Collections.unmodifiableSet(retval);
    }

    @Override
    public Set<TypeMemberElement> getAllTypeMembers(TypeElement typeElement) {
        final EnumSet<PhpElementKind> typeKinds = EnumSet.of(
                PhpElementKind.CLASS,
                PhpElementKind.IFACE,
                PhpElementKind.TRAIT
                );
        final EnumSet<PhpElementKind> memberKinds = EnumSet.of(
                PhpElementKind.METHOD,
                PhpElementKind.FIELD,
                PhpElementKind.TYPE_CONSTANT
                );
        return getInheritedTypeMembers(typeElement, new LinkedHashSet<TypeElement>(),
                new LinkedHashSet<>(getDeclaredTypeMembers(typeElement)), typeKinds, memberKinds);
    }

    private Set<TypeMemberElement> getAllMixinTypeMembers(TypeElement typeElement) {
        final EnumSet<PhpElementKind> typeKinds = EnumSet.of(PhpElementKind.CLASS);
        final EnumSet<PhpElementKind> memberKinds = EnumSet.of(
                PhpElementKind.METHOD,
                PhpElementKind.FIELD,
                PhpElementKind.TYPE_CONSTANT
        );
        return getMixinTypeMembers(typeElement, new LinkedHashSet<>(),
                new LinkedHashSet<>(getDeclaredTypeMembers(typeElement)), typeKinds, memberKinds);
    }

    @Override
    public Set<TypeMemberElement> getInheritedTypeMembers(final TypeElement typeElement) {
        final EnumSet<PhpElementKind> typeKinds = EnumSet.of(
                PhpElementKind.CLASS,
                PhpElementKind.IFACE,
                PhpElementKind.TRAIT
                );
        final EnumSet<PhpElementKind> memberKinds = EnumSet.of(
                PhpElementKind.METHOD,
                PhpElementKind.FIELD,
                PhpElementKind.TYPE_CONSTANT
                );
        return getInheritedTypeMembers(typeElement, new LinkedHashSet<TypeElement>(),
                new LinkedHashSet<TypeMemberElement>(), typeKinds, memberKinds);
    }

    @Override
    public Set<TypeMemberElement> getAccessibleTypeMembers(TypeElement typeElement, TypeElement calledFromEnclosingType) {
        final long start = (LOG.isLoggable(Level.FINE)) ? System.currentTimeMillis() : 0;
        final Set<TypeMemberElement> allTypeMembers = getAllTypeMembers(typeElement);
        Set<TypeMemberElement> retval = getAccessibleTypeMembers(typeElement, calledFromEnclosingType, allTypeMembers);
        if (LOG.isLoggable(Level.FINE)) {
            logQueryTime("Set<TypeMemberElement> getAccessibleTypeMembers", NameKind.exact(typeElement.getFullyQualifiedName()), start); //NOI18N
        }
        return Collections.unmodifiableSet(retval);
    }

    private Set<TypeMemberElement> getAccessibleTypeMembers(TypeElement typeElement, TypeElement calledFromEnclosingType, final Set<TypeMemberElement> allTypeMembers) {
        Collection<TypeElement> subTypes = Collections.emptySet();
        if (calledFromEnclosingType != null) {
            if (typeElement instanceof TraitElement
                    || ElementFilter.forEqualTypes(typeElement).isAccepted(calledFromEnclosingType)) {
                subTypes = toTypes(allTypeMembers);
            }
        }
        final ElementFilter filterForAccessible = forAccessibleTypeMembers(calledFromEnclosingType, subTypes);
        Set<TypeMemberElement> retval  = new HashSet<>();
        retval.addAll(filterForAccessible.filter(allTypeMembers));
        ElementFilter allOf = ElementFilter.allOf(ElementFilter.forVirtualExtensions(), ElementFilter.forMembersOfTypeName(typeElement));
        retval.addAll(allOf.filter(allTypeMembers));
        return retval;
    }

    @Override
    public Set<TypeMemberElement> getAccessibleMixinTypeMembers(TypeElement typeElement, TypeElement calledFromEnclosingType) {
        final long start = (LOG.isLoggable(Level.FINE)) ? System.currentTimeMillis() : 0;
        final Set<TypeMemberElement> allTypeMembers = getAllMixinTypeMembers(typeElement);
        Set<TypeMemberElement> retval = getAccessibleTypeMembers(typeElement, calledFromEnclosingType, allTypeMembers);
        if (LOG.isLoggable(Level.FINE)) {
            logQueryTime("Set<TypeMemberElement> getAccessibleMixinTypeMembers", NameKind.exact(typeElement.getFullyQualifiedName()), start); // NOI18N
        }
        return Collections.unmodifiableSet(retval);
    }

    private Set<TypeMemberElement> getInheritedTypeMembers(final TypeElement typeElement, final Set<TypeElement> recursionPrevention,
            Set<TypeMemberElement> retval, EnumSet<PhpElementKind> typeKinds, EnumSet<PhpElementKind> memberKinds) {
        if (recursionPrevention.add(typeElement)) {
            final Set<TypeMemberElement> typeMembers = getDirectInheritedTypeMembers(typeElement, typeKinds, memberKinds);
            retval.addAll(forEmptyElements().filter(forComparingNonAbstractNameKinds(retval).reverseFilter(typeMembers)));
            for (final TypeElement tp : typeMembers.isEmpty() ? getDirectInheritedTypes(typeElement) : toTypes(typeMembers)) {
                retval.addAll(getInheritedTypeMembers(tp, recursionPrevention, retval, typeKinds, memberKinds));
            }
        }
        return forPrefereMethodImplementation(retval).filter(retval);
    }

    private Set<TypeMemberElement> getMixinTypeMembers(final TypeElement typeElement, final Set<TypeElement> recursionPrevention,
            Set<TypeMemberElement> retval, EnumSet<PhpElementKind> typeKinds, EnumSet<PhpElementKind> memberKinds) {
        if (recursionPrevention.add(typeElement)) {
            final Set<TypeMemberElement> typeMembers = getDirectMixinTypeMembers(typeElement, typeKinds, memberKinds);
            retval.addAll(forEmptyElements().filter(forComparingNonAbstractNameKinds(retval).reverseFilter(typeMembers)));
            Set<TypeElement> types = toTypes(typeMembers);
            types.addAll(getDirectInheritedTypes(typeElement));
            types.forEach(type -> retval.addAll(getMixinTypeMembers(type, recursionPrevention, retval, typeKinds, memberKinds)));
        }
        return forPrefereMethodImplementation(retval).filter(retval);
    }

    @Override
    public Set<MethodElement> getAllMethods(final Exact typeQuery, final NameKind methodQuery) {
        Set<MethodElement> retval = new HashSet<>();
        Set<TypeElement> types = new HashSet<>();
        types.addAll(getClassesImpl(typeQuery));
        types.addAll(getInterfacesImpl(typeQuery));
        types.addAll(getTraitsImpl(typeQuery));
        for (TypeElement typeElement : types) {
            retval.addAll(ElementFilter.forName(methodQuery).filter(getAllMethods(typeElement)));
        }
        return retval;
    }

    @Override
    public Set<FieldElement> getAlllFields(final Exact typeQuery, final NameKind fieldQuery) {
        Set<FieldElement> retval = new HashSet<>();
        Set<ClassElement> types = getClassesImpl(typeQuery);
        for (TypeElement typeElement : types) {
            retval.addAll(ElementFilter.forName(fieldQuery).filter(getAlllFields(typeElement)));
        }
        return retval;
    }

    @Override
    public Set<TypeConstantElement> getAllTypeConstants(final Exact typeQuery, final NameKind constantQuery) {
        Set<TypeConstantElement> retval = new HashSet<>();
        Set<TypeElement> types = new HashSet<>();
        types.addAll(getClassesImpl(typeQuery));
        types.addAll(getInterfacesImpl(typeQuery));
        for (TypeElement typeElement : types) {
            retval.addAll(ElementFilter.forName(constantQuery).filter(getAllTypeConstants(typeElement)));
        }
        return retval;
    }

    @Override
    public Set<FieldElement> getAccessibleStaticFields(final TypeElement classElement, final TypeElement calledFromEnclosingType) {
        return ElementFilter.forStaticModifiers(true).filter(getAccessibleFields(classElement, calledFromEnclosingType));
    }

    @Override
    public Set<MethodElement> getAccessibleStaticMethods(final TypeElement typeElement, final TypeElement calledFromEnclosingType) {
        return ElementFilter.forStaticModifiers(true).filter(getAccessibleMethods(typeElement, calledFromEnclosingType));
    }

    private Set<TypeConstantElement> getNotPrivateTypeConstants(TypeElement oneType) {
        return ElementFilter.forPrivateModifiers(false).filter(getDeclaredTypeConstants(oneType));
    }

    private Set<FieldElement> getNotPrivateFields(ClassElement oneClass) {
        return ElementFilter.forPrivateModifiers(false).filter(getDeclaredFields(oneClass));
    }

    @Override
    public Set<FieldElement> getStaticInheritedFields(final TypeElement classElement) {
        return ElementFilter.forStaticModifiers(true).filter(getInheritedFields(classElement));
    }

    @Override
    public Set<FieldElement> getInheritedFields(final TypeElement classElement) {
        final long start = (LOG.isLoggable(Level.FINE)) ? System.currentTimeMillis() : 0;
        final Set<FieldElement> retval = new HashSet<>();
        final Set<ClassElement> inheritedClasses = getInheritedClasses(classElement);
        for (ClassElement oneClass : inheritedClasses) {
            final Set<FieldElement> fields = getNotPrivateFields(oneClass);
            for (final FieldElement fieldElement : fields) {
                retval.add(fieldElement);
            }
        }
        if (LOG.isLoggable(Level.FINE)) {
            logQueryTime("Set<FieldElement> getInheritedFields", NameKind.exact(classElement.getFullyQualifiedName()), start); //NOI18N
        }
        return Collections.unmodifiableSet(retval);
    }


    @Override
    public Set<TypeConstantElement> getInheritedTypeConstants(TypeElement typeElement) {
        final long start = (LOG.isLoggable(Level.FINE)) ? System.currentTimeMillis() : 0;
        final Set<TypeConstantElement> retval = new HashSet<>();
        final Set<? extends TypeElement> inheritedTypes = getInheritedTypes(typeElement);
        for (TypeElement oneType : inheritedTypes) {
            final Set<TypeConstantElement> constants = getNotPrivateTypeConstants(oneType);
            for (final TypeConstantElement constantElement : constants) {
                retval.add(constantElement);
            }
        }
        if (LOG.isLoggable(Level.FINE)) {
            logQueryTime("Set<TypeConstantElement> getInheritedTypeConstants", NameKind.exact(typeElement.getFullyQualifiedName()), start); //NOI18N
        }
        return Collections.unmodifiableSet(retval);
    }

    @Override
    public Set<TypeElement> getInheritedByTypes(final TypeElement typeElement) {
        final long start = (LOG.isLoggable(Level.FINE)) ? System.currentTimeMillis() : 0;
        final Set<TypeElement> retval = new LinkedHashSet<>();
        getInheritedByTypes(typeElement, retval);
        retval.remove(typeElement);
        if (LOG.isLoggable(Level.FINE)) {
            logQueryTime("LinkedHashSet<TypeElement> getInheritedByTypes", NameKind.exact(typeElement.getFullyQualifiedName()), start); //NOI18N
        }
        return retval;
    }

    @Override
    public Set<TypeElement> getInheritedTypes(final TypeElement typeElement) {
        final long start = (LOG.isLoggable(Level.FINE)) ? System.currentTimeMillis() : 0;
        final Set<TypeElement> retval = new LinkedHashSet<>();
        getInheritedTypes(typeElement, retval, true, true);
        retval.remove(typeElement);
        if (LOG.isLoggable(Level.FINE)) {
            logQueryTime("LinkedHashSet<TypeElement> getInheritedTypes", NameKind.exact(typeElement.getFullyQualifiedName()), start); //NOI18N
        }
        return retval;
    }

    @Override
    public Set<ClassElement> getInheritedClasses(final TypeElement classElement) {
        final long start = (LOG.isLoggable(Level.FINE)) ? System.currentTimeMillis() : 0;
        final Set<ClassElement> retvalClasses = new LinkedHashSet<>();
        final Set<TypeElement> retvalTypes = new LinkedHashSet<>();
        getInheritedTypes(classElement, retvalTypes, true, false);
        retvalTypes.remove(classElement);
        for (TypeElement te : retvalTypes) {
            if (te instanceof ClassElement) {
                retvalClasses.add((ClassElement) te);
            } else {
                assert false : te.toString();
            }
        }
        if (LOG.isLoggable(Level.FINE)) {
            logQueryTime("LinkedHashSet<ClassElement> getInheritedClasses", NameKind.exact(classElement.getFullyQualifiedName()), start); //NOI18N
        }
        return retvalClasses;
    }

    @Override
    public Set<InterfaceElement> getInheritedInterfaces(TypeElement ifaceElement) {
        final long start = (LOG.isLoggable(Level.FINE)) ? System.currentTimeMillis() : 0;
        final Set<InterfaceElement> retvalIfaces = new LinkedHashSet<>();
        final Set<TypeElement> retvalTypes = new LinkedHashSet<>();
        getInheritedTypes(ifaceElement, retvalTypes, false, true);
        retvalTypes.remove(ifaceElement);
        for (TypeElement te : retvalTypes) {
            if (te instanceof InterfaceElement) {
                retvalIfaces.add((InterfaceElement) te);
            } else {
                assert false : te.toString();
            }
        }
        if (LOG.isLoggable(Level.FINE)) {
            logQueryTime("LinkedHashSet<InterfaceElement> getInheritedInterfaces", NameKind.exact(ifaceElement.getFullyQualifiedName()), start); //NOI18N
        }
        return retvalIfaces;
    }

    private static ElementFilter forComparingNonAbstractNameKinds(final Collection<? extends PhpElement> elements) {
        return new ElementFilter() {

            @Override
            public boolean isAccepted(PhpElement element) {
                final ElementFilter forKind = ElementFilter.forKind(element.getPhpElementKind());
                final ElementFilter forName = ElementFilter.forName(NameKind.exact(element.getName()));
                for (PhpElement nextElement : elements) {
                    if (forKind.isAccepted(nextElement) && forName.isAccepted(nextElement)) {
                        if (!nextElement.getPhpModifiers().isAbstract()) {
                            return true;
                        }
                    }
                }
                return false;
            }
        };
    }

    private static ElementFilter forPrefereMethodImplementation(final Collection<? extends PhpElement> elements) {
        return new ElementFilter() {

            @Override
            public boolean isAccepted(PhpElement element) {
                boolean isAbstract = element.getPhpModifiers().isAbstract();
                boolean isMethod = PhpElementKind.METHOD.equals(element.getPhpElementKind());
                if (isAbstract && isMethod) {
                    final ElementFilter forKind = ElementFilter.forKind(element.getPhpElementKind());
                    final ElementFilter forName = ElementFilter.forName(NameKind.exact(element.getName()));
                    for (PhpElement phpElement : elements) {
                        if (!phpElement.equals(element) && forKind.isAccepted(phpElement) && forName.isAccepted(phpElement) && !phpElement.getPhpModifiers().isAbstract()) {
                            return false;
                        }
                    }
                }
                return true;
            }
        };
    }

    private static ElementFilter forEmptyElements() {
        return new ElementFilter() {

            @Override
            public boolean isAccepted(final PhpElement element) {
                boolean result = true;
                if (PhpElementKind.EMPTY.equals(element.getPhpElementKind())) {
                    result = false;
                }
                return result;
            }
        };
    }

    private static Set<TypeElement> toTypes(final Collection<? extends TypeMemberElement> typeMembers) {
        final Set<TypeElement> retval = new LinkedHashSet<>();
        for (final TypeMemberElement typeMemberElement : typeMembers) {
            retval.add(typeMemberElement.getType());
        }
        return retval;
    }

    private void getInheritedTypes(final TypeElement typeElement, final Set<TypeElement> retval,
            final boolean includeClasses, final boolean includeIfaces) {
        if (retval.add(typeElement)) {
            Set<TypeElement> directTypes = getDirectInheritedTypes(typeElement, includeClasses, includeIfaces);
            for (TypeElement tp : directTypes) {
                getInheritedTypes(tp, retval, includeClasses, includeIfaces);
            }
        }
    }

    @Override
    public Set<ClassElement> getDirectInheritedClasses(final TypeElement typeElement) {
        final Set<ClassElement> retval = new LinkedHashSet<>();
        final Set<TypeElement> types = getDirectInheritedTypes(typeElement, true, false);
        for (final TypeElement nextType : types) {
            if (nextType instanceof ClassElement) {
                retval.add((ClassElement) nextType);
            }
        }
        return retval;
    }

    @Override
    public Set<InterfaceElement> getDirectInheritedInterfaces(final TypeElement typeElement) {
        final Set<InterfaceElement> retval = new LinkedHashSet<>();
        final Set<TypeElement> types = getDirectInheritedTypes(typeElement, false, true);
        for (final TypeElement nextType : types) {
            if (nextType instanceof InterfaceElement) {
                retval.add((InterfaceElement) nextType);
            }
        }
        return retval;
    }

    @Override
    public Set<TypeElement> getDirectInheritedTypes(final TypeElement typeElement) {
        return getDirectInheritedTypes(typeElement, true, true);
    }

    private Set<TypeElement> getDirectInheritedTypes(final TypeElement typeElement, final boolean includeClasses, final boolean includeIfaces) {
        final Set<TypeElement> directTypes = new LinkedHashSet<>();
        if (includeClasses && (typeElement instanceof ClassElement)) {
            QualifiedName superClassName;
            Collection<QualifiedName> possibleFQSuperClassNames = ((ClassElement) typeElement).getPossibleFQSuperClassNames();
            if (possibleFQSuperClassNames.size() == 1) {
                superClassName = possibleFQSuperClassNames.iterator().next();
            } else {
                superClassName = ((ClassElement) typeElement).getSuperClassName();
            }
            if (superClassName != null) {
                directTypes.addAll(ElementFilter.forFiles(typeElement.getFileObject()).prefer(getClassesImpl(NameKind.exact(superClassName))));
            }
        }
        if (includeIfaces) {
            for (QualifiedName iface : typeElement.getSuperInterfaces()) {
                directTypes.addAll(ElementFilter.forFiles(typeElement.getFileObject()).prefer(getInterfacesImpl(NameKind.exact(iface))));
            }
        }
        return directTypes;
    }

    private void getInheritedByTypes(final TypeElement typeElement, final Set<TypeElement> retval) {
        if (retval.add(typeElement)) {
            Set<TypeElement> directTypes = getDirectInheritedByTypes(typeElement);
            for (TypeElement tp : directTypes) {
                getInheritedByTypes(tp, retval);
            }
        }
    }

    @Override
    public Set<TypeElement> getDirectInheritedByTypes(final TypeElement typeElement) {
        final Set<TypeElement> directTypes = new LinkedHashSet<>();
        final Exact query = NameKind.exact(typeElement.getFullyQualifiedName());
        if (typeElement.isClass()) {
            final Collection<? extends IndexResult> result = results(PHPIndexer.FIELD_SUPER_CLASS, query,
                    new String[] {PHPIndexer.FIELD_SUPER_CLASS, ClassElementImpl.IDX_FIELD});
            for (final IndexResult indexResult : result) {
                String[] values = indexResult.getValues(PHPIndexer.FIELD_SUPER_CLASS);
                for (String value : values) {
                    Signature signature = Signature.get(value);
                    final QualifiedName fqnForValue = QualifiedName.createFullyQualified(signature.string(1), signature.string(2));
                    if (query.matchesName(PhpElementKind.CLASS, fqnForValue)) {
                        directTypes.addAll(ClassElementImpl.fromSignature(NameKind.empty(), this, indexResult));
                    }
                }
            }
        } else if (typeElement.isInterface()) {
            final Collection<? extends IndexResult> result = results(PHPIndexer.FIELD_SUPER_IFACE, query,
                    new String[] {PHPIndexer.FIELD_SUPER_IFACE, InterfaceElementImpl.IDX_FIELD, ClassElementImpl.IDX_FIELD});
            for (final IndexResult indexResult : result) {
                String[] values = indexResult.getValues(PHPIndexer.FIELD_SUPER_IFACE);
                for (String value : values) {
                    Signature signature = Signature.get(value);
                    final QualifiedName fqnForValue = QualifiedName.createFullyQualified(signature.string(1), signature.string(2));
                    if (query.matchesName(PhpElementKind.IFACE, fqnForValue)) {
                        directTypes.addAll(InterfaceElementImpl.fromSignature(NameKind.empty(), this, indexResult));
                        directTypes.addAll(ClassElementImpl.fromSignature(NameKind.empty(), this, indexResult));
                    }
                }
            }
        }
        return directTypes;
    }

    private static Set<String> toNames(Set<? extends PhpElement> elements) {
        Set<String> names = new HashSet<>();
        for (PhpElement elem : elements) {
            names.add(elem.getName());
        }
        return names;
    }

    private Collection<? extends IndexResult> search(String fieldName, String fieldValue, QuerySupport.Kind kind, String... fieldsToLoad) {
        try {
            long start = (LOG.isLoggable(Level.FINER)) ? System.currentTimeMillis() : 0;
            Collection<? extends IndexResult> results = index.query(fieldName, fieldValue, kind, fieldsToLoad);

            if (LOG.isLoggable(Level.FINER)) {
                String msg = "IndexQuery.search(" + fieldName + ", " + fieldValue + ", " + kind + ", " //NOI18N
                        + (fieldsToLoad == null || fieldsToLoad.length == 0 ? "no terms" : Arrays.asList(fieldsToLoad)) + ")"; //NOI18N
                LOG.finer(msg);

                if (LOG.isLoggable(Level.FINEST)) {
                    LOG.log(Level.FINEST, null, new Throwable(msg));
                }

                for (IndexResult r : results) {
                    LOG.log(Level.FINER, "Fields in {0} ({1}):", new Object[]{r, r.getFile().getPath()}); //NOI18N
                    for (String field : PHPIndexer.getAllFields()) {
                        String value = r.getValue(field);
                        if (value != null) {
                            LOG.log(Level.FINEST, " <{0}> = <{1}>", new Object[]{field, value}); //NOI18N
                        }
                    }
                    LOG.finer("----"); //NOI18N
                }
                LOG.finer(String.format("took: %d [ms]", System.currentTimeMillis() - start)); //NOI18N
                LOG.finer("===="); //NOI18N
            }

            return results;
        } catch (IOException ioe) {
            Exceptions.printStackTrace(ioe);
            return Collections.<IndexResult>emptySet();
        }
    }

    private Collection<? extends IndexResult> results(final String indexField, final NameKind query) {
        return results(indexField, query, new String[]{indexField});
    }

    private Collection<? extends IndexResult> results(final String indexField,
            final NameKind query, final String[] fieldsToLoad) {
        return search(indexField, prepareIdxQuery(query.getQueryName(), query.getQueryKind()), Kind.CASE_INSENSITIVE_PREFIX, fieldsToLoad);
    }

    private void logQueryTime(final String queryDescription, final NameKind typeQuery,
            final NameKind memberQuery, final long start) {
        LOG.fine(String.format("%s for type query: [%s:%s] and took: member query: [%s:%s] %d [ms]", queryDescription, //NOI18N
                typeQuery.getQueryKind().toString(), typeQuery.getQuery().toString(),
                memberQuery.getQueryKind().toString(), memberQuery.getQuery().toString(),
                System.currentTimeMillis() - start)); //NOI18N

    }

    private void logQueryTime(final String queryDescription, final NameKind query, final long start) {
        LOG.fine(String.format("%s for query: [%s:%s] took: %d [ms]", queryDescription, //NOI18N
                query.getQueryKind().toString(), query.getQuery().toString(),
                System.currentTimeMillis() - start)); //NOI18N
    }

    private static String prepareIdxQuery(String textForQuery, Kind kind) {
        String query = textForQuery.toLowerCase();
        if (kind.equals(QuerySupport.Kind.CAMEL_CASE)) {
            final int length = textForQuery.length();
            if (length > 0 && Character.isLetter(textForQuery.charAt(0))) {
                query = query.substring(0, 1); //NOI18N
            } else if (length > 1 && textForQuery.charAt(0) == '$') { //NOI18N
                query = query.substring(0, 1); //NOI18N
            } else {
                query = ""; //NOI18N
            }
        }
        return query;
    }

    @Override
    public TreeElement<TypeElement> getInheritedTypesAsTree(TypeElement typeElement) {
        return new TypeTreeElementImpl(typeElement, true);
    }

    @Override
    public TreeElement<TypeElement> getInheritedTypesAsTree(TypeElement typeElement, Set<TypeElement> preferredTypes) {
        return new TypeTreeElementImpl(typeElement, preferredTypes, true);
    }

    @Override
    public TreeElement<TypeElement> getInheritedByTypesAsTree(TypeElement typeElement) {
                return new TypeTreeElementImpl(typeElement, false);
    }

    @Override
    public TreeElement<TypeElement> getInheritedByTypesAsTree(TypeElement typeElement, Set<TypeElement> preferredTypes) {
                return new TypeTreeElementImpl(typeElement, preferredTypes, false);
    }

    @Override
    public Set<PhpElement> getTopLevelElements(NameKind query) {
        return getTopLevelElements(query, aliases, null);
    }

    @Override
    public Set<ClassElement> getClasses() {
        return getClasses(NameKind.empty(), aliases, null);
    }

    @Override
    public Set<ClassElement> getClasses(NameKind query) {
        return getClasses(query, aliases, null);
    }

    @Override
    public Set<InterfaceElement> getInterfaces() {
        return getInterfaces(NameKind.empty(), aliases, null);
    }

    @Override
    public Set<InterfaceElement> getInterfaces(NameKind query) {
        return getInterfaces(query, aliases, null);
    }

    @Override
    public Set<TypeElement> getTypes(NameKind query) {
        return getTypes(query, aliases, null);
    }

    @Override
    public Set<FunctionElement> getFunctions() {
        return getFunctions(NameKind.empty(), aliases, null);
    }

    @Override
    public Set<FunctionElement> getFunctions(NameKind query) {
        return getFunctions(query, aliases, null);
    }

    @Override
    public Set<ConstantElement> getConstants() {
        return getConstants(NameKind.empty(), aliases, null);
    }

    @Override
    public Set<ConstantElement> getConstants(NameKind query) {
        return getConstants(query, aliases, null);
    }

    @Override
    public Set<MethodElement> getConstructors(NameKind typeQuery) {
        return getConstructors(typeQuery, aliases, null);
    }

    @Override
    public Set<NamespaceElement> getNamespaces(NameKind query) {
        return getNamespaces(query, aliases, null);
    }

    @Override
    public Set<ClassElement> getClasses(final NameKind query, final Set<AliasedName> aliasedNames, final Trait trait) {
        final Set<ClassElement> retval = new HashSet<>();
        for (final AliasedName aliasedName : aliasedNames) {
            for (final NameKind nextQuery : queriesForAlias(query, aliasedName, PhpElementKind.CLASS)) {
                for (final ClassElement nextClass : getClassesImpl(nextQuery)) {
                    final AliasedClass aliasedClass = new AliasedClass(aliasedName, nextClass);
                    if (trait != null) {
                        aliasedClass.setTrait(trait);
                    }
                    retval.add(aliasedClass);
                }
            }
        }
        retval.addAll(getClassesImpl(query));
        return retval;
    }

    @Override
    public Set<NamespaceElement> getNamespaces(final NameKind query, final Set<AliasedName> aliasedNames, final Trait trait) {
        final Set<NamespaceElement> retval = new HashSet<>();
        for (final AliasedName aliasedName : aliasedNames) {
            final Set<NameKind> queriesForAlias = queriesForAlias(query, aliasedName, PhpElementKind.NAMESPACE_DECLARATION);
            for (final NameKind nextQuery : queriesForAlias) {
                for (final NamespaceElement nextNamespace : getNamespacesImpl(nextQuery)) {
                    final AliasedNamespace aliasedNamespace = new AliasedNamespace(aliasedName, nextNamespace);
                    if (trait != null) {
                        aliasedNamespace.setTrait(trait);
                    }
                    retval.add(aliasedNamespace);
                }
            }
        }
        retval.addAll(getNamespacesImpl(query));
        return retval;
    }

    @Override
    public Set<FunctionElement> getFunctions(final NameKind query, final Set<AliasedName> aliasedNames, final Trait trait) {
        final Set<FunctionElement> retval = new HashSet<>();
        for (final AliasedName aliasedName : aliasedNames) {
            for (final NameKind nextQuery : queriesForAlias(query, aliasedName, PhpElementKind.FUNCTION)) {
                for (final FunctionElement nextFunction : getFunctionsImpl(nextQuery)) {
                    final AliasedFunction aliasedFunction = new AliasedFunction(aliasedName, nextFunction);
                    if (trait != null) {
                        aliasedFunction.setTrait(trait);
                    }
                    retval.add(aliasedFunction);
                }
            }
        }
        retval.addAll(getFunctionsImpl(query));
        return retval;
    }

    @Override
    public Set<ConstantElement> getConstants(final NameKind query, final Set<AliasedName> aliasedNames, final Trait trait) {
        final Set<ConstantElement> retval = new HashSet<>();
        for (final AliasedName aliasedName : aliasedNames) {
            for (final NameKind nextQuery : queriesForAlias(query, aliasedName, PhpElementKind.CONSTANT)) {
                for (final ConstantElement nextConstant : getConstantsImpl(nextQuery)) {
                    final AliasedConstant aliasedConstant = new AliasedConstant(aliasedName, nextConstant);
                    if (trait != null) {
                        aliasedConstant.setTrait(trait);
                    }
                    retval.add(aliasedConstant);
                }
            }
        }
        retval.addAll(getConstantsImpl(query));
        return retval;
    }

    @Override
    public Set<MethodElement> getConstructors(final NameKind typeQuery, final Set<AliasedName> aliasedNames, final Trait trait) {
        final Set<MethodElement> retval = new HashSet<>();
        for (final AliasedName aliasedName : aliasedNames) {
            for (final NameKind nextQuery : queriesForAlias(typeQuery, aliasedName, PhpElementKind.CLASS)) {
                for (ClassElement classElement : getClassesImpl(nextQuery)) {
                    final AliasedClass aliasedClass = new AliasedClass(aliasedName, classElement);
                    if (trait != null) {
                        aliasedClass.setTrait(trait);
                    }
                    final Set<MethodElement> constructorsImpl = getConstructorsImpl(aliasedClass, classElement, new LinkedHashSet<ClassElement>());
                    retval.addAll(constructorsImpl.isEmpty() ? getDefaultConstructors(aliasedClass) : constructorsImpl);
                }
            }
        }
        retval.addAll(getConstructorsImpl(typeQuery));
        return retval;
    }


    @Override
    public Set<PhpElement> getTopLevelElements(final NameKind query, final Set<AliasedName> aliasedNames, final Trait trait) {
        final Set<PhpElement> retval = new HashSet<>();
        for (final AliasedName aliasedName : aliasedNames) {
            for (final NameKind nextQuery : queriesForAlias(query, aliasedName, PhpElementKind.CLASS)) {
                for (final PhpElement nextElement : getTopLevelElementsImpl(nextQuery)) {
                    AliasedElement aliasedElement = null;
                    if (nextElement instanceof ConstantElement) {
                        aliasedElement = new AliasedConstant(aliasedName, (ConstantElement) nextElement);
                    } else if (nextElement instanceof FunctionElement) {
                        aliasedElement = new AliasedFunction(aliasedName, (FunctionElement) nextElement);
                    } else if (nextElement instanceof ClassElement) {
                        aliasedElement = new AliasedClass(aliasedName, (ClassElement) nextElement);
                    } else if (nextElement instanceof InterfaceElement) {
                        aliasedElement = new AliasedInterface(aliasedName, (InterfaceElement) nextElement);
                    } else if (nextElement instanceof TraitElement) {
                        aliasedElement = new AliasedTrait(aliasedName, (TraitElement) nextElement);
                    }
                    if (aliasedElement != null) {
                        if (trait != null) {
                            aliasedElement.setTrait(trait);
                        }
                        retval.add(aliasedElement);
                    }
                }
            }
        }
        retval.addAll(getTopLevelElementsImpl(query));
        return retval;
    }

    @Override
    public Set<InterfaceElement> getInterfaces(final NameKind query, final Set<AliasedName> aliasedNames, final Trait trait) {
        final Set<InterfaceElement> retval = new HashSet<>();
        for (final AliasedName aliasedName : aliasedNames) {
            for (final NameKind nextQuery : queriesForAlias(query, aliasedName, PhpElementKind.IFACE)) {
                for (final InterfaceElement nextIface : getInterfacesImpl(nextQuery)) {
                    final AliasedInterface aliasedInterface = new AliasedInterface(aliasedName, nextIface);
                    if (trait != null) {
                        aliasedInterface.setTrait(trait);
                    }
                    retval.add(aliasedInterface);
                }
            }
        }
        retval.addAll(getInterfacesImpl(query));
        return retval;
    }

    public Set<TraitElement> getTraits() {
        return getTraits(NameKind.empty());
    }

    @Override
    public Set<TraitElement> getTraits(final NameKind query) {
        final Set<TraitElement> retval = new HashSet<>();
        retval.addAll(getTraitsImpl(query));
        return retval;
    }

    @Override
    public Set<TypeElement> getTypes(final NameKind query, final Set<AliasedName> aliasedNames, final Trait trait) {
        final Set<TypeElement> retval = new HashSet<>();
        for (final AliasedName aliasedName : aliasedNames) {
            for (final NameKind nextQuery : queriesForAlias(query, aliasedName, PhpElementKind.CLASS)) {
                for (final TypeElement nextType : getTypesImpl(nextQuery)) {
                    AliasedType aliasedType = null;
                    if (nextType instanceof ClassElement) {
                        aliasedType = new AliasedClass(aliasedName, (ClassElement) nextType);
                    } else if (nextType instanceof InterfaceElement) {
                        aliasedType = new AliasedInterface(aliasedName, (InterfaceElement) nextType);
                    } else if (nextType instanceof TraitElement) {
                        aliasedType = new AliasedTrait(aliasedName, (TraitElement) nextType);
                    } else {
                        assert false : nextType.getClass();
                    }
                    if (aliasedType != null) {
                        if (trait != null) {
                            aliasedType.setTrait(trait);
                        }
                        retval.add(aliasedType);
                    }
                }
            }
        }
        retval.addAll(getTypesImpl(query));
        return retval;
    }


}
